pax_global_header00006660000000000000000000000064143051552500014512gustar00rootroot0000000000000052 comment=9c008066d2f54b90e98dcca5bdc14f552ea0a1b3 objcryst-2022.1/000077500000000000000000000000001430515525000134375ustar00rootroot00000000000000objcryst-2022.1/.gitignore000066400000000000000000000006521430515525000154320ustar00rootroot00000000000000*.o *.obj *.dep *.a *.xcworkspacedata *.xccheckout project.xcworkspace *.xcuserdatad *.app build *.log /cctbx/cctbx /cctbx/include /newmat /freeglut* /fftw* /mysql* *.tlog /static-libs *.tar.bz2 *.tar.gz cctbx_install_script.csh cctbx_sources newmat11 .idea /wxWidgets* *.pyc /ObjCryst/rules.mak /Fox/Makefile *.OLD JOB*.xml* /Fox/src/Fox /Fox/src/Fox-nogui /Fox/example/client *.dmg Fox/wikihtml *.pov boost_1_68_0 GridRslt objcryst-2022.1/ChangeLog.txt000066400000000000000000000671641430515525000160450ustar00rootroot00000000000000#### 2022.1 (May 2022) NEW FEATURES * Add cylindrical absorption correction (mu*R) * Access to Crystallography Open Database now uses an http access without need for MySQL, and should work through firewalls * Added more internal functions for the pyobjcryst Python interface. See https://pyobjcryst.readthedocs.io/en/latest/examples/index.html IMPROVEMENTS * Improve indexing: use the integrated goodness-of-fit based on P1 integration intervals as a default indicator, normalised by the number of reflections used (* nb_refl / nb_refl_P1) * Switched to wxWidgets 3.1 * When using --cif2pattern, do not convert atoms to a Molecule (faster) * Fox grid allows a working directory with spaces in the path. * In the XML output, the atom list inside a RigidGroup will now be valid XML. NB: older Fox versions will not be able to read correctly the list of atoms inside the group. BUG FIXES * Correct EstimateCellVolume estimation for orthorombic F * Correct calculation of integrated figures of merit (Rwp, etc..) with multiple crystalline phases (https://github.com/vincefn/objcryst/pull/53) * + several minor issues #### 2017.2 (28 June 2017) NEW FEATURES * 3D crystal view: add 'M' shortcut to allow forcing the full display of molecules when their center is inside the display limits. * 3D crystal view: add 'Y' shortcut to toggle hydrogen display, and 'L' to toggle labels * Add button to export indexing results in csv file IMPROVEMENTS * Hide X-ray tube alpha1/alpha2 parameters when not relevant * Restore minimize/maximize button for 3D and diffraction pattern views (windows) BUG FIXES * Re-enable popup menu to set limits for parameters (windows) * Fix rare NaN when estimating indexing volume for centered monoclinic lattices #### 2017.1 (20 June 2017) IMPROVEMENTS * More stable Le Bail fit, notably in the auto-profile fit of indexing results * Indexing: * take into account centering. * Try only 1 or 2 spurious lines in the quick indexing approach * 3D Crystal view: add more shortcuts (h to toggle), to shift viewing area BUG FIXES * Correct output of z-matrices independently of the locale * Corrections to the FoxGrid client/server * Safer least squares refinement #### 2016.2 (13 November 2016) IMPROVEMENTS * faded atoms which are part of a Molecule which is centered in the display region are displayed with their names (if displaying names is activated). * CIF import: more informative messages when loading diffraction data * CIF import: better recognition of Molecules with higher coordination centers (Li,..), accept more polyhedra BUG FIXES * correctly save optically active/non-flip atom status in .xmlgz files * correct bug in Le Bail mode/profile fitting which could lead to a crash #### 2016.1 (6 November 2016) NEW FEATURES * direct search on the Crystallography Open Database: - search using keywords, formula or lattice parameters - double-click to display the Crystal structure (this requires access to the default database port, 3306. Some firewalls may prevent that) * automatically recognizing Molecules and isolated polyhedra from CIF files * ability to combine several powder diffraction data sets from different temperatures (or any other variable condition) to solve a single crystal structure (it is possible to override the lattice parameters in the powder pattern diffraction) * the extension for .xml.gz files is now .xmlgz * define 'optically active atoms' than will no be flipped during global (Jan Rohlicek) optimization (previously this was only possible using dihedral restraints) * support for anisotropic pseudo-Voigt profiles * support for ellipsoid texture description (Alexandr Zaloga) IMPROVEMENTS * faster, more robust CIF import * better flexibility search for Molecules * 3D display: - nicer using transparency (can be disabled from preferences) - standard atom colors from jmol * drag & drop files on MacOSX * take into account excluded regions when searching for peaks. * faster initial optimization (and randomization) of Molecules * Unicode interface (should be more friendly to directories with accents, symbols..) * localized number display (using , rather than . for decimal separation) BUG FIXES * Avoid crashes during profile fitting and indexing * internal fixes (Pavol Juhas) #### 1.9.8 - 2011 (Revision 1350) NEW FEATURES * Add import of Single crystal diffraction data (hklf4 format) IMPROVEMENTS * Add SSE optimization using sse_mathfun. Need compile with sse=1 #### 1.9.7 - 2011 (Revision 1312) NEW FEATURES * Add Browser to quickly open Fox and cif files * When closing & re-opening a 3D Crystal view, keep the same window size and view. * When exploring spacegroups, also give the number of systematic extinct reflections for each spacegroup IMPROVEMENTS * Handle cases when xml or cif files do not open correctly * Nicer display of large molecules (>200 atoms) * When exploring spacegroups, exploit extinction conditions to avoid performing redundant Le Bail fits BUG FIXES * Correct file opening from the Fox.Grid server window * Correct identification of monoclinic spacegroups with unique axis=c #### 1.9.6 - 2011 (Revision 1295) NEW FEATURES IMPROVEMENTS * More efficient Le Bail extraction * Nicer color display of crystalline phases in powder graph * Auto-download wxGTK and fftw for linux compilation BUG FIXES * Update cctbx & boost for compilation with gcc >=4.6 #### 1.9.5 - March 2010 (Revision 1274) NEW FEATURES * Add Fox.Grid extension allowing distributed computing for Fox, with a server and a client graphical interface. It also allows distributing computation on all the cores of a single computer. (J. Rohlicek, M Husak) IMPROVEMENTS * More accurate Bayesian estimation of background * Use a better evaluation of peak positions for indexing * Better CIF import BUG FIXES * Prevent running Le Bail/profile fitting in the absence of a crystalline phase * Fix rare infinite loop when scaling ill-conditionned multiphase powder patterns #### 1.9.0.2 - January 2010 (Revision #1215) BUG FIXES * Fix display of imported (e.g. .grd) Fourier maps #### 1.9.0.1 - November 2009 (Revision #1204) NEW FEATURES * Add automatic least-squares refinement of the structure during a global optimization run * Take into account rigid groups during least-squares refinement * Working triclinic indexing * Allow manual adding of peaks for indexing without a peak search * Add manual least-squares refinement of the structure in the global optimization run/stop menu * Better import of CIF files, using either the Hall symbol or the symmetry_equiv_pos_as_xyz fields to avoid ambiguous space group * Enable auto-generation of powder patterns from a CIF file for both X-ray and neutron radiation * When importing powder pattern CIF files, recognize both _pd_proc_2theta_range_XXX and _pd_meas_2theta_range_XXX BUG FIXES * Avoid deadlock (freezing fox) when using the 3D crystal view or the powder pattern graph * Correct molecule rotation quaternion when using least squares * Correct log(likelihood) calculation using integrated intensities (could cause invalid Chi^2 values when used without gui) * Correct Fullprof export when 3 or more independent atoms are overlapping * Work around visual c++ compilation bug during Fullprof export, that would output U U U instead of U V W parameters * Updated cctbx (and boost) version - fixes compilation with gcc 4.4 * Enable importing Fenske-Hall zmatrices file both for human-written files (with whitespace between fields), and for strictly formatted files (sometimes without any space between fields) * Avoid giving up when encountering parameters with the same name, notably for least squares refinements #### 1.8.1.2 - April 2009 (Revision #1117) BUG FIXES * Fix auto-scrolling bug with wxWidgets >=2.8.8 * Better formatting of some fields (overall cost,...) #### 1.8.1 - March 2009 (Revision #1113) NEW FEATURES * Add an option to use molecular dynamics random moves when generating new molecule conformations, for molecules with severe restraints (e.g. macro-cycles) * Add a menu to test random moves of a crystal structure for 30s BUG FIXES * Correct calculation speed for powder patterns when using integrated profiles * Correct display of colours in 3D view for Mac OSX * Correct import of gsas raw format * Faster read of uncompressed xml files under windows * Many fixes for the Linux unicode build of Fox #### 1.8.0.3 - February 2009 (Revision #1088) BUG FIXES * Fixed reading, writing files and display of labels in the linux unicode version of Fox #### 1.8.0 - January 2009 (Revision #1080) NEW FEATURES * Add a "spacegroup explorer" feature to the profile fitting widget, trying all spacegroups compatible with the unit cell, and calculating the corresponding Rwp and GoP. * Manual selection of profile parameters is now possible during profile fitting. * Add powder pattern -> Fullprof export (creates .pcr and .dat) * Add the ability to convert a list of atoms to a Molecule. * Mac version is now provided as a universal binary IMPROVEMENTS * More optimized integration intervals for powder pattern * Allow choosing the number of peaks used for manual indexing * Avoid identical triclinic unit cells * Fox can now more easily be compiled with shared libraries for wxWidgets, fftw, (free)glut and newmat * Enable compilation with the unicode version of wxWidgets BUG FIXES * Correctly handle change of Crystal for powder patterns, regenerate HKL list. * Correctlky handle change of spacegroups during profile fitting #### 1.7.7 - June 2008 (Revision #1013) NEW FEATURES * Import single crystal data from CIF * Use M(n) for indexing scores, with n=20 as default IMPROVEMENTS * Faster Le Bail * Improved triclinic indexing BUG FIXES * Correct Fourier maps listing, when the 3D crystal view is opened during the Le Bail extraction * Fix freezing of optimization during long runs on windows. * Handle cas when scale factors or intensities would be written as NaN in xml files. * Correctly add/remove Fourier maps #### 1.7.6.2 - April 2008 (Revision #995) NEW FEATURES * Support Fourier maps for single crystal data * Display Fourier maps with the original resolution used for the extraction, no matter what resolution is used afterwards (e.g. during the optimisation) IMPROVEMENTS * More efficient random moves for molecules, particularly for large molecules or with flexible cycles. * Better automatic changes of temperature for parallel tempering * Linux: enable compilation using "make -jN" (j2, j4...) * Nicer atom drawing. Force double buffering BUG FIXES * Fixed incorrect formula for sample displacement * Linux: avoid lock of optimisation when 3D view is opened * Correct monoclinic indexing * Fix issue with manual auto-indexing * Disable auto-check for updates (could crash under Linux when no network can be reached) #### 1.7.5 - February 2008 (Revision #956) NEW FEATURES * Add support to compute Fourier maps (observed, difference), with a "live" update during optimization * Profile fitting and Le Bail extraction is now directly available from a right-click on the powder pattern graph. * Support for Intel macs * Indexing triclinic lattices * Explore centered lattices during auto-indexing * LeBail-extracted structure factors are now saved in the xml file IMPROVEMENTS * More stable profile fitting * Linux: keyboard shortcuts are working again * Correctly compute reflections beyond the supplied max(sin(theta)/lambda), but whose profile extend below the limit. BUG FIXES * Fixed incorrect computation of dynamical occupancy correction in some asymmetric unit configurations * Fixed crash when switching labels on/off during optimization * Fixed windows crash when removing atoms in a Molecule/Polyhedron #### 1.7.1 - December 2007 (Revision #903) NEW FEATURES * Add peak detection & auto-indexing (still beta for some values) * Add Le Bail fitting * Add graph representing Iobs and Icalc as a function of 1/d for single crystal data. * Add user-controlled rotation of atoms around any existing bond IMPROVEMENTS * Better support for CIF files import * More responsive UI (refresh display even when no new solution has been found, every 30s at least, and no more than once every second) * Always report *real* time instead of process-time for the first 100s, and then real time BUG FIXES * Correct distance table calculations in some cases, and therefore dynamical occupancy correction... #### 1.7.0 - February 2007 NEW FEATURES * Support for multiple optimizations - store all the solutions obtained, then allow 'browsing' the solutions. * Support for neutron time-of-flight data * Support for reflection profiles other than symmetrical pseudo-Voigt * Add bond-valence computation * CIF import (powder patterns / crystal structures) * Background can be automaticaly estimated using a Bayesian approach (David-Sivia method) * Background calculation can now use either a linear or a cubic spline interpolation * Support for Mac OS X (using XCode /Apple Developper tools) * Add a 'tracker' window to display the progress of the optimization, including all the Chi^2, antibump costs, ... * Add preferences (remembered between sessions) to automatically open crystal 3D view, powder pattern graph, display names / reflections Miller indices,... * Enable saving files in a compressed (gzip) format (*.xml.gz) * Add graph display for Single Crystal data (Iobs and Icalc vs 1/d) IMPROVEMENTS * Add choices for scaling of powder pattern graphs: x as 2theta/tof, 1/d or 2pi/d ; y as I, sqrt(I) or log10(I) * Compilation for windows is now done using the free (as in 'free as a beer') compiler Visual C++ 2005. Large speed improvement. * Fox can be compiled without GUI under *nix, using "make Fox-nogui" removing the requirement for wxGTK on *nix servers. * Support for large Molecules (1000's of atoms) - these *must* be treated as rigid bodies * Better graphical interface to a Molecule's parameters, including rigid sub-groups * Better graphical interface to access scattering power parameters (Biso, antibump, bond valence, colour...) * Significant speed improvements for powder patterns when using the default integrated Chi^2 * Rotation amplitudes for torsion angles and overall molecule rotation is now tuned so that the average displacament per atom is now set to 0.1 Angstroem. * Faster refresh of graphical user interface * Using cctbx rather than atominfo + sglite, enabling using either Hall, Hermann-Mauguin or spacegroup number for spacegroup description. Fox will revert to the Hermann-Mauguin symbol. * freeglut and wxWidgets are statically linked under Linux as well to avoid compilation issues for user without root access. BUG FIXES * Avoid creating H-H bonds when converting ZScatterer to a Molecule #### 1.6.0.2 - december 2003 NEW FEATURES * Added the export to a POV-Ray file to create a Ray-traced view of the 3D Crystal window, with support for both Crystal structure and Fourier maps. * Added more user control on the fexibility of a Molecule: - Added "Rigid Body" and "User-Chosen Free Torsion" choices for the flexibility model of the Molecule. - Also added an option to disable the optimisation of the orientation of the Molecule (only useful for "Rigid Body" mode) - Give access to the delta and sigma parameters to calculate restraints, although users are HIGHLY advised not to change the default values unless they really know what they are doing Also, a Molecule will by default be less flexible than before * Added import of DSN6 Fourier maps, which can be created by forplot in GSAS. * Reverted to using GLUT under Linux to display atom labels in the OpenGL window, as some graphical drivers did not fare well with the new method. * Ability to remove several atoms/bonds/angles at the same time. When removing a bond, offer to remove the bond angles and dihedral angles using that bond. * Added reflection labels on the powder pattern graphical display. * Speed improvements by avoiding (more) recomputations. * Fox now uses wxWindows 2.4.x (no support for versions <2.4). * Added support for Cobalt X-Ray tube. Also, correctly save X-Ray tube parameters when they have been entered manually. * Fourier maps with negative contour values will now be highlighted towards negative values, for Fobs-Fcalc maps display. BUG FIXES * The position of peaks on a powder pattern was randomly displaced by up to +/-2 pixels for each reflection. This could be serious for patterns recorded with a low resolution relatively to the peak widths, although the use of "integrated" Chi^2 and R-factors reduced the gravity of this bug. (thanks Michal Husak for serious testing and reporting) * In the CIF output, some atoms were wrongly labeled as being overlapping with another identical element. * In the graphical display of powder patterns, improve the precison of the display. * Correct center of view coordinates when the center of the displayed structure is not at (0.5,0.5,0.5) #### 1.5 - june 2003 NEW FEATURES-MAJOR CHANGES * The optimization will now use log(likelihood) as a criterion: in practice, this means that the Chi^2 statistics are used rather than the user-chosen cost functions. The likelihood can sometimes be parametrized in the objects (crystal, pattern), but not any more in the Global Optimization objects. * Added a Molecule class, which suprsedes the ZScatterer approach The scatterer is defined by a list of atoms, and restraints (bond lengths, angles and dihedral angles) to specify the geometry. This gives more flexibility, allows a better convergence and allows to correctly define cyclic molecules. * Added the ability to define a statistical positionnal error for atoms, which will be taken into account following Maximum Likelihood principles (ML field in ScatteringPowers), of course with a significant amount of approximations to be computationnaly friendly. * CIF output (with the help of Brian Toby). OTHER NEW FEATURES * Faster computation when using integrated profiles for powder pattern objects * Error bars are now displayed on the Powder Pattern graphical display. * Further improvements of the Fourier maps display (mostly from Brian Toby) * A cursor can be displayed in the center of the 3D Crystal view, its coordinates are displayed at the bottom of the window, with the value of Fourier maps (if any) * Added atom labels in 3D Crystal view (right-click menu to deactivate) * In OpenGL view of a Crystal structure, shift-dragging with left mouse button now correctly changes the center of the view without changing the rotation center. * Changed lighting model in 3D Crystal view * Added the ability to save structure factors from a DiffractionSingleCrystal object, including detailed contributions from different elements (useful for anomalous diffraction experiments) BUG FIXES * Fixed bug when exporting to a Fenske-Hall z-matrix, the 4th atom was always repeated twice * Overall ZScatterer occupancy is now correctly taken into account. * Auto-save of xml files will now use local time rather than gmt. #### 1.3 - december 2002 NEW FEATURES * Added a contribution from Michael Y. Polyakov, (working with Brian Toby) to display Fourier maps exported from GSAS in Fox (use right-click when displaying 3D structure to import). * Added scattering power for a sphere, e.g. to modelize a disordered fullerene. * Added the option to use pseudo-crystallographic symmetry in a Crystal structure (i.e. use a spacegroup which is not allowed by the unit cell). Could be useful for phase transitions. * Added data format for FullProf formats 4 (synchrotron) and 6 (multi-detector, LLB G42) * Now more than 100 atoms can be displayed in a ZScatterer unit. * Added the ability to set relative limits on all scatterer translations from their current positions. * Added the ability to run Fox without the graphical interface, once all objects to be optimized have been setup and saved in a xml file. * shift-dragging with left mouse button allows to change center of the 3D Crystal view. BUG FIXES * Fix serious bug in the dtermination of systematic extinctions, which lead to missing reflections for (body|face)-centered spacegroups with a center of symmetry not on the origin (e.g. for Fd3m (Si,...)) * Fixed various bugs in the display and update of powder patterns #### 1.2 - august 2002 NEW FEATURES * FOX now supports Preferred Orientation, using the March-Dollase model. The texture parameters can be searched ab initio. * The 3D display of the crystal structure is now also refreshed automatically under WinNT and above (still much less responsive than under Linux -hint,hint). * The default size of crystal structure and powder pattern are more reasonable under windows. * New atoms in ZScatterer are now given a sensible default name, ScattPowName+number of the atom. * The wavelength is now directly displayed in the window, rather than exclusively through a menu. * Added ability to duplicate scatterers in Crystal. * Powder diffraction pattern keeps zoomed during optimization. BUG FIXES * The atom names in ZScatterer are now validated without the 'enter' key being hit. * Adding atoms in a z-matrix scatterer does not crash anymore. * removing a scatterer (or any object...) after running an optimisation, does not crash any more when optimization is relaunched (the parameter list is now correctly rebuilt). * Now correctly zooming when the dragged area goes beyond 2theta limits. #### 1.1.2 - 2002/02/18 License changed to the GNU General Public License. NEW FEATURES * Added a maximum value of sin(theta)/lambda for diffraction data objects. All data above is ignored. * Added an *experimental* option in single crystal data for twinned data, to work on the sum of metrically-equivalent reflections. Entirely untested (contact me to use it !) * Some parameter are automatically fixed for global optimizations (unit cell, background & profile parameters). * Fox will write a few messages for some key events (importing data, creating spacegroup,...) BUG FIXES * The dynamical occupancy correction now begins for interatomic distances below 1A, and proceeds to full correction for .1A (before that 2 and .8A where used (why?)) * Spacegroup and Unit Cell values can now be changed even if scattering data has already been computed, without crash. * Importing a Z-Matrix would give the 3rd and 4th atoms the same number, and if atoms were of the same type, both atoms would have the same name in the .xml saved file, and would crash on reloading. Molecules thus created need to be re-imported. #### 1.1.1 - 2002/01/17 BUG FIXES * Under windows, the global optimization lead to a crash after some random time. * Under windows, clicking on some part of a powder pattern graph would make Fox crash #### 1.1 - 2002/01/8 NEW FEATURES * Now it is possible to import Z-matrices to build a molecule structure (eg a Z-matrix file can be generated from a .pdb file using babel, and then imported into Fox) * Added integrated R and RW factors as new cost functions (thus less sensitive to badly defined profiles). Unless you have *very* good profile parameters, I recommend using the integrated Rw as a cost function. * Now it is recommended to choose an "exponential" schedule for the amplitude, from 8 to .125, and a "smart" schedule for the temperature. This should be optimized for *all* experiments, so that users don't have to guess the right choices. * It is no longer necessary to validate all input by hitting the 'return' key (which was *very* annoying) * Ability to zoom on the powder pattern graph, using the left button (double-click to unzoom) * Possibility to reduce the part of the displayed unit cell in 3D view (use the popup menu with right-click) * Significant speed improvement. * The Parallel Tempering algorithm has been tuned to yield a higher success ratio. * Possibility to used single-crystal data (eg extracted intensities) for crystal structure optimization (honest crystallographer's note: if you have high quality extracted intensities, try direct methods first...) * Added interface for 2theta zero/displacement/transparency parameters in a Powder Pattern object * Added an overall temperature factor (Biso) for each crystalline phase in powder diffraction (also available in single crystal). * new examples for organic molecules (potassium tartrate and cimetidine with powder & extracted pseud-single crystal intensities) * The program now forbids to check lattice or profile parameters for a global optimization. -LINUX: * Now using a distribution from source using the wxWindows RPM, which * should make things easier under Linux. -BUG FIX: * under linux, the antibump cost function was not properly restored from an xml file (preventing merging of identical atoms) * Changing the spacegroup (and thus extinction rules) will now will re-generate the list of reflections for powder diffraction. Same if the lattice parameters or the wavelength has changed. * a number of minor bugfixes... #### 1.0.1 - 2001/10/15 -BUG FIX: * corrected minimum FWHM for profiles from .001 to .00001 radians #### 1.0 - 2001/10/15 -NEW FEATURES * support for multiple crystalline phases in Powder Diffraction (you can refine several phases from one pattern ...provided you can index them) * the Windows version now displays a console to give a better idea about what the program is doing. * Import of Sietronics data files (.cpi) * Linux binary version also available for glibc 2.1 -BUG FIXES: * removed another bug in ZMatrix interpretation, which prevented the correct coordinates to be generated when using mono/triclinic unit cells (thanks Mark Edgar). * the program will no longer crash when importing data with null or negative points. * U,V and W parameters leading to negative profile width will no longer crash the program (profile forced to be strictly positive) * various cosmetic bugs #### 0.9.1 Beta - 2001/09/20 -NEW FEATURES * Added menus to change limits globally in a ZScatterer(bond,angles) * Now the pivot atom (around which the ZScatterer is rotated, and which corresponds to the displayed x,y,z position of the ZScatterer) is saved in the .xml file. It can also be changed from a menu. * Limits can be changed individually for all parameters, using a popu menu: right-click on the parameter name to get the local menu -BUG FIXES: * removed a nasty bug in ZMatrix interpretation, which prevented the correct coordinates to be generated for chains longer than 3 atoms. Did not affect polyhedras... (thanks Yuri Andreev) #### 0.9 Beta - 2001/09/18 Initial Public release #### 0.5-0.9 Internal release only... Thanks to Laure Guenee, Guillaume Renaudin and Radovan Cerny for testing ! objcryst-2022.1/Fox/000077500000000000000000000000001430515525000141735ustar00rootroot00000000000000objcryst-2022.1/Fox/.cvsignore000066400000000000000000000001771430515525000162000ustar00rootroot00000000000000*.o *.exe *.out *.old *.dep *.a .directory .systemG.Desktop tags html latex *.oxy *.xml profile.0.0.0 *.pov Makefile rules.mak objcryst-2022.1/Fox/Fox-Info.plist000066400000000000000000000032001430515525000166700ustar00rootroot00000000000000 CFBundleDevelopmentRegion English CFBundleDocumentTypes CFBundleTypeExtensions cif CFBundleTypeIconFile Fox.icns CFBundleTypeName Crystallographic Information File CFBundleTypeRole Viewer LSItemContentTypes LSTypeIsPackage NSPersistentStoreTypeKey XML CFBundleTypeExtensions xml gz xmlgz CFBundleTypeIconFile Fox.icns CFBundleTypeName ObjCryst++-Fox structure CFBundleTypeRole Editor LSTypeIsPackage NSPersistentStoreTypeKey XML CFBundleExecutable Fox CFBundleIconFile Fox CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType APPL CFBundleSignature ???? CFBundleVersion 2020.1 objcryst-2022.1/Fox/Fox.sdf000066400000000000000000012000001430515525000154160ustar00rootroot00000000000000Ç1ýÏ =Š L¬"J<È8p_ V KIIH½’®—è$g @X‹30œg`oX¥é0gA  B4>>¯®¯®(#½`pDB4 A5%EEq |p#2%D#2H!‘Eq |Q~2H!‘A6‘A)p#2%D#2H!‘A0‘A%#2H!‘`@%~Š‘!Š‘`@'Š|5! ™‘`@+~!Š™2!‘`@EEq |!D2™!QD62p‘Eq~6D |!D2™!QD62p‘D2B‘Eq2¦D |!D2™!Q‘D#2H!D2B‘Eq~6D |!D2™!Q‘D2A p#2%D#2H!‘Eq2¦D |p#2%D#2H!‘D |p#2%D2AE#2H!D2A%Ÿ‰D |p#2%D#2H!‘D |p#2%D2D#2H!D2A p#2%‘Eq2¦D |p#2%‘DpQ!A1~Š|5! ™D2 A~6D |p#2%‘D2AŸ‰D |p#2%‘D~Š|5! ™D2DpQ!A#2H!‘Eq2¦D#2H!‘DH!#DpQ!A~6D#2H!‘D2AŸ‰D#2H!‘DpQ! `@~Š‘!Š‘Eq~6D~Š‘!Š‘D~Š‘!Š`@Š|5! ™‘Eq~6D~Š|5! ™‘D2`@Ÿ‰D~Š|5! ™‘D%Ÿ2`@5pQ!`@ ~!Š™2!‘Eq~6D~Š|~!Š™2!‘DpQ! `@EEq |!D2™!QD62p‘Eq2 `@+pQ!`@+~Š‘!Š B‘Eq‘‘| D™!¦™B‘Eq™™Š2 Ÿ™!‘B!!pD |HŸQpB)H2p!A‘Eq#2H!D2A!2A!62p B!H|¤!ŠDpQ!D,2p™A!pQ!B(D!pD |HŸQpB3H2p!B+‘™Š™D |HŸQpB7H2p! B!~ŠQD!#ŸH™D¢HŸ!BFD!pD |HŸQpBQH2p!BFD‘™Š™D |HŸQpBUH2p! B-pŸQ !ŠA!~Š!p™D2B!‘™Š™D |HŸQpB-H2p! B!™§~! A p#2%D#2H!‘Eq |Q~2H! A4D~ ,A p#2%D#2H!‘Eq |p#2%D2 A%!¦~H2 2™D‘‘!Q H§A%#2H!D2A%2Q~H2 2™ A'p HŸ!D~™,A%|~™2|p‘A%Š!#!Š!p ! A%‘,Š!A‘Eq |p#2%D2p HŸ!D~™,A)|~™2|p‘A,‘,A2ApQ! A~H™#|ŠQD2p HŸ!D~™, A-|~™2|p‘AŠ|5! ™D2A#2H!‘Eq™2Q!A™™Š2 Ÿ™!‘A2##™2Q!A2AH!#DpQ!ApQ!A~Š‘!ŠA!™2Q!A™2Q!‘™Q~`@~Š‘!Š‘EqpQ!`@~Š‘!Š`@‘,|Š™DpQ!`@Š|5! ™‘Eq%Ÿ2`@2`@pQ!`@‘,Š!`@ ~!Š™2!‘EqpQ!`@!¢HŸ!`@EEq |!D2™!QD62p‘Eq#6D |!D2™!QD62p‘D~Š‘!Š`@+~6D |!D2™!QD62p‘D2B‘Eq~6D |!D2™!Q‘D2A p#2%D#2H!‘Eq#6D |p#2%D#2H!‘D |p#2%D2AE#2H!D2A%Ÿ‰D |p#2%D#2H!‘D |p#2%D2D#2H!D2 A p#2%‘Eq#6D |p#2%‘D~Š|5! ™D2 A~6D |p#2%‘D2AŸ‰D |p#2%‘D~Š|5! ™D2DpQ!A#2H!‘Eq#6D#2H!‘D~Š‘!ŠA~6D#2H!‘D2AŸ‰D#2H!‘DpQ! `@~Š‘!Š‘Eq~6D~Š‘!Š‘D~Š‘!Š`@Š|5! ™‘Eq~6D~Š|5! ™‘D2`@Ÿ‰D~Š|5! ™‘D%Ÿ2`@5pQ!`@ ~!Š™2!‘Eq~6D~Š|~!Š™2!‘DpQ!Eq~6D~Š|~!Š™2!‘DpQ!DpQ!DpQ!!Š™2°ë‘çæñãQàQÜ!Ú1رÔáбÎqÊÁÅQÄñ¾Á»‘¸@²±±®a­Q¬«!©Q§¦¡£ñ¡á ‘ŸžÑœœqšÁ˜A–‘”!“ñᎎ‘‹ˆ±†…‘ƒ¡€¡~ñ{‘xqw0t!srpQnmñk±i¡h¡f±c¡b‘`_]q\ZñX!XVU1SÁPQNMñK€HaDQCÁ@!=!9ñ65!1Q-!+Q)Ñ%!!±Q!Q€  ¡ 1 AqP-Ïm0FF`@fìÎY@=@÷&àÿÿÿ ÿÿ€ €__SysObjectsproperties&€@ÿÿ €è€ €propertiesname&€@ÿÿ þè€ €propertiesvalue&€ÿÿ?óÿÿÿÿÿÿÿÿÿÿ€ €€1111propertiespk_properties_namepk_properties_name&€ÿÿÀÿ€€ €2~~~~~propertiespk_properties_nameDõ@m§¤€€?&àÿÿÿyÿÿ€ €__SysObjectsparsers&€@ÿÿ( e耀parsersparser&€@ÿÿ  €è€€ parsersname&€@ÿÿ €è€€parsersshort_name&€ÿÿ?óÿÿÿÿÿÿÿÿÿÿ€€€,,,,parserspk_parsers_parserpk_parsers_parser&€ÿÿÀÿ€ €€.zzzzzparserspk_parsers_parser€Dõ@m§¤ €?&àÿÿÿvÿÿ € €__SysObjectscode_item_kinds&€@ÿÿ(耀code_item_kindsid&€@ÿÿ €è€€code_item_kindsname&€@ÿÿ(e耀code_item_kindsparser&€ÿÿ?óÿÿÿÿÿÿÿÿÿÿ€€&&&&€<<<<code_item_kindspk_code_item_kinds_idpk_code_item_kinds_id&€ÿÿÀÿ€ €€&&:†††††code_item_kindspk_code_item_kinds_id@Dõ@m§¤€?&€ÿÿ¿à!ÿÿ€€*****€<€DXcode_item_kindsfk_code_item_kinds_parserpk_parsers_parserparsers€&àÿÿÿ[ÿÿ € €__SysObjectsprojects&€@ÿÿ($hè€ € projectsid&€@ÿÿ &è€ €projectsname&€@ÿÿ((eè€ €projectsguid&€@ÿÿ(* è€ €projectsshared&€ÿÿ?ó-ÿÿÿÿÿÿÿÿÿÿ€ €€''''projectspk_projects_idpk_projects_id&€ÿÿÀÿ€. € €,xxxxxprojectspk_projects_id@Dõ@m§¤€?&€ÿÿ?ó1ÿÿÿÿÿÿÿÿÿÿ€ €€++++projectsuq_projects_nameuq_projects_name&€ÿÿÀÿ€2€ €.zzzzzprojectsuq_projects_nameDõ@m§¤€?A&€ÿÿ?ó5ÿÿA&€ÿÿÀÿ€6€ €.zzzzzprojectsuq_projects_guid€©é¾JÒ} ñKu\ „Û»®ºEšÒ9Y ¡— :8-G»&KÑ¥q”út —£+ù"PáÞ± âàuÐPg, x``DEq |!D2™!Q‘DQ|`DEq~™,`DEq¢!Š‘2|p0 pfÛ6m0GG`@Ö¬äø `/pDEŠC·˜ ´’^]K>m2½éµpDEŠC·˜ ´’^]K>m5½éµpDEŠC·˜ ´’^]K>m>½éµð P Ôºn 0±HH `@=<=<½)²ª `‡=€DE€€DE€€DE€€DE€€DE€€DE€€DE€€DE€€DE€ €DE€ €DE€ €DE€ €DE€ €DE€€DE€€DE€€DE€€DE€€DE€€DE€€DE€€DE€€DE€€DE€€DE€€DE€€DE€€DE€€DE€€DE€€DE€€DE€ €DE€!!€DE€""€DE€##€DE€$$€DE€%%€DE€&&€DE€''€DE€((€DE€))€DE€**€DE€++€DE€,,€DE€--€DE€..€DE€//€DE€00€DE€11€DE€22€DE€33€DE€44€DE€55€DE€66€DE€77€DE€88€DE€99€DE€::€DE€;;€DE€<<€DE€=°@Ð`ð€ 0ÀPàp °@Ð`ð€ 0ÀPàp ° @ Ð ` ð €    0 ÀPàp °@Ð`ð€ 0ÀPàp&Ñíd 0]`@@ðà `sPì`~ͯø`‰rîÙ@Öàöÿÿÿÿÿÿÿÿ€ €€++++projectsuq_projects_guiduq_projects_guidDõ@m§¤ €?&àÿÿÿ¥ÿÿ€ €__SysObjectsconfigs&€@ÿÿ(9h耀 configsid&€@ÿÿ(;h耀 configshash&€@ÿÿ(=h耀configsproject_id&€@ÿÿ ?þ耀 configsname&€@ÿÿ0Ad @耀configsconfig_include_path&€@ÿÿ0Cd @耀configsconfig_options&€@ÿÿ0Ed @耀configsplatform_include_path&€@ÿÿ0Gd @耀configsplatform_options&€ÿÿ?óJÿÿÿÿÿÿÿÿÿÿ€€€$$$$configspk_configs_idpk_configs_id&€ÿÿÀÿ€K€€*vvvvvconfigspk_configs_id@Dõ@m§¤€?&€ÿÿ?óQÿÿÿÿÿÿÿÿÿÿ€€####€>>>>configsuq_configs_project_id_nameuq_configs_project_id_name&€ÿÿÀÿ€R€€##KŸŸŸŸŸconfigsuq_configs_project_id_name@Lõ@m§¤€?€?&€ÿÿ?àZÿÿ€€€4€C€L`configsfk_configs_project_idix_configs_project_idpk_projects_idprojects@&€ÿÿÀÿW€€2~~~~~configsix_configs_project_id@Dõ@m§¤€?&€ÿÿÀÿ\€€,xxxxxconfigsix_configs_nameDõ@m§¤þ€?&àÿÿÿWÿÿ€ €__SysObjectsfiles&€@ÿÿ(_h耀 filesid&€@ÿÿ(ah耀filestimestamp&€@ÿÿ(c耀filesparsetime&€@ÿÿ(e耀filesaddtime&€@ÿÿ(g耀filesdifftime&€@ÿÿ i耀 filesname&€@ÿÿ k耀filesleaf_name&€@ÿÿ(m耀filesattributes&€@ÿÿ(oe è €€ filesparser&€ÿÿ?órÿÿÿÿÿÿÿÿÿÿ€€€filespk_files_idpk_files_id&€ÿÿÀÿ€s€€&rrrrrfilespk_files_id@Dý@m§¤€?$¾Ÿþ º­LíßÜwŒ Ì »3ÛÆÚ`jð Y @¸ ìµ ‡Æƒ× ˜5 "d§³3Cº’P¢àv¡œ LÀ{Õ"0šA¤–5`ÃM&G`Ô†S`ßãÕ]`è¾20óA½´™`"¦`.¦7õ@†°ö&€ÿÿ?óvÿÿÿÿÿÿÿÿÿÿ€€€""""filesuq_files_nameuq_files_name&€ÿÿÀÿ€w€€(tttttfilesuq_files_nameDý@m§¤€?&€ÿÿ¿àzÿÿ€€€(€0Dfilesfk_files_parserpk_parsers_parserparsers€&€ÿÿÀÿ}€€-yyyyyfilesix_files_leaf_nameDý@m§¤€?&àÿÿÿ©ÿÿ€ €__SysObjectsconfig_files&€@ÿÿ(€hè€ €config_filesconfig_id&€@ÿÿ(‚hè€ €config_filesfile_id&€@ÿÿ(„ è€ €config_filesimplicit&€@ÿÿ(† è€ €config_filesreference&€@ÿÿ(ˆ è€ €config_filescompiled&€@ÿÿ(Š è€ €config_filescompiled_pch&€@ÿÿ(Œ è€ €config_filesexplicit_assembly&€@ÿÿ(Ž è€ €config_filesshared&€@ÿÿ0d @è€ €config_filesinclude_path&€@ÿÿ0’ d @è€ €config_filesoptions&€ÿÿ?ó›ÿÿÿÿÿÿÿÿÿÿ€ €////€QQQQconfig_filesuq_config_files_config_id_file_iduq_config_files_config_id_file_id&€ÿÿÀÿ€œ€ €//W«««««config_filesuq_config_files_config_id_file_id@@LAm§¤€?€?&€ÿÿ?à¤ÿÿ€ €''''€A€O€Wkconfig_filesfk_config_files_config_idix_config_files_config_idpk_configs_idconfigs@&€ÿÿÀÿ¡€ €'';‡‡‡‡‡config_filesix_config_files_config_id@DAm§¤€?&€ÿÿ?à¦ÿÿ€ €%%%%€=€I€Occonfig_filesfk_config_files_file_idix_config_files_file_idpk_files_idfiles@&€ÿÿÀÿ¨€ €%%9……………config_filesix_config_files_file_id@DAm§¤€?&àÿÿÿDÿÿ€ €__SysObjectscode_items&€@ÿÿ(«hè€ €code_itemsid&€@ÿÿ(­hè€ €code_itemsfile_id&€@ÿÿ(¯hè€ €code_itemsparent_id&€@ÿÿ ±þè€ €code_itemsname&€@ÿÿ(³è€ €code_itemskindþÞ‘Þ.¯ D½Ï\í+IJËç yˆ- ‰ Y'âvqõÅ~u 5—D$4²#>CÇrña P ð .¤·`=›}Ø•0FA¹`‡b`’O²`›ŸWV–0«A#Ž @ë€÷&€@ÿÿ(µè€ €code_itemsattributes&€@ÿÿ(·è€ €code_itemsstart_column&€@ÿÿ(¹è € €code_itemsstart_line&€@ÿÿ(» è$€ €code_itemsend_column&€@ÿÿ(½  è&€ €code_itemsend_line&€@ÿÿ(¿  è*€ €code_itemsname_start_column&€@ÿÿ(Á  è,€ €code_itemsname_start_line&€@ÿÿ(à  è0€ €code_itemsname_end_column&€@ÿÿ(Å è2€ €code_itemsname_end_line&€@ÿÿ(Çè6€ €code_itemslower_name_hint&€@ÿÿ0Éþè€ €code_itemstype&€@ÿÿ8Ëè>€ €code_itemsparam_number&€@ÿÿ0Íþè€ €code_itemsassoc_text&€@ÿÿ0Ïþè€ €code_itemsparam_default_value&€@ÿÿ8Ñè@€ €,,,,,,,,code_itemsparam_default_value_start_column&€@ÿÿ8ÓèB€ €********code_itemsparam_default_value_start_line&€@ÿÿ8ÕèF€ €********code_itemsparam_default_value_end_column&€@ÿÿ8×èH€ €((((((((code_itemsparam_default_value_end_line&€ÿÿ?óÚÿÿÿÿÿÿÿÿÿÿ€ €€----code_itemspk_code_items_idpk_code_items_id&€ÿÿÀÿ€Û!€ €0|||||code_itemspk_code_items_id@DAm§¤€?&€ÿÿÀÿÞ"€ €!!5code_itemsix_code_items_file_id@DAm§¤€?&€ÿÿÀÿá#€ €##7ƒƒƒƒƒcode_itemsix_code_items_parent_id@DAm§¤€?&€ÿÿÀÿä&€ €2~~~~~code_itemsix_code_items_nameDAm§¤þ€?&€ÿÿÀÿç'€ €2~~~~~code_itemsix_code_items_kind@DAm§¤€?&€ÿÿÀÿê(€ €))=‰‰‰‰‰code_itemsix_code_items_lower_name_hintÀDAm§¤€?&àÿÿÿþÿÿ)€ €__SysObjectsassoc_text&€@ÿÿ(íhè€ €assoc_textcode_item_id B&€@ÿÿ(ïè€ €+ß¶^A^[m€¼ ¥» Å çé „¨™ ÿWxwñvh–ìÅy5U—Ô„©c1ƒ¹‚?¢Î[1è0sP0±ï¡!` sW®"`,M—¶#`3½î³Y$`dPB] BEEqDD‘§‘| 5! ™‘Eq‘‘| D‘~p‘B1™!¦™@C% ‘!D H‘‘D~Š!p™‘ `@% |!D2™!QD62p‘A6‘A)p#2%D#2H!‘A0‘ B%#2H!DQ~ @C/‘2%p™ŸŠ!‘A%#2H!‘`@%~Š‘!Š‘`@'Š|5! ™‘`@+~!Š™2!‘ àC%Š!#‘@C%‘§Q |H‘ BEEq‘‘| D‘~p‘Eq2¦D‘‘| D‘~p‘D |!D2™!QD2 B#Ÿ‰D‘‘| D‘~p‘D |!D2™!QD2D62p B™!¦™Eq2¦D‘‘| D™!¦™D |!D2™!QD2 B!Ÿ‰D‘‘| D™!¦™D |!D2™!QD2D62p @C ‘!D H‘‘D~Š!p™‘Eq2¦D ‘!D H‘‘D~Š!p™‘D ‘!D |!D2™!QD2 @C]~Š!p™D |!D2™!QD2@C1Ÿ‰D ‘!D H‘‘D~Š!p™‘D ‘!D |!D2™!QD2D~Š!p™D |!D2™!QD2`@ |!D2™!QD62p‘Eq~6D |!D2™!QD62p‘D2B‘Eq2¦D |!D2™!Q‘D#2H!D2B=62pB=H|¤!ŠDpQ!D,2p™B=pQ!B=~Š!p™D2B‘Eq~6D |!D2™!Q‘D2A p#2%D#2H!‘Eq2¦D |p#2%D#2H!‘D |p#2%D2AE#2H!D2A%Ÿ‰D |p#2%D#2H!‘D |p#2%D2D#2H!D2A p#2%‘Eq2¦D |p#2%‘DpQ!A1~Š|5! ™D2 A~6D |p#2%‘D2AŸ‰D |p#2%‘D~Š|5! ™D2DpQ! B#2H!DQ~Eq2¦D#2H!DQ~D |!D2™!QD2 B9p#2%D2@C5#2H!D2 BŸ‰D#2H!DQ~D |!D2™!QD2D |p#2%D2D#2H!D2@C‘2%p™ŸŠ!‘Eq2¦D#2H!D‘2%p™ŸŠ!‘D#2H!D2@C+Ÿ‰D#2H!D‘2%p™ŸŠ!‘D#2H!D2D62pA#2H!‘Eq2¦D#2H!‘DH!#DpQ!A~6D#2H!‘D2AŸ‰D#2H!‘DpQ! `@~Š‘!Š‘Eq~6D~Š‘!Š‘D~Š‘!Š`@Š|5! ™‘Eq~6D~Š|5! ™‘D2`@Ÿ‰D~Š|5! ™‘D%Ÿ2`@5pQ!`@ ~!Š™2!‘Eq~6D~Š|~!Š™2!‘DpQ!àCEEqŠ!#‘Eq2¦DŠ!#‘D|¤p!ŠD2àCEEqŠ!#‘Eq2¦DŠ!#‘D‘§Q |HD2 àC‘§Q |H‘Eq2¦D‘§Q |H‘D62pàC1pQ!àC1~Š!p™D2àC~6D‘§Q |H‘D2 BEEq‘‘| D‘~p‘Eq |!D2™!QD2  B#!pD |HŸQp  B+H2p! B#62p  B#‘™Š™D |HŸQp  B/H2p!B™!¦™Eq |!D2™!QD2B!62p B!™!¦™@C ‘!D H‘‘D~Š!p™‘Eq ‘!D |!D2™!QD2@C1~Š!p™D |!D2™!QD2 `@ |!D2™!QD62p‘Eq2 `@+pQ!`@+~Š‘!Š B‘Eq‘‘| D™!¦™B‘Eq™™Š2 Ÿ™!‘B!!pD |HŸQpB)H2p!A‘Eq#2H!D2A!2A!62p B!H|¤!ŠDpQ!D,2p™A!pQ!B(D!pD |HŸQpB3H2p!B+‘™Š™D |HŸQpB7H2p! B!~ŠQD!#ŸH™D¢HŸ!BFD!pD |HŸQpBQH2p!BFD‘™Š™D |HŸQpBUH2p! B-pŸQ !ŠA!~Š!p™D2B!‘™Š™D |HŸQpB-H2p! B!™§~!2B!‘™Š™D |HŸQpB-H2p! B!™§~!íìñêáè1çáåÑä‘âáß‘ÜÛqÙaØaÖQÕáÒÑÑÑñÎáÍÌ¡É1ÇáÅÑıÁÁ¾a¹Q¸A·A´1³!±°¯1­©Ñ¦!¥¤Q `œ˜q”a“Ñ11‰‡…1Á|Awqqp‘n‘iÁe‘cÁaA^‘Y!XÁR‘OáMÑLaJQIE@8!5-‘(Ñ#A0Á±AÑa1aÑ  A A1§4%h%`VR@B AEEq |p#2%D#2H!‘Eq |Q~2H! A4D~ ,A p#2%D#2H!‘Eq |p#2%D2 A%!¦~H2 2™D‘‘!Q H§A%#2H!D2A%2Q~H2 2™ A'p HŸ!D~™,A%|~™2|p‘A%Š!#!Š!p ! A%‘,Š!A‘Eq |p#2%D2p HŸ!D~™,A)|~™2|p‘A,‘,A2ApQ! A~H™#|ŠQD2p HŸ!D~™, A-|~™2|p‘AŠ|5! ™D2 B#2H!DQ~Eq |!D2™!QD2 B!p#2%D2 B#2H!D2 @C‘2%p™ŸŠ!‘Eq#2H!D2 @C+62p@C+‘2%p™ŸŠ!A#2H!‘Eq™2Q!A™™Š2 Ÿ™!‘A2##™2Q!A2AH!#DpQ!ApQ!A~Š‘!ŠA!™2Q!A™2Q!‘™Q~`@~Š‘!Š‘EqpQ!`@~Š‘!Š`@‘,|Š™DpQ!`@Š|5! ™‘Eq%Ÿ2`@2`@pQ!`@‘,Š!`@ ~!Š™2!‘EqpQ!`@!¢HŸ!àCEEqŠ!#‘Eq#2H!D2àCEEqŠ!#‘EqH2p! àCEEqŠ!#‘Eq|¤p!ŠD2 àCEEqŠ!#‘EqŠ!#62p àCEEqŠ!#‘Eq‘§Q |HD2àC‘§Q |H‘Eq™™Š2 Ÿ™!‘@C2àC62p@CpQ!@C~Š!p™D2àC™§~!  BEEq‘‘| D‘~p‘Eq#6D‘‘| D‘~p‘D |!D2™!QD2 B#Ÿ‰D‘‘| D‘~p‘D |!D2™!QD2D62p B™!¦™Eq#6D‘‘| D™!¦™D |!D2™!QD2 B!Ÿ‰D‘‘| D™!¦™D |!D2™!QD2D62p@C ‘!D H‘‘D~Š!p™‘Eq#6D ‘!D H‘‘D~Š!p™‘D ‘!D |!D2™!QD2@C]~Š!p™D |!D2™!QD2@C1Ÿ‰D ‘!D H‘‘D~Š!p™‘D ‘!D |!D2™!QD2D~Š!p™D |!D2™!QD2`@ |!D2™!QD62p‘Eq#6D |!D2™!QD62p‘D~Š‘!Š`@+~6D |!D2™!QD62p‘D2B‘Eq~6D |!D2™!Q‘D2A p#2%D#2H!‘Eq#6D |p#2%D#2H!‘D |p#2%D2AE#2H!D2A%Ÿ‰D |p#2%D#2H!‘D |p#2%D2D#2H!D2 A p#2%‘Eq#6D |p#2%‘D~Š|5! ™D2 A~6D |p#2%‘D2AŸ‰D |p#2%‘D~Š|5! ™D2DpQ! BEEq#2H!DQ~EqŸ‰D#2H!DQ~D |!D2™!QD2D |p#2%D2D#2H!D2@C‘2%p™ŸŠ!‘Eq#6D#2H!D‘2%p™ŸŠ!‘D#2H!D2@C+Ÿ‰D#2H!D‘2%p™ŸŠ!‘D#2H!D2D62pA#2H!‘Eq#6D#2H!‘D~Š‘!ŠA~6D#2H!‘D2AŸ‰D#2H!‘DpQ! `@~Š‘!Š‘Eq~6D~Š‘!Š‘D~Š‘!Š`@Š|5! ™‘Eq~6D~Š|5! ™‘D2`@Ÿ‰D~Š|5! ™‘D%Ÿ2`@5pQ!`@ ~!Š™2!‘Eq~6D~Š|~!Š™2!‘DpQ!àC‘§Q |H‘Eq#6D‘§Q |H‘D62pàC~6D‘§Q |H‘D2AŸ‰D#2H!‘DpQ! `@~Š‘!Š‘Eq~6D~Š‘!Š‘D~Š‘!Š`@Š|5! ™‘Eq~6D~Š|5! ™‘D2`@Ÿ‰D~Š|5! ™‘D%Ÿ2`@5pQ!`@ ~!Š™2!‘Eq~6D~Š|~!Š™2!‘DpQ!àC‘§Q |H‘Eq#6D‘§Q |H‘D62pàC~6D‘§Q |H‘D2D‘§Q |H‘D2€ØQÖ‘ÒqÎaÍÑÊ1Ç1ÃÁ¿‘»!·¡±ªA¦¤ÑŸ!›±™Q”!‘ññ‡€}ñtpÁk1g a`a^Q]A\q[QX`U°RàOMàJ±IQGFñD!DÁAñ?¡>A<‘:918!7q5¡43a1á.1-!,)‘'!&¡"ñ QAqañaañq  QñÑ÷Â&`<ò6Ê'`CÌvÒ(`J‡ï)0RBu¬•¡*@Ž@øassoc_textkind&€@ÿÿ ñd @è€ €assoc_texttext&€ÿÿ?ó÷ÿÿÿÿÿÿÿÿÿÿ€ €++++€KKKKassoc_textuq_assoc_text_code_item_id_kinduq_assoc_text_code_item_id_kind&€ÿÿÀÿ€ø+€ €++S§§§§§assoc_textuq_assoc_text_code_item_id_kind@LAm§¤€?€?&€ÿÿ?àûÿÿ€ €&&&&€A€R€]qassoc_textfk_assoc_text_code_item_idix_assoc_text_code_item_idpk_code_items_idcode_items@&€ÿÿÀÿý,€ €&&:†††††assoc_textix_assoc_text_code_item_id@DAm§¤€?&àÿÿÿÿÿ-€ €__SysObjectsassoc_spans&€@ÿÿ(hè€ €assoc_spanscode_item_id&€@ÿÿ(è€ €assoc_spanskind&€@ÿÿ(è € €assoc_spansstart_column&€@ÿÿ(è € €assoc_spansstart_line&€@ÿÿ(è€ €assoc_spansend_column&€@ÿÿ( è€ €assoc_spansend_line&€ÿÿ?óÿÿÿÿÿÿÿÿÿÿ€ €----€NNNNassoc_spansuq_assoc_spans_code_item_id_kinduq_assoc_spans_code_item_id_kind&€ÿÿÀÿ€.€ €--U©©©©©assoc_spansuq_assoc_spans_code_item_id_kind@LAm§¤€?€?&€ÿÿ?àÿÿ€ €((((€D€U€`tassoc_spansfk_assoc_spans_code_item_idix_assoc_spans_code_item_idpk_code_items_idcode_items@&€ÿÿÀÿ/€ €((<ˆˆˆˆˆassoc_spansix_assoc_spans_code_item_id@DAm§¤€?&àÿÿÿ+ÿÿ0€ €__SysObjectsfile_map&€@ÿÿ(hè€ €file_mapcode_item_id&€@ÿÿ(hè€ €file_mapconfig_id&€@ÿÿ(hè€ €file_mapfile_id&€ÿÿ?ó ÿÿÿÿÿÿÿÿÿÿ€ €4444€____file_mapuq_file_map_code_item_id_config_id_file_iduq_file_map_code_item_id_config_id_file_id&€ÿÿÀÿ€!1€ €44pÌÌÌÌÌfile_mapuq_file_map_code_item_id_config_id_file_id@@@TAm§¤€?€?€?&€ÿÿÀÿ$2€ €""6‚‚‚‚‚file_mapix_file_map_code_item_id@DAm§¤€?@C&€ÿÿÀÿ'3€ €3file_mapix_file_map_config_idß(þ CÌ ÿœÕëe ò::šY· ÃgÉ ¦&2F¾EHeÚäddîc 3‘€ 9A=â $Ð@ž÷+`láý,`wŽ^'§-0 Bç”6.`¨­ôB/`³ˆÅu§00¿ Bä`1`ÏãCl2`Ú½ƒt3`áðÄ. 4@Àø@DAm§¤€?&€ÿÿÀÿ*5€ €1}}}}}file_mapix_file_map_file_id@DAm§¤€?&àÿÿÿFÿÿ6€ € __SysObjectsbase_class_parents&€@ÿÿ(-h耀%%%%%%%%base_class_parentsbase_code_item_id&€@ÿÿ(/h耀''''''''base_class_parentsparent_code_item_id&€ÿÿ?ó8ÿÿÿÿÿÿÿÿÿÿ€€OOOO€‹‹‹‹base_class_parentsuq_base_class_parents_base_code_item_id_parent_code_item_iduq_base_class_parents_base_code_item_id_parent_code_item_id&€ÿÿÀÿ€97€€OOwËËËËËbase_class_parentsuq_base_class_parents_base_code_item_id_parent_code_item_id@@LAm§¤€?€?&€ÿÿ?àAÿÿ€€;;;;€c€t€“base_class_parentsfk_base_class_parents_base_code_item_idix_base_class_parents_base_code_item_idpk_code_items_idcode_items@&€ÿÿÀÿ>8€€;;O›››››base_class_parentsix_base_class_parents_base_code_item_id@DAm§¤€?&€ÿÿ?àCÿÿ€€====€g€x€ƒ—base_class_parentsfk_base_class_parents_parent_code_item_idix_base_class_parents_parent_code_item_idpk_code_items_idcode_items@&€ÿÿÀÿE9€€==Qbase_class_parentsix_base_class_parents_parent_code_item_id@DAm§¤€?&àÿÿÿYÿÿ:€ €__SysObjectsfile_signatures&€@ÿÿ(Hh耀file_signaturesfile_id&€@ÿÿ(J耀file_signatureskind&€@ÿÿ LA @耀file_signaturessignature&€ÿÿ?óRÿÿÿÿÿÿÿÿÿÿ€€0000€PPPPfile_signaturesuq_file_signatures_file_id_kinduq_file_signatures_file_id_kind&€ÿÿÀÿ€S;€€00X¬¬¬¬¬file_signaturesuq_file_signatures_file_id_kind@L Am§¤€?€?&€ÿÿ?àVÿÿ€€++++€F€R€Xlfile_signaturesfk_file_signatures_file_idix_file_signatures_file_idpk_files_idfiles@&€ÿÿÀÿX<€€++?‹‹‹‹‹file_signaturesix_file_signatures_file_id@D Am§¤€?&àÿÿÿxÿÿ=€ €__SysObjectssymbols&€@ÿÿ([h耀 symbolsid&€@ÿÿ(]h耀symbolsparent_idàC&€@ÿÿ _þ耀 s.ï¿þWŽå-ýŒ~Ú +›4œ z•) Y¦¨¬§À…À‚¨ƒ¸FÐ@ŠP>€ßymbolsname&€@ÿÿ(a耀 symbolskind&€@ÿÿ(c耀symbolsattributes&€@ÿÿ0eþ耀 symbolstype&€ÿÿàÿ€g?€€******symbolspk_symbols_id@&€ÿÿ?óhÿÿÿÿÿÿÿÿÿÿ€€€$$$$symbolspk_symbols_idpk_symbols_id&€ÿÿÀÿ€i?€€*vvvvvsymbolspk_symbols_id@D Am§¤€?&€ÿÿ¿àlÿÿ€€€.€>Rsymbolsfk_symbols_kindpk_code_item_kinds_idcode_item_kinds@&€ÿÿàÿn@€€111111symbolsix_symbols_parent_id@&€ÿÿÀÿo@€€1}}}}}symbolsix_symbols_parent_id@D Am§¤€?&€ÿÿàÿqA€€,,,,,,symbolsix_symbols_name&€ÿÿÀÿrA€€,xxxxxsymbolsix_symbols_nameD Am§¤þ€?&€ÿÿàÿtB€€,,,,,,symbolsix_symbols_kind@&€ÿÿ?àuÿÿ€€€(€>€Nbsymbolsfk_symbols_kindix_symbols_kindpk_code_item_kinds_idcode_item_kinds@&€ÿÿÀÿwB€€,xxxxxsymbolsix_symbols_kind@D Am§¤€?&àÿÿÿ‰ÿÿC€ €__SysObjectsrefs&€@ÿÿ(zh耀refssymbol_id&€@ÿÿ(|h耀refsowner_id&€@ÿÿ(~耀 refsrefkind&€@ÿÿ(€h耀 refsfile_id&€@ÿÿ(‚耀 refsline&€ÿÿàÿ„D€€++++++refsix_refs_symbol_id@&€ÿÿÀÿ…D€€+wwwwwrefsix_refs_symbol_id@DAm§¤€?&€ÿÿàÿ‡E€€******refsix_refs_owner_id@&€ÿÿÀÿˆE€€*vvvvvrefsix_refs_owner_id@DAm§¤€?%= ÊK Ûzqªªœ¹0ÉÁøìW ÏU l¤ -÷ Û\2 ê z È?`~6X/@`˜7A`–ê×?B`thèC0§ àC#hD`ÄøfqE`Ì&Ë:F@ˆ`ü€€version12.0003ü€€pathC:\Users\Vincent\Documents\Fox-git\Fox\Fox.sdfü€€code_items_mod0ZÀð°òà‘ÔG@ðø2½éµ>m]K’^ŠC·˜ ´€€C/C++cppø5½éµ>m]K’^ŠC·˜ ´€€IDLidlø>½éµ>m]K’^ŠC·˜ ´€€MetadatamdHp%0PòoØH@Ì =Зø2½éµ>m]K’^ŠC·˜ ´€classø2½éµ>m]K’^ŠC·˜ ´€structø2½éµ>m]K’^ŠC·˜ ´€unionø2½éµ>m]K’^ŠC·˜ ´€enumø2½éµ>m]K’^ŠC·˜ ´€interfaceø2½éµ>m]K’^ŠC·˜ ´€unknown_declø2½éµ>m]K’^ŠC·˜ ´€member_functionø2½éµ>m]K’^ŠC·˜ ´€memberø 2½éµ>m]K’^ŠC·˜ ´€enumeratorø 2½éµ>m]K’^ŠC·˜ ´€parameterø 2½éµ>m]K’^ŠC·˜ ´€templateø 2½éµ>m]K’^ŠC·˜ ´€template_argumentø 2½éµ>m]K’^ŠC·˜ ´€template_type_parameterø2½éµ>m]K’^ŠC·˜ ´€template_non_type_parameterø2½éµ>m]K’^ŠC·˜ ´€template_template_parameterø2½éµ>m]K’^ŠC·˜ ´€generic_constraintø2½éµ>m]K’^ŠC·˜ ´€base_classø2½éµ>m]K’^ŠC·˜ ´€namespaceø2½éµ>m]K’^ŠC·˜ ´€namespace_aliasø2½éµ>m]K’^ŠC·˜ ´€using_namespaceø2½éµ>m]K’^ŠC·˜ ´€using_declø2½éµ>m]K’^ŠC·˜ ´€functionø2½éµ>m]K’^ŠC·˜ ´€variableø2½éµ>m]K’^ŠC·˜ ´€attributeø2½éµ>m]K’^ŠC·˜ ´€attribute_argumentø2½éµ>m]K’^ŠC·˜ ´€mapø2½éµ>m]K’^ŠC·˜ ´€map_itemø2½éµ>m]K’^ŠC·˜ ´€dialog_idø2½éµ>m]K’^ŠC·˜ ´€propertyø2½éµ>m]K’^ŠC·˜ ´€eventø2½éµ>m]K’^ŠC·˜ ´€delegateø 2½éµ>m]K’^ŠC·˜ ´€explicit_overrideø!2½éµ>m]K’^ŠC·˜ ´€macro_defineø"2½éµ>m]K’^ŠC·˜ ´€macro_undefø#2½éµ>m]K’^ŠC·˜ ´€pound_includeø$2½éµ>m]K’^ŠC·˜ ´€pound_importø%2½éµ>m]K’^ŠC·˜ ´€pound_usingø&2½éµ>m]K’^ŠC·˜ ´€pound_errorø'2½éµ>m]K’^ŠC·˜ ´€pound_lineø(2½éµ>m]K’^ŠC·˜ ´€pound_pragmaø)2½éµ>m]K’^ŠC·˜ ´€pound_ifdefø*2½éµ>m]K’^ŠC·˜ ´€pound_ifø+2½éµ>m]K’^ŠC·˜ ´€pound_ifndefø,2½éµ>m]K’^ŠC·˜ ´€pound_elseø-2½éµ>m]K’^ŠC·˜ ´€pound_elifø.2½éµ>m]K’^ŠC·˜ ´€pound_endifø/2½éµ>m]K’^ŠC·˜ ´€typedefø02½éµ>m]K’^ŠC·˜ ´€using_aliasø12½éµ>m]K’^ŠC·˜ ´€labelø22½éµ>m]K’^ŠC·˜ ´€commentø32½éµ>m]K’^ŠC·˜ ´€scopeø42½éµ>m]K’^ŠC·˜ ´€skippedø52½éµ>m]K’^ŠC·˜ ´€coclass_idlø62½éµ>m]K’^ŠC·˜ ´€interface_idlø72½éµ>m]K’^ŠC·˜ ´€dispinterface_idlø82½éµ>m]K’^ŠC·˜ ´€library_idlø92½éµ>m]K’^ŠC·˜ ´€module_idlø:2½éµ>m]K’^ŠC·˜ ´€import_idlø;2½éµ>m]K’^ŠC·˜ ´€importlib_idlø<2½éµ>m]K’^ŠC·˜ ´€mfc_comment_idlø=2½éµ>m]K’^ŠC·˜ ´€max] 1É©àx¹x‘ˆcè9¨ˆíGË'§G…']‡9G‡êvÃvš–uVM†$–ýuÕ…­…„•Z¥2… •Ûä¶T”$oTId$TÕó¯cŠSeS>sÃæÂÀb™rjò2‚úÆA˜ásQMa&q1×À®ˆ`gE "0 —˜tÔ F` À ð P€°à "#@%&p() +,Ð./12045`78:;À=>ð@A CDPFG€IJFå^Kobjcryst-2022.1/Fox/Fox.sln000066400000000000000000000166651430515525000154630ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Fox", "src\Fox.vcxproj", "{49D0D342-DE29-4270-AFA1-032247DB2E7F}" ProjectSection(ProjectDependencies) = postProject {64886AC3-4FBE-46FF-AA73-BBC4F3B39620} = {64886AC3-4FBE-46FF-AA73-BBC4F3B39620} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cctbx", "..\cctbx\cctbx.vcxproj", "{D8E557F4-1838-4E64-A5C4-797338DA28D3}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "newmat", "..\newmat\newmat.vcxproj", "{8ECF53EB-FC6C-40F9-961E-6611992D29C8}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libfftw", "..\fftw3-vc6\fftw-3.0.1\win32\libfftw.vcxproj", "{64886AC3-4FBE-46FF-AA73-BBC4F3B39620}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug float|Win32 = Debug float|Win32 Debug|Win32 = Debug|Win32 Debug-normal|Win32 = Debug-normal|Win32 Release float|Win32 = Release float|Win32 Release SSE|Win32 = Release SSE|Win32 Release SSE2|Win32 = Release SSE2|Win32 Release X64|Win32 = Release X64|Win32 Release|Win32 = Release|Win32 Template|Win32 = Template|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {49D0D342-DE29-4270-AFA1-032247DB2E7F}.Debug float|Win32.ActiveCfg = Debug|Win32 {49D0D342-DE29-4270-AFA1-032247DB2E7F}.Debug float|Win32.Build.0 = Debug|Win32 {49D0D342-DE29-4270-AFA1-032247DB2E7F}.Debug|Win32.ActiveCfg = Debug|Win32 {49D0D342-DE29-4270-AFA1-032247DB2E7F}.Debug|Win32.Build.0 = Debug|Win32 {49D0D342-DE29-4270-AFA1-032247DB2E7F}.Debug-normal|Win32.ActiveCfg = Debug|Win32 {49D0D342-DE29-4270-AFA1-032247DB2E7F}.Debug-normal|Win32.Build.0 = Debug|Win32 {49D0D342-DE29-4270-AFA1-032247DB2E7F}.Release float|Win32.ActiveCfg = Release UNICODE|Win32 {49D0D342-DE29-4270-AFA1-032247DB2E7F}.Release float|Win32.Build.0 = Release UNICODE|Win32 {49D0D342-DE29-4270-AFA1-032247DB2E7F}.Release SSE|Win32.ActiveCfg = Release UNICODE|Win32 {49D0D342-DE29-4270-AFA1-032247DB2E7F}.Release SSE|Win32.Build.0 = Release UNICODE|Win32 {49D0D342-DE29-4270-AFA1-032247DB2E7F}.Release SSE2|Win32.ActiveCfg = Release UNICODE|Win32 {49D0D342-DE29-4270-AFA1-032247DB2E7F}.Release SSE2|Win32.Build.0 = Release UNICODE|Win32 {49D0D342-DE29-4270-AFA1-032247DB2E7F}.Release X64|Win32.ActiveCfg = Release X64|Win32 {49D0D342-DE29-4270-AFA1-032247DB2E7F}.Release X64|Win32.Build.0 = Release X64|Win32 {49D0D342-DE29-4270-AFA1-032247DB2E7F}.Release|Win32.ActiveCfg = Release|Win32 {49D0D342-DE29-4270-AFA1-032247DB2E7F}.Release|Win32.Build.0 = Release|Win32 {49D0D342-DE29-4270-AFA1-032247DB2E7F}.Template|Win32.ActiveCfg = Release|Win32 {49D0D342-DE29-4270-AFA1-032247DB2E7F}.Template|Win32.Build.0 = Release|Win32 {D8E557F4-1838-4E64-A5C4-797338DA28D3}.Debug float|Win32.ActiveCfg = Debug|Win32 {D8E557F4-1838-4E64-A5C4-797338DA28D3}.Debug float|Win32.Build.0 = Debug|Win32 {D8E557F4-1838-4E64-A5C4-797338DA28D3}.Debug|Win32.ActiveCfg = Debug|Win32 {D8E557F4-1838-4E64-A5C4-797338DA28D3}.Debug|Win32.Build.0 = Debug|Win32 {D8E557F4-1838-4E64-A5C4-797338DA28D3}.Debug-normal|Win32.ActiveCfg = Debug|Win32 {D8E557F4-1838-4E64-A5C4-797338DA28D3}.Debug-normal|Win32.Build.0 = Debug|Win32 {D8E557F4-1838-4E64-A5C4-797338DA28D3}.Release float|Win32.ActiveCfg = Release|Win32 {D8E557F4-1838-4E64-A5C4-797338DA28D3}.Release float|Win32.Build.0 = Release|Win32 {D8E557F4-1838-4E64-A5C4-797338DA28D3}.Release SSE|Win32.ActiveCfg = Release|Win32 {D8E557F4-1838-4E64-A5C4-797338DA28D3}.Release SSE|Win32.Build.0 = Release|Win32 {D8E557F4-1838-4E64-A5C4-797338DA28D3}.Release SSE2|Win32.ActiveCfg = Release|Win32 {D8E557F4-1838-4E64-A5C4-797338DA28D3}.Release SSE2|Win32.Build.0 = Release|Win32 {D8E557F4-1838-4E64-A5C4-797338DA28D3}.Release X64|Win32.ActiveCfg = Release X64|Win32 {D8E557F4-1838-4E64-A5C4-797338DA28D3}.Release X64|Win32.Build.0 = Release X64|Win32 {D8E557F4-1838-4E64-A5C4-797338DA28D3}.Release|Win32.ActiveCfg = Release|Win32 {D8E557F4-1838-4E64-A5C4-797338DA28D3}.Release|Win32.Build.0 = Release|Win32 {D8E557F4-1838-4E64-A5C4-797338DA28D3}.Template|Win32.ActiveCfg = Release|Win32 {D8E557F4-1838-4E64-A5C4-797338DA28D3}.Template|Win32.Build.0 = Release|Win32 {8ECF53EB-FC6C-40F9-961E-6611992D29C8}.Debug float|Win32.ActiveCfg = Debug|Win32 {8ECF53EB-FC6C-40F9-961E-6611992D29C8}.Debug float|Win32.Build.0 = Debug|Win32 {8ECF53EB-FC6C-40F9-961E-6611992D29C8}.Debug|Win32.ActiveCfg = Debug|Win32 {8ECF53EB-FC6C-40F9-961E-6611992D29C8}.Debug|Win32.Build.0 = Debug|Win32 {8ECF53EB-FC6C-40F9-961E-6611992D29C8}.Debug-normal|Win32.ActiveCfg = Debug|Win32 {8ECF53EB-FC6C-40F9-961E-6611992D29C8}.Debug-normal|Win32.Build.0 = Debug|Win32 {8ECF53EB-FC6C-40F9-961E-6611992D29C8}.Release float|Win32.ActiveCfg = Release|Win32 {8ECF53EB-FC6C-40F9-961E-6611992D29C8}.Release float|Win32.Build.0 = Release|Win32 {8ECF53EB-FC6C-40F9-961E-6611992D29C8}.Release SSE|Win32.ActiveCfg = Release|Win32 {8ECF53EB-FC6C-40F9-961E-6611992D29C8}.Release SSE|Win32.Build.0 = Release|Win32 {8ECF53EB-FC6C-40F9-961E-6611992D29C8}.Release SSE2|Win32.ActiveCfg = Release|Win32 {8ECF53EB-FC6C-40F9-961E-6611992D29C8}.Release SSE2|Win32.Build.0 = Release|Win32 {8ECF53EB-FC6C-40F9-961E-6611992D29C8}.Release X64|Win32.ActiveCfg = Release X64|Win32 {8ECF53EB-FC6C-40F9-961E-6611992D29C8}.Release X64|Win32.Build.0 = Release X64|Win32 {8ECF53EB-FC6C-40F9-961E-6611992D29C8}.Release|Win32.ActiveCfg = Release|Win32 {8ECF53EB-FC6C-40F9-961E-6611992D29C8}.Release|Win32.Build.0 = Release|Win32 {8ECF53EB-FC6C-40F9-961E-6611992D29C8}.Template|Win32.ActiveCfg = Release|Win32 {8ECF53EB-FC6C-40F9-961E-6611992D29C8}.Template|Win32.Build.0 = Release|Win32 {64886AC3-4FBE-46FF-AA73-BBC4F3B39620}.Debug float|Win32.ActiveCfg = Debug float|Win32 {64886AC3-4FBE-46FF-AA73-BBC4F3B39620}.Debug float|Win32.Build.0 = Debug float|Win32 {64886AC3-4FBE-46FF-AA73-BBC4F3B39620}.Debug|Win32.ActiveCfg = Release|Win32 {64886AC3-4FBE-46FF-AA73-BBC4F3B39620}.Debug|Win32.Build.0 = Release|Win32 {64886AC3-4FBE-46FF-AA73-BBC4F3B39620}.Debug-normal|Win32.ActiveCfg = Debug float|Win32 {64886AC3-4FBE-46FF-AA73-BBC4F3B39620}.Debug-normal|Win32.Build.0 = Debug float|Win32 {64886AC3-4FBE-46FF-AA73-BBC4F3B39620}.Release float|Win32.ActiveCfg = Release float|Win32 {64886AC3-4FBE-46FF-AA73-BBC4F3B39620}.Release float|Win32.Build.0 = Release float|Win32 {64886AC3-4FBE-46FF-AA73-BBC4F3B39620}.Release SSE|Win32.ActiveCfg = Release SSE|Win32 {64886AC3-4FBE-46FF-AA73-BBC4F3B39620}.Release SSE|Win32.Build.0 = Release SSE|Win32 {64886AC3-4FBE-46FF-AA73-BBC4F3B39620}.Release SSE2|Win32.ActiveCfg = Release SSE2|Win32 {64886AC3-4FBE-46FF-AA73-BBC4F3B39620}.Release SSE2|Win32.Build.0 = Release SSE2|Win32 {64886AC3-4FBE-46FF-AA73-BBC4F3B39620}.Release X64|Win32.ActiveCfg = Release X64|Win32 {64886AC3-4FBE-46FF-AA73-BBC4F3B39620}.Release X64|Win32.Build.0 = Release X64|Win32 {64886AC3-4FBE-46FF-AA73-BBC4F3B39620}.Release|Win32.ActiveCfg = Release float|Win32 {64886AC3-4FBE-46FF-AA73-BBC4F3B39620}.Release|Win32.Build.0 = Release float|Win32 {64886AC3-4FBE-46FF-AA73-BBC4F3B39620}.Template|Win32.ActiveCfg = Release|Win32 {64886AC3-4FBE-46FF-AA73-BBC4F3B39620}.Template|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal objcryst-2022.1/Fox/Fox.xcodeproj/000077500000000000000000000000001430515525000167235ustar00rootroot00000000000000objcryst-2022.1/Fox/Fox.xcodeproj/project.pbxproj000066400000000000000000016512071430515525000220130ustar00rootroot00000000000000// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ BF11E7BA2440AA42009C104D /* GlobalOptimObj.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7B42440AA40009C104D /* GlobalOptimObj.h */; }; BF11E7BB2440AA42009C104D /* Simplex.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7B52440AA40009C104D /* Simplex.h */; }; BF11E7BC2440AA42009C104D /* RefinableObj.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7B62440AA41009C104D /* RefinableObj.h */; }; BF11E7BD2440AA42009C104D /* LSQNumObj.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7B72440AA42009C104D /* LSQNumObj.h */; }; BF11E7BE2440AA42009C104D /* Tracker.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7B82440AA42009C104D /* Tracker.h */; }; BF11E7BF2440AA42009C104D /* IO.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7B92440AA42009C104D /* IO.h */; }; BF11E7C12440C199009C104D /* CrystVector.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7C02440C199009C104D /* CrystVector.h */; }; BF11E7DA2440C1BF009C104D /* ScatteringData.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7C22440C1BB009C104D /* ScatteringData.h */; }; BF11E7DB2440C1BF009C104D /* Crystal.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7C32440C1BB009C104D /* Crystal.h */; }; BF11E7DC2440C1BF009C104D /* ReflectionProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7C42440C1BB009C104D /* ReflectionProfile.h */; }; BF11E7DD2440C1BF009C104D /* SpaceGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7C52440C1BB009C104D /* SpaceGroup.h */; }; BF11E7DE2440C1BF009C104D /* ScatteringCorr.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7C62440C1BC009C104D /* ScatteringCorr.h */; }; BF11E7DF2440C1BF009C104D /* PowderPattern.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7C72440C1BC009C104D /* PowderPattern.h */; }; BF11E7E02440C1BF009C104D /* ScatteringPower.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7C82440C1BC009C104D /* ScatteringPower.h */; }; BF11E7E12440C1BF009C104D /* IO.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7C92440C1BC009C104D /* IO.h */; }; BF11E7E22440C1BF009C104D /* test.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7CA2440C1BC009C104D /* test.h */; }; BF11E7E32440C1BF009C104D /* DiffractionDataSingleCrystal.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7CB2440C1BC009C104D /* DiffractionDataSingleCrystal.h */; }; BF11E7E42440C1BF009C104D /* ScatteringPowerSphere.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7CC2440C1BD009C104D /* ScatteringPowerSphere.h */; }; BF11E7E52440C1BF009C104D /* ZScatterer.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7CD2440C1BD009C104D /* ZScatterer.h */; }; BF11E7E62440C1BF009C104D /* Molecule.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7CE2440C1BD009C104D /* Molecule.h */; }; BF11E7E72440C1BF009C104D /* Colours.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7CF2440C1BD009C104D /* Colours.h */; }; BF11E7E82440C1BF009C104D /* Scatterer.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7D02440C1BD009C104D /* Scatterer.h */; }; BF11E7E92440C1BF009C104D /* PDF.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7D12440C1BD009C104D /* PDF.h */; }; BF11E7EA2440C1BF009C104D /* Atom.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7D22440C1BE009C104D /* Atom.h */; }; BF11E7EB2440C1BF009C104D /* General.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7D32440C1BE009C104D /* General.h */; }; BF11E7EC2440C1BF009C104D /* CIF.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7D42440C1BE009C104D /* CIF.h */; }; BF11E7ED2440C1BF009C104D /* PowderPatternBackgroundBayesianMinimiser.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7D52440C1BE009C104D /* PowderPatternBackgroundBayesianMinimiser.h */; }; BF11E7EE2440C1BF009C104D /* Indexing.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7D62440C1BE009C104D /* Indexing.h */; }; BF11E7EF2440C1BF009C104D /* Polyhedron.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7D72440C1BE009C104D /* Polyhedron.h */; }; BF11E7F02440C1BF009C104D /* GeomStructFactor.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7D82440C1BF009C104D /* GeomStructFactor.h */; }; BF11E7F12440C1BF009C104D /* UnitCell.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7D92440C1BF009C104D /* UnitCell.h */; }; BF11E7F72440C1D6009C104D /* VFNStreamFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7F22440C1D6009C104D /* VFNStreamFormat.h */; }; BF11E7F82440C1D6009C104D /* sse_mathfun.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7F32440C1D6009C104D /* sse_mathfun.h */; }; BF11E7F92440C1D6009C104D /* ci_string.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7F42440C1D6009C104D /* ci_string.h */; }; BF11E7FA2440C1D6009C104D /* Chronometer.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7F52440C1D6009C104D /* Chronometer.h */; }; BF11E7FB2440C1D6009C104D /* VFNDebug.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7F62440C1D6009C104D /* VFNDebug.h */; }; BF11E8102440C1EB009C104D /* wxAtom.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7FC2440C1E8009C104D /* wxAtom.h */; }; BF11E8112440C1EB009C104D /* wxZScatterer.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7FD2440C1E8009C104D /* wxZScatterer.h */; }; BF11E8122440C1EB009C104D /* wxTrackerGraph.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7FE2440C1E8009C104D /* wxTrackerGraph.h */; }; BF11E8132440C1EB009C104D /* wxMultiGraph.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E7FF2440C1E8009C104D /* wxMultiGraph.h */; }; BF11E8142440C1EB009C104D /* wxScatteringPower.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E8002440C1E8009C104D /* wxScatteringPower.h */; }; BF11E8152440C1EB009C104D /* wxDiffractionSingleCrystal.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E8012440C1E9009C104D /* wxDiffractionSingleCrystal.h */; }; BF11E8162440C1EB009C104D /* wxRefinableObj.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E8022440C1E9009C104D /* wxRefinableObj.h */; }; BF11E8172440C1EB009C104D /* wxLSQ.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E8032440C1E9009C104D /* wxLSQ.h */; }; BF11E8182440C1EB009C104D /* mpVector.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E8042440C1E9009C104D /* mpVector.h */; }; BF11E8192440C1EB009C104D /* wxCrystal.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E8052440C1E9009C104D /* wxCrystal.h */; }; BF11E81A2440C1EB009C104D /* wxRadiation.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E8062440C1E9009C104D /* wxRadiation.h */; }; BF11E81B2440C1EB009C104D /* MC.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E8072440C1E9009C104D /* MC.h */; }; BF11E81C2440C1EB009C104D /* wxScatterer.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E8082440C1EA009C104D /* wxScatterer.h */; }; BF11E81D2440C1EB009C104D /* wxScatteringPowerSphere.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E8092440C1EA009C104D /* wxScatteringPowerSphere.h */; }; BF11E81E2440C1EB009C104D /* MCTable.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E80A2440C1EA009C104D /* MCTable.h */; }; BF11E81F2440C1EB009C104D /* wxPowderPattern.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E80B2440C1EA009C104D /* wxPowderPattern.h */; }; BF11E8202440C1EB009C104D /* wxGlobalOptimObj.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E80C2440C1EA009C104D /* wxGlobalOptimObj.h */; }; BF11E8212440C1EB009C104D /* wxMolecule.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E80D2440C1EA009C104D /* wxMolecule.h */; }; BF11E8222440C1EB009C104D /* wxCryst.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E80E2440C1EB009C104D /* wxCryst.h */; }; BF11E8232440C1EB009C104D /* trackball.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E80F2440C1EB009C104D /* trackball.h */; }; BF11E82D2440C200009C104D /* IOSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E8242440C1FE009C104D /* IOSocket.h */; }; BF11E82E2440C200009C104D /* FoxJob.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E8252440C1FF009C104D /* FoxJob.h */; }; BF11E82F2440C200009C104D /* WXFoxServer.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E8262440C1FF009C104D /* WXFoxServer.h */; }; BF11E8312440C200009C104D /* WXFoxClient.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E8282440C1FF009C104D /* WXFoxClient.h */; }; BF11E8322440C200009C104D /* WXGridWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E8292440C1FF009C104D /* WXGridWindow.h */; }; BF11E8332440C200009C104D /* GridResult.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E82A2440C1FF009C104D /* GridResult.h */; }; BF11E8342440C200009C104D /* FoxServer.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E82B2440C1FF009C104D /* FoxServer.h */; }; BF11E8352440C200009C104D /* FoxClient.h in Headers */ = {isa = PBXBuildFile; fileRef = BF11E82C2440C200009C104D /* FoxClient.h */; }; BF1DDDEE0D228E3700A3939D /* Fox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD88E0890422000044EBA /* Fox.cpp */; }; BF1DDDEF0D228E3700A3939D /* Atom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8900890426600044EBA /* Atom.cpp */; }; BF1DDDF00D228E3700A3939D /* Crystal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8910890426600044EBA /* Crystal.cpp */; }; BF1DDDF10D228E3700A3939D /* CrystVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8920890426600044EBA /* CrystVector.cpp */; }; BF1DDDF20D228E3700A3939D /* DiffractionDataSingleCrystal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8930890426600044EBA /* DiffractionDataSingleCrystal.cpp */; }; BF1DDDF30D228E3700A3939D /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8940890426600044EBA /* Exception.cpp */; }; BF1DDDF40D228E3700A3939D /* geomStructFactor_001.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8960890426600044EBA /* geomStructFactor_001.cpp */; }; BF1DDDF50D228E3700A3939D /* geomStructFactor_002.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8970890426600044EBA /* geomStructFactor_002.cpp */; }; BF1DDDF60D228E3700A3939D /* geomStructFactor_067.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8980890426600044EBA /* geomStructFactor_067.cpp */; }; BF1DDDF70D228E3700A3939D /* geomStructFactor_097.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8990890426600044EBA /* geomStructFactor_097.cpp */; }; BF1DDDF80D228E3700A3939D /* geomStructFactor_230.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD89A0890426600044EBA /* geomStructFactor_230.cpp */; }; BF1DDDF90D228E3700A3939D /* geomStructFactor_centro.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD89B0890426600044EBA /* geomStructFactor_centro.cpp */; }; BF1DDDFA0D228E3700A3939D /* geomStructFactor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD89C0890426600044EBA /* geomStructFactor.cpp */; }; BF1DDDFB0D228E3700A3939D /* GlobalOptimObj.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD89D0890426600044EBA /* GlobalOptimObj.cpp */; }; BF1DDDFC0D228E3700A3939D /* IO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD89E0890426600044EBA /* IO.cpp */; }; BF1DDDFD0D228E3700A3939D /* IO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD89F0890426600044EBA /* IO.cpp */; }; BF1DDDFE0D228E3700A3939D /* LSQNumObj.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8A00890426600044EBA /* LSQNumObj.cpp */; }; BF1DDDFF0D228E3700A3939D /* MC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8A10890426600044EBA /* MC.cpp */; }; BF1DDE000D228E3700A3939D /* Molecule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8A20890426600044EBA /* Molecule.cpp */; }; BF1DDE010D228E3700A3939D /* mpVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8A30890426600044EBA /* mpVector.cpp */; }; BF1DDE020D228E3700A3939D /* Polyhedron.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8A50890426600044EBA /* Polyhedron.cpp */; }; BF1DDE030D228E3700A3939D /* PowderPattern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8A60890426600044EBA /* PowderPattern.cpp */; }; BF1DDE040D228E3700A3939D /* PowderPatternBackgroundBayesianMinimiser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8A70890426600044EBA /* PowderPatternBackgroundBayesianMinimiser.cpp */; }; BF1DDE050D228E3700A3939D /* RefinableObj.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8A80890426600044EBA /* RefinableObj.cpp */; }; BF1DDE060D228E3700A3939D /* ReflectionProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8A90890426600044EBA /* ReflectionProfile.cpp */; }; BF1DDE070D228E3700A3939D /* Scatterer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8AA0890426600044EBA /* Scatterer.cpp */; }; BF1DDE080D228E3700A3939D /* ScatteringCorr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8AB0890426600044EBA /* ScatteringCorr.cpp */; }; BF1DDE090D228E3700A3939D /* ScatteringData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8AC0890426600044EBA /* ScatteringData.cpp */; }; BF1DDE0A0D228E3700A3939D /* ScatteringPower.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8AD0890426600044EBA /* ScatteringPower.cpp */; }; BF1DDE0B0D228E3700A3939D /* ScatteringPowerSphere.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8AE0890426600044EBA /* ScatteringPowerSphere.cpp */; }; BF1DDE0C0D228E3700A3939D /* Simplex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8AF0890426600044EBA /* Simplex.cpp */; }; BF1DDE0D0D228E3700A3939D /* SpaceGroup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8B00890426600044EBA /* SpaceGroup.cpp */; }; BF1DDE0E0D228E3700A3939D /* test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8B10890426600044EBA /* test.cpp */; }; BF1DDE0F0D228E3700A3939D /* Tracker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8B20890426600044EBA /* Tracker.cpp */; }; BF1DDE100D228E3700A3939D /* UnitCell.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8B30890426600044EBA /* UnitCell.cpp */; }; BF1DDE110D228E3700A3939D /* VFNDebug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8B40890426600044EBA /* VFNDebug.cpp */; }; BF1DDE120D228E3700A3939D /* VFNStreamFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8B50890426600044EBA /* VFNStreamFormat.cpp */; }; BF1DDE130D228E3700A3939D /* wxAtom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8B60890426600044EBA /* wxAtom.cpp */; }; BF1DDE140D228E3700A3939D /* wxCryst.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8B70890426600044EBA /* wxCryst.cpp */; }; BF1DDE150D228E3700A3939D /* wxCrystal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8B80890426600044EBA /* wxCrystal.cpp */; }; BF1DDE160D228E3700A3939D /* wxDiffractionSingleCrystal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8B90890426600044EBA /* wxDiffractionSingleCrystal.cpp */; }; BF1DDE170D228E3700A3939D /* wxGlobalOptimObj.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8BA0890426600044EBA /* wxGlobalOptimObj.cpp */; }; BF1DDE180D228E3700A3939D /* wxMolecule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8BB0890426600044EBA /* wxMolecule.cpp */; }; BF1DDE190D228E3700A3939D /* wxMultiGraph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8BC0890426600044EBA /* wxMultiGraph.cpp */; }; BF1DDE1A0D228E3700A3939D /* wxPowderPattern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8BD0890426600044EBA /* wxPowderPattern.cpp */; }; BF1DDE1B0D228E3700A3939D /* wxRefinableObj.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8BE0890426600044EBA /* wxRefinableObj.cpp */; }; BF1DDE1C0D228E3700A3939D /* wxScatterer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8BF0890426600044EBA /* wxScatterer.cpp */; }; BF1DDE1D0D228E3700A3939D /* wxScatteringPower.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8C00890426600044EBA /* wxScatteringPower.cpp */; }; BF1DDE1E0D228E3700A3939D /* wxScatteringPowerSphere.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8C10890426600044EBA /* wxScatteringPowerSphere.cpp */; }; BF1DDE1F0D228E3700A3939D /* wxTrackerGraph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8C20890426600044EBA /* wxTrackerGraph.cpp */; }; BF1DDE200D228E3700A3939D /* wxZScatterer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8C30890426700044EBA /* wxZScatterer.cpp */; }; BF1DDE210D228E3700A3939D /* ZScatterer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD8C60890426700044EBA /* ZScatterer.cpp */; }; BF1DDE220D228E3700A3939D /* trackball.c in Sources */ = {isa = PBXBuildFile; fileRef = BFFCD97C08904D7D00044EBA /* trackball.c */; }; BF1DDE230D228E3700A3939D /* CIF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF08978A0B072DF600C0F576 /* CIF.cpp */; }; BF1DDE240D228E3700A3939D /* ci_string.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF08978D0B072E2F00C0F576 /* ci_string.cpp */; }; BF1DDE250D228E3700A3939D /* Indexing.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFE6AC680B886ACA007AFBA8 /* Indexing.cpp */; }; BF1DDE260D228E4100A3939D /* Fox.icns in Resources */ = {isa = PBXBuildFile; fileRef = BF26F598089306500008175B /* Fox.icns */; }; BF1DE1110D228E5D00A3939D /* libcctbx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BFFCCBE50890309900044EBA /* libcctbx.a */; }; BF1DE1120D228E5D00A3939D /* libnewmat.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BFFCCB5D089028E500044EBA /* libnewmat.a */; }; BF1DE1130D228E6100A3939D /* AGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF3611180BD6E30F000C0EE9 /* AGL.framework */; }; BF1DE1140D228E6100A3939D /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF36111A0BD6E326000C0EE9 /* Carbon.framework */; }; BF1DE1150D228E6100A3939D /* System.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF3611220BD6E38F000C0EE9 /* System.framework */; }; BF1DE1160D228E6100A3939D /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF3611240BD6E3A6000C0EE9 /* IOKit.framework */; }; BF1DE1170D228E6100A3939D /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF3611260BD6E3B6000C0EE9 /* OpenGL.framework */; }; BF1DE1180D228E6100A3939D /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF3611280BD6E3CA000C0EE9 /* AppKit.framework */; }; BF1DE1190D228E6100A3939D /* GLUT.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF36112B0BD6E3F5000C0EE9 /* GLUT.framework */; }; BF1DE11A0D228E6100A3939D /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF36112F0BD6E409000C0EE9 /* WebKit.framework */; }; BF1DE1240D228EA500A3939D /* libfftw3f.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BF1DE1230D228EA500A3939D /* libfftw3f.a */; }; BF3EB05508968F5500E02367 /* uctbx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF3EB05408968F5500E02367 /* uctbx.cpp */; }; BF3EB063089690D200E02367 /* spoil_optimization.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF3EB062089690D200E02367 /* spoil_optimization.cpp */; }; BF49CDF01B0BC56E0012BF3B /* covalent_radii.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF49CDEF1B0BC56E0012BF3B /* covalent_radii.cpp */; }; BF5EBF13283F8CB2000D09FE /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF5EBF12283F8CB2000D09FE /* QuartzCore.framework */; }; BF69C4D1124F8C310035CF57 /* FoxClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF69C4C8124F8C310035CF57 /* FoxClient.cpp */; }; BF69C4D2124F8C310035CF57 /* FoxJob.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF69C4C9124F8C310035CF57 /* FoxJob.cpp */; }; BF69C4D3124F8C310035CF57 /* FoxServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF69C4CA124F8C310035CF57 /* FoxServer.cpp */; }; BF69C4D5124F8C310035CF57 /* GridResult.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF69C4CC124F8C310035CF57 /* GridResult.cpp */; }; BF69C4D6124F8C310035CF57 /* IOSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF69C4CD124F8C310035CF57 /* IOSocket.cpp */; }; BF69C4D7124F8C310035CF57 /* WXFoxClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF69C4CE124F8C310035CF57 /* WXFoxClient.cpp */; }; BF69C4D8124F8C310035CF57 /* WXFoxServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF69C4CF124F8C310035CF57 /* WXFoxServer.cpp */; }; BF69C4D9124F8C310035CF57 /* WXGridWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF69C4D0124F8C310035CF57 /* WXGridWindow.cpp */; }; BF92D5CF259F2D50005FD5D7 /* Undo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF92D5CE259F2D4F005FD5D7 /* Undo.cpp */; }; BFCB29CD258F7484008A8CCB /* include.h in Headers */ = {isa = PBXBuildFile; fileRef = BFCB29CC258F7484008A8CCB /* include.h */; }; BFE729E4243A6A6D00BABE40 /* libwx_osx_cocoau_gl-3.1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BFF7D0BF1478047800799F7A /* libwx_osx_cocoau_gl-3.1.a */; }; BFE729E5243A6A7000BABE40 /* libwx_osx_cocoau-3.1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BFF7D0C01478047800799F7A /* libwx_osx_cocoau-3.1.a */; }; BFE729E6243A6A7300BABE40 /* libwxjpeg-3.1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BFF7D0C11478047800799F7A /* libwxjpeg-3.1.a */; }; BFE729E7243A6A7600BABE40 /* libwxpng-3.1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BFF7D0C21478047800799F7A /* libwxpng-3.1.a */; }; BFFB474E0E5E0E620027591E /* wxLSQ.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFB474D0E5E0E620027591E /* wxLSQ.cpp */; }; BFFCCB670890296D00044EBA /* bandmat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCB660890296D00044EBA /* bandmat.cpp */; }; BFFCCBA0089029F400044EBA /* cholesky.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCB6A089029F400044EBA /* cholesky.cpp */; }; BFFCCBA1089029F400044EBA /* evalue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCB6B089029F400044EBA /* evalue.cpp */; }; BFFCCBA3089029F400044EBA /* fft.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCB6D089029F400044EBA /* fft.cpp */; }; BFFCCBA5089029F400044EBA /* hholder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCB6F089029F400044EBA /* hholder.cpp */; }; BFFCCBA6089029F400044EBA /* jacobi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCB70089029F400044EBA /* jacobi.cpp */; }; BFFCCBA7089029F400044EBA /* myexcept.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCB71089029F400044EBA /* myexcept.cpp */; }; BFFCCBA8089029F400044EBA /* newfft.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCB72089029F400044EBA /* newfft.cpp */; }; BFFCCBA9089029F400044EBA /* newmat1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCB73089029F400044EBA /* newmat1.cpp */; }; BFFCCBAA089029F400044EBA /* newmat2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCB74089029F400044EBA /* newmat2.cpp */; }; BFFCCBAB089029F400044EBA /* newmat3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCB75089029F400044EBA /* newmat3.cpp */; }; BFFCCBAC089029F400044EBA /* newmat4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCB76089029F400044EBA /* newmat4.cpp */; }; BFFCCBAD089029F400044EBA /* newmat5.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCB77089029F400044EBA /* newmat5.cpp */; }; BFFCCBAE089029F400044EBA /* newmat6.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCB78089029F400044EBA /* newmat6.cpp */; }; BFFCCBAF089029F400044EBA /* newmat7.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCB79089029F400044EBA /* newmat7.cpp */; }; BFFCCBB0089029F400044EBA /* newmat8.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCB7A089029F400044EBA /* newmat8.cpp */; }; BFFCCBB1089029F400044EBA /* newmat9.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCB7B089029F400044EBA /* newmat9.cpp */; }; BFFCCBB2089029F400044EBA /* newmatex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCB7C089029F400044EBA /* newmatex.cpp */; }; BFFCCBB3089029F400044EBA /* newmatnl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCB7D089029F400044EBA /* newmatnl.cpp */; }; BFFCCBB4089029F400044EBA /* newmatrm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCB7E089029F400044EBA /* newmatrm.cpp */; }; BFFCCBB8089029F400044EBA /* nm_misc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCB82089029F400044EBA /* nm_misc.cpp */; }; BFFCCBBA089029F400044EBA /* solution.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCB84089029F400044EBA /* solution.cpp */; }; BFFCCBBB089029F400044EBA /* sort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCB85089029F400044EBA /* sort.cpp */; }; BFFCCBBC089029F400044EBA /* submat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCB86089029F400044EBA /* submat.cpp */; }; BFFCCBBD089029F400044EBA /* svd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCB87089029F400044EBA /* svd.cpp */; }; BFFCCC0E089031B000044EBA /* basic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCBEB089031AF00044EBA /* basic.cpp */; }; BFFCCC10089031B000044EBA /* fp_fdp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCBED089031AF00044EBA /* fp_fdp.cpp */; }; BFFCCC12089031B000044EBA /* henke_tables_01_12.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCBEF089031AF00044EBA /* henke_tables_01_12.cpp */; }; BFFCCC13089031B000044EBA /* henke_tables_13_24.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCBF0089031AF00044EBA /* henke_tables_13_24.cpp */; }; BFFCCC14089031B000044EBA /* henke_tables_25_36.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCBF1089031AF00044EBA /* henke_tables_25_36.cpp */; }; BFFCCC15089031B000044EBA /* henke_tables_37_48.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCBF2089031AF00044EBA /* henke_tables_37_48.cpp */; }; BFFCCC16089031B000044EBA /* henke_tables_49_60.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCBF3089031AF00044EBA /* henke_tables_49_60.cpp */; }; BFFCCC17089031B000044EBA /* henke_tables_61_72.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCBF4089031AF00044EBA /* henke_tables_61_72.cpp */; }; BFFCCC18089031B000044EBA /* henke_tables_73_84.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCBF5089031AF00044EBA /* henke_tables_73_84.cpp */; }; BFFCCC19089031B000044EBA /* henke_tables_85_92.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCBF6089031AF00044EBA /* henke_tables_85_92.cpp */; }; BFFCCC1A089031B000044EBA /* henke.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCBF7089031AF00044EBA /* henke.cpp */; }; BFFCCC1C089031B000044EBA /* icsd_radii.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCBF9089031AF00044EBA /* icsd_radii.cpp */; }; BFFCCC1D089031B000044EBA /* it1992.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCBFA089031AF00044EBA /* it1992.cpp */; }; BFFCCC1E089031B000044EBA /* n_gaussian_raw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCBFB089031AF00044EBA /* n_gaussian_raw.cpp */; }; BFFCCC1F089031B000044EBA /* n_gaussian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCBFC089031AF00044EBA /* n_gaussian.cpp */; }; BFFCCC21089031B000044EBA /* neutron.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCBFE089031AF00044EBA /* neutron.cpp */; }; BFFCCC23089031B000044EBA /* sasaki_tables_01_12.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC00089031AF00044EBA /* sasaki_tables_01_12.cpp */; }; BFFCCC24089031B000044EBA /* sasaki_tables_13_24.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC01089031AF00044EBA /* sasaki_tables_13_24.cpp */; }; BFFCCC25089031B000044EBA /* sasaki_tables_25_36.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC02089031AF00044EBA /* sasaki_tables_25_36.cpp */; }; BFFCCC26089031B000044EBA /* sasaki_tables_37_48.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC03089031AF00044EBA /* sasaki_tables_37_48.cpp */; }; BFFCCC27089031B000044EBA /* sasaki_tables_49_60.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC04089031AF00044EBA /* sasaki_tables_49_60.cpp */; }; BFFCCC28089031B000044EBA /* sasaki_tables_61_72.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC05089031AF00044EBA /* sasaki_tables_61_72.cpp */; }; BFFCCC29089031B000044EBA /* sasaki_tables_73_82.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC06089031AF00044EBA /* sasaki_tables_73_82.cpp */; }; BFFCCC2A089031B000044EBA /* sasaki.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC07089031AF00044EBA /* sasaki.cpp */; }; BFFCCC2C089031B000044EBA /* tiny_pse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC09089031AF00044EBA /* tiny_pse.cpp */; }; BFFCCC2E089031B000044EBA /* wavelengths.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC0B089031AF00044EBA /* wavelengths.cpp */; }; BFFCCC2F089031B000044EBA /* wk1995.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC0C089031AF00044EBA /* wk1995.cpp */; }; BFFCCC620890324D00044EBA /* bricks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC320890324D00044EBA /* bricks.cpp */; }; BFFCCC630890324D00044EBA /* change_of_basis_op.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC330890324D00044EBA /* change_of_basis_op.cpp */; }; BFFCCC660890324D00044EBA /* find_affine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC360890324D00044EBA /* find_affine.cpp */; }; BFFCCC670890324D00044EBA /* group_codes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC370890324D00044EBA /* group_codes.cpp */; }; BFFCCC680890324D00044EBA /* hall_in.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC380890324D00044EBA /* hall_in.cpp */; }; BFFCCC690890324D00044EBA /* hall_symbol_table.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC390890324D00044EBA /* hall_symbol_table.cpp */; }; BFFCCC6B0890324D00044EBA /* lattice_symmetry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC3B0890324D00044EBA /* lattice_symmetry.cpp */; }; BFFCCC6C0890324D00044EBA /* lattice_tr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC3C0890324D00044EBA /* lattice_tr.cpp */; }; BFFCCC6D0890324D00044EBA /* matrix_group_code_table.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC3D0890324D00044EBA /* matrix_group_code_table.cpp */; }; BFFCCC6E0890324D00044EBA /* miller.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC3E0890324D00044EBA /* miller.cpp */; }; BFFCCC6F0890324D00044EBA /* normalizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC3F0890324D00044EBA /* normalizer.cpp */; }; BFFCCC720890324D00044EBA /* reciprocal_space_asu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC420890324D00044EBA /* reciprocal_space_asu.cpp */; }; BFFCCC730890324D00044EBA /* reciprocal_space_ref_asu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC430890324D00044EBA /* reciprocal_space_ref_asu.cpp */; }; BFFCCC740890324D00044EBA /* rot_mx_info.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC440890324D00044EBA /* rot_mx_info.cpp */; }; BFFCCC760890324D00044EBA /* rot_mx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC460890324D00044EBA /* rot_mx.cpp */; }; BFFCCC770890324D00044EBA /* row_echelon_solve.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC470890324D00044EBA /* row_echelon_solve.cpp */; }; BFFCCC790890324D00044EBA /* rt_mx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC490890324D00044EBA /* rt_mx.cpp */; }; BFFCCC7B0890324D00044EBA /* select_generators.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC4B0890324D00044EBA /* select_generators.cpp */; }; BFFCCC7D0890324D00044EBA /* seminvariant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC4D0890324D00044EBA /* seminvariant.cpp */; }; BFFCCC800890324D00044EBA /* site_symmetry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC500890324D00044EBA /* site_symmetry.cpp */; }; BFFCCC820890324D00044EBA /* space_group_type.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC520890324D00044EBA /* space_group_type.cpp */; }; BFFCCC840890324D00044EBA /* space_group.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC540890324D00044EBA /* space_group.cpp */; }; BFFCCC870890324D00044EBA /* symbols.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC570890324D00044EBA /* symbols.cpp */; }; BFFCCC890890324D00044EBA /* tensor_rank_2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC590890324D00044EBA /* tensor_rank_2.cpp */; }; BFFCCC8A0890324D00044EBA /* tr_group.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC5A0890324D00044EBA /* tr_group.cpp */; }; BFFCCC8C0890324D00044EBA /* tr_vec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC5C0890324D00044EBA /* tr_vec.cpp */; }; BFFCCC8D0890324D00044EBA /* utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC5D0890324D00044EBA /* utils.cpp */; }; BFFCCC8F0890324D00044EBA /* wyckoff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC5F0890324D00044EBA /* wyckoff.cpp */; }; BFFCCC900890324D00044EBA /* wyckoff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC600890324D00044EBA /* wyckoff.cpp */; }; BFFCCC990890328F00044EBA /* asu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC930890328F00044EBA /* asu.cpp */; }; BFFCCC9A0890328F00044EBA /* bins.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC940890328F00044EBA /* bins.cpp */; }; BFFCCC9B0890328F00044EBA /* index_generator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC950890328F00044EBA /* index_generator.cpp */; }; BFFCCC9C0890328F00044EBA /* match_bijvoet_mates.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC960890328F00044EBA /* match_bijvoet_mates.cpp */; }; BFFCCC9D0890328F00044EBA /* match_indices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC970890328F00044EBA /* match_indices.cpp */; }; BFFCCC9E0890328F00044EBA /* sym_equiv.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFFCCC980890328F00044EBA /* sym_equiv.cpp */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ BF1DE1880D229E1B00A3939D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFFCCB51089028D300044EBA /* Project object */; proxyType = 1; remoteGlobalIDString = BFFCCB5C089028E500044EBA; remoteInfo = newmat; }; BF1DE18A0D229E1B00A3939D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFFCCB51089028D300044EBA /* Project object */; proxyType = 1; remoteGlobalIDString = BFFCCBE40890309900044EBA; remoteInfo = cctbx; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ BF08978A0B072DF600C0F576 /* CIF.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = CIF.cpp; path = ../ObjCryst/ObjCryst/CIF.cpp; sourceTree = ""; }; BF08978D0B072E2F00C0F576 /* ci_string.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ci_string.cpp; path = ../ObjCryst/Quirks/ci_string.cpp; sourceTree = ""; }; BF11E7B42440AA40009C104D /* GlobalOptimObj.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GlobalOptimObj.h; path = ../ObjCryst/RefinableObj/GlobalOptimObj.h; sourceTree = ""; }; BF11E7B52440AA40009C104D /* Simplex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Simplex.h; path = ../ObjCryst/RefinableObj/Simplex.h; sourceTree = ""; }; BF11E7B62440AA41009C104D /* RefinableObj.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RefinableObj.h; path = ../ObjCryst/RefinableObj/RefinableObj.h; sourceTree = ""; }; BF11E7B72440AA42009C104D /* LSQNumObj.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LSQNumObj.h; path = ../ObjCryst/RefinableObj/LSQNumObj.h; sourceTree = ""; }; BF11E7B82440AA42009C104D /* Tracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Tracker.h; path = ../ObjCryst/RefinableObj/Tracker.h; sourceTree = ""; }; BF11E7B92440AA42009C104D /* IO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IO.h; path = ../ObjCryst/RefinableObj/IO.h; sourceTree = ""; }; BF11E7C02440C199009C104D /* CrystVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CrystVector.h; path = ../ObjCryst/CrystVector/CrystVector.h; sourceTree = ""; }; BF11E7C22440C1BB009C104D /* ScatteringData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ScatteringData.h; path = ../ObjCryst/ObjCryst/ScatteringData.h; sourceTree = ""; }; BF11E7C32440C1BB009C104D /* Crystal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Crystal.h; path = ../ObjCryst/ObjCryst/Crystal.h; sourceTree = ""; }; BF11E7C42440C1BB009C104D /* ReflectionProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ReflectionProfile.h; path = ../ObjCryst/ObjCryst/ReflectionProfile.h; sourceTree = ""; }; BF11E7C52440C1BB009C104D /* SpaceGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SpaceGroup.h; path = ../ObjCryst/ObjCryst/SpaceGroup.h; sourceTree = ""; }; BF11E7C62440C1BC009C104D /* ScatteringCorr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ScatteringCorr.h; path = ../ObjCryst/ObjCryst/ScatteringCorr.h; sourceTree = ""; }; BF11E7C72440C1BC009C104D /* PowderPattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PowderPattern.h; path = ../ObjCryst/ObjCryst/PowderPattern.h; sourceTree = ""; }; BF11E7C82440C1BC009C104D /* ScatteringPower.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ScatteringPower.h; path = ../ObjCryst/ObjCryst/ScatteringPower.h; sourceTree = ""; }; BF11E7C92440C1BC009C104D /* IO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IO.h; path = ../ObjCryst/ObjCryst/IO.h; sourceTree = ""; }; BF11E7CA2440C1BC009C104D /* test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = test.h; path = ../ObjCryst/ObjCryst/test.h; sourceTree = ""; }; BF11E7CB2440C1BC009C104D /* DiffractionDataSingleCrystal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DiffractionDataSingleCrystal.h; path = ../ObjCryst/ObjCryst/DiffractionDataSingleCrystal.h; sourceTree = ""; }; BF11E7CC2440C1BD009C104D /* ScatteringPowerSphere.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ScatteringPowerSphere.h; path = ../ObjCryst/ObjCryst/ScatteringPowerSphere.h; sourceTree = ""; }; BF11E7CD2440C1BD009C104D /* ZScatterer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ZScatterer.h; path = ../ObjCryst/ObjCryst/ZScatterer.h; sourceTree = ""; }; BF11E7CE2440C1BD009C104D /* Molecule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Molecule.h; path = ../ObjCryst/ObjCryst/Molecule.h; sourceTree = ""; }; BF11E7CF2440C1BD009C104D /* Colours.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Colours.h; path = ../ObjCryst/ObjCryst/Colours.h; sourceTree = ""; }; BF11E7D02440C1BD009C104D /* Scatterer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Scatterer.h; path = ../ObjCryst/ObjCryst/Scatterer.h; sourceTree = ""; }; BF11E7D12440C1BD009C104D /* PDF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PDF.h; path = ../ObjCryst/ObjCryst/PDF.h; sourceTree = ""; }; BF11E7D22440C1BE009C104D /* Atom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Atom.h; path = ../ObjCryst/ObjCryst/Atom.h; sourceTree = ""; }; BF11E7D32440C1BE009C104D /* General.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = General.h; path = ../ObjCryst/ObjCryst/General.h; sourceTree = ""; }; BF11E7D42440C1BE009C104D /* CIF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CIF.h; path = ../ObjCryst/ObjCryst/CIF.h; sourceTree = ""; }; BF11E7D52440C1BE009C104D /* PowderPatternBackgroundBayesianMinimiser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PowderPatternBackgroundBayesianMinimiser.h; path = ../ObjCryst/ObjCryst/PowderPatternBackgroundBayesianMinimiser.h; sourceTree = ""; }; BF11E7D62440C1BE009C104D /* Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Indexing.h; path = ../ObjCryst/ObjCryst/Indexing.h; sourceTree = ""; }; BF11E7D72440C1BE009C104D /* Polyhedron.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Polyhedron.h; path = ../ObjCryst/ObjCryst/Polyhedron.h; sourceTree = ""; }; BF11E7D82440C1BF009C104D /* GeomStructFactor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GeomStructFactor.h; path = ../ObjCryst/ObjCryst/GeomStructFactor.h; sourceTree = ""; }; BF11E7D92440C1BF009C104D /* UnitCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UnitCell.h; path = ../ObjCryst/ObjCryst/UnitCell.h; sourceTree = ""; }; BF11E7F22440C1D6009C104D /* VFNStreamFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VFNStreamFormat.h; path = ../ObjCryst/Quirks/VFNStreamFormat.h; sourceTree = ""; }; BF11E7F32440C1D6009C104D /* sse_mathfun.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sse_mathfun.h; path = ../ObjCryst/Quirks/sse_mathfun.h; sourceTree = ""; }; BF11E7F42440C1D6009C104D /* ci_string.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ci_string.h; path = ../ObjCryst/Quirks/ci_string.h; sourceTree = ""; }; BF11E7F52440C1D6009C104D /* Chronometer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Chronometer.h; path = ../ObjCryst/Quirks/Chronometer.h; sourceTree = ""; }; BF11E7F62440C1D6009C104D /* VFNDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VFNDebug.h; path = ../ObjCryst/Quirks/VFNDebug.h; sourceTree = ""; }; BF11E7FC2440C1E8009C104D /* wxAtom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wxAtom.h; path = ../ObjCryst/wxCryst/wxAtom.h; sourceTree = ""; }; BF11E7FD2440C1E8009C104D /* wxZScatterer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wxZScatterer.h; path = ../ObjCryst/wxCryst/wxZScatterer.h; sourceTree = ""; }; BF11E7FE2440C1E8009C104D /* wxTrackerGraph.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wxTrackerGraph.h; path = ../ObjCryst/wxCryst/wxTrackerGraph.h; sourceTree = ""; }; BF11E7FF2440C1E8009C104D /* wxMultiGraph.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wxMultiGraph.h; path = ../ObjCryst/wxCryst/wxMultiGraph.h; sourceTree = ""; }; BF11E8002440C1E8009C104D /* wxScatteringPower.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wxScatteringPower.h; path = ../ObjCryst/wxCryst/wxScatteringPower.h; sourceTree = ""; }; BF11E8012440C1E9009C104D /* wxDiffractionSingleCrystal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wxDiffractionSingleCrystal.h; path = ../ObjCryst/wxCryst/wxDiffractionSingleCrystal.h; sourceTree = ""; }; BF11E8022440C1E9009C104D /* wxRefinableObj.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wxRefinableObj.h; path = ../ObjCryst/wxCryst/wxRefinableObj.h; sourceTree = ""; }; BF11E8032440C1E9009C104D /* wxLSQ.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wxLSQ.h; path = ../ObjCryst/wxCryst/wxLSQ.h; sourceTree = ""; }; BF11E8042440C1E9009C104D /* mpVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mpVector.h; path = ../ObjCryst/wxCryst/mpVector.h; sourceTree = ""; }; BF11E8052440C1E9009C104D /* wxCrystal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wxCrystal.h; path = ../ObjCryst/wxCryst/wxCrystal.h; sourceTree = ""; }; BF11E8062440C1E9009C104D /* wxRadiation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wxRadiation.h; path = ../ObjCryst/wxCryst/wxRadiation.h; sourceTree = ""; }; BF11E8072440C1E9009C104D /* MC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MC.h; path = ../ObjCryst/wxCryst/MC.h; sourceTree = ""; }; BF11E8082440C1EA009C104D /* wxScatterer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wxScatterer.h; path = ../ObjCryst/wxCryst/wxScatterer.h; sourceTree = ""; }; BF11E8092440C1EA009C104D /* wxScatteringPowerSphere.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wxScatteringPowerSphere.h; path = ../ObjCryst/wxCryst/wxScatteringPowerSphere.h; sourceTree = ""; }; BF11E80A2440C1EA009C104D /* MCTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MCTable.h; path = ../ObjCryst/wxCryst/MCTable.h; sourceTree = ""; }; BF11E80B2440C1EA009C104D /* wxPowderPattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wxPowderPattern.h; path = ../ObjCryst/wxCryst/wxPowderPattern.h; sourceTree = ""; }; BF11E80C2440C1EA009C104D /* wxGlobalOptimObj.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wxGlobalOptimObj.h; path = ../ObjCryst/wxCryst/wxGlobalOptimObj.h; sourceTree = ""; }; BF11E80D2440C1EA009C104D /* wxMolecule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wxMolecule.h; path = ../ObjCryst/wxCryst/wxMolecule.h; sourceTree = ""; }; BF11E80E2440C1EB009C104D /* wxCryst.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wxCryst.h; path = ../ObjCryst/wxCryst/wxCryst.h; sourceTree = ""; }; BF11E80F2440C1EB009C104D /* trackball.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = trackball.h; path = ../ObjCryst/wxCryst/trackball.h; sourceTree = ""; }; BF11E8242440C1FE009C104D /* IOSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IOSocket.h; path = src/IOSocket.h; sourceTree = ""; }; BF11E8252440C1FF009C104D /* FoxJob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FoxJob.h; path = src/FoxJob.h; sourceTree = ""; }; BF11E8262440C1FF009C104D /* WXFoxServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WXFoxServer.h; path = src/WXFoxServer.h; sourceTree = ""; }; BF11E8282440C1FF009C104D /* WXFoxClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WXFoxClient.h; path = src/WXFoxClient.h; sourceTree = ""; }; BF11E8292440C1FF009C104D /* WXGridWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WXGridWindow.h; path = src/WXGridWindow.h; sourceTree = ""; }; BF11E82A2440C1FF009C104D /* GridResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GridResult.h; path = src/GridResult.h; sourceTree = ""; }; BF11E82B2440C1FF009C104D /* FoxServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FoxServer.h; path = src/FoxServer.h; sourceTree = ""; }; BF11E82C2440C200009C104D /* FoxClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FoxClient.h; path = src/FoxClient.h; sourceTree = ""; }; BF1DDDE90D228DCF00A3939D /* Fox.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Fox.app; sourceTree = BUILT_PRODUCTS_DIR; }; BF1DDDEB0D228DCF00A3939D /* FoxCocoa-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "FoxCocoa-Info.plist"; sourceTree = ""; }; BF1DE1230D228EA500A3939D /* libfftw3f.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libfftw3f.a; path = "../static-libs/lib/libfftw3f.a"; sourceTree = SOURCE_ROOT; }; BF26F598089306500008175B /* Fox.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = Fox.icns; path = src/Fox.icns; sourceTree = ""; }; BF3611180BD6E30F000C0EE9 /* AGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AGL.framework; path = ../../../../../System/Library/Frameworks/AGL.framework; sourceTree = SOURCE_ROOT; }; BF36111A0BD6E326000C0EE9 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = ../../../../../System/Library/Frameworks/Carbon.framework; sourceTree = SOURCE_ROOT; }; BF3611220BD6E38F000C0EE9 /* System.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = System.framework; path = ../../../../../System/Library/Frameworks/System.framework; sourceTree = SOURCE_ROOT; }; BF3611240BD6E3A6000C0EE9 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = ../../../../../System/Library/Frameworks/IOKit.framework; sourceTree = SOURCE_ROOT; }; BF3611260BD6E3B6000C0EE9 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = ../../../../../System/Library/Frameworks/OpenGL.framework; sourceTree = SOURCE_ROOT; }; BF3611280BD6E3CA000C0EE9 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = ../../../../../System/Library/Frameworks/AppKit.framework; sourceTree = SOURCE_ROOT; }; BF36112B0BD6E3F5000C0EE9 /* GLUT.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLUT.framework; path = ../../../../../System/Library/Frameworks/GLUT.framework; sourceTree = SOURCE_ROOT; }; BF36112F0BD6E409000C0EE9 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = ../../../../../System/Library/Frameworks/WebKit.framework; sourceTree = SOURCE_ROOT; }; BF3EB05408968F5500E02367 /* uctbx.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = uctbx.cpp; path = ../cctbx/cctbx/uctbx/uctbx.cpp; sourceTree = ""; }; BF3EB062089690D200E02367 /* spoil_optimization.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = spoil_optimization.cpp; path = ../cctbx/cctbx/uctbx/spoil_optimization.cpp; sourceTree = ""; }; BF49CDEF1B0BC56E0012BF3B /* covalent_radii.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = covalent_radii.cpp; path = ../cctbx/cctbx/eltbx/covalent_radii.cpp; sourceTree = ""; }; BF5EBF12283F8CB2000D09FE /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; BF69C4C8124F8C310035CF57 /* FoxClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FoxClient.cpp; path = src/FoxClient.cpp; sourceTree = ""; }; BF69C4C9124F8C310035CF57 /* FoxJob.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FoxJob.cpp; path = src/FoxJob.cpp; sourceTree = ""; }; BF69C4CA124F8C310035CF57 /* FoxServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FoxServer.cpp; path = src/FoxServer.cpp; sourceTree = ""; }; BF69C4CC124F8C310035CF57 /* GridResult.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GridResult.cpp; path = src/GridResult.cpp; sourceTree = ""; }; BF69C4CD124F8C310035CF57 /* IOSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IOSocket.cpp; path = src/IOSocket.cpp; sourceTree = ""; }; BF69C4CE124F8C310035CF57 /* WXFoxClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WXFoxClient.cpp; path = src/WXFoxClient.cpp; sourceTree = ""; }; BF69C4CF124F8C310035CF57 /* WXFoxServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WXFoxServer.cpp; path = src/WXFoxServer.cpp; sourceTree = ""; }; BF69C4D0124F8C310035CF57 /* WXGridWindow.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WXGridWindow.cpp; path = src/WXGridWindow.cpp; sourceTree = ""; }; BF92D5CD259F2D4F005FD5D7 /* Undo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Undo.h; path = ../ObjCryst/ObjCryst/Undo.h; sourceTree = ""; }; BF92D5CE259F2D4F005FD5D7 /* Undo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Undo.cpp; path = ../ObjCryst/ObjCryst/Undo.cpp; sourceTree = ""; }; BFCB29CC258F7484008A8CCB /* include.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = include.h; path = ../newmat/include.h; sourceTree = ""; }; BFE6AC680B886ACA007AFBA8 /* Indexing.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Indexing.cpp; path = ../ObjCryst/ObjCryst/Indexing.cpp; sourceTree = SOURCE_ROOT; }; BFF7D0BF1478047800799F7A /* libwx_osx_cocoau_gl-3.1.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libwx_osx_cocoau_gl-3.1.a"; path = "../static-libs/lib/libwx_osx_cocoau_gl-3.1.a"; sourceTree = ""; }; BFF7D0C01478047800799F7A /* libwx_osx_cocoau-3.1.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libwx_osx_cocoau-3.1.a"; path = "../static-libs/lib/libwx_osx_cocoau-3.1.a"; sourceTree = ""; }; BFF7D0C11478047800799F7A /* libwxjpeg-3.1.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libwxjpeg-3.1.a"; path = "../static-libs/lib/libwxjpeg-3.1.a"; sourceTree = ""; }; BFF7D0C21478047800799F7A /* libwxpng-3.1.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libwxpng-3.1.a"; path = "../static-libs/lib/libwxpng-3.1.a"; sourceTree = ""; }; BFFB474D0E5E0E620027591E /* wxLSQ.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = wxLSQ.cpp; path = ../ObjCryst/wxCryst/wxLSQ.cpp; sourceTree = SOURCE_ROOT; }; BFFCCB5D089028E500044EBA /* libnewmat.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libnewmat.a; sourceTree = BUILT_PRODUCTS_DIR; }; BFFCCB660890296D00044EBA /* bandmat.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = bandmat.cpp; path = ../newmat/bandmat.cpp; sourceTree = ""; }; BFFCCB6A089029F400044EBA /* cholesky.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = cholesky.cpp; path = ../newmat/cholesky.cpp; sourceTree = ""; }; BFFCCB6B089029F400044EBA /* evalue.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = evalue.cpp; path = ../newmat/evalue.cpp; sourceTree = ""; }; BFFCCB6D089029F400044EBA /* fft.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = fft.cpp; path = ../newmat/fft.cpp; sourceTree = ""; }; BFFCCB6E089029F400044EBA /* garch.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = garch.cpp; path = ../newmat/garch.cpp; sourceTree = ""; }; BFFCCB6F089029F400044EBA /* hholder.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = hholder.cpp; path = ../newmat/hholder.cpp; sourceTree = ""; }; BFFCCB70089029F400044EBA /* jacobi.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = jacobi.cpp; path = ../newmat/jacobi.cpp; sourceTree = ""; }; BFFCCB71089029F400044EBA /* myexcept.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = myexcept.cpp; path = ../newmat/myexcept.cpp; sourceTree = ""; }; BFFCCB72089029F400044EBA /* newfft.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = newfft.cpp; path = ../newmat/newfft.cpp; sourceTree = ""; }; BFFCCB73089029F400044EBA /* newmat1.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = newmat1.cpp; path = ../newmat/newmat1.cpp; sourceTree = ""; }; BFFCCB74089029F400044EBA /* newmat2.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = newmat2.cpp; path = ../newmat/newmat2.cpp; sourceTree = ""; }; BFFCCB75089029F400044EBA /* newmat3.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = newmat3.cpp; path = ../newmat/newmat3.cpp; sourceTree = ""; }; BFFCCB76089029F400044EBA /* newmat4.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = newmat4.cpp; path = ../newmat/newmat4.cpp; sourceTree = ""; }; BFFCCB77089029F400044EBA /* newmat5.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = newmat5.cpp; path = ../newmat/newmat5.cpp; sourceTree = ""; }; BFFCCB78089029F400044EBA /* newmat6.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = newmat6.cpp; path = ../newmat/newmat6.cpp; sourceTree = ""; }; BFFCCB79089029F400044EBA /* newmat7.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = newmat7.cpp; path = ../newmat/newmat7.cpp; sourceTree = ""; }; BFFCCB7A089029F400044EBA /* newmat8.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = newmat8.cpp; path = ../newmat/newmat8.cpp; sourceTree = ""; }; BFFCCB7B089029F400044EBA /* newmat9.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = newmat9.cpp; path = ../newmat/newmat9.cpp; sourceTree = ""; }; BFFCCB7C089029F400044EBA /* newmatex.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = newmatex.cpp; path = ../newmat/newmatex.cpp; sourceTree = ""; }; BFFCCB7D089029F400044EBA /* newmatnl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = newmatnl.cpp; path = ../newmat/newmatnl.cpp; sourceTree = ""; }; BFFCCB7E089029F400044EBA /* newmatrm.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = newmatrm.cpp; path = ../newmat/newmatrm.cpp; sourceTree = ""; }; BFFCCB82089029F400044EBA /* nm_misc.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = nm_misc.cpp; path = ../newmat/nm_misc.cpp; sourceTree = ""; }; BFFCCB83089029F400044EBA /* sl_ex.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = sl_ex.cpp; path = ../newmat/sl_ex.cpp; sourceTree = ""; }; BFFCCB84089029F400044EBA /* solution.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = solution.cpp; path = ../newmat/solution.cpp; sourceTree = ""; }; BFFCCB85089029F400044EBA /* sort.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = sort.cpp; path = ../newmat/sort.cpp; sourceTree = ""; }; BFFCCB86089029F400044EBA /* submat.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = submat.cpp; path = ../newmat/submat.cpp; sourceTree = ""; }; BFFCCB87089029F400044EBA /* svd.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = svd.cpp; path = ../newmat/svd.cpp; sourceTree = ""; }; BFFCCBE50890309900044EBA /* libcctbx.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libcctbx.a; sourceTree = BUILT_PRODUCTS_DIR; }; BFFCCBEB089031AF00044EBA /* basic.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = basic.cpp; path = ../cctbx/cctbx/eltbx/basic.cpp; sourceTree = ""; }; BFFCCBED089031AF00044EBA /* fp_fdp.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = fp_fdp.cpp; path = ../cctbx/cctbx/eltbx/fp_fdp.cpp; sourceTree = ""; }; BFFCCBEF089031AF00044EBA /* henke_tables_01_12.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = henke_tables_01_12.cpp; path = ../cctbx/cctbx/eltbx/henke_tables_01_12.cpp; sourceTree = ""; }; BFFCCBF0089031AF00044EBA /* henke_tables_13_24.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = henke_tables_13_24.cpp; path = ../cctbx/cctbx/eltbx/henke_tables_13_24.cpp; sourceTree = ""; }; BFFCCBF1089031AF00044EBA /* henke_tables_25_36.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = henke_tables_25_36.cpp; path = ../cctbx/cctbx/eltbx/henke_tables_25_36.cpp; sourceTree = ""; }; BFFCCBF2089031AF00044EBA /* henke_tables_37_48.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = henke_tables_37_48.cpp; path = ../cctbx/cctbx/eltbx/henke_tables_37_48.cpp; sourceTree = ""; }; BFFCCBF3089031AF00044EBA /* henke_tables_49_60.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = henke_tables_49_60.cpp; path = ../cctbx/cctbx/eltbx/henke_tables_49_60.cpp; sourceTree = ""; }; BFFCCBF4089031AF00044EBA /* henke_tables_61_72.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = henke_tables_61_72.cpp; path = ../cctbx/cctbx/eltbx/henke_tables_61_72.cpp; sourceTree = ""; }; BFFCCBF5089031AF00044EBA /* henke_tables_73_84.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = henke_tables_73_84.cpp; path = ../cctbx/cctbx/eltbx/henke_tables_73_84.cpp; sourceTree = ""; }; BFFCCBF6089031AF00044EBA /* henke_tables_85_92.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = henke_tables_85_92.cpp; path = ../cctbx/cctbx/eltbx/henke_tables_85_92.cpp; sourceTree = ""; }; BFFCCBF7089031AF00044EBA /* henke.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = henke.cpp; path = ../cctbx/cctbx/eltbx/henke.cpp; sourceTree = ""; }; BFFCCBF9089031AF00044EBA /* icsd_radii.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = icsd_radii.cpp; path = ../cctbx/cctbx/eltbx/icsd_radii.cpp; sourceTree = ""; }; BFFCCBFA089031AF00044EBA /* it1992.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = it1992.cpp; path = ../cctbx/cctbx/eltbx/xray_scattering/it1992.cpp; sourceTree = ""; }; BFFCCBFB089031AF00044EBA /* n_gaussian_raw.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = n_gaussian_raw.cpp; path = ../cctbx/cctbx/eltbx/xray_scattering/n_gaussian_raw.cpp; sourceTree = ""; }; BFFCCBFC089031AF00044EBA /* n_gaussian.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = n_gaussian.cpp; path = ../cctbx/cctbx/eltbx/xray_scattering/n_gaussian.cpp; sourceTree = ""; }; BFFCCBFE089031AF00044EBA /* neutron.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = neutron.cpp; path = ../cctbx/cctbx/eltbx/neutron.cpp; sourceTree = ""; }; BFFCCC00089031AF00044EBA /* sasaki_tables_01_12.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = sasaki_tables_01_12.cpp; path = ../cctbx/cctbx/eltbx/sasaki_tables_01_12.cpp; sourceTree = ""; }; BFFCCC01089031AF00044EBA /* sasaki_tables_13_24.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = sasaki_tables_13_24.cpp; path = ../cctbx/cctbx/eltbx/sasaki_tables_13_24.cpp; sourceTree = ""; }; BFFCCC02089031AF00044EBA /* sasaki_tables_25_36.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = sasaki_tables_25_36.cpp; path = ../cctbx/cctbx/eltbx/sasaki_tables_25_36.cpp; sourceTree = ""; }; BFFCCC03089031AF00044EBA /* sasaki_tables_37_48.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = sasaki_tables_37_48.cpp; path = ../cctbx/cctbx/eltbx/sasaki_tables_37_48.cpp; sourceTree = ""; }; BFFCCC04089031AF00044EBA /* sasaki_tables_49_60.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = sasaki_tables_49_60.cpp; path = ../cctbx/cctbx/eltbx/sasaki_tables_49_60.cpp; sourceTree = ""; }; BFFCCC05089031AF00044EBA /* sasaki_tables_61_72.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = sasaki_tables_61_72.cpp; path = ../cctbx/cctbx/eltbx/sasaki_tables_61_72.cpp; sourceTree = ""; }; BFFCCC06089031AF00044EBA /* sasaki_tables_73_82.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = sasaki_tables_73_82.cpp; path = ../cctbx/cctbx/eltbx/sasaki_tables_73_82.cpp; sourceTree = ""; }; BFFCCC07089031AF00044EBA /* sasaki.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = sasaki.cpp; path = ../cctbx/cctbx/eltbx/sasaki.cpp; sourceTree = ""; }; BFFCCC09089031AF00044EBA /* tiny_pse.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = tiny_pse.cpp; path = ../cctbx/cctbx/eltbx/tiny_pse.cpp; sourceTree = ""; }; BFFCCC0B089031AF00044EBA /* wavelengths.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = wavelengths.cpp; path = ../cctbx/cctbx/eltbx/wavelengths.cpp; sourceTree = ""; }; BFFCCC0C089031AF00044EBA /* wk1995.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = wk1995.cpp; path = ../cctbx/cctbx/eltbx/xray_scattering/wk1995.cpp; sourceTree = ""; }; BFFCCC320890324D00044EBA /* bricks.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = bricks.cpp; path = ../cctbx/cctbx/sgtbx/bricks.cpp; sourceTree = ""; }; BFFCCC330890324D00044EBA /* change_of_basis_op.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = change_of_basis_op.cpp; path = ../cctbx/cctbx/sgtbx/change_of_basis_op.cpp; sourceTree = ""; }; BFFCCC360890324D00044EBA /* find_affine.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = find_affine.cpp; path = ../cctbx/cctbx/sgtbx/find_affine.cpp; sourceTree = ""; }; BFFCCC370890324D00044EBA /* group_codes.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = group_codes.cpp; path = ../cctbx/cctbx/sgtbx/group_codes.cpp; sourceTree = ""; }; BFFCCC380890324D00044EBA /* hall_in.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = hall_in.cpp; path = ../cctbx/cctbx/sgtbx/hall_in.cpp; sourceTree = ""; }; BFFCCC390890324D00044EBA /* hall_symbol_table.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = hall_symbol_table.cpp; path = ../cctbx/cctbx/sgtbx/reference_settings/hall_symbol_table.cpp; sourceTree = ""; }; BFFCCC3B0890324D00044EBA /* lattice_symmetry.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = lattice_symmetry.cpp; path = ../cctbx/cctbx/sgtbx/lattice_symmetry.cpp; sourceTree = ""; }; BFFCCC3C0890324D00044EBA /* lattice_tr.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = lattice_tr.cpp; path = ../cctbx/cctbx/sgtbx/lattice_tr.cpp; sourceTree = ""; }; BFFCCC3D0890324D00044EBA /* matrix_group_code_table.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = matrix_group_code_table.cpp; path = ../cctbx/cctbx/sgtbx/reference_settings/matrix_group_code_table.cpp; sourceTree = ""; }; BFFCCC3E0890324D00044EBA /* miller.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = miller.cpp; path = ../cctbx/cctbx/sgtbx/miller.cpp; sourceTree = ""; }; BFFCCC3F0890324D00044EBA /* normalizer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = normalizer.cpp; path = ../cctbx/cctbx/sgtbx/reference_settings/normalizer.cpp; sourceTree = ""; }; BFFCCC420890324D00044EBA /* reciprocal_space_asu.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = reciprocal_space_asu.cpp; path = ../cctbx/cctbx/sgtbx/reciprocal_space_asu.cpp; sourceTree = ""; }; BFFCCC430890324D00044EBA /* reciprocal_space_ref_asu.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = reciprocal_space_ref_asu.cpp; path = ../cctbx/cctbx/sgtbx/reciprocal_space_ref_asu.cpp; sourceTree = ""; }; BFFCCC440890324D00044EBA /* rot_mx_info.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = rot_mx_info.cpp; path = ../cctbx/cctbx/sgtbx/rot_mx_info.cpp; sourceTree = ""; }; BFFCCC460890324D00044EBA /* rot_mx.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = rot_mx.cpp; path = ../cctbx/cctbx/sgtbx/rot_mx.cpp; sourceTree = ""; }; BFFCCC470890324D00044EBA /* row_echelon_solve.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = row_echelon_solve.cpp; path = ../cctbx/cctbx/sgtbx/row_echelon_solve.cpp; sourceTree = ""; }; BFFCCC490890324D00044EBA /* rt_mx.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = rt_mx.cpp; path = ../cctbx/cctbx/sgtbx/rt_mx.cpp; sourceTree = ""; }; BFFCCC4B0890324D00044EBA /* select_generators.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = select_generators.cpp; path = ../cctbx/cctbx/sgtbx/select_generators.cpp; sourceTree = ""; }; BFFCCC4D0890324D00044EBA /* seminvariant.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = seminvariant.cpp; path = ../cctbx/cctbx/sgtbx/seminvariant.cpp; sourceTree = ""; }; BFFCCC500890324D00044EBA /* site_symmetry.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = site_symmetry.cpp; path = ../cctbx/cctbx/sgtbx/site_symmetry.cpp; sourceTree = ""; }; BFFCCC520890324D00044EBA /* space_group_type.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = space_group_type.cpp; path = ../cctbx/cctbx/sgtbx/space_group_type.cpp; sourceTree = ""; }; BFFCCC540890324D00044EBA /* space_group.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = space_group.cpp; path = ../cctbx/cctbx/sgtbx/space_group.cpp; sourceTree = ""; }; BFFCCC570890324D00044EBA /* symbols.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = symbols.cpp; path = ../cctbx/cctbx/sgtbx/symbols.cpp; sourceTree = ""; }; BFFCCC590890324D00044EBA /* tensor_rank_2.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = tensor_rank_2.cpp; path = ../cctbx/cctbx/sgtbx/tensor_rank_2.cpp; sourceTree = ""; }; BFFCCC5A0890324D00044EBA /* tr_group.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = tr_group.cpp; path = ../cctbx/cctbx/sgtbx/tr_group.cpp; sourceTree = ""; }; BFFCCC5C0890324D00044EBA /* tr_vec.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = tr_vec.cpp; path = ../cctbx/cctbx/sgtbx/tr_vec.cpp; sourceTree = ""; }; BFFCCC5D0890324D00044EBA /* utils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = utils.cpp; path = ../cctbx/cctbx/sgtbx/utils.cpp; sourceTree = ""; }; BFFCCC5F0890324D00044EBA /* wyckoff.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = wyckoff.cpp; path = ../cctbx/cctbx/sgtbx/reference_settings/wyckoff.cpp; sourceTree = ""; }; BFFCCC600890324D00044EBA /* wyckoff.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = wyckoff.cpp; path = ../cctbx/cctbx/sgtbx/wyckoff.cpp; sourceTree = ""; }; BFFCCC930890328F00044EBA /* asu.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = asu.cpp; path = ../cctbx/cctbx/miller/asu.cpp; sourceTree = ""; }; BFFCCC940890328F00044EBA /* bins.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = bins.cpp; path = ../cctbx/cctbx/miller/bins.cpp; sourceTree = ""; }; BFFCCC950890328F00044EBA /* index_generator.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = index_generator.cpp; path = ../cctbx/cctbx/miller/index_generator.cpp; sourceTree = ""; }; BFFCCC960890328F00044EBA /* match_bijvoet_mates.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = match_bijvoet_mates.cpp; path = ../cctbx/cctbx/miller/match_bijvoet_mates.cpp; sourceTree = ""; }; BFFCCC970890328F00044EBA /* match_indices.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = match_indices.cpp; path = ../cctbx/cctbx/miller/match_indices.cpp; sourceTree = ""; }; BFFCCC980890328F00044EBA /* sym_equiv.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = sym_equiv.cpp; path = ../cctbx/cctbx/miller/sym_equiv.cpp; sourceTree = ""; }; BFFCCCC40890389700044EBA /* aligned_storage.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = aligned_storage.hpp; sourceTree = ""; }; BFFCCCC50890389700044EBA /* call_traits.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = call_traits.hpp; sourceTree = ""; }; BFFCCCC80890389700044EBA /* borland_prefix.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = borland_prefix.hpp; sourceTree = ""; }; BFFCCCC90890389700044EBA /* borland_suffix.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = borland_suffix.hpp; sourceTree = ""; }; BFFCCCCA0890389700044EBA /* msvc_prefix.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = msvc_prefix.hpp; sourceTree = ""; }; BFFCCCCB0890389700044EBA /* msvc_suffix.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = msvc_suffix.hpp; sourceTree = ""; }; BFFCCCCC0890389700044EBA /* abi_prefix.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = abi_prefix.hpp; sourceTree = ""; }; BFFCCCCD0890389700044EBA /* abi_suffix.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = abi_suffix.hpp; sourceTree = ""; }; BFFCCCCE0890389700044EBA /* auto_link.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = auto_link.hpp; sourceTree = ""; }; BFFCCCD00890389700044EBA /* borland.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = borland.hpp; sourceTree = ""; }; BFFCCCD10890389700044EBA /* comeau.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = comeau.hpp; sourceTree = ""; }; BFFCCCD20890389700044EBA /* common_edg.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = common_edg.hpp; sourceTree = ""; }; BFFCCCD30890389700044EBA /* compaq_cxx.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = compaq_cxx.hpp; sourceTree = ""; }; BFFCCCD40890389700044EBA /* digitalmars.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = digitalmars.hpp; sourceTree = ""; }; BFFCCCD50890389700044EBA /* gcc.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = gcc.hpp; sourceTree = ""; }; BFFCCCD60890389700044EBA /* greenhills.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = greenhills.hpp; sourceTree = ""; }; BFFCCCD70890389700044EBA /* hp_acc.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = hp_acc.hpp; sourceTree = ""; }; BFFCCCD80890389700044EBA /* intel.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = intel.hpp; sourceTree = ""; }; BFFCCCD90890389700044EBA /* kai.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = kai.hpp; sourceTree = ""; }; BFFCCCDA0890389700044EBA /* metrowerks.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = metrowerks.hpp; sourceTree = ""; }; BFFCCCDB0890389700044EBA /* mpw.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = mpw.hpp; sourceTree = ""; }; BFFCCCDC0890389700044EBA /* sgi_mipspro.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = sgi_mipspro.hpp; sourceTree = ""; }; BFFCCCDD0890389700044EBA /* sunpro_cc.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = sunpro_cc.hpp; sourceTree = ""; }; BFFCCCDE0890389700044EBA /* vacpp.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vacpp.hpp; sourceTree = ""; }; BFFCCCDF0890389700044EBA /* visualc.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = visualc.hpp; sourceTree = ""; }; BFFCCCE10890389700044EBA /* aix.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = aix.hpp; sourceTree = ""; }; BFFCCCE20890389700044EBA /* amigaos.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = amigaos.hpp; sourceTree = ""; }; BFFCCCE30890389700044EBA /* beos.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = beos.hpp; sourceTree = ""; }; BFFCCCE40890389700044EBA /* bsd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bsd.hpp; sourceTree = ""; }; BFFCCCE50890389700044EBA /* cygwin.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = cygwin.hpp; sourceTree = ""; }; BFFCCCE60890389700044EBA /* hpux.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = hpux.hpp; sourceTree = ""; }; BFFCCCE70890389700044EBA /* irix.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = irix.hpp; sourceTree = ""; }; BFFCCCE80890389700044EBA /* linux.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = linux.hpp; sourceTree = ""; }; BFFCCCE90890389700044EBA /* macos.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = macos.hpp; sourceTree = ""; }; BFFCCCEA0890389700044EBA /* solaris.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = solaris.hpp; sourceTree = ""; }; BFFCCCEB0890389700044EBA /* win32.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = win32.hpp; sourceTree = ""; }; BFFCCCEC0890389700044EBA /* posix_features.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = posix_features.hpp; sourceTree = ""; }; BFFCCCED0890389700044EBA /* requires_threads.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = requires_threads.hpp; sourceTree = ""; }; BFFCCCEE0890389700044EBA /* select_compiler_config.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = select_compiler_config.hpp; sourceTree = ""; }; BFFCCCEF0890389700044EBA /* select_platform_config.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = select_platform_config.hpp; sourceTree = ""; }; BFFCCCF00890389700044EBA /* select_stdlib_config.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = select_stdlib_config.hpp; sourceTree = ""; }; BFFCCCF20890389700044EBA /* dinkumware.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = dinkumware.hpp; sourceTree = ""; }; BFFCCCF30890389700044EBA /* libcomo.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = libcomo.hpp; sourceTree = ""; }; BFFCCCF40890389700044EBA /* libstdcpp3.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = libstdcpp3.hpp; sourceTree = ""; }; BFFCCCF50890389700044EBA /* modena.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = modena.hpp; sourceTree = ""; }; BFFCCCF60890389700044EBA /* msl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = msl.hpp; sourceTree = ""; }; BFFCCCF70890389700044EBA /* roguewave.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = roguewave.hpp; sourceTree = ""; }; BFFCCCF80890389700044EBA /* sgi.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = sgi.hpp; sourceTree = ""; }; BFFCCCF90890389700044EBA /* stlport.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = stlport.hpp; sourceTree = ""; }; BFFCCCFA0890389700044EBA /* vacpp.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vacpp.hpp; sourceTree = ""; }; BFFCCCFB0890389700044EBA /* suffix.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = suffix.hpp; sourceTree = ""; }; BFFCCCFC0890389700044EBA /* user.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = user.hpp; sourceTree = ""; }; BFFCCCFD0890389700044EBA /* config.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = config.hpp; sourceTree = ""; }; BFFCCCFF0890389700044EBA /* algorithm.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = algorithm.hpp; sourceTree = ""; }; BFFCCD000890389700044EBA /* allocator_utilities.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = allocator_utilities.hpp; sourceTree = ""; }; BFFCCD010890389700044EBA /* atomic_count.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = atomic_count.hpp; sourceTree = ""; }; BFFCCD020890389700044EBA /* atomic_count_gcc.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = atomic_count_gcc.hpp; sourceTree = ""; }; BFFCCD030890389700044EBA /* atomic_count_pthreads.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = atomic_count_pthreads.hpp; sourceTree = ""; }; BFFCCD040890389700044EBA /* atomic_count_win32.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = atomic_count_win32.hpp; sourceTree = ""; }; BFFCCD050890389700044EBA /* bad_weak_ptr.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bad_weak_ptr.hpp; sourceTree = ""; }; BFFCCD060890389700044EBA /* binary_search.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = binary_search.hpp; sourceTree = ""; }; BFFCCD070890389700044EBA /* call_traits.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = call_traits.hpp; sourceTree = ""; }; BFFCCD080890389700044EBA /* catch_exceptions.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = catch_exceptions.hpp; sourceTree = ""; }; BFFCCD090890389700044EBA /* compressed_pair.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = compressed_pair.hpp; sourceTree = ""; }; BFFCCD0A0890389700044EBA /* dynamic_bitset.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = dynamic_bitset.hpp; sourceTree = ""; }; BFFCCD0B0890389700044EBA /* indirect_traits.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = indirect_traits.hpp; sourceTree = ""; }; BFFCCD0C0890389700044EBA /* interlocked.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = interlocked.hpp; sourceTree = ""; }; BFFCCD0D0890389700044EBA /* is_function_ref_tester.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_function_ref_tester.hpp; sourceTree = ""; }; BFFCCD0E0890389700044EBA /* is_incrementable.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_incrementable.hpp; sourceTree = ""; }; BFFCCD0F0890389700044EBA /* iterator.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iterator.hpp; sourceTree = ""; }; BFFCCD100890389700044EBA /* lightweight_mutex.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lightweight_mutex.hpp; sourceTree = ""; }; BFFCCD110890389700044EBA /* lightweight_test.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lightweight_test.hpp; sourceTree = ""; }; BFFCCD120890389700044EBA /* limits.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = limits.hpp; sourceTree = ""; }; BFFCCD130890389700044EBA /* lwm_nop.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lwm_nop.hpp; sourceTree = ""; }; BFFCCD140890389700044EBA /* lwm_pthreads.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lwm_pthreads.hpp; sourceTree = ""; }; BFFCCD150890389700044EBA /* lwm_win32_cs.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lwm_win32_cs.hpp; sourceTree = ""; }; BFFCCD160890389700044EBA /* named_template_params.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = named_template_params.hpp; sourceTree = ""; }; BFFCCD170890389700044EBA /* no_exceptions_support.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = no_exceptions_support.hpp; sourceTree = ""; }; BFFCCD180890389700044EBA /* none_t.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = none_t.hpp; sourceTree = ""; }; BFFCCD190890389700044EBA /* numeric_traits.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = numeric_traits.hpp; sourceTree = ""; }; BFFCCD1A0890389700044EBA /* ob_call_traits.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = ob_call_traits.hpp; sourceTree = ""; }; BFFCCD1B0890389700044EBA /* ob_compressed_pair.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = ob_compressed_pair.hpp; sourceTree = ""; }; BFFCCD1C0890389700044EBA /* quick_allocator.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = quick_allocator.hpp; sourceTree = ""; }; BFFCCD1D0890389700044EBA /* reference_content.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reference_content.hpp; sourceTree = ""; }; BFFCCD1E0890389700044EBA /* select_type.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = select_type.hpp; sourceTree = ""; }; BFFCCD1F0890389700044EBA /* shared_array_nmt.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shared_array_nmt.hpp; sourceTree = ""; }; BFFCCD200890389700044EBA /* shared_count.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shared_count.hpp; sourceTree = ""; }; BFFCCD210890389700044EBA /* shared_ptr_nmt.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shared_ptr_nmt.hpp; sourceTree = ""; }; BFFCCD220890389700044EBA /* sp_counted_base.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = sp_counted_base.hpp; sourceTree = ""; }; BFFCCD230890389700044EBA /* sp_counted_base_cw_ppc.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = sp_counted_base_cw_ppc.hpp; sourceTree = ""; }; BFFCCD240890389700044EBA /* sp_counted_base_gcc_ia64.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = sp_counted_base_gcc_ia64.hpp; sourceTree = ""; }; BFFCCD250890389700044EBA /* sp_counted_base_gcc_ppc.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = sp_counted_base_gcc_ppc.hpp; sourceTree = ""; }; BFFCCD260890389800044EBA /* sp_counted_base_gcc_x86.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = sp_counted_base_gcc_x86.hpp; sourceTree = ""; }; BFFCCD270890389800044EBA /* sp_counted_base_nt.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = sp_counted_base_nt.hpp; sourceTree = ""; }; BFFCCD280890389800044EBA /* sp_counted_base_pt.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = sp_counted_base_pt.hpp; sourceTree = ""; }; BFFCCD290890389800044EBA /* sp_counted_base_w32.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = sp_counted_base_w32.hpp; sourceTree = ""; }; BFFCCD2A0890389800044EBA /* sp_counted_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = sp_counted_impl.hpp; sourceTree = ""; }; BFFCCD2B0890389800044EBA /* templated_streams.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = templated_streams.hpp; sourceTree = ""; }; BFFCCD2C0890389800044EBA /* utf8_codecvt_facet.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = utf8_codecvt_facet.hpp; sourceTree = ""; }; BFFCCD2D0890389800044EBA /* workaround.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = workaround.hpp; sourceTree = ""; }; BFFCCD470890389800044EBA /* iterator.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iterator.hpp; sourceTree = ""; }; BFFCCD490890389800044EBA /* common_factor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = common_factor.hpp; sourceTree = ""; }; BFFCCD4A0890389800044EBA /* common_factor_ct.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = common_factor_ct.hpp; sourceTree = ""; }; BFFCCD4B0890389800044EBA /* common_factor_rt.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = common_factor_rt.hpp; sourceTree = ""; }; BFFCCD4C0890389800044EBA /* octonion.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = octonion.hpp; sourceTree = ""; }; BFFCCD4D0890389800044EBA /* quaternion.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = quaternion.hpp; sourceTree = ""; }; BFFCCD4F0890389800044EBA /* acosh.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = acosh.hpp; sourceTree = ""; }; BFFCCD500890389800044EBA /* asinh.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = asinh.hpp; sourceTree = ""; }; BFFCCD510890389800044EBA /* atanh.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = atanh.hpp; sourceTree = ""; }; BFFCCD520890389800044EBA /* sinc.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = sinc.hpp; sourceTree = ""; }; BFFCCD530890389800044EBA /* sinhc.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = sinhc.hpp; sourceTree = ""; }; BFFCCD550890389800044EBA /* accumulate.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = accumulate.hpp; sourceTree = ""; }; BFFCCD560890389800044EBA /* advance.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = advance.hpp; sourceTree = ""; }; BFFCCD570890389800044EBA /* advance_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = advance_fwd.hpp; sourceTree = ""; }; BFFCCD580890389800044EBA /* alias.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = alias.hpp; sourceTree = ""; }; BFFCCD590890389800044EBA /* always.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = always.hpp; sourceTree = ""; }; BFFCCD5A0890389800044EBA /* and.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = and.hpp; sourceTree = ""; }; BFFCCD5B0890389800044EBA /* apply.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply.hpp; sourceTree = ""; }; BFFCCD5C0890389800044EBA /* apply_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply_fwd.hpp; sourceTree = ""; }; BFFCCD5D0890389800044EBA /* apply_wrap.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply_wrap.hpp; sourceTree = ""; }; BFFCCD5E0890389800044EBA /* arg.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = arg.hpp; sourceTree = ""; }; BFFCCD5F0890389800044EBA /* arg_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = arg_fwd.hpp; sourceTree = ""; }; BFFCCD600890389800044EBA /* arithmetic.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = arithmetic.hpp; sourceTree = ""; }; BFFCCD610890389800044EBA /* as_sequence.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = as_sequence.hpp; sourceTree = ""; }; BFFCCD620890389800044EBA /* assert.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = assert.hpp; sourceTree = ""; }; BFFCCD630890389800044EBA /* at.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = at.hpp; sourceTree = ""; }; BFFCCD640890389800044EBA /* at_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = at_fwd.hpp; sourceTree = ""; }; BFFCCD660890389800044EBA /* adl_barrier.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = adl_barrier.hpp; sourceTree = ""; }; BFFCCD670890389800044EBA /* advance_backward.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = advance_backward.hpp; sourceTree = ""; }; BFFCCD680890389800044EBA /* advance_forward.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = advance_forward.hpp; sourceTree = ""; }; BFFCCD690890389800044EBA /* apply_1st.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply_1st.hpp; sourceTree = ""; }; BFFCCD6A0890389800044EBA /* arg_typedef.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = arg_typedef.hpp; sourceTree = ""; }; BFFCCD6B0890389800044EBA /* arithmetic_op.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = arithmetic_op.hpp; sourceTree = ""; }; BFFCCD6C0890389800044EBA /* arity.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = arity.hpp; sourceTree = ""; }; BFFCCD6D0890389800044EBA /* arity_spec.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = arity_spec.hpp; sourceTree = ""; }; BFFCCD6E0890389800044EBA /* at_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = at_impl.hpp; sourceTree = ""; }; BFFCCD6F0890389800044EBA /* back_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = back_impl.hpp; sourceTree = ""; }; BFFCCD700890389800044EBA /* basic_bind.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = basic_bind.hpp; sourceTree = ""; }; BFFCCD710890389800044EBA /* begin_end_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = begin_end_impl.hpp; sourceTree = ""; }; BFFCCD720890389800044EBA /* clear_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = clear_impl.hpp; sourceTree = ""; }; BFFCCD730890389800044EBA /* common_name_wknd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = common_name_wknd.hpp; sourceTree = ""; }; BFFCCD740890389800044EBA /* comparison_op.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = comparison_op.hpp; sourceTree = ""; }; BFFCCD760890389800044EBA /* adl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = adl.hpp; sourceTree = ""; }; BFFCCD770890389800044EBA /* arrays.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = arrays.hpp; sourceTree = ""; }; BFFCCD780890389800044EBA /* bind.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bind.hpp; sourceTree = ""; }; BFFCCD790890389800044EBA /* compiler.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = compiler.hpp; sourceTree = ""; }; BFFCCD7A0890389800044EBA /* ctps.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = ctps.hpp; sourceTree = ""; }; BFFCCD7B0890389800044EBA /* dependent_nttp.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = dependent_nttp.hpp; sourceTree = ""; }; BFFCCD7C0890389800044EBA /* dmc_ambiguous_ctps.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = dmc_ambiguous_ctps.hpp; sourceTree = ""; }; BFFCCD7D0890389800044EBA /* dtp.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = dtp.hpp; sourceTree = ""; }; BFFCCD7E0890389800044EBA /* eti.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = eti.hpp; sourceTree = ""; }; BFFCCD7F0890389800044EBA /* forwarding.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = forwarding.hpp; sourceTree = ""; }; BFFCCD800890389800044EBA /* gcc.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = gcc.hpp; sourceTree = ""; }; BFFCCD810890389800044EBA /* has_apply.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = has_apply.hpp; sourceTree = ""; }; BFFCCD820890389800044EBA /* has_xxx.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = has_xxx.hpp; sourceTree = ""; }; BFFCCD830890389800044EBA /* integral.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = integral.hpp; sourceTree = ""; }; BFFCCD840890389800044EBA /* intel.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = intel.hpp; sourceTree = ""; }; BFFCCD850890389800044EBA /* lambda.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lambda.hpp; sourceTree = ""; }; BFFCCD860890389800044EBA /* msvc.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = msvc.hpp; sourceTree = ""; }; BFFCCD870890389800044EBA /* msvc_typename.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = msvc_typename.hpp; sourceTree = ""; }; BFFCCD880890389800044EBA /* nttp.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = nttp.hpp; sourceTree = ""; }; BFFCCD890890389800044EBA /* operators.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = operators.hpp; sourceTree = ""; }; BFFCCD8A0890389800044EBA /* overload_resolution.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = overload_resolution.hpp; sourceTree = ""; }; BFFCCD8B0890389800044EBA /* preprocessor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = preprocessor.hpp; sourceTree = ""; }; BFFCCD8C0890389800044EBA /* static_constant.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = static_constant.hpp; sourceTree = ""; }; BFFCCD8D0890389800044EBA /* ttp.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = ttp.hpp; sourceTree = ""; }; BFFCCD8E0890389800044EBA /* typeof.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = typeof.hpp; sourceTree = ""; }; BFFCCD8F0890389800044EBA /* use_preprocessed.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = use_preprocessed.hpp; sourceTree = ""; }; BFFCCD900890389800044EBA /* workaround.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = workaround.hpp; sourceTree = ""; }; BFFCCD910890389900044EBA /* contains_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = contains_impl.hpp; sourceTree = ""; }; BFFCCD920890389900044EBA /* count_args.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = count_args.hpp; sourceTree = ""; }; BFFCCD930890389900044EBA /* count_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = count_impl.hpp; sourceTree = ""; }; BFFCCD940890389900044EBA /* empty_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = empty_impl.hpp; sourceTree = ""; }; BFFCCD950890389900044EBA /* erase_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = erase_impl.hpp; sourceTree = ""; }; BFFCCD960890389900044EBA /* erase_key_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = erase_key_impl.hpp; sourceTree = ""; }; BFFCCD970890389900044EBA /* filter_iter.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = filter_iter.hpp; sourceTree = ""; }; BFFCCD980890389900044EBA /* find_if_pred.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = find_if_pred.hpp; sourceTree = ""; }; BFFCCD990890389900044EBA /* fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = fold_impl.hpp; sourceTree = ""; }; BFFCCD9A0890389900044EBA /* fold_impl_body.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = fold_impl_body.hpp; sourceTree = ""; }; BFFCCD9B0890389900044EBA /* fold_op.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = fold_op.hpp; sourceTree = ""; }; BFFCCD9C0890389900044EBA /* fold_pred.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = fold_pred.hpp; sourceTree = ""; }; BFFCCD9D0890389900044EBA /* front_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = front_impl.hpp; sourceTree = ""; }; BFFCCD9E0890389900044EBA /* full_lambda.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = full_lambda.hpp; sourceTree = ""; }; BFFCCD9F0890389900044EBA /* has_apply.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = has_apply.hpp; sourceTree = ""; }; BFFCCDA00890389900044EBA /* has_begin.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = has_begin.hpp; sourceTree = ""; }; BFFCCDA10890389900044EBA /* has_key_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = has_key_impl.hpp; sourceTree = ""; }; BFFCCDA20890389900044EBA /* has_rebind.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = has_rebind.hpp; sourceTree = ""; }; BFFCCDA30890389900044EBA /* has_size.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = has_size.hpp; sourceTree = ""; }; BFFCCDA40890389900044EBA /* has_tag.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = has_tag.hpp; sourceTree = ""; }; BFFCCDA50890389900044EBA /* has_type.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = has_type.hpp; sourceTree = ""; }; BFFCCDA60890389900044EBA /* include_preprocessed.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = include_preprocessed.hpp; sourceTree = ""; }; BFFCCDA70890389900044EBA /* insert_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = insert_impl.hpp; sourceTree = ""; }; BFFCCDA80890389900044EBA /* insert_range_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = insert_range_impl.hpp; sourceTree = ""; }; BFFCCDA90890389900044EBA /* inserter_algorithm.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = inserter_algorithm.hpp; sourceTree = ""; }; BFFCCDAA0890389900044EBA /* integral_wrapper.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = integral_wrapper.hpp; sourceTree = ""; }; BFFCCDAB0890389900044EBA /* is_msvc_eti_arg.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_msvc_eti_arg.hpp; sourceTree = ""; }; BFFCCDAC0890389900044EBA /* iter_apply.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_apply.hpp; sourceTree = ""; }; BFFCCDAD0890389900044EBA /* iter_fold_if_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_fold_if_impl.hpp; sourceTree = ""; }; BFFCCDAE0890389900044EBA /* iter_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_fold_impl.hpp; sourceTree = ""; }; BFFCCDAF0890389900044EBA /* iter_push_front.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_push_front.hpp; sourceTree = ""; }; BFFCCDB00890389900044EBA /* joint_iter.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = joint_iter.hpp; sourceTree = ""; }; BFFCCDB10890389900044EBA /* lambda_arity_param.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lambda_arity_param.hpp; sourceTree = ""; }; BFFCCDB20890389900044EBA /* lambda_no_ctps.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lambda_no_ctps.hpp; sourceTree = ""; }; BFFCCDB30890389900044EBA /* lambda_spec.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lambda_spec.hpp; sourceTree = ""; }; BFFCCDB40890389900044EBA /* lambda_support.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lambda_support.hpp; sourceTree = ""; }; BFFCCDB50890389900044EBA /* largest_int.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = largest_int.hpp; sourceTree = ""; }; BFFCCDB60890389900044EBA /* logical_op.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = logical_op.hpp; sourceTree = ""; }; BFFCCDB70890389900044EBA /* msvc_dtw.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = msvc_dtw.hpp; sourceTree = ""; }; BFFCCDB80890389900044EBA /* msvc_eti_base.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = msvc_eti_base.hpp; sourceTree = ""; }; BFFCCDB90890389900044EBA /* msvc_is_class.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = msvc_is_class.hpp; sourceTree = ""; }; BFFCCDBA0890389900044EBA /* msvc_never_true.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = msvc_never_true.hpp; sourceTree = ""; }; BFFCCDBB0890389900044EBA /* msvc_type.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = msvc_type.hpp; sourceTree = ""; }; BFFCCDBC0890389900044EBA /* na.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = na.hpp; sourceTree = ""; }; BFFCCDBD0890389900044EBA /* na_assert.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = na_assert.hpp; sourceTree = ""; }; BFFCCDBE0890389900044EBA /* na_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = na_fwd.hpp; sourceTree = ""; }; BFFCCDBF0890389900044EBA /* na_spec.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = na_spec.hpp; sourceTree = ""; }; BFFCCDC00890389900044EBA /* nested_type_wknd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = nested_type_wknd.hpp; sourceTree = ""; }; BFFCCDC10890389900044EBA /* nttp_decl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = nttp_decl.hpp; sourceTree = ""; }; BFFCCDC20890389900044EBA /* numeric_cast_utils.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = numeric_cast_utils.hpp; sourceTree = ""; }; BFFCCDC30890389900044EBA /* numeric_op.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = numeric_op.hpp; sourceTree = ""; }; BFFCCDC40890389900044EBA /* O1_size_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = O1_size_impl.hpp; sourceTree = ""; }; BFFCCDC50890389900044EBA /* order_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = order_impl.hpp; sourceTree = ""; }; BFFCCDC60890389900044EBA /* overload_names.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = overload_names.hpp; sourceTree = ""; }; BFFCCDC70890389900044EBA /* partition_op.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = partition_op.hpp; sourceTree = ""; }; BFFCCDC80890389900044EBA /* pop_back_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = pop_back_impl.hpp; sourceTree = ""; }; BFFCCDC90890389900044EBA /* pop_front_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = pop_front_impl.hpp; sourceTree = ""; }; BFFCCDCC0890389900044EBA /* advance_backward.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = advance_backward.hpp; sourceTree = ""; }; BFFCCDCD0890389900044EBA /* advance_forward.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = advance_forward.hpp; sourceTree = ""; }; BFFCCDCE0890389900044EBA /* and.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = and.hpp; sourceTree = ""; }; BFFCCDCF0890389900044EBA /* apply.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply.hpp; sourceTree = ""; }; BFFCCDD00890389900044EBA /* apply_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply_fwd.hpp; sourceTree = ""; }; BFFCCDD10890389900044EBA /* apply_wrap.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply_wrap.hpp; sourceTree = ""; }; BFFCCDD20890389900044EBA /* arg.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = arg.hpp; sourceTree = ""; }; BFFCCDD30890389900044EBA /* basic_bind.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = basic_bind.hpp; sourceTree = ""; }; BFFCCDD40890389900044EBA /* bind.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bind.hpp; sourceTree = ""; }; BFFCCDD50890389900044EBA /* bind_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bind_fwd.hpp; sourceTree = ""; }; BFFCCDD60890389900044EBA /* bitand.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitand.hpp; sourceTree = ""; }; BFFCCDD70890389900044EBA /* bitor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitor.hpp; sourceTree = ""; }; BFFCCDD80890389900044EBA /* bitxor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitxor.hpp; sourceTree = ""; }; BFFCCDD90890389900044EBA /* deque.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = deque.hpp; sourceTree = ""; }; BFFCCDDA0890389900044EBA /* divides.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = divides.hpp; sourceTree = ""; }; BFFCCDDB0890389900044EBA /* equal_to.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = equal_to.hpp; sourceTree = ""; }; BFFCCDDC0890389900044EBA /* fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = fold_impl.hpp; sourceTree = ""; }; BFFCCDDD0890389900044EBA /* full_lambda.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = full_lambda.hpp; sourceTree = ""; }; BFFCCDDE0890389900044EBA /* greater.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = greater.hpp; sourceTree = ""; }; BFFCCDDF0890389900044EBA /* greater_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = greater_equal.hpp; sourceTree = ""; }; BFFCCDE00890389900044EBA /* inherit.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = inherit.hpp; sourceTree = ""; }; BFFCCDE10890389900044EBA /* iter_fold_if_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_fold_if_impl.hpp; sourceTree = ""; }; BFFCCDE20890389900044EBA /* iter_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_fold_impl.hpp; sourceTree = ""; }; BFFCCDE30890389900044EBA /* lambda_no_ctps.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lambda_no_ctps.hpp; sourceTree = ""; }; BFFCCDE40890389900044EBA /* less.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = less.hpp; sourceTree = ""; }; BFFCCDE50890389900044EBA /* less_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = less_equal.hpp; sourceTree = ""; }; BFFCCDE60890389900044EBA /* list.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list.hpp; sourceTree = ""; }; BFFCCDE70890389900044EBA /* list_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list_c.hpp; sourceTree = ""; }; BFFCCDE80890389900044EBA /* map.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map.hpp; sourceTree = ""; }; BFFCCDE90890389900044EBA /* minus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = minus.hpp; sourceTree = ""; }; BFFCCDEA0890389900044EBA /* modulus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = modulus.hpp; sourceTree = ""; }; BFFCCDEB0890389900044EBA /* not_equal_to.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = not_equal_to.hpp; sourceTree = ""; }; BFFCCDEC0890389900044EBA /* or.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = or.hpp; sourceTree = ""; }; BFFCCDED0890389900044EBA /* placeholders.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = placeholders.hpp; sourceTree = ""; }; BFFCCDEE0890389900044EBA /* plus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = plus.hpp; sourceTree = ""; }; BFFCCDEF0890389900044EBA /* quote.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = quote.hpp; sourceTree = ""; }; BFFCCDF00890389900044EBA /* reverse_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse_fold_impl.hpp; sourceTree = ""; }; BFFCCDF10890389900044EBA /* reverse_iter_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse_iter_fold_impl.hpp; sourceTree = ""; }; BFFCCDF20890389900044EBA /* set.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set.hpp; sourceTree = ""; }; BFFCCDF30890389900044EBA /* set_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set_c.hpp; sourceTree = ""; }; BFFCCDF40890389900044EBA /* shift_left.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shift_left.hpp; sourceTree = ""; }; BFFCCDF50890389900044EBA /* shift_right.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shift_right.hpp; sourceTree = ""; }; BFFCCDF60890389900044EBA /* template_arity.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = template_arity.hpp; sourceTree = ""; }; BFFCCDF70890389900044EBA /* times.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = times.hpp; sourceTree = ""; }; BFFCCDF80890389900044EBA /* unpack_args.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = unpack_args.hpp; sourceTree = ""; }; BFFCCDF90890389900044EBA /* vector.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector.hpp; sourceTree = ""; }; BFFCCDFA0890389900044EBA /* vector_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector_c.hpp; sourceTree = ""; }; BFFCCDFC0890389900044EBA /* advance_backward.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = advance_backward.hpp; sourceTree = ""; }; BFFCCDFD0890389900044EBA /* advance_forward.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = advance_forward.hpp; sourceTree = ""; }; BFFCCDFE0890389900044EBA /* and.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = and.hpp; sourceTree = ""; }; BFFCCDFF0890389900044EBA /* apply.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply.hpp; sourceTree = ""; }; BFFCCE000890389900044EBA /* apply_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply_fwd.hpp; sourceTree = ""; }; BFFCCE010890389A00044EBA /* apply_wrap.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply_wrap.hpp; sourceTree = ""; }; BFFCCE020890389A00044EBA /* arg.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = arg.hpp; sourceTree = ""; }; BFFCCE030890389A00044EBA /* basic_bind.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = basic_bind.hpp; sourceTree = ""; }; BFFCCE040890389A00044EBA /* bind.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bind.hpp; sourceTree = ""; }; BFFCCE050890389A00044EBA /* bind_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bind_fwd.hpp; sourceTree = ""; }; BFFCCE060890389A00044EBA /* bitand.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitand.hpp; sourceTree = ""; }; BFFCCE070890389A00044EBA /* bitor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitor.hpp; sourceTree = ""; }; BFFCCE080890389A00044EBA /* bitxor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitxor.hpp; sourceTree = ""; }; BFFCCE090890389A00044EBA /* deque.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = deque.hpp; sourceTree = ""; }; BFFCCE0A0890389A00044EBA /* divides.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = divides.hpp; sourceTree = ""; }; BFFCCE0B0890389A00044EBA /* equal_to.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = equal_to.hpp; sourceTree = ""; }; BFFCCE0C0890389A00044EBA /* fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = fold_impl.hpp; sourceTree = ""; }; BFFCCE0D0890389A00044EBA /* full_lambda.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = full_lambda.hpp; sourceTree = ""; }; BFFCCE0E0890389A00044EBA /* greater.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = greater.hpp; sourceTree = ""; }; BFFCCE0F0890389A00044EBA /* greater_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = greater_equal.hpp; sourceTree = ""; }; BFFCCE100890389A00044EBA /* inherit.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = inherit.hpp; sourceTree = ""; }; BFFCCE110890389A00044EBA /* iter_fold_if_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_fold_if_impl.hpp; sourceTree = ""; }; BFFCCE120890389A00044EBA /* iter_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_fold_impl.hpp; sourceTree = ""; }; BFFCCE130890389A00044EBA /* lambda_no_ctps.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lambda_no_ctps.hpp; sourceTree = ""; }; BFFCCE140890389A00044EBA /* less.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = less.hpp; sourceTree = ""; }; BFFCCE150890389A00044EBA /* less_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = less_equal.hpp; sourceTree = ""; }; BFFCCE160890389A00044EBA /* list.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list.hpp; sourceTree = ""; }; BFFCCE170890389A00044EBA /* list_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list_c.hpp; sourceTree = ""; }; BFFCCE180890389A00044EBA /* map.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map.hpp; sourceTree = ""; }; BFFCCE190890389A00044EBA /* minus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = minus.hpp; sourceTree = ""; }; BFFCCE1A0890389A00044EBA /* modulus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = modulus.hpp; sourceTree = ""; }; BFFCCE1B0890389A00044EBA /* not_equal_to.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = not_equal_to.hpp; sourceTree = ""; }; BFFCCE1C0890389A00044EBA /* or.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = or.hpp; sourceTree = ""; }; BFFCCE1D0890389A00044EBA /* placeholders.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = placeholders.hpp; sourceTree = ""; }; BFFCCE1E0890389A00044EBA /* plus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = plus.hpp; sourceTree = ""; }; BFFCCE1F0890389A00044EBA /* quote.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = quote.hpp; sourceTree = ""; }; BFFCCE200890389A00044EBA /* reverse_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse_fold_impl.hpp; sourceTree = ""; }; BFFCCE210890389A00044EBA /* reverse_iter_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse_iter_fold_impl.hpp; sourceTree = ""; }; BFFCCE220890389A00044EBA /* set.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set.hpp; sourceTree = ""; }; BFFCCE230890389A00044EBA /* set_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set_c.hpp; sourceTree = ""; }; BFFCCE240890389A00044EBA /* shift_left.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shift_left.hpp; sourceTree = ""; }; BFFCCE250890389A00044EBA /* shift_right.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shift_right.hpp; sourceTree = ""; }; BFFCCE260890389A00044EBA /* template_arity.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = template_arity.hpp; sourceTree = ""; }; BFFCCE270890389A00044EBA /* times.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = times.hpp; sourceTree = ""; }; BFFCCE280890389A00044EBA /* unpack_args.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = unpack_args.hpp; sourceTree = ""; }; BFFCCE290890389A00044EBA /* vector.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector.hpp; sourceTree = ""; }; BFFCCE2A0890389A00044EBA /* vector_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector_c.hpp; sourceTree = ""; }; BFFCCE2C0890389A00044EBA /* advance_backward.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = advance_backward.hpp; sourceTree = ""; }; BFFCCE2D0890389A00044EBA /* advance_forward.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = advance_forward.hpp; sourceTree = ""; }; BFFCCE2E0890389A00044EBA /* and.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = and.hpp; sourceTree = ""; }; BFFCCE2F0890389A00044EBA /* apply.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply.hpp; sourceTree = ""; }; BFFCCE300890389A00044EBA /* apply_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply_fwd.hpp; sourceTree = ""; }; BFFCCE310890389A00044EBA /* apply_wrap.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply_wrap.hpp; sourceTree = ""; }; BFFCCE320890389A00044EBA /* arg.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = arg.hpp; sourceTree = ""; }; BFFCCE330890389A00044EBA /* basic_bind.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = basic_bind.hpp; sourceTree = ""; }; BFFCCE340890389A00044EBA /* bind.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bind.hpp; sourceTree = ""; }; BFFCCE350890389A00044EBA /* bind_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bind_fwd.hpp; sourceTree = ""; }; BFFCCE360890389A00044EBA /* bitand.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitand.hpp; sourceTree = ""; }; BFFCCE370890389A00044EBA /* bitor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitor.hpp; sourceTree = ""; }; BFFCCE380890389A00044EBA /* bitxor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitxor.hpp; sourceTree = ""; }; BFFCCE390890389A00044EBA /* deque.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = deque.hpp; sourceTree = ""; }; BFFCCE3A0890389A00044EBA /* divides.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = divides.hpp; sourceTree = ""; }; BFFCCE3B0890389A00044EBA /* equal_to.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = equal_to.hpp; sourceTree = ""; }; BFFCCE3C0890389A00044EBA /* fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = fold_impl.hpp; sourceTree = ""; }; BFFCCE3D0890389A00044EBA /* full_lambda.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = full_lambda.hpp; sourceTree = ""; }; BFFCCE3E0890389A00044EBA /* greater.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = greater.hpp; sourceTree = ""; }; BFFCCE3F0890389A00044EBA /* greater_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = greater_equal.hpp; sourceTree = ""; }; BFFCCE400890389A00044EBA /* inherit.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = inherit.hpp; sourceTree = ""; }; BFFCCE410890389A00044EBA /* iter_fold_if_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_fold_if_impl.hpp; sourceTree = ""; }; BFFCCE420890389A00044EBA /* iter_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_fold_impl.hpp; sourceTree = ""; }; BFFCCE430890389A00044EBA /* lambda_no_ctps.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lambda_no_ctps.hpp; sourceTree = ""; }; BFFCCE440890389A00044EBA /* less.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = less.hpp; sourceTree = ""; }; BFFCCE450890389A00044EBA /* less_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = less_equal.hpp; sourceTree = ""; }; BFFCCE460890389A00044EBA /* list.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list.hpp; sourceTree = ""; }; BFFCCE470890389A00044EBA /* list_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list_c.hpp; sourceTree = ""; }; BFFCCE480890389A00044EBA /* map.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map.hpp; sourceTree = ""; }; BFFCCE490890389A00044EBA /* minus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = minus.hpp; sourceTree = ""; }; BFFCCE4A0890389A00044EBA /* modulus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = modulus.hpp; sourceTree = ""; }; BFFCCE4B0890389A00044EBA /* not_equal_to.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = not_equal_to.hpp; sourceTree = ""; }; BFFCCE4C0890389A00044EBA /* or.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = or.hpp; sourceTree = ""; }; BFFCCE4D0890389A00044EBA /* placeholders.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = placeholders.hpp; sourceTree = ""; }; BFFCCE4E0890389A00044EBA /* plus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = plus.hpp; sourceTree = ""; }; BFFCCE4F0890389A00044EBA /* quote.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = quote.hpp; sourceTree = ""; }; BFFCCE500890389A00044EBA /* reverse_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse_fold_impl.hpp; sourceTree = ""; }; BFFCCE510890389A00044EBA /* reverse_iter_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse_iter_fold_impl.hpp; sourceTree = ""; }; BFFCCE520890389A00044EBA /* set.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set.hpp; sourceTree = ""; }; BFFCCE530890389A00044EBA /* set_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set_c.hpp; sourceTree = ""; }; BFFCCE540890389A00044EBA /* shift_left.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shift_left.hpp; sourceTree = ""; }; BFFCCE550890389A00044EBA /* shift_right.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shift_right.hpp; sourceTree = ""; }; BFFCCE560890389A00044EBA /* template_arity.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = template_arity.hpp; sourceTree = ""; }; BFFCCE570890389A00044EBA /* times.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = times.hpp; sourceTree = ""; }; BFFCCE580890389A00044EBA /* unpack_args.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = unpack_args.hpp; sourceTree = ""; }; BFFCCE590890389A00044EBA /* vector.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector.hpp; sourceTree = ""; }; BFFCCE5A0890389A00044EBA /* vector_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector_c.hpp; sourceTree = ""; }; BFFCCE5C0890389A00044EBA /* advance_backward.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = advance_backward.hpp; sourceTree = ""; }; BFFCCE5D0890389A00044EBA /* advance_forward.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = advance_forward.hpp; sourceTree = ""; }; BFFCCE5E0890389A00044EBA /* and.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = and.hpp; sourceTree = ""; }; BFFCCE5F0890389A00044EBA /* apply.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply.hpp; sourceTree = ""; }; BFFCCE600890389A00044EBA /* apply_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply_fwd.hpp; sourceTree = ""; }; BFFCCE610890389A00044EBA /* apply_wrap.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply_wrap.hpp; sourceTree = ""; }; BFFCCE620890389A00044EBA /* arg.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = arg.hpp; sourceTree = ""; }; BFFCCE630890389A00044EBA /* basic_bind.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = basic_bind.hpp; sourceTree = ""; }; BFFCCE640890389A00044EBA /* bind.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bind.hpp; sourceTree = ""; }; BFFCCE650890389A00044EBA /* bind_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bind_fwd.hpp; sourceTree = ""; }; BFFCCE660890389A00044EBA /* bitand.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitand.hpp; sourceTree = ""; }; BFFCCE670890389A00044EBA /* bitor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitor.hpp; sourceTree = ""; }; BFFCCE680890389A00044EBA /* bitxor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitxor.hpp; sourceTree = ""; }; BFFCCE690890389A00044EBA /* deque.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = deque.hpp; sourceTree = ""; }; BFFCCE6A0890389A00044EBA /* divides.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = divides.hpp; sourceTree = ""; }; BFFCCE6B0890389A00044EBA /* equal_to.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = equal_to.hpp; sourceTree = ""; }; BFFCCE6C0890389A00044EBA /* fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = fold_impl.hpp; sourceTree = ""; }; BFFCCE6D0890389A00044EBA /* full_lambda.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = full_lambda.hpp; sourceTree = ""; }; BFFCCE6E0890389A00044EBA /* greater.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = greater.hpp; sourceTree = ""; }; BFFCCE6F0890389A00044EBA /* greater_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = greater_equal.hpp; sourceTree = ""; }; BFFCCE700890389A00044EBA /* inherit.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = inherit.hpp; sourceTree = ""; }; BFFCCE710890389A00044EBA /* iter_fold_if_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_fold_if_impl.hpp; sourceTree = ""; }; BFFCCE720890389A00044EBA /* iter_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_fold_impl.hpp; sourceTree = ""; }; BFFCCE730890389A00044EBA /* lambda_no_ctps.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lambda_no_ctps.hpp; sourceTree = ""; }; BFFCCE740890389A00044EBA /* less.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = less.hpp; sourceTree = ""; }; BFFCCE750890389A00044EBA /* less_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = less_equal.hpp; sourceTree = ""; }; BFFCCE760890389A00044EBA /* list.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list.hpp; sourceTree = ""; }; BFFCCE770890389A00044EBA /* list_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list_c.hpp; sourceTree = ""; }; BFFCCE780890389A00044EBA /* map.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map.hpp; sourceTree = ""; }; BFFCCE790890389A00044EBA /* minus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = minus.hpp; sourceTree = ""; }; BFFCCE7A0890389A00044EBA /* modulus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = modulus.hpp; sourceTree = ""; }; BFFCCE7B0890389A00044EBA /* not_equal_to.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = not_equal_to.hpp; sourceTree = ""; }; BFFCCE7C0890389A00044EBA /* or.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = or.hpp; sourceTree = ""; }; BFFCCE7D0890389A00044EBA /* placeholders.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = placeholders.hpp; sourceTree = ""; }; BFFCCE7E0890389A00044EBA /* plus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = plus.hpp; sourceTree = ""; }; BFFCCE7F0890389A00044EBA /* quote.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = quote.hpp; sourceTree = ""; }; BFFCCE800890389A00044EBA /* reverse_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse_fold_impl.hpp; sourceTree = ""; }; BFFCCE810890389A00044EBA /* reverse_iter_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse_iter_fold_impl.hpp; sourceTree = ""; }; BFFCCE820890389A00044EBA /* set.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set.hpp; sourceTree = ""; }; BFFCCE830890389A00044EBA /* set_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set_c.hpp; sourceTree = ""; }; BFFCCE840890389A00044EBA /* shift_left.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shift_left.hpp; sourceTree = ""; }; BFFCCE850890389A00044EBA /* shift_right.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shift_right.hpp; sourceTree = ""; }; BFFCCE860890389A00044EBA /* template_arity.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = template_arity.hpp; sourceTree = ""; }; BFFCCE870890389B00044EBA /* times.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = times.hpp; sourceTree = ""; }; BFFCCE880890389B00044EBA /* unpack_args.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = unpack_args.hpp; sourceTree = ""; }; BFFCCE890890389B00044EBA /* vector.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector.hpp; sourceTree = ""; }; BFFCCE8A0890389B00044EBA /* vector_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector_c.hpp; sourceTree = ""; }; BFFCCE8C0890389B00044EBA /* advance_backward.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = advance_backward.hpp; sourceTree = ""; }; BFFCCE8D0890389B00044EBA /* advance_forward.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = advance_forward.hpp; sourceTree = ""; }; BFFCCE8E0890389B00044EBA /* and.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = and.hpp; sourceTree = ""; }; BFFCCE8F0890389B00044EBA /* apply.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply.hpp; sourceTree = ""; }; BFFCCE900890389B00044EBA /* apply_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply_fwd.hpp; sourceTree = ""; }; BFFCCE910890389B00044EBA /* apply_wrap.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply_wrap.hpp; sourceTree = ""; }; BFFCCE920890389B00044EBA /* arg.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = arg.hpp; sourceTree = ""; }; BFFCCE930890389B00044EBA /* basic_bind.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = basic_bind.hpp; sourceTree = ""; }; BFFCCE940890389B00044EBA /* bind.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bind.hpp; sourceTree = ""; }; BFFCCE950890389B00044EBA /* bind_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bind_fwd.hpp; sourceTree = ""; }; BFFCCE960890389B00044EBA /* bitand.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitand.hpp; sourceTree = ""; }; BFFCCE970890389B00044EBA /* bitor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitor.hpp; sourceTree = ""; }; BFFCCE980890389B00044EBA /* bitxor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitxor.hpp; sourceTree = ""; }; BFFCCE990890389B00044EBA /* deque.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = deque.hpp; sourceTree = ""; }; BFFCCE9A0890389B00044EBA /* divides.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = divides.hpp; sourceTree = ""; }; BFFCCE9B0890389B00044EBA /* equal_to.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = equal_to.hpp; sourceTree = ""; }; BFFCCE9C0890389B00044EBA /* fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = fold_impl.hpp; sourceTree = ""; }; BFFCCE9D0890389B00044EBA /* full_lambda.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = full_lambda.hpp; sourceTree = ""; }; BFFCCE9E0890389B00044EBA /* greater.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = greater.hpp; sourceTree = ""; }; BFFCCE9F0890389B00044EBA /* greater_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = greater_equal.hpp; sourceTree = ""; }; BFFCCEA00890389B00044EBA /* inherit.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = inherit.hpp; sourceTree = ""; }; BFFCCEA10890389B00044EBA /* iter_fold_if_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_fold_if_impl.hpp; sourceTree = ""; }; BFFCCEA20890389B00044EBA /* iter_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_fold_impl.hpp; sourceTree = ""; }; BFFCCEA30890389B00044EBA /* lambda_no_ctps.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lambda_no_ctps.hpp; sourceTree = ""; }; BFFCCEA40890389B00044EBA /* less.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = less.hpp; sourceTree = ""; }; BFFCCEA50890389B00044EBA /* less_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = less_equal.hpp; sourceTree = ""; }; BFFCCEA60890389B00044EBA /* list.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list.hpp; sourceTree = ""; }; BFFCCEA70890389B00044EBA /* list_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list_c.hpp; sourceTree = ""; }; BFFCCEA80890389B00044EBA /* map.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map.hpp; sourceTree = ""; }; BFFCCEA90890389B00044EBA /* minus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = minus.hpp; sourceTree = ""; }; BFFCCEAA0890389B00044EBA /* modulus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = modulus.hpp; sourceTree = ""; }; BFFCCEAB0890389B00044EBA /* not_equal_to.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = not_equal_to.hpp; sourceTree = ""; }; BFFCCEAC0890389B00044EBA /* or.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = or.hpp; sourceTree = ""; }; BFFCCEAD0890389B00044EBA /* placeholders.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = placeholders.hpp; sourceTree = ""; }; BFFCCEAE0890389B00044EBA /* plus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = plus.hpp; sourceTree = ""; }; BFFCCEAF0890389B00044EBA /* quote.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = quote.hpp; sourceTree = ""; }; BFFCCEB00890389B00044EBA /* reverse_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse_fold_impl.hpp; sourceTree = ""; }; BFFCCEB10890389B00044EBA /* reverse_iter_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse_iter_fold_impl.hpp; sourceTree = ""; }; BFFCCEB20890389B00044EBA /* set.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set.hpp; sourceTree = ""; }; BFFCCEB30890389B00044EBA /* set_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set_c.hpp; sourceTree = ""; }; BFFCCEB40890389B00044EBA /* shift_left.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shift_left.hpp; sourceTree = ""; }; BFFCCEB50890389B00044EBA /* shift_right.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shift_right.hpp; sourceTree = ""; }; BFFCCEB60890389B00044EBA /* template_arity.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = template_arity.hpp; sourceTree = ""; }; BFFCCEB70890389B00044EBA /* times.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = times.hpp; sourceTree = ""; }; BFFCCEB80890389B00044EBA /* unpack_args.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = unpack_args.hpp; sourceTree = ""; }; BFFCCEB90890389B00044EBA /* vector.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector.hpp; sourceTree = ""; }; BFFCCEBA0890389B00044EBA /* vector_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector_c.hpp; sourceTree = ""; }; BFFCCEBC0890389B00044EBA /* advance_backward.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = advance_backward.hpp; sourceTree = ""; }; BFFCCEBD0890389B00044EBA /* advance_forward.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = advance_forward.hpp; sourceTree = ""; }; BFFCCEBE0890389B00044EBA /* and.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = and.hpp; sourceTree = ""; }; BFFCCEBF0890389B00044EBA /* apply.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply.hpp; sourceTree = ""; }; BFFCCEC00890389B00044EBA /* apply_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply_fwd.hpp; sourceTree = ""; }; BFFCCEC10890389B00044EBA /* apply_wrap.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply_wrap.hpp; sourceTree = ""; }; BFFCCEC20890389B00044EBA /* arg.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = arg.hpp; sourceTree = ""; }; BFFCCEC30890389B00044EBA /* basic_bind.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = basic_bind.hpp; sourceTree = ""; }; BFFCCEC40890389B00044EBA /* bind.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bind.hpp; sourceTree = ""; }; BFFCCEC50890389B00044EBA /* bind_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bind_fwd.hpp; sourceTree = ""; }; BFFCCEC60890389B00044EBA /* bitand.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitand.hpp; sourceTree = ""; }; BFFCCEC70890389B00044EBA /* bitor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitor.hpp; sourceTree = ""; }; BFFCCEC80890389B00044EBA /* bitxor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitxor.hpp; sourceTree = ""; }; BFFCCEC90890389B00044EBA /* deque.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = deque.hpp; sourceTree = ""; }; BFFCCECA0890389B00044EBA /* divides.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = divides.hpp; sourceTree = ""; }; BFFCCECB0890389B00044EBA /* equal_to.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = equal_to.hpp; sourceTree = ""; }; BFFCCECC0890389B00044EBA /* fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = fold_impl.hpp; sourceTree = ""; }; BFFCCECD0890389B00044EBA /* full_lambda.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = full_lambda.hpp; sourceTree = ""; }; BFFCCECE0890389B00044EBA /* greater.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = greater.hpp; sourceTree = ""; }; BFFCCECF0890389B00044EBA /* greater_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = greater_equal.hpp; sourceTree = ""; }; BFFCCED00890389B00044EBA /* inherit.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = inherit.hpp; sourceTree = ""; }; BFFCCED10890389B00044EBA /* iter_fold_if_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_fold_if_impl.hpp; sourceTree = ""; }; BFFCCED20890389B00044EBA /* iter_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_fold_impl.hpp; sourceTree = ""; }; BFFCCED30890389B00044EBA /* lambda_no_ctps.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lambda_no_ctps.hpp; sourceTree = ""; }; BFFCCED40890389B00044EBA /* less.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = less.hpp; sourceTree = ""; }; BFFCCED50890389B00044EBA /* less_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = less_equal.hpp; sourceTree = ""; }; BFFCCED60890389B00044EBA /* list.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list.hpp; sourceTree = ""; }; BFFCCED70890389B00044EBA /* list_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list_c.hpp; sourceTree = ""; }; BFFCCED80890389B00044EBA /* map.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map.hpp; sourceTree = ""; }; BFFCCED90890389B00044EBA /* minus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = minus.hpp; sourceTree = ""; }; BFFCCEDA0890389B00044EBA /* modulus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = modulus.hpp; sourceTree = ""; }; BFFCCEDB0890389B00044EBA /* not_equal_to.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = not_equal_to.hpp; sourceTree = ""; }; BFFCCEDC0890389B00044EBA /* or.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = or.hpp; sourceTree = ""; }; BFFCCEDD0890389B00044EBA /* placeholders.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = placeholders.hpp; sourceTree = ""; }; BFFCCEDE0890389B00044EBA /* plus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = plus.hpp; sourceTree = ""; }; BFFCCEDF0890389B00044EBA /* quote.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = quote.hpp; sourceTree = ""; }; BFFCCEE00890389B00044EBA /* reverse_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse_fold_impl.hpp; sourceTree = ""; }; BFFCCEE10890389B00044EBA /* reverse_iter_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse_iter_fold_impl.hpp; sourceTree = ""; }; BFFCCEE20890389B00044EBA /* set.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set.hpp; sourceTree = ""; }; BFFCCEE30890389B00044EBA /* set_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set_c.hpp; sourceTree = ""; }; BFFCCEE40890389B00044EBA /* shift_left.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shift_left.hpp; sourceTree = ""; }; BFFCCEE50890389B00044EBA /* shift_right.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shift_right.hpp; sourceTree = ""; }; BFFCCEE60890389B00044EBA /* template_arity.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = template_arity.hpp; sourceTree = ""; }; BFFCCEE70890389B00044EBA /* times.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = times.hpp; sourceTree = ""; }; BFFCCEE80890389B00044EBA /* unpack_args.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = unpack_args.hpp; sourceTree = ""; }; BFFCCEE90890389B00044EBA /* vector.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector.hpp; sourceTree = ""; }; BFFCCEEA0890389B00044EBA /* vector_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector_c.hpp; sourceTree = ""; }; BFFCCEEC0890389B00044EBA /* advance_backward.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = advance_backward.hpp; sourceTree = ""; }; BFFCCEED0890389B00044EBA /* advance_forward.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = advance_forward.hpp; sourceTree = ""; }; BFFCCEEE0890389B00044EBA /* and.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = and.hpp; sourceTree = ""; }; BFFCCEEF0890389B00044EBA /* apply.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply.hpp; sourceTree = ""; }; BFFCCEF00890389B00044EBA /* apply_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply_fwd.hpp; sourceTree = ""; }; BFFCCEF10890389B00044EBA /* apply_wrap.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply_wrap.hpp; sourceTree = ""; }; BFFCCEF20890389B00044EBA /* arg.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = arg.hpp; sourceTree = ""; }; BFFCCEF30890389B00044EBA /* basic_bind.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = basic_bind.hpp; sourceTree = ""; }; BFFCCEF40890389B00044EBA /* bind.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bind.hpp; sourceTree = ""; }; BFFCCEF50890389B00044EBA /* bind_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bind_fwd.hpp; sourceTree = ""; }; BFFCCEF60890389B00044EBA /* bitand.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitand.hpp; sourceTree = ""; }; BFFCCEF70890389B00044EBA /* bitor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitor.hpp; sourceTree = ""; }; BFFCCEF80890389B00044EBA /* bitxor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitxor.hpp; sourceTree = ""; }; BFFCCEF90890389B00044EBA /* deque.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = deque.hpp; sourceTree = ""; }; BFFCCEFA0890389B00044EBA /* divides.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = divides.hpp; sourceTree = ""; }; BFFCCEFB0890389B00044EBA /* equal_to.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = equal_to.hpp; sourceTree = ""; }; BFFCCEFC0890389B00044EBA /* fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = fold_impl.hpp; sourceTree = ""; }; BFFCCEFD0890389B00044EBA /* full_lambda.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = full_lambda.hpp; sourceTree = ""; }; BFFCCEFE0890389B00044EBA /* greater.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = greater.hpp; sourceTree = ""; }; BFFCCEFF0890389B00044EBA /* greater_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = greater_equal.hpp; sourceTree = ""; }; BFFCCF000890389B00044EBA /* inherit.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = inherit.hpp; sourceTree = ""; }; BFFCCF010890389B00044EBA /* iter_fold_if_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_fold_if_impl.hpp; sourceTree = ""; }; BFFCCF020890389B00044EBA /* iter_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_fold_impl.hpp; sourceTree = ""; }; BFFCCF030890389B00044EBA /* lambda_no_ctps.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lambda_no_ctps.hpp; sourceTree = ""; }; BFFCCF040890389B00044EBA /* less.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = less.hpp; sourceTree = ""; }; BFFCCF050890389B00044EBA /* less_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = less_equal.hpp; sourceTree = ""; }; BFFCCF060890389B00044EBA /* list.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list.hpp; sourceTree = ""; }; BFFCCF070890389C00044EBA /* list_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list_c.hpp; sourceTree = ""; }; BFFCCF080890389C00044EBA /* map.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map.hpp; sourceTree = ""; }; BFFCCF090890389C00044EBA /* minus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = minus.hpp; sourceTree = ""; }; BFFCCF0A0890389C00044EBA /* modulus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = modulus.hpp; sourceTree = ""; }; BFFCCF0B0890389C00044EBA /* not_equal_to.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = not_equal_to.hpp; sourceTree = ""; }; BFFCCF0C0890389C00044EBA /* or.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = or.hpp; sourceTree = ""; }; BFFCCF0D0890389C00044EBA /* placeholders.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = placeholders.hpp; sourceTree = ""; }; BFFCCF0E0890389C00044EBA /* plus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = plus.hpp; sourceTree = ""; }; BFFCCF0F0890389C00044EBA /* quote.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = quote.hpp; sourceTree = ""; }; BFFCCF100890389C00044EBA /* reverse_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse_fold_impl.hpp; sourceTree = ""; }; BFFCCF110890389C00044EBA /* reverse_iter_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse_iter_fold_impl.hpp; sourceTree = ""; }; BFFCCF120890389C00044EBA /* set.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set.hpp; sourceTree = ""; }; BFFCCF130890389C00044EBA /* set_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set_c.hpp; sourceTree = ""; }; BFFCCF140890389C00044EBA /* shift_left.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shift_left.hpp; sourceTree = ""; }; BFFCCF150890389C00044EBA /* shift_right.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shift_right.hpp; sourceTree = ""; }; BFFCCF160890389C00044EBA /* template_arity.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = template_arity.hpp; sourceTree = ""; }; BFFCCF170890389C00044EBA /* times.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = times.hpp; sourceTree = ""; }; BFFCCF180890389C00044EBA /* unpack_args.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = unpack_args.hpp; sourceTree = ""; }; BFFCCF190890389C00044EBA /* vector.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector.hpp; sourceTree = ""; }; BFFCCF1A0890389C00044EBA /* vector_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector_c.hpp; sourceTree = ""; }; BFFCCF1C0890389C00044EBA /* advance_backward.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = advance_backward.hpp; sourceTree = ""; }; BFFCCF1D0890389C00044EBA /* advance_forward.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = advance_forward.hpp; sourceTree = ""; }; BFFCCF1E0890389C00044EBA /* and.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = and.hpp; sourceTree = ""; }; BFFCCF1F0890389C00044EBA /* apply.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply.hpp; sourceTree = ""; }; BFFCCF200890389C00044EBA /* apply_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply_fwd.hpp; sourceTree = ""; }; BFFCCF210890389C00044EBA /* apply_wrap.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply_wrap.hpp; sourceTree = ""; }; BFFCCF220890389C00044EBA /* arg.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = arg.hpp; sourceTree = ""; }; BFFCCF230890389C00044EBA /* basic_bind.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = basic_bind.hpp; sourceTree = ""; }; BFFCCF240890389C00044EBA /* bind.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bind.hpp; sourceTree = ""; }; BFFCCF250890389C00044EBA /* bind_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bind_fwd.hpp; sourceTree = ""; }; BFFCCF260890389C00044EBA /* bitand.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitand.hpp; sourceTree = ""; }; BFFCCF270890389C00044EBA /* bitor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitor.hpp; sourceTree = ""; }; BFFCCF280890389C00044EBA /* bitxor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitxor.hpp; sourceTree = ""; }; BFFCCF290890389C00044EBA /* deque.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = deque.hpp; sourceTree = ""; }; BFFCCF2A0890389C00044EBA /* divides.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = divides.hpp; sourceTree = ""; }; BFFCCF2B0890389C00044EBA /* equal_to.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = equal_to.hpp; sourceTree = ""; }; BFFCCF2C0890389C00044EBA /* fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = fold_impl.hpp; sourceTree = ""; }; BFFCCF2D0890389C00044EBA /* full_lambda.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = full_lambda.hpp; sourceTree = ""; }; BFFCCF2E0890389C00044EBA /* greater.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = greater.hpp; sourceTree = ""; }; BFFCCF2F0890389C00044EBA /* greater_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = greater_equal.hpp; sourceTree = ""; }; BFFCCF300890389C00044EBA /* inherit.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = inherit.hpp; sourceTree = ""; }; BFFCCF310890389C00044EBA /* iter_fold_if_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_fold_if_impl.hpp; sourceTree = ""; }; BFFCCF320890389C00044EBA /* iter_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_fold_impl.hpp; sourceTree = ""; }; BFFCCF330890389C00044EBA /* lambda_no_ctps.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lambda_no_ctps.hpp; sourceTree = ""; }; BFFCCF340890389C00044EBA /* less.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = less.hpp; sourceTree = ""; }; BFFCCF350890389C00044EBA /* less_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = less_equal.hpp; sourceTree = ""; }; BFFCCF360890389C00044EBA /* list.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list.hpp; sourceTree = ""; }; BFFCCF370890389C00044EBA /* list_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list_c.hpp; sourceTree = ""; }; BFFCCF380890389C00044EBA /* map.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map.hpp; sourceTree = ""; }; BFFCCF390890389C00044EBA /* minus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = minus.hpp; sourceTree = ""; }; BFFCCF3A0890389C00044EBA /* modulus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = modulus.hpp; sourceTree = ""; }; BFFCCF3B0890389C00044EBA /* not_equal_to.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = not_equal_to.hpp; sourceTree = ""; }; BFFCCF3C0890389C00044EBA /* or.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = or.hpp; sourceTree = ""; }; BFFCCF3D0890389C00044EBA /* placeholders.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = placeholders.hpp; sourceTree = ""; }; BFFCCF3E0890389C00044EBA /* plus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = plus.hpp; sourceTree = ""; }; BFFCCF3F0890389C00044EBA /* quote.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = quote.hpp; sourceTree = ""; }; BFFCCF400890389C00044EBA /* reverse_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse_fold_impl.hpp; sourceTree = ""; }; BFFCCF410890389C00044EBA /* reverse_iter_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse_iter_fold_impl.hpp; sourceTree = ""; }; BFFCCF420890389C00044EBA /* set.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set.hpp; sourceTree = ""; }; BFFCCF430890389C00044EBA /* set_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set_c.hpp; sourceTree = ""; }; BFFCCF440890389C00044EBA /* shift_left.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shift_left.hpp; sourceTree = ""; }; BFFCCF450890389C00044EBA /* shift_right.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shift_right.hpp; sourceTree = ""; }; BFFCCF460890389C00044EBA /* template_arity.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = template_arity.hpp; sourceTree = ""; }; BFFCCF470890389C00044EBA /* times.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = times.hpp; sourceTree = ""; }; BFFCCF480890389C00044EBA /* unpack_args.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = unpack_args.hpp; sourceTree = ""; }; BFFCCF490890389C00044EBA /* vector.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector.hpp; sourceTree = ""; }; BFFCCF4A0890389C00044EBA /* vector_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector_c.hpp; sourceTree = ""; }; BFFCCF4C0890389C00044EBA /* advance_backward.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = advance_backward.hpp; sourceTree = ""; }; BFFCCF4D0890389C00044EBA /* advance_forward.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = advance_forward.hpp; sourceTree = ""; }; BFFCCF4E0890389C00044EBA /* and.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = and.hpp; sourceTree = ""; }; BFFCCF4F0890389C00044EBA /* apply.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply.hpp; sourceTree = ""; }; BFFCCF500890389C00044EBA /* apply_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply_fwd.hpp; sourceTree = ""; }; BFFCCF510890389C00044EBA /* apply_wrap.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply_wrap.hpp; sourceTree = ""; }; BFFCCF520890389C00044EBA /* arg.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = arg.hpp; sourceTree = ""; }; BFFCCF530890389C00044EBA /* basic_bind.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = basic_bind.hpp; sourceTree = ""; }; BFFCCF540890389C00044EBA /* bind.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bind.hpp; sourceTree = ""; }; BFFCCF550890389C00044EBA /* bind_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bind_fwd.hpp; sourceTree = ""; }; BFFCCF560890389C00044EBA /* bitand.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitand.hpp; sourceTree = ""; }; BFFCCF570890389C00044EBA /* bitor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitor.hpp; sourceTree = ""; }; BFFCCF580890389C00044EBA /* bitxor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitxor.hpp; sourceTree = ""; }; BFFCCF590890389C00044EBA /* deque.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = deque.hpp; sourceTree = ""; }; BFFCCF5A0890389C00044EBA /* divides.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = divides.hpp; sourceTree = ""; }; BFFCCF5B0890389C00044EBA /* equal_to.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = equal_to.hpp; sourceTree = ""; }; BFFCCF5C0890389C00044EBA /* fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = fold_impl.hpp; sourceTree = ""; }; BFFCCF5D0890389C00044EBA /* full_lambda.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = full_lambda.hpp; sourceTree = ""; }; BFFCCF5E0890389C00044EBA /* greater.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = greater.hpp; sourceTree = ""; }; BFFCCF5F0890389C00044EBA /* greater_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = greater_equal.hpp; sourceTree = ""; }; BFFCCF600890389C00044EBA /* inherit.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = inherit.hpp; sourceTree = ""; }; BFFCCF610890389C00044EBA /* iter_fold_if_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_fold_if_impl.hpp; sourceTree = ""; }; BFFCCF620890389C00044EBA /* iter_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_fold_impl.hpp; sourceTree = ""; }; BFFCCF630890389C00044EBA /* lambda_no_ctps.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lambda_no_ctps.hpp; sourceTree = ""; }; BFFCCF640890389C00044EBA /* less.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = less.hpp; sourceTree = ""; }; BFFCCF650890389C00044EBA /* less_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = less_equal.hpp; sourceTree = ""; }; BFFCCF660890389C00044EBA /* list.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list.hpp; sourceTree = ""; }; BFFCCF670890389C00044EBA /* list_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list_c.hpp; sourceTree = ""; }; BFFCCF680890389C00044EBA /* map.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map.hpp; sourceTree = ""; }; BFFCCF690890389C00044EBA /* minus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = minus.hpp; sourceTree = ""; }; BFFCCF6A0890389C00044EBA /* modulus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = modulus.hpp; sourceTree = ""; }; BFFCCF6B0890389C00044EBA /* not_equal_to.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = not_equal_to.hpp; sourceTree = ""; }; BFFCCF6C0890389C00044EBA /* or.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = or.hpp; sourceTree = ""; }; BFFCCF6D0890389C00044EBA /* placeholders.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = placeholders.hpp; sourceTree = ""; }; BFFCCF6E0890389C00044EBA /* plus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = plus.hpp; sourceTree = ""; }; BFFCCF6F0890389C00044EBA /* quote.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = quote.hpp; sourceTree = ""; }; BFFCCF700890389C00044EBA /* reverse_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse_fold_impl.hpp; sourceTree = ""; }; BFFCCF710890389C00044EBA /* reverse_iter_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse_iter_fold_impl.hpp; sourceTree = ""; }; BFFCCF720890389C00044EBA /* set.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set.hpp; sourceTree = ""; }; BFFCCF730890389C00044EBA /* set_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set_c.hpp; sourceTree = ""; }; BFFCCF740890389C00044EBA /* shift_left.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shift_left.hpp; sourceTree = ""; }; BFFCCF750890389C00044EBA /* shift_right.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shift_right.hpp; sourceTree = ""; }; BFFCCF760890389C00044EBA /* template_arity.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = template_arity.hpp; sourceTree = ""; }; BFFCCF770890389C00044EBA /* times.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = times.hpp; sourceTree = ""; }; BFFCCF780890389C00044EBA /* unpack_args.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = unpack_args.hpp; sourceTree = ""; }; BFFCCF790890389C00044EBA /* vector.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector.hpp; sourceTree = ""; }; BFFCCF7A0890389C00044EBA /* vector_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector_c.hpp; sourceTree = ""; }; BFFCCF7C0890389D00044EBA /* advance_backward.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = advance_backward.hpp; sourceTree = ""; }; BFFCCF7D0890389D00044EBA /* advance_forward.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = advance_forward.hpp; sourceTree = ""; }; BFFCCF7E0890389D00044EBA /* and.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = and.hpp; sourceTree = ""; }; BFFCCF7F0890389D00044EBA /* apply.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply.hpp; sourceTree = ""; }; BFFCCF800890389D00044EBA /* apply_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply_fwd.hpp; sourceTree = ""; }; BFFCCF810890389D00044EBA /* apply_wrap.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply_wrap.hpp; sourceTree = ""; }; BFFCCF820890389D00044EBA /* arg.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = arg.hpp; sourceTree = ""; }; BFFCCF830890389D00044EBA /* basic_bind.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = basic_bind.hpp; sourceTree = ""; }; BFFCCF840890389D00044EBA /* bind.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bind.hpp; sourceTree = ""; }; BFFCCF850890389D00044EBA /* bind_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bind_fwd.hpp; sourceTree = ""; }; BFFCCF860890389D00044EBA /* bitand.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitand.hpp; sourceTree = ""; }; BFFCCF870890389D00044EBA /* bitor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitor.hpp; sourceTree = ""; }; BFFCCF880890389D00044EBA /* bitxor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitxor.hpp; sourceTree = ""; }; BFFCCF890890389D00044EBA /* deque.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = deque.hpp; sourceTree = ""; }; BFFCCF8A0890389D00044EBA /* divides.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = divides.hpp; sourceTree = ""; }; BFFCCF8B0890389D00044EBA /* equal_to.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = equal_to.hpp; sourceTree = ""; }; BFFCCF8C0890389D00044EBA /* fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = fold_impl.hpp; sourceTree = ""; }; BFFCCF8D0890389D00044EBA /* full_lambda.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = full_lambda.hpp; sourceTree = ""; }; BFFCCF8E0890389D00044EBA /* greater.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = greater.hpp; sourceTree = ""; }; BFFCCF8F0890389D00044EBA /* greater_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = greater_equal.hpp; sourceTree = ""; }; BFFCCF900890389D00044EBA /* inherit.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = inherit.hpp; sourceTree = ""; }; BFFCCF910890389D00044EBA /* iter_fold_if_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_fold_if_impl.hpp; sourceTree = ""; }; BFFCCF920890389D00044EBA /* iter_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_fold_impl.hpp; sourceTree = ""; }; BFFCCF930890389D00044EBA /* lambda_no_ctps.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lambda_no_ctps.hpp; sourceTree = ""; }; BFFCCF940890389D00044EBA /* less.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = less.hpp; sourceTree = ""; }; BFFCCF950890389D00044EBA /* less_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = less_equal.hpp; sourceTree = ""; }; BFFCCF960890389D00044EBA /* list.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list.hpp; sourceTree = ""; }; BFFCCF970890389D00044EBA /* list_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list_c.hpp; sourceTree = ""; }; BFFCCF980890389D00044EBA /* map.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map.hpp; sourceTree = ""; }; BFFCCF990890389D00044EBA /* minus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = minus.hpp; sourceTree = ""; }; BFFCCF9A0890389D00044EBA /* modulus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = modulus.hpp; sourceTree = ""; }; BFFCCF9B0890389D00044EBA /* not_equal_to.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = not_equal_to.hpp; sourceTree = ""; }; BFFCCF9C0890389D00044EBA /* or.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = or.hpp; sourceTree = ""; }; BFFCCF9D0890389D00044EBA /* placeholders.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = placeholders.hpp; sourceTree = ""; }; BFFCCF9E0890389D00044EBA /* plus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = plus.hpp; sourceTree = ""; }; BFFCCF9F0890389D00044EBA /* quote.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = quote.hpp; sourceTree = ""; }; BFFCCFA00890389D00044EBA /* reverse_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse_fold_impl.hpp; sourceTree = ""; }; BFFCCFA10890389D00044EBA /* reverse_iter_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse_iter_fold_impl.hpp; sourceTree = ""; }; BFFCCFA20890389D00044EBA /* set.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set.hpp; sourceTree = ""; }; BFFCCFA30890389D00044EBA /* set_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set_c.hpp; sourceTree = ""; }; BFFCCFA40890389D00044EBA /* shift_left.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shift_left.hpp; sourceTree = ""; }; BFFCCFA50890389D00044EBA /* shift_right.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shift_right.hpp; sourceTree = ""; }; BFFCCFA60890389D00044EBA /* template_arity.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = template_arity.hpp; sourceTree = ""; }; BFFCCFA70890389D00044EBA /* times.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = times.hpp; sourceTree = ""; }; BFFCCFA80890389D00044EBA /* unpack_args.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = unpack_args.hpp; sourceTree = ""; }; BFFCCFA90890389D00044EBA /* vector.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector.hpp; sourceTree = ""; }; BFFCCFAA0890389D00044EBA /* vector_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector_c.hpp; sourceTree = ""; }; BFFCCFAC0890389D00044EBA /* add.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = add.hpp; sourceTree = ""; }; BFFCCFAD0890389D00044EBA /* def_params_tail.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = def_params_tail.hpp; sourceTree = ""; }; BFFCCFAE0890389D00044EBA /* default_params.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = default_params.hpp; sourceTree = ""; }; BFFCCFAF0890389D00044EBA /* enum.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = enum.hpp; sourceTree = ""; }; BFFCCFB00890389D00044EBA /* ext_params.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = ext_params.hpp; sourceTree = ""; }; BFFCCFB10890389D00044EBA /* filter_params.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = filter_params.hpp; sourceTree = ""; }; BFFCCFB20890389D00044EBA /* is_seq.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_seq.hpp; sourceTree = ""; }; BFFCCFB30890389D00044EBA /* params.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = params.hpp; sourceTree = ""; }; BFFCCFB40890389D00044EBA /* partial_spec_params.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = partial_spec_params.hpp; sourceTree = ""; }; BFFCCFB50890389D00044EBA /* range.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = range.hpp; sourceTree = ""; }; BFFCCFB60890389D00044EBA /* repeat.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = repeat.hpp; sourceTree = ""; }; BFFCCFB70890389D00044EBA /* sub.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = sub.hpp; sourceTree = ""; }; BFFCCFB80890389D00044EBA /* token_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = token_equal.hpp; sourceTree = ""; }; BFFCCFB90890389D00044EBA /* tuple.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = tuple.hpp; sourceTree = ""; }; BFFCCFBA0890389D00044EBA /* ptr_to_ref.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = ptr_to_ref.hpp; sourceTree = ""; }; BFFCCFBB0890389D00044EBA /* push_back_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = push_back_impl.hpp; sourceTree = ""; }; BFFCCFBC0890389D00044EBA /* push_front_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = push_front_impl.hpp; sourceTree = ""; }; BFFCCFBE0890389D00044EBA /* back.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = back.hpp; sourceTree = ""; }; BFFCCFBF0890389D00044EBA /* empty.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = empty.hpp; sourceTree = ""; }; BFFCCFC00890389D00044EBA /* front.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = front.hpp; sourceTree = ""; }; BFFCCFC10890389D00044EBA /* iterator.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iterator.hpp; sourceTree = ""; }; BFFCCFC20890389D00044EBA /* O1_size.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = O1_size.hpp; sourceTree = ""; }; BFFCCFC30890389D00044EBA /* size.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = size.hpp; sourceTree = ""; }; BFFCCFC40890389D00044EBA /* tag.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = tag.hpp; sourceTree = ""; }; BFFCCFC50890389D00044EBA /* reverse_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse_fold_impl.hpp; sourceTree = ""; }; BFFCCFC60890389D00044EBA /* reverse_fold_impl_body.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse_fold_impl_body.hpp; sourceTree = ""; }; BFFCCFC70890389D00044EBA /* reverse_iter_fold_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse_iter_fold_impl.hpp; sourceTree = ""; }; BFFCCFC80890389D00044EBA /* sequence_wrapper.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = sequence_wrapper.hpp; sourceTree = ""; }; BFFCCFC90890389D00044EBA /* shift_op.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shift_op.hpp; sourceTree = ""; }; BFFCCFCA0890389D00044EBA /* single_element_iter.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = single_element_iter.hpp; sourceTree = ""; }; BFFCCFCB0890389D00044EBA /* size_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = size_impl.hpp; sourceTree = ""; }; BFFCCFCC0890389D00044EBA /* sort_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = sort_impl.hpp; sourceTree = ""; }; BFFCCFCD0890389D00044EBA /* static_cast.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = static_cast.hpp; sourceTree = ""; }; BFFCCFCE0890389D00044EBA /* template_arity.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = template_arity.hpp; sourceTree = ""; }; BFFCCFCF0890389D00044EBA /* template_arity_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = template_arity_fwd.hpp; sourceTree = ""; }; BFFCCFD10890389D00044EBA /* assert.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = assert.hpp; sourceTree = ""; }; BFFCCFD20890389D00044EBA /* data.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = data.hpp; sourceTree = ""; }; BFFCCFD30890389D00044EBA /* test_case.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = test_case.hpp; sourceTree = ""; }; BFFCCFD40890389D00044EBA /* test.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = test.hpp; sourceTree = ""; }; BFFCCFD50890389D00044EBA /* traits_lambda_spec.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = traits_lambda_spec.hpp; sourceTree = ""; }; BFFCCFD60890389D00044EBA /* transform_iter.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = transform_iter.hpp; sourceTree = ""; }; BFFCCFD70890389D00044EBA /* type_wrapper.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = type_wrapper.hpp; sourceTree = ""; }; BFFCCFD80890389D00044EBA /* unwrap.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = unwrap.hpp; sourceTree = ""; }; BFFCCFD90890389D00044EBA /* value_wknd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = value_wknd.hpp; sourceTree = ""; }; BFFCCFDA0890389D00044EBA /* yes_no.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = yes_no.hpp; sourceTree = ""; }; BFFCCFDB0890389D00044EBA /* back.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = back.hpp; sourceTree = ""; }; BFFCCFDC0890389D00044EBA /* back_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = back_fwd.hpp; sourceTree = ""; }; BFFCCFDD0890389D00044EBA /* back_inserter.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = back_inserter.hpp; sourceTree = ""; }; BFFCCFDE0890389D00044EBA /* base.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = base.hpp; sourceTree = ""; }; BFFCCFDF0890389D00044EBA /* begin.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = begin.hpp; sourceTree = ""; }; BFFCCFE00890389D00044EBA /* begin_end.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = begin_end.hpp; sourceTree = ""; }; BFFCCFE10890389D00044EBA /* begin_end_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = begin_end_fwd.hpp; sourceTree = ""; }; BFFCCFE20890389D00044EBA /* bind.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bind.hpp; sourceTree = ""; }; BFFCCFE30890389D00044EBA /* bind_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bind_fwd.hpp; sourceTree = ""; }; BFFCCFE40890389D00044EBA /* bitand.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitand.hpp; sourceTree = ""; }; BFFCCFE50890389D00044EBA /* bitor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitor.hpp; sourceTree = ""; }; BFFCCFE60890389D00044EBA /* bitwise.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitwise.hpp; sourceTree = ""; }; BFFCCFE70890389D00044EBA /* bitxor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitxor.hpp; sourceTree = ""; }; BFFCCFE80890389D00044EBA /* bool.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bool.hpp; sourceTree = ""; }; BFFCCFE90890389D00044EBA /* bool_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bool_fwd.hpp; sourceTree = ""; }; BFFCCFEA0890389D00044EBA /* clear.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = clear.hpp; sourceTree = ""; }; BFFCCFEB0890389D00044EBA /* clear_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = clear_fwd.hpp; sourceTree = ""; }; BFFCCFEC0890389D00044EBA /* comparison.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = comparison.hpp; sourceTree = ""; }; BFFCCFED0890389D00044EBA /* contains.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = contains.hpp; sourceTree = ""; }; BFFCCFEE0890389D00044EBA /* contains_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = contains_fwd.hpp; sourceTree = ""; }; BFFCCFEF0890389D00044EBA /* copy.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = copy.hpp; sourceTree = ""; }; BFFCCFF00890389D00044EBA /* copy_if.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = copy_if.hpp; sourceTree = ""; }; BFFCCFF10890389D00044EBA /* count.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = count.hpp; sourceTree = ""; }; BFFCCFF20890389D00044EBA /* count_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = count_fwd.hpp; sourceTree = ""; }; BFFCCFF30890389D00044EBA /* count_if.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = count_if.hpp; sourceTree = ""; }; BFFCCFF40890389D00044EBA /* deque.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = deque.hpp; sourceTree = ""; }; BFFCCFF50890389D00044EBA /* deref.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = deref.hpp; sourceTree = ""; }; BFFCCFF60890389D00044EBA /* distance.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = distance.hpp; sourceTree = ""; }; BFFCCFF70890389D00044EBA /* distance_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = distance_fwd.hpp; sourceTree = ""; }; BFFCCFF80890389D00044EBA /* divides.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = divides.hpp; sourceTree = ""; }; BFFCCFF90890389D00044EBA /* empty.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = empty.hpp; sourceTree = ""; }; BFFCCFFA0890389D00044EBA /* empty_base.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = empty_base.hpp; sourceTree = ""; }; BFFCCFFB0890389D00044EBA /* empty_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = empty_fwd.hpp; sourceTree = ""; }; BFFCCFFC0890389D00044EBA /* empty_sequence.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = empty_sequence.hpp; sourceTree = ""; }; BFFCCFFD0890389D00044EBA /* end.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = end.hpp; sourceTree = ""; }; BFFCCFFE0890389D00044EBA /* equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = equal.hpp; sourceTree = ""; }; BFFCCFFF0890389E00044EBA /* equal_to.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = equal_to.hpp; sourceTree = ""; }; BFFCD0000890389E00044EBA /* erase.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = erase.hpp; sourceTree = ""; }; BFFCD0010890389E00044EBA /* erase_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = erase_fwd.hpp; sourceTree = ""; }; BFFCD0020890389E00044EBA /* erase_key.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = erase_key.hpp; sourceTree = ""; }; BFFCD0030890389E00044EBA /* erase_key_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = erase_key_fwd.hpp; sourceTree = ""; }; BFFCD0040890389E00044EBA /* eval_if.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = eval_if.hpp; sourceTree = ""; }; BFFCD0050890389E00044EBA /* filter_view.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = filter_view.hpp; sourceTree = ""; }; BFFCD0060890389E00044EBA /* find.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = find.hpp; sourceTree = ""; }; BFFCD0070890389E00044EBA /* find_if.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = find_if.hpp; sourceTree = ""; }; BFFCD0080890389E00044EBA /* fold.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = fold.hpp; sourceTree = ""; }; BFFCD0090890389E00044EBA /* for_each.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = for_each.hpp; sourceTree = ""; }; BFFCD00A0890389E00044EBA /* front.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = front.hpp; sourceTree = ""; }; BFFCD00B0890389E00044EBA /* front_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = front_fwd.hpp; sourceTree = ""; }; BFFCD00C0890389E00044EBA /* front_inserter.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = front_inserter.hpp; sourceTree = ""; }; BFFCD00D0890389E00044EBA /* greater.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = greater.hpp; sourceTree = ""; }; BFFCD00E0890389E00044EBA /* greater_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = greater_equal.hpp; sourceTree = ""; }; BFFCD00F0890389E00044EBA /* has_key.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = has_key.hpp; sourceTree = ""; }; BFFCD0100890389E00044EBA /* has_key_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = has_key_fwd.hpp; sourceTree = ""; }; BFFCD0110890389E00044EBA /* has_xxx.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = has_xxx.hpp; sourceTree = ""; }; BFFCD0120890389E00044EBA /* identity.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = identity.hpp; sourceTree = ""; }; BFFCD0130890389E00044EBA /* if.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = if.hpp; sourceTree = ""; }; BFFCD0140890389E00044EBA /* index_if.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = index_if.hpp; sourceTree = ""; }; BFFCD0150890389E00044EBA /* index_of.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = index_of.hpp; sourceTree = ""; }; BFFCD0160890389E00044EBA /* inherit.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = inherit.hpp; sourceTree = ""; }; BFFCD0170890389E00044EBA /* inherit_linearly.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = inherit_linearly.hpp; sourceTree = ""; }; BFFCD0180890389E00044EBA /* insert.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = insert.hpp; sourceTree = ""; }; BFFCD0190890389E00044EBA /* insert_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = insert_fwd.hpp; sourceTree = ""; }; BFFCD01A0890389E00044EBA /* insert_range.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = insert_range.hpp; sourceTree = ""; }; BFFCD01B0890389E00044EBA /* insert_range_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = insert_range_fwd.hpp; sourceTree = ""; }; BFFCD01C0890389E00044EBA /* inserter.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = inserter.hpp; sourceTree = ""; }; BFFCD01D0890389E00044EBA /* int.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = int.hpp; sourceTree = ""; }; BFFCD01E0890389E00044EBA /* int_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = int_fwd.hpp; sourceTree = ""; }; BFFCD01F0890389E00044EBA /* integral_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = integral_c.hpp; sourceTree = ""; }; BFFCD0200890389E00044EBA /* integral_c_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = integral_c_fwd.hpp; sourceTree = ""; }; BFFCD0210890389E00044EBA /* integral_c_tag.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = integral_c_tag.hpp; sourceTree = ""; }; BFFCD0220890389E00044EBA /* is_placeholder.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_placeholder.hpp; sourceTree = ""; }; BFFCD0230890389E00044EBA /* is_sequence.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_sequence.hpp; sourceTree = ""; }; BFFCD0240890389E00044EBA /* iter_fold.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_fold.hpp; sourceTree = ""; }; BFFCD0250890389E00044EBA /* iter_fold_if.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iter_fold_if.hpp; sourceTree = ""; }; BFFCD0260890389E00044EBA /* iterator_category.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iterator_category.hpp; sourceTree = ""; }; BFFCD0270890389E00044EBA /* iterator_range.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iterator_range.hpp; sourceTree = ""; }; BFFCD0280890389E00044EBA /* iterator_tags.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iterator_tags.hpp; sourceTree = ""; }; BFFCD0290890389E00044EBA /* joint_view.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = joint_view.hpp; sourceTree = ""; }; BFFCD02A0890389E00044EBA /* key_type.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = key_type.hpp; sourceTree = ""; }; BFFCD02B0890389E00044EBA /* key_type_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = key_type_fwd.hpp; sourceTree = ""; }; BFFCD02C0890389E00044EBA /* lambda.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lambda.hpp; sourceTree = ""; }; BFFCD02D0890389E00044EBA /* lambda_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lambda_fwd.hpp; sourceTree = ""; }; BFFCD02E0890389E00044EBA /* less.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = less.hpp; sourceTree = ""; }; BFFCD02F0890389E00044EBA /* less_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = less_equal.hpp; sourceTree = ""; }; BFFCD0310890389E00044EBA /* arity.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = arity.hpp; sourceTree = ""; }; BFFCD0320890389E00044EBA /* list.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list.hpp; sourceTree = ""; }; BFFCD0330890389E00044EBA /* map.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map.hpp; sourceTree = ""; }; BFFCD0340890389E00044EBA /* set.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set.hpp; sourceTree = ""; }; BFFCD0350890389E00044EBA /* unrolling.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = unrolling.hpp; sourceTree = ""; }; BFFCD0360890389E00044EBA /* vector.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector.hpp; sourceTree = ""; }; BFFCD0390890389E00044EBA /* begin_end.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = begin_end.hpp; sourceTree = ""; }; BFFCD03A0890389E00044EBA /* clear.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = clear.hpp; sourceTree = ""; }; BFFCD03B0890389E00044EBA /* empty.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = empty.hpp; sourceTree = ""; }; BFFCD03C0890389E00044EBA /* front.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = front.hpp; sourceTree = ""; }; BFFCD03D0890389E00044EBA /* include_preprocessed.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = include_preprocessed.hpp; sourceTree = ""; }; BFFCD03E0890389E00044EBA /* item.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = item.hpp; sourceTree = ""; }; BFFCD03F0890389E00044EBA /* iterator.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iterator.hpp; sourceTree = ""; }; BFFCD0400890389E00044EBA /* numbered.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = numbered.hpp; sourceTree = ""; }; BFFCD0410890389E00044EBA /* numbered_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = numbered_c.hpp; sourceTree = ""; }; BFFCD0420890389E00044EBA /* O1_size.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = O1_size.hpp; sourceTree = ""; }; BFFCD0430890389E00044EBA /* pop_front.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = pop_front.hpp; sourceTree = ""; }; BFFCD0460890389E00044EBA /* list10.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list10.hpp; sourceTree = ""; }; BFFCD0470890389E00044EBA /* list10_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list10_c.hpp; sourceTree = ""; }; BFFCD0480890389E00044EBA /* list20.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list20.hpp; sourceTree = ""; }; BFFCD0490890389E00044EBA /* list20_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list20_c.hpp; sourceTree = ""; }; BFFCD04A0890389E00044EBA /* list30.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list30.hpp; sourceTree = ""; }; BFFCD04B0890389E00044EBA /* list30_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list30_c.hpp; sourceTree = ""; }; BFFCD04C0890389E00044EBA /* list40.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list40.hpp; sourceTree = ""; }; BFFCD04D0890389E00044EBA /* list40_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list40_c.hpp; sourceTree = ""; }; BFFCD04E0890389E00044EBA /* list50.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list50.hpp; sourceTree = ""; }; BFFCD04F0890389E00044EBA /* list50_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list50_c.hpp; sourceTree = ""; }; BFFCD0500890389E00044EBA /* push_back.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = push_back.hpp; sourceTree = ""; }; BFFCD0510890389E00044EBA /* push_front.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = push_front.hpp; sourceTree = ""; }; BFFCD0520890389E00044EBA /* size.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = size.hpp; sourceTree = ""; }; BFFCD0530890389E00044EBA /* tag.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = tag.hpp; sourceTree = ""; }; BFFCD0540890389E00044EBA /* list0.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list0.hpp; sourceTree = ""; }; BFFCD0550890389E00044EBA /* list0_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list0_c.hpp; sourceTree = ""; }; BFFCD0560890389E00044EBA /* list10.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list10.hpp; sourceTree = ""; }; BFFCD0570890389E00044EBA /* list10_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list10_c.hpp; sourceTree = ""; }; BFFCD0580890389E00044EBA /* list20.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list20.hpp; sourceTree = ""; }; BFFCD0590890389E00044EBA /* list20_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list20_c.hpp; sourceTree = ""; }; BFFCD05A0890389E00044EBA /* list30.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list30.hpp; sourceTree = ""; }; BFFCD05B0890389E00044EBA /* list30_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list30_c.hpp; sourceTree = ""; }; BFFCD05C0890389E00044EBA /* list40.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list40.hpp; sourceTree = ""; }; BFFCD05D0890389E00044EBA /* list40_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list40_c.hpp; sourceTree = ""; }; BFFCD05E0890389F00044EBA /* list50.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list50.hpp; sourceTree = ""; }; BFFCD05F0890389F00044EBA /* list50_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list50_c.hpp; sourceTree = ""; }; BFFCD0600890389F00044EBA /* list.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list.hpp; sourceTree = ""; }; BFFCD0610890389F00044EBA /* list_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list_c.hpp; sourceTree = ""; }; BFFCD0620890389F00044EBA /* logical.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = logical.hpp; sourceTree = ""; }; BFFCD0630890389F00044EBA /* long.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = long.hpp; sourceTree = ""; }; BFFCD0640890389F00044EBA /* long_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = long_fwd.hpp; sourceTree = ""; }; BFFCD0650890389F00044EBA /* lower_bound.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lower_bound.hpp; sourceTree = ""; }; BFFCD0680890389F00044EBA /* at_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = at_impl.hpp; sourceTree = ""; }; BFFCD0690890389F00044EBA /* begin_end_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = begin_end_impl.hpp; sourceTree = ""; }; BFFCD06A0890389F00044EBA /* clear_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = clear_impl.hpp; sourceTree = ""; }; BFFCD06B0890389F00044EBA /* contains_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = contains_impl.hpp; sourceTree = ""; }; BFFCD06C0890389F00044EBA /* empty_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = empty_impl.hpp; sourceTree = ""; }; BFFCD06D0890389F00044EBA /* erase_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = erase_impl.hpp; sourceTree = ""; }; BFFCD06E0890389F00044EBA /* erase_key_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = erase_key_impl.hpp; sourceTree = ""; }; BFFCD06F0890389F00044EBA /* has_key_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = has_key_impl.hpp; sourceTree = ""; }; BFFCD0700890389F00044EBA /* include_preprocessed.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = include_preprocessed.hpp; sourceTree = ""; }; BFFCD0710890389F00044EBA /* insert_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = insert_impl.hpp; sourceTree = ""; }; BFFCD0720890389F00044EBA /* item.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = item.hpp; sourceTree = ""; }; BFFCD0730890389F00044EBA /* iterator.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iterator.hpp; sourceTree = ""; }; BFFCD0740890389F00044EBA /* key_type_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = key_type_impl.hpp; sourceTree = ""; }; BFFCD0750890389F00044EBA /* map0.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map0.hpp; sourceTree = ""; }; BFFCD0760890389F00044EBA /* numbered.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = numbered.hpp; sourceTree = ""; }; BFFCD0790890389F00044EBA /* map10.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map10.hpp; sourceTree = ""; }; BFFCD07A0890389F00044EBA /* map20.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map20.hpp; sourceTree = ""; }; BFFCD07B0890389F00044EBA /* map30.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map30.hpp; sourceTree = ""; }; BFFCD07C0890389F00044EBA /* map40.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map40.hpp; sourceTree = ""; }; BFFCD07D0890389F00044EBA /* map50.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map50.hpp; sourceTree = ""; }; BFFCD07F0890389F00044EBA /* map10.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map10.hpp; sourceTree = ""; }; BFFCD0800890389F00044EBA /* map20.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map20.hpp; sourceTree = ""; }; BFFCD0810890389F00044EBA /* map30.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map30.hpp; sourceTree = ""; }; BFFCD0820890389F00044EBA /* map40.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map40.hpp; sourceTree = ""; }; BFFCD0830890389F00044EBA /* map50.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map50.hpp; sourceTree = ""; }; BFFCD0850890389F00044EBA /* map10.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map10.hpp; sourceTree = ""; }; BFFCD0860890389F00044EBA /* map20.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map20.hpp; sourceTree = ""; }; BFFCD0870890389F00044EBA /* map30.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map30.hpp; sourceTree = ""; }; BFFCD0880890389F00044EBA /* map40.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map40.hpp; sourceTree = ""; }; BFFCD0890890389F00044EBA /* map50.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map50.hpp; sourceTree = ""; }; BFFCD08A0890389F00044EBA /* size_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = size_impl.hpp; sourceTree = ""; }; BFFCD08B0890389F00044EBA /* tag.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = tag.hpp; sourceTree = ""; }; BFFCD08C0890389F00044EBA /* value_type_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = value_type_impl.hpp; sourceTree = ""; }; BFFCD08D0890389F00044EBA /* map0.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map0.hpp; sourceTree = ""; }; BFFCD08E0890389F00044EBA /* map10.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map10.hpp; sourceTree = ""; }; BFFCD08F0890389F00044EBA /* map20.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map20.hpp; sourceTree = ""; }; BFFCD0900890389F00044EBA /* map30.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map30.hpp; sourceTree = ""; }; BFFCD0910890389F00044EBA /* map40.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map40.hpp; sourceTree = ""; }; BFFCD0920890389F00044EBA /* map50.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map50.hpp; sourceTree = ""; }; BFFCD0930890389F00044EBA /* map.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = map.hpp; sourceTree = ""; }; BFFCD0950890389F00044EBA /* fixed_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = fixed_c.hpp; sourceTree = ""; }; BFFCD0960890389F00044EBA /* is_even.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_even.hpp; sourceTree = ""; }; BFFCD0970890389F00044EBA /* rational_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = rational_c.hpp; sourceTree = ""; }; BFFCD0980890389F00044EBA /* max.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = max.hpp; sourceTree = ""; }; BFFCD0990890389F00044EBA /* max_element.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = max_element.hpp; sourceTree = ""; }; BFFCD09A0890389F00044EBA /* min.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = min.hpp; sourceTree = ""; }; BFFCD09B0890389F00044EBA /* min_element.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = min_element.hpp; sourceTree = ""; }; BFFCD09C0890389F00044EBA /* min_max.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = min_max.hpp; sourceTree = ""; }; BFFCD09D0890389F00044EBA /* minus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = minus.hpp; sourceTree = ""; }; BFFCD09E0890389F00044EBA /* modulus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = modulus.hpp; sourceTree = ""; }; BFFCD09F0890389F00044EBA /* multiplies.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = multiplies.hpp; sourceTree = ""; }; BFFCD0A20890389F00044EBA /* count_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = count_impl.hpp; sourceTree = ""; }; BFFCD0A30890389F00044EBA /* insert_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = insert_impl.hpp; sourceTree = ""; }; BFFCD0A40890389F00044EBA /* item.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = item.hpp; sourceTree = ""; }; BFFCD0A50890389F00044EBA /* multiset0.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = multiset0.hpp; sourceTree = ""; }; BFFCD0A60890389F00044EBA /* tag.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = tag.hpp; sourceTree = ""; }; BFFCD0A70890389F00044EBA /* multiset0.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = multiset0.hpp; sourceTree = ""; }; BFFCD0A80890389F00044EBA /* negate.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = negate.hpp; sourceTree = ""; }; BFFCD0A90890389F00044EBA /* next.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = next.hpp; sourceTree = ""; }; BFFCD0AA0890389F00044EBA /* next_prior.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = next_prior.hpp; sourceTree = ""; }; BFFCD0AB0890389F00044EBA /* not.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = not.hpp; sourceTree = ""; }; BFFCD0AC0890389F00044EBA /* not_equal_to.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = not_equal_to.hpp; sourceTree = ""; }; BFFCD0AD0890389F00044EBA /* numeric_cast.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = numeric_cast.hpp; sourceTree = ""; }; BFFCD0AE0890389F00044EBA /* O1_size.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = O1_size.hpp; sourceTree = ""; }; BFFCD0AF0890389F00044EBA /* O1_size_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = O1_size_fwd.hpp; sourceTree = ""; }; BFFCD0B00890389F00044EBA /* or.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = or.hpp; sourceTree = ""; }; BFFCD0B10890389F00044EBA /* order.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = order.hpp; sourceTree = ""; }; BFFCD0B20890389F00044EBA /* order_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = order_fwd.hpp; sourceTree = ""; }; BFFCD0B30890389F00044EBA /* pair.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = pair.hpp; sourceTree = ""; }; BFFCD0B40890389F00044EBA /* pair_view.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = pair_view.hpp; sourceTree = ""; }; BFFCD0B50890389F00044EBA /* partition.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = partition.hpp; sourceTree = ""; }; BFFCD0B60890389F00044EBA /* placeholders.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = placeholders.hpp; sourceTree = ""; }; BFFCD0B70890389F00044EBA /* plus.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = plus.hpp; sourceTree = ""; }; BFFCD0B80890389F00044EBA /* pop_back.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = pop_back.hpp; sourceTree = ""; }; BFFCD0B90890389F00044EBA /* pop_back_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = pop_back_fwd.hpp; sourceTree = ""; }; BFFCD0BA0890389F00044EBA /* pop_front.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = pop_front.hpp; sourceTree = ""; }; BFFCD0BB0890389F00044EBA /* pop_front_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = pop_front_fwd.hpp; sourceTree = ""; }; BFFCD0BC0890389F00044EBA /* print.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = print.hpp; sourceTree = ""; }; BFFCD0BD0890389F00044EBA /* prior.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = prior.hpp; sourceTree = ""; }; BFFCD0BE0890389F00044EBA /* protect.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = protect.hpp; sourceTree = ""; }; BFFCD0BF0890389F00044EBA /* push_back.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = push_back.hpp; sourceTree = ""; }; BFFCD0C00890389F00044EBA /* push_back_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = push_back_fwd.hpp; sourceTree = ""; }; BFFCD0C10890389F00044EBA /* push_front.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = push_front.hpp; sourceTree = ""; }; BFFCD0C20890389F00044EBA /* push_front_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = push_front_fwd.hpp; sourceTree = ""; }; BFFCD0C30890389F00044EBA /* quote.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = quote.hpp; sourceTree = ""; }; BFFCD0C40890389F00044EBA /* range_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = range_c.hpp; sourceTree = ""; }; BFFCD0C50890389F00044EBA /* remove.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = remove.hpp; sourceTree = ""; }; BFFCD0C60890389F00044EBA /* remove_if.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = remove_if.hpp; sourceTree = ""; }; BFFCD0C70890389F00044EBA /* replace.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = replace.hpp; sourceTree = ""; }; BFFCD0C80890389F00044EBA /* replace_if.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = replace_if.hpp; sourceTree = ""; }; BFFCD0C90890389F00044EBA /* reverse.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse.hpp; sourceTree = ""; }; BFFCD0CA0890389F00044EBA /* reverse_fold.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse_fold.hpp; sourceTree = ""; }; BFFCD0CB0890389F00044EBA /* reverse_iter_fold.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse_iter_fold.hpp; sourceTree = ""; }; BFFCD0CC0890389F00044EBA /* same_as.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = same_as.hpp; sourceTree = ""; }; BFFCD0CD0890389F00044EBA /* sequence_tag.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = sequence_tag.hpp; sourceTree = ""; }; BFFCD0CE0890389F00044EBA /* sequence_tag_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = sequence_tag_fwd.hpp; sourceTree = ""; }; BFFCD0D10890389F00044EBA /* at_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = at_impl.hpp; sourceTree = ""; }; BFFCD0D20890389F00044EBA /* begin_end_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = begin_end_impl.hpp; sourceTree = ""; }; BFFCD0D30890389F00044EBA /* clear_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = clear_impl.hpp; sourceTree = ""; }; BFFCD0D4089038A000044EBA /* empty_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = empty_impl.hpp; sourceTree = ""; }; BFFCD0D5089038A000044EBA /* erase_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = erase_impl.hpp; sourceTree = ""; }; BFFCD0D6089038A000044EBA /* erase_key_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = erase_key_impl.hpp; sourceTree = ""; }; BFFCD0D7089038A000044EBA /* has_key_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = has_key_impl.hpp; sourceTree = ""; }; BFFCD0D8089038A000044EBA /* include_preprocessed.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = include_preprocessed.hpp; sourceTree = ""; }; BFFCD0D9089038A000044EBA /* insert_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = insert_impl.hpp; sourceTree = ""; }; BFFCD0DA089038A000044EBA /* item.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = item.hpp; sourceTree = ""; }; BFFCD0DB089038A000044EBA /* iterator.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iterator.hpp; sourceTree = ""; }; BFFCD0DC089038A000044EBA /* key_type_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = key_type_impl.hpp; sourceTree = ""; }; BFFCD0DD089038A000044EBA /* numbered.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = numbered.hpp; sourceTree = ""; }; BFFCD0DE089038A000044EBA /* numbered_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = numbered_c.hpp; sourceTree = ""; }; BFFCD0E1089038A000044EBA /* set10.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set10.hpp; sourceTree = ""; }; BFFCD0E2089038A000044EBA /* set10_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set10_c.hpp; sourceTree = ""; }; BFFCD0E3089038A000044EBA /* set20.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set20.hpp; sourceTree = ""; }; BFFCD0E4089038A000044EBA /* set20_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set20_c.hpp; sourceTree = ""; }; BFFCD0E5089038A000044EBA /* set30.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set30.hpp; sourceTree = ""; }; BFFCD0E6089038A000044EBA /* set30_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set30_c.hpp; sourceTree = ""; }; BFFCD0E7089038A000044EBA /* set40.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set40.hpp; sourceTree = ""; }; BFFCD0E8089038A000044EBA /* set40_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set40_c.hpp; sourceTree = ""; }; BFFCD0E9089038A000044EBA /* set50.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set50.hpp; sourceTree = ""; }; BFFCD0EA089038A000044EBA /* set50_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set50_c.hpp; sourceTree = ""; }; BFFCD0EB089038A000044EBA /* set0.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set0.hpp; sourceTree = ""; }; BFFCD0EC089038A000044EBA /* size_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = size_impl.hpp; sourceTree = ""; }; BFFCD0ED089038A000044EBA /* tag.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = tag.hpp; sourceTree = ""; }; BFFCD0EE089038A000044EBA /* value_type_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = value_type_impl.hpp; sourceTree = ""; }; BFFCD0EF089038A000044EBA /* set0.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set0.hpp; sourceTree = ""; }; BFFCD0F0089038A000044EBA /* set0_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set0_c.hpp; sourceTree = ""; }; BFFCD0F1089038A000044EBA /* set10.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set10.hpp; sourceTree = ""; }; BFFCD0F2089038A000044EBA /* set10_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set10_c.hpp; sourceTree = ""; }; BFFCD0F3089038A000044EBA /* set20.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set20.hpp; sourceTree = ""; }; BFFCD0F4089038A000044EBA /* set20_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set20_c.hpp; sourceTree = ""; }; BFFCD0F5089038A000044EBA /* set30.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set30.hpp; sourceTree = ""; }; BFFCD0F6089038A000044EBA /* set30_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set30_c.hpp; sourceTree = ""; }; BFFCD0F7089038A000044EBA /* set40.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set40.hpp; sourceTree = ""; }; BFFCD0F8089038A000044EBA /* set40_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set40_c.hpp; sourceTree = ""; }; BFFCD0F9089038A000044EBA /* set50.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set50.hpp; sourceTree = ""; }; BFFCD0FA089038A000044EBA /* set50_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set50_c.hpp; sourceTree = ""; }; BFFCD0FB089038A000044EBA /* set.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set.hpp; sourceTree = ""; }; BFFCD0FC089038A000044EBA /* set_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = set_c.hpp; sourceTree = ""; }; BFFCD0FD089038A000044EBA /* shift_left.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shift_left.hpp; sourceTree = ""; }; BFFCD0FE089038A000044EBA /* shift_right.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shift_right.hpp; sourceTree = ""; }; BFFCD0FF089038A000044EBA /* single_view.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = single_view.hpp; sourceTree = ""; }; BFFCD100089038A000044EBA /* size.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = size.hpp; sourceTree = ""; }; BFFCD101089038A000044EBA /* size_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = size_fwd.hpp; sourceTree = ""; }; BFFCD102089038A000044EBA /* size_t.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = size_t.hpp; sourceTree = ""; }; BFFCD103089038A000044EBA /* size_t_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = size_t_fwd.hpp; sourceTree = ""; }; BFFCD104089038A000044EBA /* sizeof.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = sizeof.hpp; sourceTree = ""; }; BFFCD105089038A000044EBA /* sort.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = sort.hpp; sourceTree = ""; }; BFFCD106089038A000044EBA /* stable_partition.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = stable_partition.hpp; sourceTree = ""; }; BFFCD107089038A000044EBA /* switch.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = switch.hpp; sourceTree = ""; }; BFFCD108089038A000044EBA /* tag.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = tag.hpp; sourceTree = ""; }; BFFCD109089038A000044EBA /* times.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = times.hpp; sourceTree = ""; }; BFFCD10A089038A000044EBA /* transform.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = transform.hpp; sourceTree = ""; }; BFFCD10B089038A000044EBA /* transform_view.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = transform_view.hpp; sourceTree = ""; }; BFFCD10C089038A000044EBA /* unique.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = unique.hpp; sourceTree = ""; }; BFFCD10D089038A000044EBA /* unpack_args.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = unpack_args.hpp; sourceTree = ""; }; BFFCD10E089038A000044EBA /* upper_bound.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = upper_bound.hpp; sourceTree = ""; }; BFFCD10F089038A000044EBA /* value_type.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = value_type.hpp; sourceTree = ""; }; BFFCD110089038A000044EBA /* value_type_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = value_type_fwd.hpp; sourceTree = ""; }; BFFCD113089038A000044EBA /* at.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = at.hpp; sourceTree = ""; }; BFFCD114089038A000044EBA /* back.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = back.hpp; sourceTree = ""; }; BFFCD115089038A000044EBA /* begin_end.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = begin_end.hpp; sourceTree = ""; }; BFFCD116089038A000044EBA /* clear.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = clear.hpp; sourceTree = ""; }; BFFCD117089038A000044EBA /* empty.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = empty.hpp; sourceTree = ""; }; BFFCD118089038A000044EBA /* front.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = front.hpp; sourceTree = ""; }; BFFCD119089038A000044EBA /* include_preprocessed.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = include_preprocessed.hpp; sourceTree = ""; }; BFFCD11A089038A000044EBA /* item.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = item.hpp; sourceTree = ""; }; BFFCD11B089038A000044EBA /* iterator.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iterator.hpp; sourceTree = ""; }; BFFCD11C089038A000044EBA /* numbered.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = numbered.hpp; sourceTree = ""; }; BFFCD11D089038A000044EBA /* numbered_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = numbered_c.hpp; sourceTree = ""; }; BFFCD11E089038A000044EBA /* O1_size.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = O1_size.hpp; sourceTree = ""; }; BFFCD11F089038A000044EBA /* pop_back.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = pop_back.hpp; sourceTree = ""; }; BFFCD120089038A000044EBA /* pop_front.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = pop_front.hpp; sourceTree = ""; }; BFFCD123089038A000044EBA /* vector10.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector10.hpp; sourceTree = ""; }; BFFCD124089038A000044EBA /* vector10_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector10_c.hpp; sourceTree = ""; }; BFFCD125089038A000044EBA /* vector20.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector20.hpp; sourceTree = ""; }; BFFCD126089038A000044EBA /* vector20_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector20_c.hpp; sourceTree = ""; }; BFFCD127089038A000044EBA /* vector30.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector30.hpp; sourceTree = ""; }; BFFCD128089038A000044EBA /* vector30_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector30_c.hpp; sourceTree = ""; }; BFFCD129089038A000044EBA /* vector40.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector40.hpp; sourceTree = ""; }; BFFCD12A089038A000044EBA /* vector40_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector40_c.hpp; sourceTree = ""; }; BFFCD12B089038A000044EBA /* vector50.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector50.hpp; sourceTree = ""; }; BFFCD12C089038A000044EBA /* vector50_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector50_c.hpp; sourceTree = ""; }; BFFCD12E089038A000044EBA /* vector10.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector10.hpp; sourceTree = ""; }; BFFCD12F089038A000044EBA /* vector10_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector10_c.hpp; sourceTree = ""; }; BFFCD130089038A000044EBA /* vector20.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector20.hpp; sourceTree = ""; }; BFFCD131089038A000044EBA /* vector20_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector20_c.hpp; sourceTree = ""; }; BFFCD132089038A000044EBA /* vector30.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector30.hpp; sourceTree = ""; }; BFFCD133089038A000044EBA /* vector30_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector30_c.hpp; sourceTree = ""; }; BFFCD134089038A000044EBA /* vector40.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector40.hpp; sourceTree = ""; }; BFFCD135089038A000044EBA /* vector40_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector40_c.hpp; sourceTree = ""; }; BFFCD136089038A000044EBA /* vector50.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector50.hpp; sourceTree = ""; }; BFFCD137089038A000044EBA /* vector50_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector50_c.hpp; sourceTree = ""; }; BFFCD139089038A000044EBA /* vector10.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector10.hpp; sourceTree = ""; }; BFFCD13A089038A000044EBA /* vector10_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector10_c.hpp; sourceTree = ""; }; BFFCD13B089038A000044EBA /* vector20.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector20.hpp; sourceTree = ""; }; BFFCD13C089038A000044EBA /* vector20_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector20_c.hpp; sourceTree = ""; }; BFFCD13D089038A000044EBA /* vector30.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector30.hpp; sourceTree = ""; }; BFFCD13E089038A000044EBA /* vector30_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector30_c.hpp; sourceTree = ""; }; BFFCD13F089038A000044EBA /* vector40.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector40.hpp; sourceTree = ""; }; BFFCD140089038A000044EBA /* vector40_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector40_c.hpp; sourceTree = ""; }; BFFCD141089038A000044EBA /* vector50.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector50.hpp; sourceTree = ""; }; BFFCD142089038A000044EBA /* vector50_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector50_c.hpp; sourceTree = ""; }; BFFCD143089038A000044EBA /* push_back.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = push_back.hpp; sourceTree = ""; }; BFFCD144089038A000044EBA /* push_front.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = push_front.hpp; sourceTree = ""; }; BFFCD145089038A000044EBA /* size.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = size.hpp; sourceTree = ""; }; BFFCD146089038A000044EBA /* tag.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = tag.hpp; sourceTree = ""; }; BFFCD147089038A000044EBA /* vector0.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector0.hpp; sourceTree = ""; }; BFFCD148089038A000044EBA /* vector0.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector0.hpp; sourceTree = ""; }; BFFCD149089038A000044EBA /* vector0_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector0_c.hpp; sourceTree = ""; }; BFFCD14A089038A000044EBA /* vector10.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector10.hpp; sourceTree = ""; }; BFFCD14B089038A000044EBA /* vector10_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector10_c.hpp; sourceTree = ""; }; BFFCD14C089038A000044EBA /* vector20.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector20.hpp; sourceTree = ""; }; BFFCD14D089038A000044EBA /* vector20_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector20_c.hpp; sourceTree = ""; }; BFFCD14E089038A000044EBA /* vector30.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector30.hpp; sourceTree = ""; }; BFFCD14F089038A000044EBA /* vector30_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector30_c.hpp; sourceTree = ""; }; BFFCD150089038A000044EBA /* vector40.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector40.hpp; sourceTree = ""; }; BFFCD151089038A000044EBA /* vector40_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector40_c.hpp; sourceTree = ""; }; BFFCD152089038A000044EBA /* vector50.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector50.hpp; sourceTree = ""; }; BFFCD153089038A000044EBA /* vector50_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector50_c.hpp; sourceTree = ""; }; BFFCD154089038A000044EBA /* vector.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector.hpp; sourceTree = ""; }; BFFCD155089038A000044EBA /* vector_c.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = vector_c.hpp; sourceTree = ""; }; BFFCD156089038A000044EBA /* void.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = void.hpp; sourceTree = ""; }; BFFCD157089038A000044EBA /* void_fwd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = void_fwd.hpp; sourceTree = ""; }; BFFCD158089038A000044EBA /* zip_view.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = zip_view.hpp; sourceTree = ""; }; BFFCD159089038A000044EBA /* operators.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = operators.hpp; sourceTree = ""; }; BFFCD15C089038A000044EBA /* add.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = add.hpp; sourceTree = ""; }; BFFCD15D089038A000044EBA /* dec.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = dec.hpp; sourceTree = ""; }; BFFCD15F089038A000044EBA /* div_base.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = div_base.hpp; sourceTree = ""; }; BFFCD160089038A000044EBA /* div.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = div.hpp; sourceTree = ""; }; BFFCD161089038A000044EBA /* inc.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = inc.hpp; sourceTree = ""; }; BFFCD162089038A000044EBA /* mod.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = mod.hpp; sourceTree = ""; }; BFFCD163089038A000044EBA /* mul.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = mul.hpp; sourceTree = ""; }; BFFCD164089038A000044EBA /* sub.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = sub.hpp; sourceTree = ""; }; BFFCD165089038A000044EBA /* arithmetic.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = arithmetic.hpp; sourceTree = ""; }; BFFCD167089038A000044EBA /* data.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = data.hpp; sourceTree = ""; }; BFFCD168089038A000044EBA /* elem.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = elem.hpp; sourceTree = ""; }; BFFCD169089038A100044EBA /* insert.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = insert.hpp; sourceTree = ""; }; BFFCD16A089038A100044EBA /* pop_back.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = pop_back.hpp; sourceTree = ""; }; BFFCD16B089038A100044EBA /* pop_front.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = pop_front.hpp; sourceTree = ""; }; BFFCD16C089038A100044EBA /* push_back.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = push_back.hpp; sourceTree = ""; }; BFFCD16D089038A100044EBA /* push_front.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = push_front.hpp; sourceTree = ""; }; BFFCD16E089038A100044EBA /* remove.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = remove.hpp; sourceTree = ""; }; BFFCD16F089038A100044EBA /* replace.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = replace.hpp; sourceTree = ""; }; BFFCD170089038A100044EBA /* reverse.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse.hpp; sourceTree = ""; }; BFFCD171089038A100044EBA /* size.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = size.hpp; sourceTree = ""; }; BFFCD172089038A100044EBA /* array.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = array.hpp; sourceTree = ""; }; BFFCD173089038A100044EBA /* assert_msg.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = assert_msg.hpp; sourceTree = ""; }; BFFCD174089038A100044EBA /* cat.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = cat.hpp; sourceTree = ""; }; BFFCD175089038A100044EBA /* comma.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = comma.hpp; sourceTree = ""; }; BFFCD176089038A100044EBA /* comma_if.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = comma_if.hpp; sourceTree = ""; }; BFFCD178089038A100044EBA /* equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = equal.hpp; sourceTree = ""; }; BFFCD179089038A100044EBA /* greater.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = greater.hpp; sourceTree = ""; }; BFFCD17A089038A100044EBA /* greater_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = greater_equal.hpp; sourceTree = ""; }; BFFCD17B089038A100044EBA /* less.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = less.hpp; sourceTree = ""; }; BFFCD17C089038A100044EBA /* less_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = less_equal.hpp; sourceTree = ""; }; BFFCD17D089038A100044EBA /* not_equal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = not_equal.hpp; sourceTree = ""; }; BFFCD17E089038A100044EBA /* comparison.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = comparison.hpp; sourceTree = ""; }; BFFCD180089038A100044EBA /* config.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = config.hpp; sourceTree = ""; }; BFFCD181089038A100044EBA /* limits.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = limits.hpp; sourceTree = ""; }; BFFCD183089038A100044EBA /* deduce_d.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = deduce_d.hpp; sourceTree = ""; }; BFFCD186089038A100044EBA /* while.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = while.hpp; sourceTree = ""; }; BFFCD188089038A100044EBA /* while.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = while.hpp; sourceTree = ""; }; BFFCD18A089038A100044EBA /* while.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = while.hpp; sourceTree = ""; }; BFFCD18B089038A100044EBA /* while.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = while.hpp; sourceTree = ""; }; BFFCD18C089038A100044EBA /* expr_if.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = expr_if.hpp; sourceTree = ""; }; BFFCD18D089038A100044EBA /* expr_iif.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = expr_iif.hpp; sourceTree = ""; }; BFFCD18E089038A100044EBA /* if.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = if.hpp; sourceTree = ""; }; BFFCD18F089038A100044EBA /* iif.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iif.hpp; sourceTree = ""; }; BFFCD190089038A100044EBA /* while.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = while.hpp; sourceTree = ""; }; BFFCD191089038A100044EBA /* control.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = control.hpp; sourceTree = ""; }; BFFCD193089038A100044EBA /* assert.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = assert.hpp; sourceTree = ""; }; BFFCD194089038A100044EBA /* error.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = error.hpp; sourceTree = ""; }; BFFCD195089038A100044EBA /* line.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = line.hpp; sourceTree = ""; }; BFFCD196089038A100044EBA /* debug.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = debug.hpp; sourceTree = ""; }; BFFCD197089038A100044EBA /* dec.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = dec.hpp; sourceTree = ""; }; BFFCD199089038A100044EBA /* auto_rec.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = auto_rec.hpp; sourceTree = ""; }; BFFCD19A089038A100044EBA /* check.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = check.hpp; sourceTree = ""; }; BFFCD19C089038A100044EBA /* auto_rec.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = auto_rec.hpp; sourceTree = ""; }; BFFCD19D089038A100044EBA /* is_binary.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_binary.hpp; sourceTree = ""; }; BFFCD19E089038A100044EBA /* is_nullary.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_nullary.hpp; sourceTree = ""; }; BFFCD19F089038A100044EBA /* is_unary.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_unary.hpp; sourceTree = ""; }; BFFCD1A0089038A100044EBA /* null.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = null.hpp; sourceTree = ""; }; BFFCD1A1089038A100044EBA /* split.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = split.hpp; sourceTree = ""; }; BFFCD1A2089038A100044EBA /* empty.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = empty.hpp; sourceTree = ""; }; BFFCD1A3089038A100044EBA /* enum.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = enum.hpp; sourceTree = ""; }; BFFCD1A4089038A100044EBA /* enum_params.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = enum_params.hpp; sourceTree = ""; }; BFFCD1A5089038A100044EBA /* enum_params_with_a_default.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = enum_params_with_a_default.hpp; sourceTree = ""; }; BFFCD1A6089038A100044EBA /* enum_params_with_defaults.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = enum_params_with_defaults.hpp; sourceTree = ""; }; BFFCD1A7089038A100044EBA /* enum_shifted.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = enum_shifted.hpp; sourceTree = ""; }; BFFCD1A8089038A100044EBA /* enum_shifted_params.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = enum_shifted_params.hpp; sourceTree = ""; }; BFFCD1A9089038A100044EBA /* expand.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = expand.hpp; sourceTree = ""; }; BFFCD1AA089038A100044EBA /* expr_if.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = expr_if.hpp; sourceTree = ""; }; BFFCD1AC089038A100044EBA /* apply.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = apply.hpp; sourceTree = ""; }; BFFCD1AD089038A100044EBA /* empty.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = empty.hpp; sourceTree = ""; }; BFFCD1AE089038A100044EBA /* expand.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = expand.hpp; sourceTree = ""; }; BFFCD1AF089038A100044EBA /* identity.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = identity.hpp; sourceTree = ""; }; BFFCD1B0089038A100044EBA /* intercept.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = intercept.hpp; sourceTree = ""; }; BFFCD1B1089038A100044EBA /* is_1.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_1.hpp; sourceTree = ""; }; BFFCD1B2089038A100044EBA /* is_empty.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_empty.hpp; sourceTree = ""; }; BFFCD1B3089038A100044EBA /* is_empty_or_1.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_empty_or_1.hpp; sourceTree = ""; }; BFFCD1B4089038A100044EBA /* facilities.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = facilities.hpp; sourceTree = ""; }; BFFCD1B5089038A100044EBA /* for.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = for.hpp; sourceTree = ""; }; BFFCD1B6089038A100044EBA /* identity.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = identity.hpp; sourceTree = ""; }; BFFCD1B7089038A100044EBA /* if.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = if.hpp; sourceTree = ""; }; BFFCD1B8089038A100044EBA /* inc.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = inc.hpp; sourceTree = ""; }; BFFCD1B9089038A100044EBA /* iterate.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iterate.hpp; sourceTree = ""; }; BFFCD1BD089038A100044EBA /* lower1.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lower1.hpp; sourceTree = ""; }; BFFCD1BE089038A100044EBA /* lower2.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lower2.hpp; sourceTree = ""; }; BFFCD1BF089038A100044EBA /* lower3.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lower3.hpp; sourceTree = ""; }; BFFCD1C0089038A100044EBA /* lower4.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lower4.hpp; sourceTree = ""; }; BFFCD1C1089038A100044EBA /* lower5.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = lower5.hpp; sourceTree = ""; }; BFFCD1C2089038A100044EBA /* upper1.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = upper1.hpp; sourceTree = ""; }; BFFCD1C3089038A100044EBA /* upper2.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = upper2.hpp; sourceTree = ""; }; BFFCD1C4089038A100044EBA /* upper3.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = upper3.hpp; sourceTree = ""; }; BFFCD1C5089038A100044EBA /* upper4.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = upper4.hpp; sourceTree = ""; }; BFFCD1C6089038A100044EBA /* upper5.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = upper5.hpp; sourceTree = ""; }; BFFCD1C7089038A100044EBA /* finish.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = finish.hpp; sourceTree = ""; }; BFFCD1C9089038A100044EBA /* forward1.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = forward1.hpp; sourceTree = ""; }; BFFCD1CA089038A100044EBA /* forward2.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = forward2.hpp; sourceTree = ""; }; BFFCD1CB089038A100044EBA /* forward3.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = forward3.hpp; sourceTree = ""; }; BFFCD1CC089038A100044EBA /* forward4.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = forward4.hpp; sourceTree = ""; }; BFFCD1CD089038A100044EBA /* forward5.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = forward5.hpp; sourceTree = ""; }; BFFCD1CE089038A100044EBA /* reverse1.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse1.hpp; sourceTree = ""; }; BFFCD1CF089038A100044EBA /* reverse2.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse2.hpp; sourceTree = ""; }; BFFCD1D0089038A100044EBA /* reverse3.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse3.hpp; sourceTree = ""; }; BFFCD1D1089038A100044EBA /* reverse4.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse4.hpp; sourceTree = ""; }; BFFCD1D2089038A100044EBA /* reverse5.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse5.hpp; sourceTree = ""; }; BFFCD1D3089038A100044EBA /* local.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = local.hpp; sourceTree = ""; }; BFFCD1D4089038A200044EBA /* rlocal.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = rlocal.hpp; sourceTree = ""; }; BFFCD1D5089038A200044EBA /* self.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = self.hpp; sourceTree = ""; }; BFFCD1D6089038A200044EBA /* start.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = start.hpp; sourceTree = ""; }; BFFCD1D7089038A200044EBA /* iterate.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iterate.hpp; sourceTree = ""; }; BFFCD1D8089038A200044EBA /* local.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = local.hpp; sourceTree = ""; }; BFFCD1D9089038A200044EBA /* self.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = self.hpp; sourceTree = ""; }; BFFCD1DA089038A200044EBA /* iteration.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = iteration.hpp; sourceTree = ""; }; BFFCD1DB089038A200044EBA /* library.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = library.hpp; sourceTree = ""; }; BFFCD1DC089038A200044EBA /* limits.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = limits.hpp; sourceTree = ""; }; BFFCD1DE089038A200044EBA /* adt.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = adt.hpp; sourceTree = ""; }; BFFCD1DF089038A200044EBA /* append.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = append.hpp; sourceTree = ""; }; BFFCD1E0089038A200044EBA /* at.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = at.hpp; sourceTree = ""; }; BFFCD1E1089038A200044EBA /* cat.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = cat.hpp; sourceTree = ""; }; BFFCD1E4089038A200044EBA /* fold_left.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = fold_left.hpp; sourceTree = ""; }; BFFCD1E6089038A200044EBA /* fold_left.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = fold_left.hpp; sourceTree = ""; }; BFFCD1E7089038A200044EBA /* fold_right.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = fold_right.hpp; sourceTree = ""; }; BFFCD1E8089038A200044EBA /* fold_left.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = fold_left.hpp; sourceTree = ""; }; BFFCD1E9089038A200044EBA /* fold_right.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = fold_right.hpp; sourceTree = ""; }; BFFCD1EA089038A200044EBA /* enum.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = enum.hpp; sourceTree = ""; }; BFFCD1EB089038A200044EBA /* filter.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = filter.hpp; sourceTree = ""; }; BFFCD1EC089038A200044EBA /* first_n.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = first_n.hpp; sourceTree = ""; }; BFFCD1ED089038A200044EBA /* fold_left.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = fold_left.hpp; sourceTree = ""; }; BFFCD1EE089038A200044EBA /* fold_right.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = fold_right.hpp; sourceTree = ""; }; BFFCD1EF089038A200044EBA /* for_each.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = for_each.hpp; sourceTree = ""; }; BFFCD1F0089038A200044EBA /* for_each_i.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = for_each_i.hpp; sourceTree = ""; }; BFFCD1F1089038A200044EBA /* for_each_product.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = for_each_product.hpp; sourceTree = ""; }; BFFCD1F2089038A200044EBA /* rest_n.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = rest_n.hpp; sourceTree = ""; }; BFFCD1F3089038A200044EBA /* reverse.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse.hpp; sourceTree = ""; }; BFFCD1F4089038A200044EBA /* size.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = size.hpp; sourceTree = ""; }; BFFCD1F5089038A200044EBA /* to_tuple.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = to_tuple.hpp; sourceTree = ""; }; BFFCD1F6089038A200044EBA /* transform.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = transform.hpp; sourceTree = ""; }; BFFCD1F7089038A200044EBA /* list.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = list.hpp; sourceTree = ""; }; BFFCD1F9089038A200044EBA /* and.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = and.hpp; sourceTree = ""; }; BFFCD1FA089038A200044EBA /* bitand.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitand.hpp; sourceTree = ""; }; BFFCD1FB089038A200044EBA /* bitnor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitnor.hpp; sourceTree = ""; }; BFFCD1FC089038A200044EBA /* bitor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitor.hpp; sourceTree = ""; }; BFFCD1FD089038A200044EBA /* bitxor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bitxor.hpp; sourceTree = ""; }; BFFCD1FE089038A200044EBA /* bool.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bool.hpp; sourceTree = ""; }; BFFCD1FF089038A200044EBA /* compl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = compl.hpp; sourceTree = ""; }; BFFCD200089038A200044EBA /* nor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = nor.hpp; sourceTree = ""; }; BFFCD201089038A200044EBA /* not.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = not.hpp; sourceTree = ""; }; BFFCD202089038A200044EBA /* or.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = or.hpp; sourceTree = ""; }; BFFCD203089038A200044EBA /* xor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = xor.hpp; sourceTree = ""; }; BFFCD204089038A200044EBA /* logical.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = logical.hpp; sourceTree = ""; }; BFFCD205089038A200044EBA /* max.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = max.hpp; sourceTree = ""; }; BFFCD206089038A200044EBA /* min.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = min.hpp; sourceTree = ""; }; BFFCD208089038A200044EBA /* comma.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = comma.hpp; sourceTree = ""; }; BFFCD209089038A200044EBA /* comma_if.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = comma_if.hpp; sourceTree = ""; }; BFFCD20A089038A200044EBA /* paren.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = paren.hpp; sourceTree = ""; }; BFFCD20B089038A200044EBA /* paren_if.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = paren_if.hpp; sourceTree = ""; }; BFFCD20C089038A200044EBA /* punctuation.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = punctuation.hpp; sourceTree = ""; }; BFFCD20D089038A200044EBA /* repeat.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = repeat.hpp; sourceTree = ""; }; BFFCD20E089038A200044EBA /* repeat_2nd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = repeat_2nd.hpp; sourceTree = ""; }; BFFCD20F089038A200044EBA /* repeat_3rd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = repeat_3rd.hpp; sourceTree = ""; }; BFFCD210089038A200044EBA /* repeat_from_to.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = repeat_from_to.hpp; sourceTree = ""; }; BFFCD211089038A200044EBA /* repeat_from_to_2nd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = repeat_from_to_2nd.hpp; sourceTree = ""; }; BFFCD212089038A200044EBA /* repeat_from_to_3rd.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = repeat_from_to_3rd.hpp; sourceTree = ""; }; BFFCD214089038A200044EBA /* deduce_r.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = deduce_r.hpp; sourceTree = ""; }; BFFCD215089038A200044EBA /* deduce_z.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = deduce_z.hpp; sourceTree = ""; }; BFFCD218089038A200044EBA /* for.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = for.hpp; sourceTree = ""; }; BFFCD21A089038A200044EBA /* for.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = for.hpp; sourceTree = ""; }; BFFCD21B089038A200044EBA /* for.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = for.hpp; sourceTree = ""; }; BFFCD21D089038A200044EBA /* for.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = for.hpp; sourceTree = ""; }; BFFCD21E089038A200044EBA /* enum.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = enum.hpp; sourceTree = ""; }; BFFCD21F089038A200044EBA /* enum_binary_params.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = enum_binary_params.hpp; sourceTree = ""; }; BFFCD220089038A200044EBA /* enum_params.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = enum_params.hpp; sourceTree = ""; }; BFFCD221089038A200044EBA /* enum_params_with_a_default.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = enum_params_with_a_default.hpp; sourceTree = ""; }; BFFCD222089038A200044EBA /* enum_params_with_defaults.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = enum_params_with_defaults.hpp; sourceTree = ""; }; BFFCD223089038A200044EBA /* enum_shifted.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = enum_shifted.hpp; sourceTree = ""; }; BFFCD224089038A200044EBA /* enum_shifted_params.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = enum_shifted_params.hpp; sourceTree = ""; }; BFFCD225089038A200044EBA /* enum_trailing.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = enum_trailing.hpp; sourceTree = ""; }; BFFCD226089038A200044EBA /* enum_trailing_binary_params.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = enum_trailing_binary_params.hpp; sourceTree = ""; }; BFFCD227089038A200044EBA /* enum_trailing_params.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = enum_trailing_params.hpp; sourceTree = ""; }; BFFCD228089038A200044EBA /* for.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = for.hpp; sourceTree = ""; }; BFFCD229089038A200044EBA /* repeat.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = repeat.hpp; sourceTree = ""; }; BFFCD22A089038A200044EBA /* repeat_from_to.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = repeat_from_to.hpp; sourceTree = ""; }; BFFCD22B089038A200044EBA /* repetition.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = repetition.hpp; sourceTree = ""; }; BFFCD22D089038A200044EBA /* max.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = max.hpp; sourceTree = ""; }; BFFCD22E089038A200044EBA /* min.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = min.hpp; sourceTree = ""; }; BFFCD22F089038A200044EBA /* selection.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = selection.hpp; sourceTree = ""; }; BFFCD231089038A200044EBA /* cat.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = cat.hpp; sourceTree = ""; }; BFFCD233089038A200044EBA /* split.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = split.hpp; sourceTree = ""; }; BFFCD234089038A200044EBA /* elem.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = elem.hpp; sourceTree = ""; }; BFFCD235089038A200044EBA /* enum.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = enum.hpp; sourceTree = ""; }; BFFCD236089038A200044EBA /* filter.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = filter.hpp; sourceTree = ""; }; BFFCD237089038A200044EBA /* first_n.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = first_n.hpp; sourceTree = ""; }; BFFCD238089038A200044EBA /* fold_left.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = fold_left.hpp; sourceTree = ""; }; BFFCD239089038A200044EBA /* fold_right.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = fold_right.hpp; sourceTree = ""; }; BFFCD23A089038A200044EBA /* for_each.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = for_each.hpp; sourceTree = ""; }; BFFCD23B089038A200044EBA /* for_each_i.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = for_each_i.hpp; sourceTree = ""; }; BFFCD23C089038A200044EBA /* for_each_product.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = for_each_product.hpp; sourceTree = ""; }; BFFCD23D089038A200044EBA /* insert.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = insert.hpp; sourceTree = ""; }; BFFCD23E089038A200044EBA /* pop_back.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = pop_back.hpp; sourceTree = ""; }; BFFCD23F089038A200044EBA /* pop_front.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = pop_front.hpp; sourceTree = ""; }; BFFCD240089038A200044EBA /* push_back.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = push_back.hpp; sourceTree = ""; }; BFFCD241089038A200044EBA /* push_front.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = push_front.hpp; sourceTree = ""; }; BFFCD242089038A200044EBA /* remove.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = remove.hpp; sourceTree = ""; }; BFFCD243089038A200044EBA /* replace.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = replace.hpp; sourceTree = ""; }; BFFCD244089038A200044EBA /* rest_n.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = rest_n.hpp; sourceTree = ""; }; BFFCD245089038A200044EBA /* reverse.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse.hpp; sourceTree = ""; }; BFFCD246089038A200044EBA /* seq.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = seq.hpp; sourceTree = ""; }; BFFCD247089038A200044EBA /* size.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = size.hpp; sourceTree = ""; }; BFFCD248089038A200044EBA /* subseq.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = subseq.hpp; sourceTree = ""; }; BFFCD249089038A200044EBA /* to_array.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = to_array.hpp; sourceTree = ""; }; BFFCD24A089038A200044EBA /* to_tuple.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = to_tuple.hpp; sourceTree = ""; }; BFFCD24B089038A200044EBA /* transform.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = transform.hpp; sourceTree = ""; }; BFFCD24C089038A200044EBA /* seq.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = seq.hpp; sourceTree = ""; }; BFFCD24F089038A200044EBA /* def.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = def.hpp; sourceTree = ""; }; BFFCD250089038A200044EBA /* shared.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = shared.hpp; sourceTree = ""; }; BFFCD251089038A200044EBA /* slot1.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = slot1.hpp; sourceTree = ""; }; BFFCD252089038A200044EBA /* slot2.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = slot2.hpp; sourceTree = ""; }; BFFCD253089038A200044EBA /* slot3.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = slot3.hpp; sourceTree = ""; }; BFFCD254089038A200044EBA /* slot4.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = slot4.hpp; sourceTree = ""; }; BFFCD255089038A300044EBA /* slot5.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = slot5.hpp; sourceTree = ""; }; BFFCD256089038A300044EBA /* slot.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = slot.hpp; sourceTree = ""; }; BFFCD257089038A300044EBA /* slot.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = slot.hpp; sourceTree = ""; }; BFFCD258089038A300044EBA /* stringize.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = stringize.hpp; sourceTree = ""; }; BFFCD25A089038A300044EBA /* eat.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = eat.hpp; sourceTree = ""; }; BFFCD25B089038A300044EBA /* elem.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = elem.hpp; sourceTree = ""; }; BFFCD25C089038A300044EBA /* rem.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = rem.hpp; sourceTree = ""; }; BFFCD25D089038A300044EBA /* reverse.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reverse.hpp; sourceTree = ""; }; BFFCD25E089038A300044EBA /* to_list.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = to_list.hpp; sourceTree = ""; }; BFFCD25F089038A300044EBA /* to_seq.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = to_seq.hpp; sourceTree = ""; }; BFFCD260089038A300044EBA /* tuple.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = tuple.hpp; sourceTree = ""; }; BFFCD261089038A300044EBA /* while.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = while.hpp; sourceTree = ""; }; BFFCD262089038A300044EBA /* wstringize.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = wstringize.hpp; sourceTree = ""; }; BFFCD263089038A300044EBA /* preprocessor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = preprocessor.hpp; sourceTree = ""; }; BFFCD264089038A300044EBA /* rational.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = rational.hpp; sourceTree = ""; }; BFFCD265089038A300044EBA /* static_assert.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = static_assert.hpp; sourceTree = ""; }; BFFCD267089038A300044EBA /* add_const.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = add_const.hpp; sourceTree = ""; }; BFFCD268089038A300044EBA /* add_cv.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = add_cv.hpp; sourceTree = ""; }; BFFCD269089038A300044EBA /* add_pointer.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = add_pointer.hpp; sourceTree = ""; }; BFFCD26A089038A300044EBA /* add_reference.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = add_reference.hpp; sourceTree = ""; }; BFFCD26B089038A300044EBA /* add_volatile.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = add_volatile.hpp; sourceTree = ""; }; BFFCD26C089038A300044EBA /* aligned_storage.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = aligned_storage.hpp; sourceTree = ""; }; BFFCD26D089038A300044EBA /* alignment_of.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = alignment_of.hpp; sourceTree = ""; }; BFFCD26E089038A300044EBA /* alignment_traits.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = alignment_traits.hpp; sourceTree = ""; }; BFFCD26F089038A300044EBA /* arithmetic_traits.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = arithmetic_traits.hpp; sourceTree = ""; }; BFFCD270089038A300044EBA /* array_traits.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = array_traits.hpp; sourceTree = ""; }; BFFCD271089038A300044EBA /* broken_compiler_spec.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = broken_compiler_spec.hpp; sourceTree = ""; }; BFFCD272089038A300044EBA /* composite_traits.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = composite_traits.hpp; sourceTree = ""; }; BFFCD273089038A300044EBA /* config.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = config.hpp; sourceTree = ""; }; BFFCD274089038A300044EBA /* conversion_traits.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = conversion_traits.hpp; sourceTree = ""; }; BFFCD275089038A300044EBA /* cv_traits.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = cv_traits.hpp; sourceTree = ""; }; BFFCD276089038A300044EBA /* decay.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = decay.hpp; sourceTree = ""; }; BFFCD278089038A300044EBA /* bool_trait_def.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bool_trait_def.hpp; sourceTree = ""; }; BFFCD279089038A300044EBA /* bool_trait_undef.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = bool_trait_undef.hpp; sourceTree = ""; }; BFFCD27A089038A300044EBA /* cv_traits_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = cv_traits_impl.hpp; sourceTree = ""; }; BFFCD27B089038A300044EBA /* false_result.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = false_result.hpp; sourceTree = ""; }; BFFCD27C089038A300044EBA /* ice_and.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = ice_and.hpp; sourceTree = ""; }; BFFCD27D089038A300044EBA /* ice_eq.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = ice_eq.hpp; sourceTree = ""; }; BFFCD27E089038A300044EBA /* ice_not.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = ice_not.hpp; sourceTree = ""; }; BFFCD27F089038A300044EBA /* ice_or.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = ice_or.hpp; sourceTree = ""; }; BFFCD280089038A300044EBA /* is_function_ptr_helper.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_function_ptr_helper.hpp; sourceTree = ""; }; BFFCD281089038A300044EBA /* is_function_ptr_tester.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_function_ptr_tester.hpp; sourceTree = ""; }; BFFCD282089038A300044EBA /* is_mem_fun_pointer_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_mem_fun_pointer_impl.hpp; sourceTree = ""; }; BFFCD283089038A300044EBA /* is_mem_fun_pointer_tester.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_mem_fun_pointer_tester.hpp; sourceTree = ""; }; BFFCD284089038A300044EBA /* size_t_trait_def.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = size_t_trait_def.hpp; sourceTree = ""; }; BFFCD285089038A300044EBA /* size_t_trait_undef.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = size_t_trait_undef.hpp; sourceTree = ""; }; BFFCD286089038A300044EBA /* template_arity_spec.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = template_arity_spec.hpp; sourceTree = ""; }; BFFCD287089038A300044EBA /* type_trait_def.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = type_trait_def.hpp; sourceTree = ""; }; BFFCD288089038A300044EBA /* type_trait_undef.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = type_trait_undef.hpp; sourceTree = ""; }; BFFCD289089038A300044EBA /* wrap.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = wrap.hpp; sourceTree = ""; }; BFFCD28A089038A300044EBA /* yes_no_type.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = yes_no_type.hpp; sourceTree = ""; }; BFFCD28B089038A300044EBA /* extent.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = extent.hpp; sourceTree = ""; }; BFFCD28C089038A300044EBA /* function_traits.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = function_traits.hpp; sourceTree = ""; }; BFFCD28D089038A300044EBA /* has_nothrow_assign.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = has_nothrow_assign.hpp; sourceTree = ""; }; BFFCD28E089038A300044EBA /* has_nothrow_constructor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = has_nothrow_constructor.hpp; sourceTree = ""; }; BFFCD28F089038A300044EBA /* has_nothrow_copy.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = has_nothrow_copy.hpp; sourceTree = ""; }; BFFCD290089038A300044EBA /* has_nothrow_destructor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = has_nothrow_destructor.hpp; sourceTree = ""; }; BFFCD291089038A300044EBA /* has_trivial_assign.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = has_trivial_assign.hpp; sourceTree = ""; }; BFFCD292089038A300044EBA /* has_trivial_constructor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = has_trivial_constructor.hpp; sourceTree = ""; }; BFFCD293089038A300044EBA /* has_trivial_copy.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = has_trivial_copy.hpp; sourceTree = ""; }; BFFCD294089038A300044EBA /* has_trivial_destructor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = has_trivial_destructor.hpp; sourceTree = ""; }; BFFCD295089038A300044EBA /* has_virtual_destructor.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = has_virtual_destructor.hpp; sourceTree = ""; }; BFFCD296089038A300044EBA /* ice.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = ice.hpp; sourceTree = ""; }; BFFCD297089038A300044EBA /* integral_constant.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = integral_constant.hpp; sourceTree = ""; }; BFFCD298089038A300044EBA /* intrinsics.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = intrinsics.hpp; sourceTree = ""; }; BFFCD299089038A300044EBA /* is_abstract.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_abstract.hpp; sourceTree = ""; }; BFFCD29A089038A300044EBA /* is_arithmetic.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_arithmetic.hpp; sourceTree = ""; }; BFFCD29B089038A300044EBA /* is_array.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_array.hpp; sourceTree = ""; }; BFFCD29C089038A300044EBA /* is_base_and_derived.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_base_and_derived.hpp; sourceTree = ""; }; BFFCD29D089038A300044EBA /* is_base_of.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_base_of.hpp; sourceTree = ""; }; BFFCD29E089038A300044EBA /* is_class.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_class.hpp; sourceTree = ""; }; BFFCD29F089038A300044EBA /* is_compound.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_compound.hpp; sourceTree = ""; }; BFFCD2A0089038A300044EBA /* is_const.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_const.hpp; sourceTree = ""; }; BFFCD2A1089038A300044EBA /* is_convertible.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_convertible.hpp; sourceTree = ""; }; BFFCD2A2089038A300044EBA /* is_empty.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_empty.hpp; sourceTree = ""; }; BFFCD2A3089038A300044EBA /* is_enum.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_enum.hpp; sourceTree = ""; }; BFFCD2A4089038A300044EBA /* is_float.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_float.hpp; sourceTree = ""; }; BFFCD2A5089038A300044EBA /* is_floating_point.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_floating_point.hpp; sourceTree = ""; }; BFFCD2A6089038A300044EBA /* is_function.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_function.hpp; sourceTree = ""; }; BFFCD2A7089038A300044EBA /* is_fundamental.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_fundamental.hpp; sourceTree = ""; }; BFFCD2A8089038A300044EBA /* is_integral.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_integral.hpp; sourceTree = ""; }; BFFCD2A9089038A300044EBA /* is_member_function_pointer.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_member_function_pointer.hpp; sourceTree = ""; }; BFFCD2AA089038A300044EBA /* is_member_object_pointer.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_member_object_pointer.hpp; sourceTree = ""; }; BFFCD2AB089038A300044EBA /* is_member_pointer.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_member_pointer.hpp; sourceTree = ""; }; BFFCD2AC089038A300044EBA /* is_object.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_object.hpp; sourceTree = ""; }; BFFCD2AD089038A300044EBA /* is_pod.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_pod.hpp; sourceTree = ""; }; BFFCD2AE089038A300044EBA /* is_pointer.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_pointer.hpp; sourceTree = ""; }; BFFCD2AF089038A300044EBA /* is_polymorphic.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_polymorphic.hpp; sourceTree = ""; }; BFFCD2B0089038A400044EBA /* is_reference.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_reference.hpp; sourceTree = ""; }; BFFCD2B1089038A400044EBA /* is_same.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_same.hpp; sourceTree = ""; }; BFFCD2B2089038A400044EBA /* is_scalar.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_scalar.hpp; sourceTree = ""; }; BFFCD2B3089038A400044EBA /* is_signed.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_signed.hpp; sourceTree = ""; }; BFFCD2B4089038A400044EBA /* is_stateless.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_stateless.hpp; sourceTree = ""; }; BFFCD2B5089038A400044EBA /* is_union.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_union.hpp; sourceTree = ""; }; BFFCD2B6089038A400044EBA /* is_unsigned.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_unsigned.hpp; sourceTree = ""; }; BFFCD2B7089038A400044EBA /* is_void.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_void.hpp; sourceTree = ""; }; BFFCD2B8089038A400044EBA /* is_volatile.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = is_volatile.hpp; sourceTree = ""; }; BFFCD2B9089038A400044EBA /* object_traits.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = object_traits.hpp; sourceTree = ""; }; BFFCD2BA089038A400044EBA /* rank.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = rank.hpp; sourceTree = ""; }; BFFCD2BB089038A400044EBA /* reference_traits.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = reference_traits.hpp; sourceTree = ""; }; BFFCD2BC089038A400044EBA /* remove_all_extents.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = remove_all_extents.hpp; sourceTree = ""; }; BFFCD2BD089038A400044EBA /* remove_bounds.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = remove_bounds.hpp; sourceTree = ""; }; BFFCD2BE089038A400044EBA /* remove_const.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = remove_const.hpp; sourceTree = ""; }; BFFCD2BF089038A400044EBA /* remove_cv.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = remove_cv.hpp; sourceTree = ""; }; BFFCD2C0089038A400044EBA /* remove_extent.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = remove_extent.hpp; sourceTree = ""; }; BFFCD2C1089038A400044EBA /* remove_pointer.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = remove_pointer.hpp; sourceTree = ""; }; BFFCD2C2089038A400044EBA /* remove_reference.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = remove_reference.hpp; sourceTree = ""; }; BFFCD2C3089038A400044EBA /* remove_volatile.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = remove_volatile.hpp; sourceTree = ""; }; BFFCD2C4089038A400044EBA /* same_traits.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = same_traits.hpp; sourceTree = ""; }; BFFCD2C5089038A400044EBA /* transform_traits.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = transform_traits.hpp; sourceTree = ""; }; BFFCD2C6089038A400044EBA /* transform_traits_spec.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = transform_traits_spec.hpp; sourceTree = ""; }; BFFCD2C7089038A400044EBA /* type_with_alignment.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = type_with_alignment.hpp; sourceTree = ""; }; BFFCD2C8089038A400044EBA /* type_traits.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = type_traits.hpp; sourceTree = ""; }; BFFCD88A089041A600044EBA /* Fox-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Fox-Info.plist"; sourceTree = SOURCE_ROOT; }; BFFCD88E0890422000044EBA /* Fox.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Fox.cpp; path = src/Fox.cpp; sourceTree = SOURCE_ROOT; }; BFFCD8900890426600044EBA /* Atom.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Atom.cpp; path = ../ObjCryst/ObjCryst/Atom.cpp; sourceTree = SOURCE_ROOT; }; BFFCD8910890426600044EBA /* Crystal.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Crystal.cpp; path = ../ObjCryst/ObjCryst/Crystal.cpp; sourceTree = SOURCE_ROOT; }; BFFCD8920890426600044EBA /* CrystVector.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = CrystVector.cpp; path = ../ObjCryst/CrystVector/CrystVector.cpp; sourceTree = ""; }; BFFCD8930890426600044EBA /* DiffractionDataSingleCrystal.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = DiffractionDataSingleCrystal.cpp; path = ../ObjCryst/ObjCryst/DiffractionDataSingleCrystal.cpp; sourceTree = SOURCE_ROOT; }; BFFCD8940890426600044EBA /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Exception.cpp; path = ../ObjCryst/ObjCryst/Exception.cpp; sourceTree = ""; }; BFFCD8960890426600044EBA /* geomStructFactor_001.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = geomStructFactor_001.cpp; path = ../ObjCryst/ObjCryst/geomStructFactor_001.cpp; sourceTree = SOURCE_ROOT; }; BFFCD8970890426600044EBA /* geomStructFactor_002.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = geomStructFactor_002.cpp; path = ../ObjCryst/ObjCryst/geomStructFactor_002.cpp; sourceTree = SOURCE_ROOT; }; BFFCD8980890426600044EBA /* geomStructFactor_067.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = geomStructFactor_067.cpp; path = ../ObjCryst/ObjCryst/geomStructFactor_067.cpp; sourceTree = SOURCE_ROOT; }; BFFCD8990890426600044EBA /* geomStructFactor_097.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = geomStructFactor_097.cpp; path = ../ObjCryst/ObjCryst/geomStructFactor_097.cpp; sourceTree = SOURCE_ROOT; }; BFFCD89A0890426600044EBA /* geomStructFactor_230.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = geomStructFactor_230.cpp; path = ../ObjCryst/ObjCryst/geomStructFactor_230.cpp; sourceTree = SOURCE_ROOT; }; BFFCD89B0890426600044EBA /* geomStructFactor_centro.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = geomStructFactor_centro.cpp; path = ../ObjCryst/ObjCryst/geomStructFactor_centro.cpp; sourceTree = SOURCE_ROOT; }; BFFCD89C0890426600044EBA /* geomStructFactor.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = geomStructFactor.cpp; path = ../ObjCryst/ObjCryst/geomStructFactor.cpp; sourceTree = SOURCE_ROOT; }; BFFCD89D0890426600044EBA /* GlobalOptimObj.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = GlobalOptimObj.cpp; path = ../ObjCryst/RefinableObj/GlobalOptimObj.cpp; sourceTree = ""; }; BFFCD89E0890426600044EBA /* IO.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = IO.cpp; path = ../ObjCryst/ObjCryst/IO.cpp; sourceTree = SOURCE_ROOT; }; BFFCD89F0890426600044EBA /* IO.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = IO.cpp; path = ../ObjCryst/RefinableObj/IO.cpp; sourceTree = ""; }; BFFCD8A00890426600044EBA /* LSQNumObj.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = LSQNumObj.cpp; path = ../ObjCryst/RefinableObj/LSQNumObj.cpp; sourceTree = ""; }; BFFCD8A10890426600044EBA /* MC.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = MC.cpp; path = ../ObjCryst/wxCryst/MC.cpp; sourceTree = ""; }; BFFCD8A20890426600044EBA /* Molecule.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Molecule.cpp; path = ../ObjCryst/ObjCryst/Molecule.cpp; sourceTree = SOURCE_ROOT; }; BFFCD8A30890426600044EBA /* mpVector.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = mpVector.cpp; path = ../ObjCryst/wxCryst/mpVector.cpp; sourceTree = ""; }; BFFCD8A50890426600044EBA /* Polyhedron.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Polyhedron.cpp; path = ../ObjCryst/ObjCryst/Polyhedron.cpp; sourceTree = SOURCE_ROOT; }; BFFCD8A60890426600044EBA /* PowderPattern.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PowderPattern.cpp; path = ../ObjCryst/ObjCryst/PowderPattern.cpp; sourceTree = SOURCE_ROOT; }; BFFCD8A70890426600044EBA /* PowderPatternBackgroundBayesianMinimiser.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PowderPatternBackgroundBayesianMinimiser.cpp; path = ../ObjCryst/ObjCryst/PowderPatternBackgroundBayesianMinimiser.cpp; sourceTree = SOURCE_ROOT; }; BFFCD8A80890426600044EBA /* RefinableObj.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = RefinableObj.cpp; path = ../ObjCryst/RefinableObj/RefinableObj.cpp; sourceTree = ""; }; BFFCD8A90890426600044EBA /* ReflectionProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ReflectionProfile.cpp; path = ../ObjCryst/ObjCryst/ReflectionProfile.cpp; sourceTree = SOURCE_ROOT; }; BFFCD8AA0890426600044EBA /* Scatterer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Scatterer.cpp; path = ../ObjCryst/ObjCryst/Scatterer.cpp; sourceTree = SOURCE_ROOT; }; BFFCD8AB0890426600044EBA /* ScatteringCorr.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ScatteringCorr.cpp; path = ../ObjCryst/ObjCryst/ScatteringCorr.cpp; sourceTree = SOURCE_ROOT; }; BFFCD8AC0890426600044EBA /* ScatteringData.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ScatteringData.cpp; path = ../ObjCryst/ObjCryst/ScatteringData.cpp; sourceTree = SOURCE_ROOT; }; BFFCD8AD0890426600044EBA /* ScatteringPower.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ScatteringPower.cpp; path = ../ObjCryst/ObjCryst/ScatteringPower.cpp; sourceTree = SOURCE_ROOT; }; BFFCD8AE0890426600044EBA /* ScatteringPowerSphere.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ScatteringPowerSphere.cpp; path = ../ObjCryst/ObjCryst/ScatteringPowerSphere.cpp; sourceTree = SOURCE_ROOT; }; BFFCD8AF0890426600044EBA /* Simplex.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Simplex.cpp; path = ../ObjCryst/RefinableObj/Simplex.cpp; sourceTree = ""; }; BFFCD8B00890426600044EBA /* SpaceGroup.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SpaceGroup.cpp; path = ../ObjCryst/ObjCryst/SpaceGroup.cpp; sourceTree = SOURCE_ROOT; }; BFFCD8B10890426600044EBA /* test.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = test.cpp; path = ../ObjCryst/ObjCryst/test.cpp; sourceTree = ""; }; BFFCD8B20890426600044EBA /* Tracker.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Tracker.cpp; path = ../ObjCryst/RefinableObj/Tracker.cpp; sourceTree = ""; }; BFFCD8B30890426600044EBA /* UnitCell.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = UnitCell.cpp; path = ../ObjCryst/ObjCryst/UnitCell.cpp; sourceTree = SOURCE_ROOT; }; BFFCD8B40890426600044EBA /* VFNDebug.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = VFNDebug.cpp; path = ../ObjCryst/Quirks/VFNDebug.cpp; sourceTree = ""; }; BFFCD8B50890426600044EBA /* VFNStreamFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = VFNStreamFormat.cpp; path = ../ObjCryst/Quirks/VFNStreamFormat.cpp; sourceTree = ""; }; BFFCD8B60890426600044EBA /* wxAtom.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = wxAtom.cpp; path = ../ObjCryst/wxCryst/wxAtom.cpp; sourceTree = ""; }; BFFCD8B70890426600044EBA /* wxCryst.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = wxCryst.cpp; path = ../ObjCryst/wxCryst/wxCryst.cpp; sourceTree = ""; }; BFFCD8B80890426600044EBA /* wxCrystal.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = wxCrystal.cpp; path = ../ObjCryst/wxCryst/wxCrystal.cpp; sourceTree = ""; }; BFFCD8B90890426600044EBA /* wxDiffractionSingleCrystal.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = wxDiffractionSingleCrystal.cpp; path = ../ObjCryst/wxCryst/wxDiffractionSingleCrystal.cpp; sourceTree = ""; }; BFFCD8BA0890426600044EBA /* wxGlobalOptimObj.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = wxGlobalOptimObj.cpp; path = ../ObjCryst/wxCryst/wxGlobalOptimObj.cpp; sourceTree = ""; }; BFFCD8BB0890426600044EBA /* wxMolecule.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = wxMolecule.cpp; path = ../ObjCryst/wxCryst/wxMolecule.cpp; sourceTree = ""; }; BFFCD8BC0890426600044EBA /* wxMultiGraph.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = wxMultiGraph.cpp; path = ../ObjCryst/wxCryst/wxMultiGraph.cpp; sourceTree = ""; }; BFFCD8BD0890426600044EBA /* wxPowderPattern.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = wxPowderPattern.cpp; path = ../ObjCryst/wxCryst/wxPowderPattern.cpp; sourceTree = ""; }; BFFCD8BE0890426600044EBA /* wxRefinableObj.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = wxRefinableObj.cpp; path = ../ObjCryst/wxCryst/wxRefinableObj.cpp; sourceTree = ""; }; BFFCD8BF0890426600044EBA /* wxScatterer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = wxScatterer.cpp; path = ../ObjCryst/wxCryst/wxScatterer.cpp; sourceTree = ""; }; BFFCD8C00890426600044EBA /* wxScatteringPower.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = wxScatteringPower.cpp; path = ../ObjCryst/wxCryst/wxScatteringPower.cpp; sourceTree = ""; }; BFFCD8C10890426600044EBA /* wxScatteringPowerSphere.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = wxScatteringPowerSphere.cpp; path = ../ObjCryst/wxCryst/wxScatteringPowerSphere.cpp; sourceTree = ""; }; BFFCD8C20890426600044EBA /* wxTrackerGraph.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = wxTrackerGraph.cpp; path = ../ObjCryst/wxCryst/wxTrackerGraph.cpp; sourceTree = ""; }; BFFCD8C30890426700044EBA /* wxZScatterer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = wxZScatterer.cpp; path = ../ObjCryst/wxCryst/wxZScatterer.cpp; sourceTree = ""; }; BFFCD8C60890426700044EBA /* ZScatterer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ZScatterer.cpp; path = ../ObjCryst/ObjCryst/ZScatterer.cpp; sourceTree = ""; }; BFFCD97C08904D7D00044EBA /* trackball.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = trackball.c; path = ../ObjCryst/wxCryst/trackball.c; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ BF1DDDE70D228DCF00A3939D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( BF1DE1130D228E6100A3939D /* AGL.framework in Frameworks */, BF5EBF13283F8CB2000D09FE /* QuartzCore.framework in Frameworks */, BF1DE1140D228E6100A3939D /* Carbon.framework in Frameworks */, BFE729E6243A6A7300BABE40 /* libwxjpeg-3.1.a in Frameworks */, BF1DE1150D228E6100A3939D /* System.framework in Frameworks */, BF1DE1160D228E6100A3939D /* IOKit.framework in Frameworks */, BFE729E7243A6A7600BABE40 /* libwxpng-3.1.a in Frameworks */, BF1DE1170D228E6100A3939D /* OpenGL.framework in Frameworks */, BF1DE1180D228E6100A3939D /* AppKit.framework in Frameworks */, BF1DE1190D228E6100A3939D /* GLUT.framework in Frameworks */, BF1DE11A0D228E6100A3939D /* WebKit.framework in Frameworks */, BF1DE1110D228E5D00A3939D /* libcctbx.a in Frameworks */, BF1DE1120D228E5D00A3939D /* libnewmat.a in Frameworks */, BFE729E5243A6A7000BABE40 /* libwx_osx_cocoau-3.1.a in Frameworks */, BFE729E4243A6A6D00BABE40 /* libwx_osx_cocoau_gl-3.1.a in Frameworks */, BF1DE1240D228EA500A3939D /* libfftw3f.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; BFFCCB5B089028E500044EBA /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; BFFCCBE30890309900044EBA /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ BF3479340915057C006E569C /* RefinableObj */ = { isa = PBXGroup; children = ( BFFCD89D0890426600044EBA /* GlobalOptimObj.cpp */, BF11E7B42440AA40009C104D /* GlobalOptimObj.h */, BFFCD89F0890426600044EBA /* IO.cpp */, BF11E7B92440AA42009C104D /* IO.h */, BFFCD8A00890426600044EBA /* LSQNumObj.cpp */, BF11E7B72440AA42009C104D /* LSQNumObj.h */, BFFCD8A80890426600044EBA /* RefinableObj.cpp */, BF11E7B62440AA41009C104D /* RefinableObj.h */, BFFCD8AF0890426600044EBA /* Simplex.cpp */, BF11E7B52440AA40009C104D /* Simplex.h */, BFFCD8B20890426600044EBA /* Tracker.cpp */, BF11E7B82440AA42009C104D /* Tracker.h */, ); name = RefinableObj; sourceTree = ""; }; BF347939091505C7006E569C /* wxCryst */ = { isa = PBXGroup; children = ( BFFCD8A10890426600044EBA /* MC.cpp */, BF11E8072440C1E9009C104D /* MC.h */, BF11E80A2440C1EA009C104D /* MCTable.h */, BFFCD8A30890426600044EBA /* mpVector.cpp */, BF11E8042440C1E9009C104D /* mpVector.h */, BFFCD97C08904D7D00044EBA /* trackball.c */, BF11E80F2440C1EB009C104D /* trackball.h */, BFFCD8B60890426600044EBA /* wxAtom.cpp */, BF11E7FC2440C1E8009C104D /* wxAtom.h */, BFFCD8B70890426600044EBA /* wxCryst.cpp */, BF11E80E2440C1EB009C104D /* wxCryst.h */, BFFCD8B80890426600044EBA /* wxCrystal.cpp */, BF11E8052440C1E9009C104D /* wxCrystal.h */, BFFCD8B90890426600044EBA /* wxDiffractionSingleCrystal.cpp */, BF11E8012440C1E9009C104D /* wxDiffractionSingleCrystal.h */, BFFCD8BA0890426600044EBA /* wxGlobalOptimObj.cpp */, BF11E80C2440C1EA009C104D /* wxGlobalOptimObj.h */, BFFB474D0E5E0E620027591E /* wxLSQ.cpp */, BF11E8032440C1E9009C104D /* wxLSQ.h */, BFFCD8BB0890426600044EBA /* wxMolecule.cpp */, BF11E80D2440C1EA009C104D /* wxMolecule.h */, BFFCD8BC0890426600044EBA /* wxMultiGraph.cpp */, BF11E7FF2440C1E8009C104D /* wxMultiGraph.h */, BFFCD8BD0890426600044EBA /* wxPowderPattern.cpp */, BF11E80B2440C1EA009C104D /* wxPowderPattern.h */, BF11E8062440C1E9009C104D /* wxRadiation.h */, BFFCD8BE0890426600044EBA /* wxRefinableObj.cpp */, BF11E8022440C1E9009C104D /* wxRefinableObj.h */, BFFCD8BF0890426600044EBA /* wxScatterer.cpp */, BF11E8082440C1EA009C104D /* wxScatterer.h */, BFFCD8C00890426600044EBA /* wxScatteringPower.cpp */, BF11E8002440C1E8009C104D /* wxScatteringPower.h */, BFFCD8C10890426600044EBA /* wxScatteringPowerSphere.cpp */, BF11E8092440C1EA009C104D /* wxScatteringPowerSphere.h */, BFFCD8C20890426600044EBA /* wxTrackerGraph.cpp */, BF11E7FE2440C1E8009C104D /* wxTrackerGraph.h */, BFFCD8C30890426700044EBA /* wxZScatterer.cpp */, BF11E7FD2440C1E8009C104D /* wxZScatterer.h */, ); name = wxCryst; sourceTree = ""; }; BF34793A091505E2006E569C /* Quirks */ = { isa = PBXGroup; children = ( BF11E7F52440C1D6009C104D /* Chronometer.h */, BF08978D0B072E2F00C0F576 /* ci_string.cpp */, BF11E7F42440C1D6009C104D /* ci_string.h */, BF11E7F32440C1D6009C104D /* sse_mathfun.h */, BFFCD8B40890426600044EBA /* VFNDebug.cpp */, BF11E7F62440C1D6009C104D /* VFNDebug.h */, BFFCD8B50890426600044EBA /* VFNStreamFormat.cpp */, BF11E7F22440C1D6009C104D /* VFNStreamFormat.h */, ); name = Quirks; sourceTree = ""; }; BF3479410915064E006E569C /* cctbx */ = { isa = PBXGroup; children = ( BF49CDEF1B0BC56E0012BF3B /* covalent_radii.cpp */, BFFCCC950890328F00044EBA /* index_generator.cpp */, BFFCCC960890328F00044EBA /* match_bijvoet_mates.cpp */, BFFCCC970890328F00044EBA /* match_indices.cpp */, BFFCCC980890328F00044EBA /* sym_equiv.cpp */, BFFCCC320890324D00044EBA /* bricks.cpp */, BFFCCC330890324D00044EBA /* change_of_basis_op.cpp */, BFFCCC360890324D00044EBA /* find_affine.cpp */, BFFCCC370890324D00044EBA /* group_codes.cpp */, BFFCCC380890324D00044EBA /* hall_in.cpp */, BFFCCC390890324D00044EBA /* hall_symbol_table.cpp */, BFFCCC3B0890324D00044EBA /* lattice_symmetry.cpp */, BFFCCC3C0890324D00044EBA /* lattice_tr.cpp */, BFFCCC3D0890324D00044EBA /* matrix_group_code_table.cpp */, BFFCCC3E0890324D00044EBA /* miller.cpp */, BFFCCC3F0890324D00044EBA /* normalizer.cpp */, BFFCCC420890324D00044EBA /* reciprocal_space_asu.cpp */, BFFCCC430890324D00044EBA /* reciprocal_space_ref_asu.cpp */, BFFCCC440890324D00044EBA /* rot_mx_info.cpp */, BFFCCC460890324D00044EBA /* rot_mx.cpp */, BFFCCC470890324D00044EBA /* row_echelon_solve.cpp */, BFFCCC490890324D00044EBA /* rt_mx.cpp */, BFFCCC4B0890324D00044EBA /* select_generators.cpp */, BFFCCC4D0890324D00044EBA /* seminvariant.cpp */, BFFCCC500890324D00044EBA /* site_symmetry.cpp */, BFFCCC520890324D00044EBA /* space_group_type.cpp */, BFFCCC540890324D00044EBA /* space_group.cpp */, BFFCCC570890324D00044EBA /* symbols.cpp */, BFFCCC590890324D00044EBA /* tensor_rank_2.cpp */, BFFCCC5A0890324D00044EBA /* tr_group.cpp */, BFFCCC5C0890324D00044EBA /* tr_vec.cpp */, BFFCCC5D0890324D00044EBA /* utils.cpp */, BFFCCC5F0890324D00044EBA /* wyckoff.cpp */, BFFCCC600890324D00044EBA /* wyckoff.cpp */, BFFCCBEB089031AF00044EBA /* basic.cpp */, BFFCCBED089031AF00044EBA /* fp_fdp.cpp */, BFFCCBEF089031AF00044EBA /* henke_tables_01_12.cpp */, BFFCCBF0089031AF00044EBA /* henke_tables_13_24.cpp */, BFFCCBF1089031AF00044EBA /* henke_tables_25_36.cpp */, BFFCCBF2089031AF00044EBA /* henke_tables_37_48.cpp */, BFFCCBF3089031AF00044EBA /* henke_tables_49_60.cpp */, BFFCCBF4089031AF00044EBA /* henke_tables_61_72.cpp */, BFFCCBF5089031AF00044EBA /* henke_tables_73_84.cpp */, BFFCCBF6089031AF00044EBA /* henke_tables_85_92.cpp */, BFFCCBF7089031AF00044EBA /* henke.cpp */, BFFCCBF9089031AF00044EBA /* icsd_radii.cpp */, BFFCCBFA089031AF00044EBA /* it1992.cpp */, BFFCCBFB089031AF00044EBA /* n_gaussian_raw.cpp */, BFFCCBFC089031AF00044EBA /* n_gaussian.cpp */, BFFCCBFE089031AF00044EBA /* neutron.cpp */, BFFCCC00089031AF00044EBA /* sasaki_tables_01_12.cpp */, BFFCCC01089031AF00044EBA /* sasaki_tables_13_24.cpp */, BFFCCC02089031AF00044EBA /* sasaki_tables_25_36.cpp */, BFFCCC03089031AF00044EBA /* sasaki_tables_37_48.cpp */, BFFCCC04089031AF00044EBA /* sasaki_tables_49_60.cpp */, BFFCCC05089031AF00044EBA /* sasaki_tables_61_72.cpp */, BFFCCC06089031AF00044EBA /* sasaki_tables_73_82.cpp */, BFFCCC07089031AF00044EBA /* sasaki.cpp */, BFFCCC09089031AF00044EBA /* tiny_pse.cpp */, BFFCCC0B089031AF00044EBA /* wavelengths.cpp */, BFFCCC0C089031AF00044EBA /* wk1995.cpp */, BF3EB062089690D200E02367 /* spoil_optimization.cpp */, BF3EB05408968F5500E02367 /* uctbx.cpp */, BFFCCC930890328F00044EBA /* asu.cpp */, BFFCCC940890328F00044EBA /* bins.cpp */, ); name = cctbx; sourceTree = ""; }; BF34794209150686006E569C /* newmat */ = { isa = PBXGroup; children = ( BFCB29CC258F7484008A8CCB /* include.h */, BFFCCB6A089029F400044EBA /* cholesky.cpp */, BFFCCB6E089029F400044EBA /* garch.cpp */, BFFCCB6F089029F400044EBA /* hholder.cpp */, BFFCCB70089029F400044EBA /* jacobi.cpp */, BFFCCB71089029F400044EBA /* myexcept.cpp */, BFFCCB72089029F400044EBA /* newfft.cpp */, BFFCCB73089029F400044EBA /* newmat1.cpp */, BFFCCB74089029F400044EBA /* newmat2.cpp */, BFFCCB75089029F400044EBA /* newmat3.cpp */, BFFCCB76089029F400044EBA /* newmat4.cpp */, BFFCCB77089029F400044EBA /* newmat5.cpp */, BFFCCB78089029F400044EBA /* newmat6.cpp */, BFFCCB79089029F400044EBA /* newmat7.cpp */, BFFCCB7A089029F400044EBA /* newmat8.cpp */, BFFCCB7B089029F400044EBA /* newmat9.cpp */, BFFCCB7C089029F400044EBA /* newmatex.cpp */, BFFCCB7D089029F400044EBA /* newmatnl.cpp */, BFFCCB7E089029F400044EBA /* newmatrm.cpp */, BFFCCB82089029F400044EBA /* nm_misc.cpp */, BFFCCB83089029F400044EBA /* sl_ex.cpp */, BFFCCB84089029F400044EBA /* solution.cpp */, BFFCCB85089029F400044EBA /* sort.cpp */, BFFCCB86089029F400044EBA /* submat.cpp */, BFFCCB87089029F400044EBA /* svd.cpp */, BFFCCB660890296D00044EBA /* bandmat.cpp */, BFFCCB6B089029F400044EBA /* evalue.cpp */, BFFCCB6D089029F400044EBA /* fft.cpp */, ); name = newmat; sourceTree = ""; }; BF347947091506B7006E569C /* CrystVector */ = { isa = PBXGroup; children = ( BF11E7C02440C199009C104D /* CrystVector.h */, BFFCD8920890426600044EBA /* CrystVector.cpp */, ); name = CrystVector; sourceTree = ""; }; BF3EAF90089628D200E02367 /* Fox */ = { isa = PBXGroup; children = ( BFFCD88E0890422000044EBA /* Fox.cpp */, BF26F598089306500008175B /* Fox.icns */, BF69C4C8124F8C310035CF57 /* FoxClient.cpp */, BF11E82C2440C200009C104D /* FoxClient.h */, BF69C4C9124F8C310035CF57 /* FoxJob.cpp */, BF11E8252440C1FF009C104D /* FoxJob.h */, BF69C4CA124F8C310035CF57 /* FoxServer.cpp */, BF11E82B2440C1FF009C104D /* FoxServer.h */, BF69C4CC124F8C310035CF57 /* GridResult.cpp */, BF11E82A2440C1FF009C104D /* GridResult.h */, BF69C4CD124F8C310035CF57 /* IOSocket.cpp */, BF11E8242440C1FE009C104D /* IOSocket.h */, BF69C4CE124F8C310035CF57 /* WXFoxClient.cpp */, BF11E8282440C1FF009C104D /* WXFoxClient.h */, BF69C4CF124F8C310035CF57 /* WXFoxServer.cpp */, BF11E8262440C1FF009C104D /* WXFoxServer.h */, BF69C4D0124F8C310035CF57 /* WXGridWindow.cpp */, BF11E8292440C1FF009C104D /* WXGridWindow.h */, ); name = Fox; sourceTree = SOURCE_ROOT; }; BF3EAF910896291100E02367 /* ObjCryst */ = { isa = PBXGroup; children = ( BF92D5CE259F2D4F005FD5D7 /* Undo.cpp */, BF92D5CD259F2D4F005FD5D7 /* Undo.h */, BFFCD8900890426600044EBA /* Atom.cpp */, BF11E7D22440C1BE009C104D /* Atom.h */, BF08978A0B072DF600C0F576 /* CIF.cpp */, BF11E7D42440C1BE009C104D /* CIF.h */, BF11E7CF2440C1BD009C104D /* Colours.h */, BFFCD8910890426600044EBA /* Crystal.cpp */, BF11E7C32440C1BB009C104D /* Crystal.h */, BFFCD8930890426600044EBA /* DiffractionDataSingleCrystal.cpp */, BF11E7CB2440C1BC009C104D /* DiffractionDataSingleCrystal.h */, BFFCD8940890426600044EBA /* Exception.cpp */, BF11E7D32440C1BE009C104D /* General.h */, BFFCD8960890426600044EBA /* geomStructFactor_001.cpp */, BFFCD8970890426600044EBA /* geomStructFactor_002.cpp */, BFFCD8980890426600044EBA /* geomStructFactor_067.cpp */, BFFCD8990890426600044EBA /* geomStructFactor_097.cpp */, BFFCD89A0890426600044EBA /* geomStructFactor_230.cpp */, BFFCD89B0890426600044EBA /* geomStructFactor_centro.cpp */, BFFCD89C0890426600044EBA /* geomStructFactor.cpp */, BF11E7D82440C1BF009C104D /* GeomStructFactor.h */, BFE6AC680B886ACA007AFBA8 /* Indexing.cpp */, BF11E7D62440C1BE009C104D /* Indexing.h */, BFFCD89E0890426600044EBA /* IO.cpp */, BF11E7C92440C1BC009C104D /* IO.h */, BFFCD8A20890426600044EBA /* Molecule.cpp */, BF11E7CE2440C1BD009C104D /* Molecule.h */, BF11E7D12440C1BD009C104D /* PDF.h */, BFFCD8A50890426600044EBA /* Polyhedron.cpp */, BF11E7D72440C1BE009C104D /* Polyhedron.h */, BFFCD8A60890426600044EBA /* PowderPattern.cpp */, BF11E7C72440C1BC009C104D /* PowderPattern.h */, BFFCD8A70890426600044EBA /* PowderPatternBackgroundBayesianMinimiser.cpp */, BF11E7D52440C1BE009C104D /* PowderPatternBackgroundBayesianMinimiser.h */, BFFCD8A90890426600044EBA /* ReflectionProfile.cpp */, BF11E7C42440C1BB009C104D /* ReflectionProfile.h */, BFFCD8AA0890426600044EBA /* Scatterer.cpp */, BF11E7D02440C1BD009C104D /* Scatterer.h */, BFFCD8AB0890426600044EBA /* ScatteringCorr.cpp */, BF11E7C62440C1BC009C104D /* ScatteringCorr.h */, BFFCD8AC0890426600044EBA /* ScatteringData.cpp */, BF11E7C22440C1BB009C104D /* ScatteringData.h */, BFFCD8AD0890426600044EBA /* ScatteringPower.cpp */, BF11E7C82440C1BC009C104D /* ScatteringPower.h */, BFFCD8AE0890426600044EBA /* ScatteringPowerSphere.cpp */, BF11E7CC2440C1BD009C104D /* ScatteringPowerSphere.h */, BFFCD8B00890426600044EBA /* SpaceGroup.cpp */, BF11E7C52440C1BB009C104D /* SpaceGroup.h */, BFFCD8B10890426600044EBA /* test.cpp */, BF11E7CA2440C1BC009C104D /* test.h */, BFFCD8B30890426600044EBA /* UnitCell.cpp */, BF11E7D92440C1BF009C104D /* UnitCell.h */, BFFCD8C60890426700044EBA /* ZScatterer.cpp */, BF11E7CD2440C1BD009C104D /* ZScatterer.h */, ); name = ObjCryst; sourceTree = ""; }; BF9466CB2205A0BB0086B9DC /* Frameworks */ = { isa = PBXGroup; children = ( BF5EBF12283F8CB2000D09FE /* QuartzCore.framework */, ); name = Frameworks; sourceTree = ""; }; BFFCCB4F089028D300044EBA = { isa = PBXGroup; children = ( BFF7D0BF1478047800799F7A /* libwx_osx_cocoau_gl-3.1.a */, BFF7D0C01478047800799F7A /* libwx_osx_cocoau-3.1.a */, BFF7D0C11478047800799F7A /* libwxjpeg-3.1.a */, BFF7D0C21478047800799F7A /* libwxpng-3.1.a */, BF1DE1230D228EA500A3939D /* libfftw3f.a */, BF36112F0BD6E409000C0EE9 /* WebKit.framework */, BF36112B0BD6E3F5000C0EE9 /* GLUT.framework */, BF3611280BD6E3CA000C0EE9 /* AppKit.framework */, BF3611260BD6E3B6000C0EE9 /* OpenGL.framework */, BF3611240BD6E3A6000C0EE9 /* IOKit.framework */, BF3611220BD6E38F000C0EE9 /* System.framework */, BF36111A0BD6E326000C0EE9 /* Carbon.framework */, BF3611180BD6E30F000C0EE9 /* AGL.framework */, BF3EAF910896291100E02367 /* ObjCryst */, BF347947091506B7006E569C /* CrystVector */, BF3479340915057C006E569C /* RefinableObj */, BF34793A091505E2006E569C /* Quirks */, BF347939091505C7006E569C /* wxCryst */, BF3EAF90089628D200E02367 /* Fox */, BFFCCCC30890389700044EBA /* boost */, BF3479410915064E006E569C /* cctbx */, BF34794209150686006E569C /* newmat */, BFFCCB5E089028E500044EBA /* Products */, BFFCD88A089041A600044EBA /* Fox-Info.plist */, BF1DDDEB0D228DCF00A3939D /* FoxCocoa-Info.plist */, BF9466CB2205A0BB0086B9DC /* Frameworks */, ); indentWidth = 3; sourceTree = ""; tabWidth = 3; }; BFFCCB5E089028E500044EBA /* Products */ = { isa = PBXGroup; children = ( BFFCCB5D089028E500044EBA /* libnewmat.a */, BFFCCBE50890309900044EBA /* libcctbx.a */, BF1DDDE90D228DCF00A3939D /* Fox.app */, ); name = Products; sourceTree = SOURCE_ROOT; }; BFFCCCC30890389700044EBA /* boost */ = { isa = PBXGroup; children = ( BFFCCCC40890389700044EBA /* aligned_storage.hpp */, BFFCCCC50890389700044EBA /* call_traits.hpp */, BFFCCCC60890389700044EBA /* config */, BFFCCCFD0890389700044EBA /* config.hpp */, BFFCCCFE0890389700044EBA /* detail */, BFFCCD470890389800044EBA /* iterator.hpp */, BFFCCD480890389800044EBA /* math */, BFFCCD540890389800044EBA /* mpl */, BFFCD159089038A000044EBA /* operators.hpp */, BFFCD15A089038A000044EBA /* preprocessor */, BFFCD263089038A300044EBA /* preprocessor.hpp */, BFFCD264089038A300044EBA /* rational.hpp */, BFFCD265089038A300044EBA /* static_assert.hpp */, BFFCD266089038A300044EBA /* type_traits */, BFFCD2C8089038A400044EBA /* type_traits.hpp */, ); name = boost; path = ../boost; sourceTree = SOURCE_ROOT; }; BFFCCCC60890389700044EBA /* config */ = { isa = PBXGroup; children = ( BFFCCCC70890389700044EBA /* abi */, BFFCCCCC0890389700044EBA /* abi_prefix.hpp */, BFFCCCCD0890389700044EBA /* abi_suffix.hpp */, BFFCCCCE0890389700044EBA /* auto_link.hpp */, BFFCCCCF0890389700044EBA /* compiler */, BFFCCCE00890389700044EBA /* platform */, BFFCCCEC0890389700044EBA /* posix_features.hpp */, BFFCCCED0890389700044EBA /* requires_threads.hpp */, BFFCCCEE0890389700044EBA /* select_compiler_config.hpp */, BFFCCCEF0890389700044EBA /* select_platform_config.hpp */, BFFCCCF00890389700044EBA /* select_stdlib_config.hpp */, BFFCCCF10890389700044EBA /* stdlib */, BFFCCCFB0890389700044EBA /* suffix.hpp */, BFFCCCFC0890389700044EBA /* user.hpp */, ); path = config; sourceTree = ""; }; BFFCCCC70890389700044EBA /* abi */ = { isa = PBXGroup; children = ( BFFCCCC80890389700044EBA /* borland_prefix.hpp */, BFFCCCC90890389700044EBA /* borland_suffix.hpp */, BFFCCCCA0890389700044EBA /* msvc_prefix.hpp */, BFFCCCCB0890389700044EBA /* msvc_suffix.hpp */, ); path = abi; sourceTree = ""; }; BFFCCCCF0890389700044EBA /* compiler */ = { isa = PBXGroup; children = ( BFFCCCD00890389700044EBA /* borland.hpp */, BFFCCCD10890389700044EBA /* comeau.hpp */, BFFCCCD20890389700044EBA /* common_edg.hpp */, BFFCCCD30890389700044EBA /* compaq_cxx.hpp */, BFFCCCD40890389700044EBA /* digitalmars.hpp */, BFFCCCD50890389700044EBA /* gcc.hpp */, BFFCCCD60890389700044EBA /* greenhills.hpp */, BFFCCCD70890389700044EBA /* hp_acc.hpp */, BFFCCCD80890389700044EBA /* intel.hpp */, BFFCCCD90890389700044EBA /* kai.hpp */, BFFCCCDA0890389700044EBA /* metrowerks.hpp */, BFFCCCDB0890389700044EBA /* mpw.hpp */, BFFCCCDC0890389700044EBA /* sgi_mipspro.hpp */, BFFCCCDD0890389700044EBA /* sunpro_cc.hpp */, BFFCCCDE0890389700044EBA /* vacpp.hpp */, BFFCCCDF0890389700044EBA /* visualc.hpp */, ); path = compiler; sourceTree = ""; }; BFFCCCE00890389700044EBA /* platform */ = { isa = PBXGroup; children = ( BFFCCCE10890389700044EBA /* aix.hpp */, BFFCCCE20890389700044EBA /* amigaos.hpp */, BFFCCCE30890389700044EBA /* beos.hpp */, BFFCCCE40890389700044EBA /* bsd.hpp */, BFFCCCE50890389700044EBA /* cygwin.hpp */, BFFCCCE60890389700044EBA /* hpux.hpp */, BFFCCCE70890389700044EBA /* irix.hpp */, BFFCCCE80890389700044EBA /* linux.hpp */, BFFCCCE90890389700044EBA /* macos.hpp */, BFFCCCEA0890389700044EBA /* solaris.hpp */, BFFCCCEB0890389700044EBA /* win32.hpp */, ); path = platform; sourceTree = ""; }; BFFCCCF10890389700044EBA /* stdlib */ = { isa = PBXGroup; children = ( BFFCCCF20890389700044EBA /* dinkumware.hpp */, BFFCCCF30890389700044EBA /* libcomo.hpp */, BFFCCCF40890389700044EBA /* libstdcpp3.hpp */, BFFCCCF50890389700044EBA /* modena.hpp */, BFFCCCF60890389700044EBA /* msl.hpp */, BFFCCCF70890389700044EBA /* roguewave.hpp */, BFFCCCF80890389700044EBA /* sgi.hpp */, BFFCCCF90890389700044EBA /* stlport.hpp */, BFFCCCFA0890389700044EBA /* vacpp.hpp */, ); path = stdlib; sourceTree = ""; }; BFFCCCFE0890389700044EBA /* detail */ = { isa = PBXGroup; children = ( BFFCCCFF0890389700044EBA /* algorithm.hpp */, BFFCCD000890389700044EBA /* allocator_utilities.hpp */, BFFCCD010890389700044EBA /* atomic_count.hpp */, BFFCCD020890389700044EBA /* atomic_count_gcc.hpp */, BFFCCD030890389700044EBA /* atomic_count_pthreads.hpp */, BFFCCD040890389700044EBA /* atomic_count_win32.hpp */, BFFCCD050890389700044EBA /* bad_weak_ptr.hpp */, BFFCCD060890389700044EBA /* binary_search.hpp */, BFFCCD070890389700044EBA /* call_traits.hpp */, BFFCCD080890389700044EBA /* catch_exceptions.hpp */, BFFCCD090890389700044EBA /* compressed_pair.hpp */, BFFCCD0A0890389700044EBA /* dynamic_bitset.hpp */, BFFCCD0B0890389700044EBA /* indirect_traits.hpp */, BFFCCD0C0890389700044EBA /* interlocked.hpp */, BFFCCD0D0890389700044EBA /* is_function_ref_tester.hpp */, BFFCCD0E0890389700044EBA /* is_incrementable.hpp */, BFFCCD0F0890389700044EBA /* iterator.hpp */, BFFCCD100890389700044EBA /* lightweight_mutex.hpp */, BFFCCD110890389700044EBA /* lightweight_test.hpp */, BFFCCD120890389700044EBA /* limits.hpp */, BFFCCD130890389700044EBA /* lwm_nop.hpp */, BFFCCD140890389700044EBA /* lwm_pthreads.hpp */, BFFCCD150890389700044EBA /* lwm_win32_cs.hpp */, BFFCCD160890389700044EBA /* named_template_params.hpp */, BFFCCD170890389700044EBA /* no_exceptions_support.hpp */, BFFCCD180890389700044EBA /* none_t.hpp */, BFFCCD190890389700044EBA /* numeric_traits.hpp */, BFFCCD1A0890389700044EBA /* ob_call_traits.hpp */, BFFCCD1B0890389700044EBA /* ob_compressed_pair.hpp */, BFFCCD1C0890389700044EBA /* quick_allocator.hpp */, BFFCCD1D0890389700044EBA /* reference_content.hpp */, BFFCCD1E0890389700044EBA /* select_type.hpp */, BFFCCD1F0890389700044EBA /* shared_array_nmt.hpp */, BFFCCD200890389700044EBA /* shared_count.hpp */, BFFCCD210890389700044EBA /* shared_ptr_nmt.hpp */, BFFCCD220890389700044EBA /* sp_counted_base.hpp */, BFFCCD230890389700044EBA /* sp_counted_base_cw_ppc.hpp */, BFFCCD240890389700044EBA /* sp_counted_base_gcc_ia64.hpp */, BFFCCD250890389700044EBA /* sp_counted_base_gcc_ppc.hpp */, BFFCCD260890389800044EBA /* sp_counted_base_gcc_x86.hpp */, BFFCCD270890389800044EBA /* sp_counted_base_nt.hpp */, BFFCCD280890389800044EBA /* sp_counted_base_pt.hpp */, BFFCCD290890389800044EBA /* sp_counted_base_w32.hpp */, BFFCCD2A0890389800044EBA /* sp_counted_impl.hpp */, BFFCCD2B0890389800044EBA /* templated_streams.hpp */, BFFCCD2C0890389800044EBA /* utf8_codecvt_facet.hpp */, BFFCCD2D0890389800044EBA /* workaround.hpp */, ); path = detail; sourceTree = ""; }; BFFCCD480890389800044EBA /* math */ = { isa = PBXGroup; children = ( BFFCCD490890389800044EBA /* common_factor.hpp */, BFFCCD4A0890389800044EBA /* common_factor_ct.hpp */, BFFCCD4B0890389800044EBA /* common_factor_rt.hpp */, BFFCCD4C0890389800044EBA /* octonion.hpp */, BFFCCD4D0890389800044EBA /* quaternion.hpp */, BFFCCD4E0890389800044EBA /* special_functions */, ); path = math; sourceTree = ""; }; BFFCCD4E0890389800044EBA /* special_functions */ = { isa = PBXGroup; children = ( BFFCCD4F0890389800044EBA /* acosh.hpp */, BFFCCD500890389800044EBA /* asinh.hpp */, BFFCCD510890389800044EBA /* atanh.hpp */, BFFCCD520890389800044EBA /* sinc.hpp */, BFFCCD530890389800044EBA /* sinhc.hpp */, ); path = special_functions; sourceTree = ""; }; BFFCCD540890389800044EBA /* mpl */ = { isa = PBXGroup; children = ( BFFCCD550890389800044EBA /* accumulate.hpp */, BFFCCD560890389800044EBA /* advance.hpp */, BFFCCD570890389800044EBA /* advance_fwd.hpp */, BFFCCD580890389800044EBA /* alias.hpp */, BFFCCD590890389800044EBA /* always.hpp */, BFFCCD5A0890389800044EBA /* and.hpp */, BFFCCD5B0890389800044EBA /* apply.hpp */, BFFCCD5C0890389800044EBA /* apply_fwd.hpp */, BFFCCD5D0890389800044EBA /* apply_wrap.hpp */, BFFCCD5E0890389800044EBA /* arg.hpp */, BFFCCD5F0890389800044EBA /* arg_fwd.hpp */, BFFCCD600890389800044EBA /* arithmetic.hpp */, BFFCCD610890389800044EBA /* as_sequence.hpp */, BFFCCD620890389800044EBA /* assert.hpp */, BFFCCD630890389800044EBA /* at.hpp */, BFFCCD640890389800044EBA /* at_fwd.hpp */, BFFCCD650890389800044EBA /* aux_ */, BFFCCFDB0890389D00044EBA /* back.hpp */, BFFCCFDC0890389D00044EBA /* back_fwd.hpp */, BFFCCFDD0890389D00044EBA /* back_inserter.hpp */, BFFCCFDE0890389D00044EBA /* base.hpp */, BFFCCFDF0890389D00044EBA /* begin.hpp */, BFFCCFE00890389D00044EBA /* begin_end.hpp */, BFFCCFE10890389D00044EBA /* begin_end_fwd.hpp */, BFFCCFE20890389D00044EBA /* bind.hpp */, BFFCCFE30890389D00044EBA /* bind_fwd.hpp */, BFFCCFE40890389D00044EBA /* bitand.hpp */, BFFCCFE50890389D00044EBA /* bitor.hpp */, BFFCCFE60890389D00044EBA /* bitwise.hpp */, BFFCCFE70890389D00044EBA /* bitxor.hpp */, BFFCCFE80890389D00044EBA /* bool.hpp */, BFFCCFE90890389D00044EBA /* bool_fwd.hpp */, BFFCCFEA0890389D00044EBA /* clear.hpp */, BFFCCFEB0890389D00044EBA /* clear_fwd.hpp */, BFFCCFEC0890389D00044EBA /* comparison.hpp */, BFFCCFED0890389D00044EBA /* contains.hpp */, BFFCCFEE0890389D00044EBA /* contains_fwd.hpp */, BFFCCFEF0890389D00044EBA /* copy.hpp */, BFFCCFF00890389D00044EBA /* copy_if.hpp */, BFFCCFF10890389D00044EBA /* count.hpp */, BFFCCFF20890389D00044EBA /* count_fwd.hpp */, BFFCCFF30890389D00044EBA /* count_if.hpp */, BFFCCFF40890389D00044EBA /* deque.hpp */, BFFCCFF50890389D00044EBA /* deref.hpp */, BFFCCFF60890389D00044EBA /* distance.hpp */, BFFCCFF70890389D00044EBA /* distance_fwd.hpp */, BFFCCFF80890389D00044EBA /* divides.hpp */, BFFCCFF90890389D00044EBA /* empty.hpp */, BFFCCFFA0890389D00044EBA /* empty_base.hpp */, BFFCCFFB0890389D00044EBA /* empty_fwd.hpp */, BFFCCFFC0890389D00044EBA /* empty_sequence.hpp */, BFFCCFFD0890389D00044EBA /* end.hpp */, BFFCCFFE0890389D00044EBA /* equal.hpp */, BFFCCFFF0890389E00044EBA /* equal_to.hpp */, BFFCD0000890389E00044EBA /* erase.hpp */, BFFCD0010890389E00044EBA /* erase_fwd.hpp */, BFFCD0020890389E00044EBA /* erase_key.hpp */, BFFCD0030890389E00044EBA /* erase_key_fwd.hpp */, BFFCD0040890389E00044EBA /* eval_if.hpp */, BFFCD0050890389E00044EBA /* filter_view.hpp */, BFFCD0060890389E00044EBA /* find.hpp */, BFFCD0070890389E00044EBA /* find_if.hpp */, BFFCD0080890389E00044EBA /* fold.hpp */, BFFCD0090890389E00044EBA /* for_each.hpp */, BFFCD00A0890389E00044EBA /* front.hpp */, BFFCD00B0890389E00044EBA /* front_fwd.hpp */, BFFCD00C0890389E00044EBA /* front_inserter.hpp */, BFFCD00D0890389E00044EBA /* greater.hpp */, BFFCD00E0890389E00044EBA /* greater_equal.hpp */, BFFCD00F0890389E00044EBA /* has_key.hpp */, BFFCD0100890389E00044EBA /* has_key_fwd.hpp */, BFFCD0110890389E00044EBA /* has_xxx.hpp */, BFFCD0120890389E00044EBA /* identity.hpp */, BFFCD0130890389E00044EBA /* if.hpp */, BFFCD0140890389E00044EBA /* index_if.hpp */, BFFCD0150890389E00044EBA /* index_of.hpp */, BFFCD0160890389E00044EBA /* inherit.hpp */, BFFCD0170890389E00044EBA /* inherit_linearly.hpp */, BFFCD0180890389E00044EBA /* insert.hpp */, BFFCD0190890389E00044EBA /* insert_fwd.hpp */, BFFCD01A0890389E00044EBA /* insert_range.hpp */, BFFCD01B0890389E00044EBA /* insert_range_fwd.hpp */, BFFCD01C0890389E00044EBA /* inserter.hpp */, BFFCD01D0890389E00044EBA /* int.hpp */, BFFCD01E0890389E00044EBA /* int_fwd.hpp */, BFFCD01F0890389E00044EBA /* integral_c.hpp */, BFFCD0200890389E00044EBA /* integral_c_fwd.hpp */, BFFCD0210890389E00044EBA /* integral_c_tag.hpp */, BFFCD0220890389E00044EBA /* is_placeholder.hpp */, BFFCD0230890389E00044EBA /* is_sequence.hpp */, BFFCD0240890389E00044EBA /* iter_fold.hpp */, BFFCD0250890389E00044EBA /* iter_fold_if.hpp */, BFFCD0260890389E00044EBA /* iterator_category.hpp */, BFFCD0270890389E00044EBA /* iterator_range.hpp */, BFFCD0280890389E00044EBA /* iterator_tags.hpp */, BFFCD0290890389E00044EBA /* joint_view.hpp */, BFFCD02A0890389E00044EBA /* key_type.hpp */, BFFCD02B0890389E00044EBA /* key_type_fwd.hpp */, BFFCD02C0890389E00044EBA /* lambda.hpp */, BFFCD02D0890389E00044EBA /* lambda_fwd.hpp */, BFFCD02E0890389E00044EBA /* less.hpp */, BFFCD02F0890389E00044EBA /* less_equal.hpp */, BFFCD0300890389E00044EBA /* limits */, BFFCD0370890389E00044EBA /* list */, BFFCD0600890389F00044EBA /* list.hpp */, BFFCD0610890389F00044EBA /* list_c.hpp */, BFFCD0620890389F00044EBA /* logical.hpp */, BFFCD0630890389F00044EBA /* long.hpp */, BFFCD0640890389F00044EBA /* long_fwd.hpp */, BFFCD0650890389F00044EBA /* lower_bound.hpp */, BFFCD0660890389F00044EBA /* map */, BFFCD0930890389F00044EBA /* map.hpp */, BFFCD0940890389F00044EBA /* math */, BFFCD0980890389F00044EBA /* max.hpp */, BFFCD0990890389F00044EBA /* max_element.hpp */, BFFCD09A0890389F00044EBA /* min.hpp */, BFFCD09B0890389F00044EBA /* min_element.hpp */, BFFCD09C0890389F00044EBA /* min_max.hpp */, BFFCD09D0890389F00044EBA /* minus.hpp */, BFFCD09E0890389F00044EBA /* modulus.hpp */, BFFCD09F0890389F00044EBA /* multiplies.hpp */, BFFCD0A00890389F00044EBA /* multiset */, BFFCD0A80890389F00044EBA /* negate.hpp */, BFFCD0A90890389F00044EBA /* next.hpp */, BFFCD0AA0890389F00044EBA /* next_prior.hpp */, BFFCD0AB0890389F00044EBA /* not.hpp */, BFFCD0AC0890389F00044EBA /* not_equal_to.hpp */, BFFCD0AD0890389F00044EBA /* numeric_cast.hpp */, BFFCD0AE0890389F00044EBA /* O1_size.hpp */, BFFCD0AF0890389F00044EBA /* O1_size_fwd.hpp */, BFFCD0B00890389F00044EBA /* or.hpp */, BFFCD0B10890389F00044EBA /* order.hpp */, BFFCD0B20890389F00044EBA /* order_fwd.hpp */, BFFCD0B30890389F00044EBA /* pair.hpp */, BFFCD0B40890389F00044EBA /* pair_view.hpp */, BFFCD0B50890389F00044EBA /* partition.hpp */, BFFCD0B60890389F00044EBA /* placeholders.hpp */, BFFCD0B70890389F00044EBA /* plus.hpp */, BFFCD0B80890389F00044EBA /* pop_back.hpp */, BFFCD0B90890389F00044EBA /* pop_back_fwd.hpp */, BFFCD0BA0890389F00044EBA /* pop_front.hpp */, BFFCD0BB0890389F00044EBA /* pop_front_fwd.hpp */, BFFCD0BC0890389F00044EBA /* print.hpp */, BFFCD0BD0890389F00044EBA /* prior.hpp */, BFFCD0BE0890389F00044EBA /* protect.hpp */, BFFCD0BF0890389F00044EBA /* push_back.hpp */, BFFCD0C00890389F00044EBA /* push_back_fwd.hpp */, BFFCD0C10890389F00044EBA /* push_front.hpp */, BFFCD0C20890389F00044EBA /* push_front_fwd.hpp */, BFFCD0C30890389F00044EBA /* quote.hpp */, BFFCD0C40890389F00044EBA /* range_c.hpp */, BFFCD0C50890389F00044EBA /* remove.hpp */, BFFCD0C60890389F00044EBA /* remove_if.hpp */, BFFCD0C70890389F00044EBA /* replace.hpp */, BFFCD0C80890389F00044EBA /* replace_if.hpp */, BFFCD0C90890389F00044EBA /* reverse.hpp */, BFFCD0CA0890389F00044EBA /* reverse_fold.hpp */, BFFCD0CB0890389F00044EBA /* reverse_iter_fold.hpp */, BFFCD0CC0890389F00044EBA /* same_as.hpp */, BFFCD0CD0890389F00044EBA /* sequence_tag.hpp */, BFFCD0CE0890389F00044EBA /* sequence_tag_fwd.hpp */, BFFCD0CF0890389F00044EBA /* set */, BFFCD0FB089038A000044EBA /* set.hpp */, BFFCD0FC089038A000044EBA /* set_c.hpp */, BFFCD0FD089038A000044EBA /* shift_left.hpp */, BFFCD0FE089038A000044EBA /* shift_right.hpp */, BFFCD0FF089038A000044EBA /* single_view.hpp */, BFFCD100089038A000044EBA /* size.hpp */, BFFCD101089038A000044EBA /* size_fwd.hpp */, BFFCD102089038A000044EBA /* size_t.hpp */, BFFCD103089038A000044EBA /* size_t_fwd.hpp */, BFFCD104089038A000044EBA /* sizeof.hpp */, BFFCD105089038A000044EBA /* sort.hpp */, BFFCD106089038A000044EBA /* stable_partition.hpp */, BFFCD107089038A000044EBA /* switch.hpp */, BFFCD108089038A000044EBA /* tag.hpp */, BFFCD109089038A000044EBA /* times.hpp */, BFFCD10A089038A000044EBA /* transform.hpp */, BFFCD10B089038A000044EBA /* transform_view.hpp */, BFFCD10C089038A000044EBA /* unique.hpp */, BFFCD10D089038A000044EBA /* unpack_args.hpp */, BFFCD10E089038A000044EBA /* upper_bound.hpp */, BFFCD10F089038A000044EBA /* value_type.hpp */, BFFCD110089038A000044EBA /* value_type_fwd.hpp */, BFFCD111089038A000044EBA /* vector */, BFFCD154089038A000044EBA /* vector.hpp */, BFFCD155089038A000044EBA /* vector_c.hpp */, BFFCD156089038A000044EBA /* void.hpp */, BFFCD157089038A000044EBA /* void_fwd.hpp */, BFFCD158089038A000044EBA /* zip_view.hpp */, ); path = mpl; sourceTree = ""; }; BFFCCD650890389800044EBA /* aux_ */ = { isa = PBXGroup; children = ( BFFCCD660890389800044EBA /* adl_barrier.hpp */, BFFCCD670890389800044EBA /* advance_backward.hpp */, BFFCCD680890389800044EBA /* advance_forward.hpp */, BFFCCD690890389800044EBA /* apply_1st.hpp */, BFFCCD6A0890389800044EBA /* arg_typedef.hpp */, BFFCCD6B0890389800044EBA /* arithmetic_op.hpp */, BFFCCD6C0890389800044EBA /* arity.hpp */, BFFCCD6D0890389800044EBA /* arity_spec.hpp */, BFFCCD6E0890389800044EBA /* at_impl.hpp */, BFFCCD6F0890389800044EBA /* back_impl.hpp */, BFFCCD700890389800044EBA /* basic_bind.hpp */, BFFCCD710890389800044EBA /* begin_end_impl.hpp */, BFFCCD720890389800044EBA /* clear_impl.hpp */, BFFCCD730890389800044EBA /* common_name_wknd.hpp */, BFFCCD740890389800044EBA /* comparison_op.hpp */, BFFCCD750890389800044EBA /* config */, BFFCCD910890389900044EBA /* contains_impl.hpp */, BFFCCD920890389900044EBA /* count_args.hpp */, BFFCCD930890389900044EBA /* count_impl.hpp */, BFFCCD940890389900044EBA /* empty_impl.hpp */, BFFCCD950890389900044EBA /* erase_impl.hpp */, BFFCCD960890389900044EBA /* erase_key_impl.hpp */, BFFCCD970890389900044EBA /* filter_iter.hpp */, BFFCCD980890389900044EBA /* find_if_pred.hpp */, BFFCCD990890389900044EBA /* fold_impl.hpp */, BFFCCD9A0890389900044EBA /* fold_impl_body.hpp */, BFFCCD9B0890389900044EBA /* fold_op.hpp */, BFFCCD9C0890389900044EBA /* fold_pred.hpp */, BFFCCD9D0890389900044EBA /* front_impl.hpp */, BFFCCD9E0890389900044EBA /* full_lambda.hpp */, BFFCCD9F0890389900044EBA /* has_apply.hpp */, BFFCCDA00890389900044EBA /* has_begin.hpp */, BFFCCDA10890389900044EBA /* has_key_impl.hpp */, BFFCCDA20890389900044EBA /* has_rebind.hpp */, BFFCCDA30890389900044EBA /* has_size.hpp */, BFFCCDA40890389900044EBA /* has_tag.hpp */, BFFCCDA50890389900044EBA /* has_type.hpp */, BFFCCDA60890389900044EBA /* include_preprocessed.hpp */, BFFCCDA70890389900044EBA /* insert_impl.hpp */, BFFCCDA80890389900044EBA /* insert_range_impl.hpp */, BFFCCDA90890389900044EBA /* inserter_algorithm.hpp */, BFFCCDAA0890389900044EBA /* integral_wrapper.hpp */, BFFCCDAB0890389900044EBA /* is_msvc_eti_arg.hpp */, BFFCCDAC0890389900044EBA /* iter_apply.hpp */, BFFCCDAD0890389900044EBA /* iter_fold_if_impl.hpp */, BFFCCDAE0890389900044EBA /* iter_fold_impl.hpp */, BFFCCDAF0890389900044EBA /* iter_push_front.hpp */, BFFCCDB00890389900044EBA /* joint_iter.hpp */, BFFCCDB10890389900044EBA /* lambda_arity_param.hpp */, BFFCCDB20890389900044EBA /* lambda_no_ctps.hpp */, BFFCCDB30890389900044EBA /* lambda_spec.hpp */, BFFCCDB40890389900044EBA /* lambda_support.hpp */, BFFCCDB50890389900044EBA /* largest_int.hpp */, BFFCCDB60890389900044EBA /* logical_op.hpp */, BFFCCDB70890389900044EBA /* msvc_dtw.hpp */, BFFCCDB80890389900044EBA /* msvc_eti_base.hpp */, BFFCCDB90890389900044EBA /* msvc_is_class.hpp */, BFFCCDBA0890389900044EBA /* msvc_never_true.hpp */, BFFCCDBB0890389900044EBA /* msvc_type.hpp */, BFFCCDBC0890389900044EBA /* na.hpp */, BFFCCDBD0890389900044EBA /* na_assert.hpp */, BFFCCDBE0890389900044EBA /* na_fwd.hpp */, BFFCCDBF0890389900044EBA /* na_spec.hpp */, BFFCCDC00890389900044EBA /* nested_type_wknd.hpp */, BFFCCDC10890389900044EBA /* nttp_decl.hpp */, BFFCCDC20890389900044EBA /* numeric_cast_utils.hpp */, BFFCCDC30890389900044EBA /* numeric_op.hpp */, BFFCCDC40890389900044EBA /* O1_size_impl.hpp */, BFFCCDC50890389900044EBA /* order_impl.hpp */, BFFCCDC60890389900044EBA /* overload_names.hpp */, BFFCCDC70890389900044EBA /* partition_op.hpp */, BFFCCDC80890389900044EBA /* pop_back_impl.hpp */, BFFCCDC90890389900044EBA /* pop_front_impl.hpp */, BFFCCDCA0890389900044EBA /* preprocessed */, BFFCCFAB0890389D00044EBA /* preprocessor */, BFFCCFBA0890389D00044EBA /* ptr_to_ref.hpp */, BFFCCFBB0890389D00044EBA /* push_back_impl.hpp */, BFFCCFBC0890389D00044EBA /* push_front_impl.hpp */, BFFCCFBD0890389D00044EBA /* range_c */, BFFCCFC50890389D00044EBA /* reverse_fold_impl.hpp */, BFFCCFC60890389D00044EBA /* reverse_fold_impl_body.hpp */, BFFCCFC70890389D00044EBA /* reverse_iter_fold_impl.hpp */, BFFCCFC80890389D00044EBA /* sequence_wrapper.hpp */, BFFCCFC90890389D00044EBA /* shift_op.hpp */, BFFCCFCA0890389D00044EBA /* single_element_iter.hpp */, BFFCCFCB0890389D00044EBA /* size_impl.hpp */, BFFCCFCC0890389D00044EBA /* sort_impl.hpp */, BFFCCFCD0890389D00044EBA /* static_cast.hpp */, BFFCCFCE0890389D00044EBA /* template_arity.hpp */, BFFCCFCF0890389D00044EBA /* template_arity_fwd.hpp */, BFFCCFD00890389D00044EBA /* test */, BFFCCFD40890389D00044EBA /* test.hpp */, BFFCCFD50890389D00044EBA /* traits_lambda_spec.hpp */, BFFCCFD60890389D00044EBA /* transform_iter.hpp */, BFFCCFD70890389D00044EBA /* type_wrapper.hpp */, BFFCCFD80890389D00044EBA /* unwrap.hpp */, BFFCCFD90890389D00044EBA /* value_wknd.hpp */, BFFCCFDA0890389D00044EBA /* yes_no.hpp */, ); path = aux_; sourceTree = ""; }; BFFCCD750890389800044EBA /* config */ = { isa = PBXGroup; children = ( BFFCCD760890389800044EBA /* adl.hpp */, BFFCCD770890389800044EBA /* arrays.hpp */, BFFCCD780890389800044EBA /* bind.hpp */, BFFCCD790890389800044EBA /* compiler.hpp */, BFFCCD7A0890389800044EBA /* ctps.hpp */, BFFCCD7B0890389800044EBA /* dependent_nttp.hpp */, BFFCCD7C0890389800044EBA /* dmc_ambiguous_ctps.hpp */, BFFCCD7D0890389800044EBA /* dtp.hpp */, BFFCCD7E0890389800044EBA /* eti.hpp */, BFFCCD7F0890389800044EBA /* forwarding.hpp */, BFFCCD800890389800044EBA /* gcc.hpp */, BFFCCD810890389800044EBA /* has_apply.hpp */, BFFCCD820890389800044EBA /* has_xxx.hpp */, BFFCCD830890389800044EBA /* integral.hpp */, BFFCCD840890389800044EBA /* intel.hpp */, BFFCCD850890389800044EBA /* lambda.hpp */, BFFCCD860890389800044EBA /* msvc.hpp */, BFFCCD870890389800044EBA /* msvc_typename.hpp */, BFFCCD880890389800044EBA /* nttp.hpp */, BFFCCD890890389800044EBA /* operators.hpp */, BFFCCD8A0890389800044EBA /* overload_resolution.hpp */, BFFCCD8B0890389800044EBA /* preprocessor.hpp */, BFFCCD8C0890389800044EBA /* static_constant.hpp */, BFFCCD8D0890389800044EBA /* ttp.hpp */, BFFCCD8E0890389800044EBA /* typeof.hpp */, BFFCCD8F0890389800044EBA /* use_preprocessed.hpp */, BFFCCD900890389800044EBA /* workaround.hpp */, ); path = config; sourceTree = ""; }; BFFCCDCA0890389900044EBA /* preprocessed */ = { isa = PBXGroup; children = ( BFFCCDCB0890389900044EBA /* bcc */, BFFCCDFB0890389900044EBA /* bcc551 */, BFFCCE2B0890389A00044EBA /* dmc */, BFFCCE5B0890389A00044EBA /* gcc */, BFFCCE8B0890389B00044EBA /* msvc60 */, BFFCCEBB0890389B00044EBA /* msvc70 */, BFFCCEEB0890389B00044EBA /* mwcw */, BFFCCF1B0890389C00044EBA /* no_ctps */, BFFCCF4B0890389C00044EBA /* no_ttp */, BFFCCF7B0890389D00044EBA /* plain */, ); path = preprocessed; sourceTree = ""; }; BFFCCDCB0890389900044EBA /* bcc */ = { isa = PBXGroup; children = ( BFFCCDCC0890389900044EBA /* advance_backward.hpp */, BFFCCDCD0890389900044EBA /* advance_forward.hpp */, BFFCCDCE0890389900044EBA /* and.hpp */, BFFCCDCF0890389900044EBA /* apply.hpp */, BFFCCDD00890389900044EBA /* apply_fwd.hpp */, BFFCCDD10890389900044EBA /* apply_wrap.hpp */, BFFCCDD20890389900044EBA /* arg.hpp */, BFFCCDD30890389900044EBA /* basic_bind.hpp */, BFFCCDD40890389900044EBA /* bind.hpp */, BFFCCDD50890389900044EBA /* bind_fwd.hpp */, BFFCCDD60890389900044EBA /* bitand.hpp */, BFFCCDD70890389900044EBA /* bitor.hpp */, BFFCCDD80890389900044EBA /* bitxor.hpp */, BFFCCDD90890389900044EBA /* deque.hpp */, BFFCCDDA0890389900044EBA /* divides.hpp */, BFFCCDDB0890389900044EBA /* equal_to.hpp */, BFFCCDDC0890389900044EBA /* fold_impl.hpp */, BFFCCDDD0890389900044EBA /* full_lambda.hpp */, BFFCCDDE0890389900044EBA /* greater.hpp */, BFFCCDDF0890389900044EBA /* greater_equal.hpp */, BFFCCDE00890389900044EBA /* inherit.hpp */, BFFCCDE10890389900044EBA /* iter_fold_if_impl.hpp */, BFFCCDE20890389900044EBA /* iter_fold_impl.hpp */, BFFCCDE30890389900044EBA /* lambda_no_ctps.hpp */, BFFCCDE40890389900044EBA /* less.hpp */, BFFCCDE50890389900044EBA /* less_equal.hpp */, BFFCCDE60890389900044EBA /* list.hpp */, BFFCCDE70890389900044EBA /* list_c.hpp */, BFFCCDE80890389900044EBA /* map.hpp */, BFFCCDE90890389900044EBA /* minus.hpp */, BFFCCDEA0890389900044EBA /* modulus.hpp */, BFFCCDEB0890389900044EBA /* not_equal_to.hpp */, BFFCCDEC0890389900044EBA /* or.hpp */, BFFCCDED0890389900044EBA /* placeholders.hpp */, BFFCCDEE0890389900044EBA /* plus.hpp */, BFFCCDEF0890389900044EBA /* quote.hpp */, BFFCCDF00890389900044EBA /* reverse_fold_impl.hpp */, BFFCCDF10890389900044EBA /* reverse_iter_fold_impl.hpp */, BFFCCDF20890389900044EBA /* set.hpp */, BFFCCDF30890389900044EBA /* set_c.hpp */, BFFCCDF40890389900044EBA /* shift_left.hpp */, BFFCCDF50890389900044EBA /* shift_right.hpp */, BFFCCDF60890389900044EBA /* template_arity.hpp */, BFFCCDF70890389900044EBA /* times.hpp */, BFFCCDF80890389900044EBA /* unpack_args.hpp */, BFFCCDF90890389900044EBA /* vector.hpp */, BFFCCDFA0890389900044EBA /* vector_c.hpp */, ); path = bcc; sourceTree = ""; }; BFFCCDFB0890389900044EBA /* bcc551 */ = { isa = PBXGroup; children = ( BFFCCDFC0890389900044EBA /* advance_backward.hpp */, BFFCCDFD0890389900044EBA /* advance_forward.hpp */, BFFCCDFE0890389900044EBA /* and.hpp */, BFFCCDFF0890389900044EBA /* apply.hpp */, BFFCCE000890389900044EBA /* apply_fwd.hpp */, BFFCCE010890389A00044EBA /* apply_wrap.hpp */, BFFCCE020890389A00044EBA /* arg.hpp */, BFFCCE030890389A00044EBA /* basic_bind.hpp */, BFFCCE040890389A00044EBA /* bind.hpp */, BFFCCE050890389A00044EBA /* bind_fwd.hpp */, BFFCCE060890389A00044EBA /* bitand.hpp */, BFFCCE070890389A00044EBA /* bitor.hpp */, BFFCCE080890389A00044EBA /* bitxor.hpp */, BFFCCE090890389A00044EBA /* deque.hpp */, BFFCCE0A0890389A00044EBA /* divides.hpp */, BFFCCE0B0890389A00044EBA /* equal_to.hpp */, BFFCCE0C0890389A00044EBA /* fold_impl.hpp */, BFFCCE0D0890389A00044EBA /* full_lambda.hpp */, BFFCCE0E0890389A00044EBA /* greater.hpp */, BFFCCE0F0890389A00044EBA /* greater_equal.hpp */, BFFCCE100890389A00044EBA /* inherit.hpp */, BFFCCE110890389A00044EBA /* iter_fold_if_impl.hpp */, BFFCCE120890389A00044EBA /* iter_fold_impl.hpp */, BFFCCE130890389A00044EBA /* lambda_no_ctps.hpp */, BFFCCE140890389A00044EBA /* less.hpp */, BFFCCE150890389A00044EBA /* less_equal.hpp */, BFFCCE160890389A00044EBA /* list.hpp */, BFFCCE170890389A00044EBA /* list_c.hpp */, BFFCCE180890389A00044EBA /* map.hpp */, BFFCCE190890389A00044EBA /* minus.hpp */, BFFCCE1A0890389A00044EBA /* modulus.hpp */, BFFCCE1B0890389A00044EBA /* not_equal_to.hpp */, BFFCCE1C0890389A00044EBA /* or.hpp */, BFFCCE1D0890389A00044EBA /* placeholders.hpp */, BFFCCE1E0890389A00044EBA /* plus.hpp */, BFFCCE1F0890389A00044EBA /* quote.hpp */, BFFCCE200890389A00044EBA /* reverse_fold_impl.hpp */, BFFCCE210890389A00044EBA /* reverse_iter_fold_impl.hpp */, BFFCCE220890389A00044EBA /* set.hpp */, BFFCCE230890389A00044EBA /* set_c.hpp */, BFFCCE240890389A00044EBA /* shift_left.hpp */, BFFCCE250890389A00044EBA /* shift_right.hpp */, BFFCCE260890389A00044EBA /* template_arity.hpp */, BFFCCE270890389A00044EBA /* times.hpp */, BFFCCE280890389A00044EBA /* unpack_args.hpp */, BFFCCE290890389A00044EBA /* vector.hpp */, BFFCCE2A0890389A00044EBA /* vector_c.hpp */, ); path = bcc551; sourceTree = ""; }; BFFCCE2B0890389A00044EBA /* dmc */ = { isa = PBXGroup; children = ( BFFCCE2C0890389A00044EBA /* advance_backward.hpp */, BFFCCE2D0890389A00044EBA /* advance_forward.hpp */, BFFCCE2E0890389A00044EBA /* and.hpp */, BFFCCE2F0890389A00044EBA /* apply.hpp */, BFFCCE300890389A00044EBA /* apply_fwd.hpp */, BFFCCE310890389A00044EBA /* apply_wrap.hpp */, BFFCCE320890389A00044EBA /* arg.hpp */, BFFCCE330890389A00044EBA /* basic_bind.hpp */, BFFCCE340890389A00044EBA /* bind.hpp */, BFFCCE350890389A00044EBA /* bind_fwd.hpp */, BFFCCE360890389A00044EBA /* bitand.hpp */, BFFCCE370890389A00044EBA /* bitor.hpp */, BFFCCE380890389A00044EBA /* bitxor.hpp */, BFFCCE390890389A00044EBA /* deque.hpp */, BFFCCE3A0890389A00044EBA /* divides.hpp */, BFFCCE3B0890389A00044EBA /* equal_to.hpp */, BFFCCE3C0890389A00044EBA /* fold_impl.hpp */, BFFCCE3D0890389A00044EBA /* full_lambda.hpp */, BFFCCE3E0890389A00044EBA /* greater.hpp */, BFFCCE3F0890389A00044EBA /* greater_equal.hpp */, BFFCCE400890389A00044EBA /* inherit.hpp */, BFFCCE410890389A00044EBA /* iter_fold_if_impl.hpp */, BFFCCE420890389A00044EBA /* iter_fold_impl.hpp */, BFFCCE430890389A00044EBA /* lambda_no_ctps.hpp */, BFFCCE440890389A00044EBA /* less.hpp */, BFFCCE450890389A00044EBA /* less_equal.hpp */, BFFCCE460890389A00044EBA /* list.hpp */, BFFCCE470890389A00044EBA /* list_c.hpp */, BFFCCE480890389A00044EBA /* map.hpp */, BFFCCE490890389A00044EBA /* minus.hpp */, BFFCCE4A0890389A00044EBA /* modulus.hpp */, BFFCCE4B0890389A00044EBA /* not_equal_to.hpp */, BFFCCE4C0890389A00044EBA /* or.hpp */, BFFCCE4D0890389A00044EBA /* placeholders.hpp */, BFFCCE4E0890389A00044EBA /* plus.hpp */, BFFCCE4F0890389A00044EBA /* quote.hpp */, BFFCCE500890389A00044EBA /* reverse_fold_impl.hpp */, BFFCCE510890389A00044EBA /* reverse_iter_fold_impl.hpp */, BFFCCE520890389A00044EBA /* set.hpp */, BFFCCE530890389A00044EBA /* set_c.hpp */, BFFCCE540890389A00044EBA /* shift_left.hpp */, BFFCCE550890389A00044EBA /* shift_right.hpp */, BFFCCE560890389A00044EBA /* template_arity.hpp */, BFFCCE570890389A00044EBA /* times.hpp */, BFFCCE580890389A00044EBA /* unpack_args.hpp */, BFFCCE590890389A00044EBA /* vector.hpp */, BFFCCE5A0890389A00044EBA /* vector_c.hpp */, ); path = dmc; sourceTree = ""; }; BFFCCE5B0890389A00044EBA /* gcc */ = { isa = PBXGroup; children = ( BFFCCE5C0890389A00044EBA /* advance_backward.hpp */, BFFCCE5D0890389A00044EBA /* advance_forward.hpp */, BFFCCE5E0890389A00044EBA /* and.hpp */, BFFCCE5F0890389A00044EBA /* apply.hpp */, BFFCCE600890389A00044EBA /* apply_fwd.hpp */, BFFCCE610890389A00044EBA /* apply_wrap.hpp */, BFFCCE620890389A00044EBA /* arg.hpp */, BFFCCE630890389A00044EBA /* basic_bind.hpp */, BFFCCE640890389A00044EBA /* bind.hpp */, BFFCCE650890389A00044EBA /* bind_fwd.hpp */, BFFCCE660890389A00044EBA /* bitand.hpp */, BFFCCE670890389A00044EBA /* bitor.hpp */, BFFCCE680890389A00044EBA /* bitxor.hpp */, BFFCCE690890389A00044EBA /* deque.hpp */, BFFCCE6A0890389A00044EBA /* divides.hpp */, BFFCCE6B0890389A00044EBA /* equal_to.hpp */, BFFCCE6C0890389A00044EBA /* fold_impl.hpp */, BFFCCE6D0890389A00044EBA /* full_lambda.hpp */, BFFCCE6E0890389A00044EBA /* greater.hpp */, BFFCCE6F0890389A00044EBA /* greater_equal.hpp */, BFFCCE700890389A00044EBA /* inherit.hpp */, BFFCCE710890389A00044EBA /* iter_fold_if_impl.hpp */, BFFCCE720890389A00044EBA /* iter_fold_impl.hpp */, BFFCCE730890389A00044EBA /* lambda_no_ctps.hpp */, BFFCCE740890389A00044EBA /* less.hpp */, BFFCCE750890389A00044EBA /* less_equal.hpp */, BFFCCE760890389A00044EBA /* list.hpp */, BFFCCE770890389A00044EBA /* list_c.hpp */, BFFCCE780890389A00044EBA /* map.hpp */, BFFCCE790890389A00044EBA /* minus.hpp */, BFFCCE7A0890389A00044EBA /* modulus.hpp */, BFFCCE7B0890389A00044EBA /* not_equal_to.hpp */, BFFCCE7C0890389A00044EBA /* or.hpp */, BFFCCE7D0890389A00044EBA /* placeholders.hpp */, BFFCCE7E0890389A00044EBA /* plus.hpp */, BFFCCE7F0890389A00044EBA /* quote.hpp */, BFFCCE800890389A00044EBA /* reverse_fold_impl.hpp */, BFFCCE810890389A00044EBA /* reverse_iter_fold_impl.hpp */, BFFCCE820890389A00044EBA /* set.hpp */, BFFCCE830890389A00044EBA /* set_c.hpp */, BFFCCE840890389A00044EBA /* shift_left.hpp */, BFFCCE850890389A00044EBA /* shift_right.hpp */, BFFCCE860890389A00044EBA /* template_arity.hpp */, BFFCCE870890389B00044EBA /* times.hpp */, BFFCCE880890389B00044EBA /* unpack_args.hpp */, BFFCCE890890389B00044EBA /* vector.hpp */, BFFCCE8A0890389B00044EBA /* vector_c.hpp */, ); path = gcc; sourceTree = ""; }; BFFCCE8B0890389B00044EBA /* msvc60 */ = { isa = PBXGroup; children = ( BFFCCE8C0890389B00044EBA /* advance_backward.hpp */, BFFCCE8D0890389B00044EBA /* advance_forward.hpp */, BFFCCE8E0890389B00044EBA /* and.hpp */, BFFCCE8F0890389B00044EBA /* apply.hpp */, BFFCCE900890389B00044EBA /* apply_fwd.hpp */, BFFCCE910890389B00044EBA /* apply_wrap.hpp */, BFFCCE920890389B00044EBA /* arg.hpp */, BFFCCE930890389B00044EBA /* basic_bind.hpp */, BFFCCE940890389B00044EBA /* bind.hpp */, BFFCCE950890389B00044EBA /* bind_fwd.hpp */, BFFCCE960890389B00044EBA /* bitand.hpp */, BFFCCE970890389B00044EBA /* bitor.hpp */, BFFCCE980890389B00044EBA /* bitxor.hpp */, BFFCCE990890389B00044EBA /* deque.hpp */, BFFCCE9A0890389B00044EBA /* divides.hpp */, BFFCCE9B0890389B00044EBA /* equal_to.hpp */, BFFCCE9C0890389B00044EBA /* fold_impl.hpp */, BFFCCE9D0890389B00044EBA /* full_lambda.hpp */, BFFCCE9E0890389B00044EBA /* greater.hpp */, BFFCCE9F0890389B00044EBA /* greater_equal.hpp */, BFFCCEA00890389B00044EBA /* inherit.hpp */, BFFCCEA10890389B00044EBA /* iter_fold_if_impl.hpp */, BFFCCEA20890389B00044EBA /* iter_fold_impl.hpp */, BFFCCEA30890389B00044EBA /* lambda_no_ctps.hpp */, BFFCCEA40890389B00044EBA /* less.hpp */, BFFCCEA50890389B00044EBA /* less_equal.hpp */, BFFCCEA60890389B00044EBA /* list.hpp */, BFFCCEA70890389B00044EBA /* list_c.hpp */, BFFCCEA80890389B00044EBA /* map.hpp */, BFFCCEA90890389B00044EBA /* minus.hpp */, BFFCCEAA0890389B00044EBA /* modulus.hpp */, BFFCCEAB0890389B00044EBA /* not_equal_to.hpp */, BFFCCEAC0890389B00044EBA /* or.hpp */, BFFCCEAD0890389B00044EBA /* placeholders.hpp */, BFFCCEAE0890389B00044EBA /* plus.hpp */, BFFCCEAF0890389B00044EBA /* quote.hpp */, BFFCCEB00890389B00044EBA /* reverse_fold_impl.hpp */, BFFCCEB10890389B00044EBA /* reverse_iter_fold_impl.hpp */, BFFCCEB20890389B00044EBA /* set.hpp */, BFFCCEB30890389B00044EBA /* set_c.hpp */, BFFCCEB40890389B00044EBA /* shift_left.hpp */, BFFCCEB50890389B00044EBA /* shift_right.hpp */, BFFCCEB60890389B00044EBA /* template_arity.hpp */, BFFCCEB70890389B00044EBA /* times.hpp */, BFFCCEB80890389B00044EBA /* unpack_args.hpp */, BFFCCEB90890389B00044EBA /* vector.hpp */, BFFCCEBA0890389B00044EBA /* vector_c.hpp */, ); path = msvc60; sourceTree = ""; }; BFFCCEBB0890389B00044EBA /* msvc70 */ = { isa = PBXGroup; children = ( BFFCCEBC0890389B00044EBA /* advance_backward.hpp */, BFFCCEBD0890389B00044EBA /* advance_forward.hpp */, BFFCCEBE0890389B00044EBA /* and.hpp */, BFFCCEBF0890389B00044EBA /* apply.hpp */, BFFCCEC00890389B00044EBA /* apply_fwd.hpp */, BFFCCEC10890389B00044EBA /* apply_wrap.hpp */, BFFCCEC20890389B00044EBA /* arg.hpp */, BFFCCEC30890389B00044EBA /* basic_bind.hpp */, BFFCCEC40890389B00044EBA /* bind.hpp */, BFFCCEC50890389B00044EBA /* bind_fwd.hpp */, BFFCCEC60890389B00044EBA /* bitand.hpp */, BFFCCEC70890389B00044EBA /* bitor.hpp */, BFFCCEC80890389B00044EBA /* bitxor.hpp */, BFFCCEC90890389B00044EBA /* deque.hpp */, BFFCCECA0890389B00044EBA /* divides.hpp */, BFFCCECB0890389B00044EBA /* equal_to.hpp */, BFFCCECC0890389B00044EBA /* fold_impl.hpp */, BFFCCECD0890389B00044EBA /* full_lambda.hpp */, BFFCCECE0890389B00044EBA /* greater.hpp */, BFFCCECF0890389B00044EBA /* greater_equal.hpp */, BFFCCED00890389B00044EBA /* inherit.hpp */, BFFCCED10890389B00044EBA /* iter_fold_if_impl.hpp */, BFFCCED20890389B00044EBA /* iter_fold_impl.hpp */, BFFCCED30890389B00044EBA /* lambda_no_ctps.hpp */, BFFCCED40890389B00044EBA /* less.hpp */, BFFCCED50890389B00044EBA /* less_equal.hpp */, BFFCCED60890389B00044EBA /* list.hpp */, BFFCCED70890389B00044EBA /* list_c.hpp */, BFFCCED80890389B00044EBA /* map.hpp */, BFFCCED90890389B00044EBA /* minus.hpp */, BFFCCEDA0890389B00044EBA /* modulus.hpp */, BFFCCEDB0890389B00044EBA /* not_equal_to.hpp */, BFFCCEDC0890389B00044EBA /* or.hpp */, BFFCCEDD0890389B00044EBA /* placeholders.hpp */, BFFCCEDE0890389B00044EBA /* plus.hpp */, BFFCCEDF0890389B00044EBA /* quote.hpp */, BFFCCEE00890389B00044EBA /* reverse_fold_impl.hpp */, BFFCCEE10890389B00044EBA /* reverse_iter_fold_impl.hpp */, BFFCCEE20890389B00044EBA /* set.hpp */, BFFCCEE30890389B00044EBA /* set_c.hpp */, BFFCCEE40890389B00044EBA /* shift_left.hpp */, BFFCCEE50890389B00044EBA /* shift_right.hpp */, BFFCCEE60890389B00044EBA /* template_arity.hpp */, BFFCCEE70890389B00044EBA /* times.hpp */, BFFCCEE80890389B00044EBA /* unpack_args.hpp */, BFFCCEE90890389B00044EBA /* vector.hpp */, BFFCCEEA0890389B00044EBA /* vector_c.hpp */, ); path = msvc70; sourceTree = ""; }; BFFCCEEB0890389B00044EBA /* mwcw */ = { isa = PBXGroup; children = ( BFFCCEEC0890389B00044EBA /* advance_backward.hpp */, BFFCCEED0890389B00044EBA /* advance_forward.hpp */, BFFCCEEE0890389B00044EBA /* and.hpp */, BFFCCEEF0890389B00044EBA /* apply.hpp */, BFFCCEF00890389B00044EBA /* apply_fwd.hpp */, BFFCCEF10890389B00044EBA /* apply_wrap.hpp */, BFFCCEF20890389B00044EBA /* arg.hpp */, BFFCCEF30890389B00044EBA /* basic_bind.hpp */, BFFCCEF40890389B00044EBA /* bind.hpp */, BFFCCEF50890389B00044EBA /* bind_fwd.hpp */, BFFCCEF60890389B00044EBA /* bitand.hpp */, BFFCCEF70890389B00044EBA /* bitor.hpp */, BFFCCEF80890389B00044EBA /* bitxor.hpp */, BFFCCEF90890389B00044EBA /* deque.hpp */, BFFCCEFA0890389B00044EBA /* divides.hpp */, BFFCCEFB0890389B00044EBA /* equal_to.hpp */, BFFCCEFC0890389B00044EBA /* fold_impl.hpp */, BFFCCEFD0890389B00044EBA /* full_lambda.hpp */, BFFCCEFE0890389B00044EBA /* greater.hpp */, BFFCCEFF0890389B00044EBA /* greater_equal.hpp */, BFFCCF000890389B00044EBA /* inherit.hpp */, BFFCCF010890389B00044EBA /* iter_fold_if_impl.hpp */, BFFCCF020890389B00044EBA /* iter_fold_impl.hpp */, BFFCCF030890389B00044EBA /* lambda_no_ctps.hpp */, BFFCCF040890389B00044EBA /* less.hpp */, BFFCCF050890389B00044EBA /* less_equal.hpp */, BFFCCF060890389B00044EBA /* list.hpp */, BFFCCF070890389C00044EBA /* list_c.hpp */, BFFCCF080890389C00044EBA /* map.hpp */, BFFCCF090890389C00044EBA /* minus.hpp */, BFFCCF0A0890389C00044EBA /* modulus.hpp */, BFFCCF0B0890389C00044EBA /* not_equal_to.hpp */, BFFCCF0C0890389C00044EBA /* or.hpp */, BFFCCF0D0890389C00044EBA /* placeholders.hpp */, BFFCCF0E0890389C00044EBA /* plus.hpp */, BFFCCF0F0890389C00044EBA /* quote.hpp */, BFFCCF100890389C00044EBA /* reverse_fold_impl.hpp */, BFFCCF110890389C00044EBA /* reverse_iter_fold_impl.hpp */, BFFCCF120890389C00044EBA /* set.hpp */, BFFCCF130890389C00044EBA /* set_c.hpp */, BFFCCF140890389C00044EBA /* shift_left.hpp */, BFFCCF150890389C00044EBA /* shift_right.hpp */, BFFCCF160890389C00044EBA /* template_arity.hpp */, BFFCCF170890389C00044EBA /* times.hpp */, BFFCCF180890389C00044EBA /* unpack_args.hpp */, BFFCCF190890389C00044EBA /* vector.hpp */, BFFCCF1A0890389C00044EBA /* vector_c.hpp */, ); path = mwcw; sourceTree = ""; }; BFFCCF1B0890389C00044EBA /* no_ctps */ = { isa = PBXGroup; children = ( BFFCCF1C0890389C00044EBA /* advance_backward.hpp */, BFFCCF1D0890389C00044EBA /* advance_forward.hpp */, BFFCCF1E0890389C00044EBA /* and.hpp */, BFFCCF1F0890389C00044EBA /* apply.hpp */, BFFCCF200890389C00044EBA /* apply_fwd.hpp */, BFFCCF210890389C00044EBA /* apply_wrap.hpp */, BFFCCF220890389C00044EBA /* arg.hpp */, BFFCCF230890389C00044EBA /* basic_bind.hpp */, BFFCCF240890389C00044EBA /* bind.hpp */, BFFCCF250890389C00044EBA /* bind_fwd.hpp */, BFFCCF260890389C00044EBA /* bitand.hpp */, BFFCCF270890389C00044EBA /* bitor.hpp */, BFFCCF280890389C00044EBA /* bitxor.hpp */, BFFCCF290890389C00044EBA /* deque.hpp */, BFFCCF2A0890389C00044EBA /* divides.hpp */, BFFCCF2B0890389C00044EBA /* equal_to.hpp */, BFFCCF2C0890389C00044EBA /* fold_impl.hpp */, BFFCCF2D0890389C00044EBA /* full_lambda.hpp */, BFFCCF2E0890389C00044EBA /* greater.hpp */, BFFCCF2F0890389C00044EBA /* greater_equal.hpp */, BFFCCF300890389C00044EBA /* inherit.hpp */, BFFCCF310890389C00044EBA /* iter_fold_if_impl.hpp */, BFFCCF320890389C00044EBA /* iter_fold_impl.hpp */, BFFCCF330890389C00044EBA /* lambda_no_ctps.hpp */, BFFCCF340890389C00044EBA /* less.hpp */, BFFCCF350890389C00044EBA /* less_equal.hpp */, BFFCCF360890389C00044EBA /* list.hpp */, BFFCCF370890389C00044EBA /* list_c.hpp */, BFFCCF380890389C00044EBA /* map.hpp */, BFFCCF390890389C00044EBA /* minus.hpp */, BFFCCF3A0890389C00044EBA /* modulus.hpp */, BFFCCF3B0890389C00044EBA /* not_equal_to.hpp */, BFFCCF3C0890389C00044EBA /* or.hpp */, BFFCCF3D0890389C00044EBA /* placeholders.hpp */, BFFCCF3E0890389C00044EBA /* plus.hpp */, BFFCCF3F0890389C00044EBA /* quote.hpp */, BFFCCF400890389C00044EBA /* reverse_fold_impl.hpp */, BFFCCF410890389C00044EBA /* reverse_iter_fold_impl.hpp */, BFFCCF420890389C00044EBA /* set.hpp */, BFFCCF430890389C00044EBA /* set_c.hpp */, BFFCCF440890389C00044EBA /* shift_left.hpp */, BFFCCF450890389C00044EBA /* shift_right.hpp */, BFFCCF460890389C00044EBA /* template_arity.hpp */, BFFCCF470890389C00044EBA /* times.hpp */, BFFCCF480890389C00044EBA /* unpack_args.hpp */, BFFCCF490890389C00044EBA /* vector.hpp */, BFFCCF4A0890389C00044EBA /* vector_c.hpp */, ); path = no_ctps; sourceTree = ""; }; BFFCCF4B0890389C00044EBA /* no_ttp */ = { isa = PBXGroup; children = ( BFFCCF4C0890389C00044EBA /* advance_backward.hpp */, BFFCCF4D0890389C00044EBA /* advance_forward.hpp */, BFFCCF4E0890389C00044EBA /* and.hpp */, BFFCCF4F0890389C00044EBA /* apply.hpp */, BFFCCF500890389C00044EBA /* apply_fwd.hpp */, BFFCCF510890389C00044EBA /* apply_wrap.hpp */, BFFCCF520890389C00044EBA /* arg.hpp */, BFFCCF530890389C00044EBA /* basic_bind.hpp */, BFFCCF540890389C00044EBA /* bind.hpp */, BFFCCF550890389C00044EBA /* bind_fwd.hpp */, BFFCCF560890389C00044EBA /* bitand.hpp */, BFFCCF570890389C00044EBA /* bitor.hpp */, BFFCCF580890389C00044EBA /* bitxor.hpp */, BFFCCF590890389C00044EBA /* deque.hpp */, BFFCCF5A0890389C00044EBA /* divides.hpp */, BFFCCF5B0890389C00044EBA /* equal_to.hpp */, BFFCCF5C0890389C00044EBA /* fold_impl.hpp */, BFFCCF5D0890389C00044EBA /* full_lambda.hpp */, BFFCCF5E0890389C00044EBA /* greater.hpp */, BFFCCF5F0890389C00044EBA /* greater_equal.hpp */, BFFCCF600890389C00044EBA /* inherit.hpp */, BFFCCF610890389C00044EBA /* iter_fold_if_impl.hpp */, BFFCCF620890389C00044EBA /* iter_fold_impl.hpp */, BFFCCF630890389C00044EBA /* lambda_no_ctps.hpp */, BFFCCF640890389C00044EBA /* less.hpp */, BFFCCF650890389C00044EBA /* less_equal.hpp */, BFFCCF660890389C00044EBA /* list.hpp */, BFFCCF670890389C00044EBA /* list_c.hpp */, BFFCCF680890389C00044EBA /* map.hpp */, BFFCCF690890389C00044EBA /* minus.hpp */, BFFCCF6A0890389C00044EBA /* modulus.hpp */, BFFCCF6B0890389C00044EBA /* not_equal_to.hpp */, BFFCCF6C0890389C00044EBA /* or.hpp */, BFFCCF6D0890389C00044EBA /* placeholders.hpp */, BFFCCF6E0890389C00044EBA /* plus.hpp */, BFFCCF6F0890389C00044EBA /* quote.hpp */, BFFCCF700890389C00044EBA /* reverse_fold_impl.hpp */, BFFCCF710890389C00044EBA /* reverse_iter_fold_impl.hpp */, BFFCCF720890389C00044EBA /* set.hpp */, BFFCCF730890389C00044EBA /* set_c.hpp */, BFFCCF740890389C00044EBA /* shift_left.hpp */, BFFCCF750890389C00044EBA /* shift_right.hpp */, BFFCCF760890389C00044EBA /* template_arity.hpp */, BFFCCF770890389C00044EBA /* times.hpp */, BFFCCF780890389C00044EBA /* unpack_args.hpp */, BFFCCF790890389C00044EBA /* vector.hpp */, BFFCCF7A0890389C00044EBA /* vector_c.hpp */, ); path = no_ttp; sourceTree = ""; }; BFFCCF7B0890389D00044EBA /* plain */ = { isa = PBXGroup; children = ( BFFCCF7C0890389D00044EBA /* advance_backward.hpp */, BFFCCF7D0890389D00044EBA /* advance_forward.hpp */, BFFCCF7E0890389D00044EBA /* and.hpp */, BFFCCF7F0890389D00044EBA /* apply.hpp */, BFFCCF800890389D00044EBA /* apply_fwd.hpp */, BFFCCF810890389D00044EBA /* apply_wrap.hpp */, BFFCCF820890389D00044EBA /* arg.hpp */, BFFCCF830890389D00044EBA /* basic_bind.hpp */, BFFCCF840890389D00044EBA /* bind.hpp */, BFFCCF850890389D00044EBA /* bind_fwd.hpp */, BFFCCF860890389D00044EBA /* bitand.hpp */, BFFCCF870890389D00044EBA /* bitor.hpp */, BFFCCF880890389D00044EBA /* bitxor.hpp */, BFFCCF890890389D00044EBA /* deque.hpp */, BFFCCF8A0890389D00044EBA /* divides.hpp */, BFFCCF8B0890389D00044EBA /* equal_to.hpp */, BFFCCF8C0890389D00044EBA /* fold_impl.hpp */, BFFCCF8D0890389D00044EBA /* full_lambda.hpp */, BFFCCF8E0890389D00044EBA /* greater.hpp */, BFFCCF8F0890389D00044EBA /* greater_equal.hpp */, BFFCCF900890389D00044EBA /* inherit.hpp */, BFFCCF910890389D00044EBA /* iter_fold_if_impl.hpp */, BFFCCF920890389D00044EBA /* iter_fold_impl.hpp */, BFFCCF930890389D00044EBA /* lambda_no_ctps.hpp */, BFFCCF940890389D00044EBA /* less.hpp */, BFFCCF950890389D00044EBA /* less_equal.hpp */, BFFCCF960890389D00044EBA /* list.hpp */, BFFCCF970890389D00044EBA /* list_c.hpp */, BFFCCF980890389D00044EBA /* map.hpp */, BFFCCF990890389D00044EBA /* minus.hpp */, BFFCCF9A0890389D00044EBA /* modulus.hpp */, BFFCCF9B0890389D00044EBA /* not_equal_to.hpp */, BFFCCF9C0890389D00044EBA /* or.hpp */, BFFCCF9D0890389D00044EBA /* placeholders.hpp */, BFFCCF9E0890389D00044EBA /* plus.hpp */, BFFCCF9F0890389D00044EBA /* quote.hpp */, BFFCCFA00890389D00044EBA /* reverse_fold_impl.hpp */, BFFCCFA10890389D00044EBA /* reverse_iter_fold_impl.hpp */, BFFCCFA20890389D00044EBA /* set.hpp */, BFFCCFA30890389D00044EBA /* set_c.hpp */, BFFCCFA40890389D00044EBA /* shift_left.hpp */, BFFCCFA50890389D00044EBA /* shift_right.hpp */, BFFCCFA60890389D00044EBA /* template_arity.hpp */, BFFCCFA70890389D00044EBA /* times.hpp */, BFFCCFA80890389D00044EBA /* unpack_args.hpp */, BFFCCFA90890389D00044EBA /* vector.hpp */, BFFCCFAA0890389D00044EBA /* vector_c.hpp */, ); path = plain; sourceTree = ""; }; BFFCCFAB0890389D00044EBA /* preprocessor */ = { isa = PBXGroup; children = ( BFFCCFAC0890389D00044EBA /* add.hpp */, BFFCCFAD0890389D00044EBA /* def_params_tail.hpp */, BFFCCFAE0890389D00044EBA /* default_params.hpp */, BFFCCFAF0890389D00044EBA /* enum.hpp */, BFFCCFB00890389D00044EBA /* ext_params.hpp */, BFFCCFB10890389D00044EBA /* filter_params.hpp */, BFFCCFB20890389D00044EBA /* is_seq.hpp */, BFFCCFB30890389D00044EBA /* params.hpp */, BFFCCFB40890389D00044EBA /* partial_spec_params.hpp */, BFFCCFB50890389D00044EBA /* range.hpp */, BFFCCFB60890389D00044EBA /* repeat.hpp */, BFFCCFB70890389D00044EBA /* sub.hpp */, BFFCCFB80890389D00044EBA /* token_equal.hpp */, BFFCCFB90890389D00044EBA /* tuple.hpp */, ); path = preprocessor; sourceTree = ""; }; BFFCCFBD0890389D00044EBA /* range_c */ = { isa = PBXGroup; children = ( BFFCCFBE0890389D00044EBA /* back.hpp */, BFFCCFBF0890389D00044EBA /* empty.hpp */, BFFCCFC00890389D00044EBA /* front.hpp */, BFFCCFC10890389D00044EBA /* iterator.hpp */, BFFCCFC20890389D00044EBA /* O1_size.hpp */, BFFCCFC30890389D00044EBA /* size.hpp */, BFFCCFC40890389D00044EBA /* tag.hpp */, ); path = range_c; sourceTree = ""; }; BFFCCFD00890389D00044EBA /* test */ = { isa = PBXGroup; children = ( BFFCCFD10890389D00044EBA /* assert.hpp */, BFFCCFD20890389D00044EBA /* data.hpp */, BFFCCFD30890389D00044EBA /* test_case.hpp */, ); path = test; sourceTree = ""; }; BFFCD0300890389E00044EBA /* limits */ = { isa = PBXGroup; children = ( BFFCD0310890389E00044EBA /* arity.hpp */, BFFCD0320890389E00044EBA /* list.hpp */, BFFCD0330890389E00044EBA /* map.hpp */, BFFCD0340890389E00044EBA /* set.hpp */, BFFCD0350890389E00044EBA /* unrolling.hpp */, BFFCD0360890389E00044EBA /* vector.hpp */, ); path = limits; sourceTree = ""; }; BFFCD0370890389E00044EBA /* list */ = { isa = PBXGroup; children = ( BFFCD0380890389E00044EBA /* aux_ */, BFFCD0540890389E00044EBA /* list0.hpp */, BFFCD0550890389E00044EBA /* list0_c.hpp */, BFFCD0560890389E00044EBA /* list10.hpp */, BFFCD0570890389E00044EBA /* list10_c.hpp */, BFFCD0580890389E00044EBA /* list20.hpp */, BFFCD0590890389E00044EBA /* list20_c.hpp */, BFFCD05A0890389E00044EBA /* list30.hpp */, BFFCD05B0890389E00044EBA /* list30_c.hpp */, BFFCD05C0890389E00044EBA /* list40.hpp */, BFFCD05D0890389E00044EBA /* list40_c.hpp */, BFFCD05E0890389F00044EBA /* list50.hpp */, BFFCD05F0890389F00044EBA /* list50_c.hpp */, ); path = list; sourceTree = ""; }; BFFCD0380890389E00044EBA /* aux_ */ = { isa = PBXGroup; children = ( BFFCD0390890389E00044EBA /* begin_end.hpp */, BFFCD03A0890389E00044EBA /* clear.hpp */, BFFCD03B0890389E00044EBA /* empty.hpp */, BFFCD03C0890389E00044EBA /* front.hpp */, BFFCD03D0890389E00044EBA /* include_preprocessed.hpp */, BFFCD03E0890389E00044EBA /* item.hpp */, BFFCD03F0890389E00044EBA /* iterator.hpp */, BFFCD0400890389E00044EBA /* numbered.hpp */, BFFCD0410890389E00044EBA /* numbered_c.hpp */, BFFCD0420890389E00044EBA /* O1_size.hpp */, BFFCD0430890389E00044EBA /* pop_front.hpp */, BFFCD0440890389E00044EBA /* preprocessed */, BFFCD0500890389E00044EBA /* push_back.hpp */, BFFCD0510890389E00044EBA /* push_front.hpp */, BFFCD0520890389E00044EBA /* size.hpp */, BFFCD0530890389E00044EBA /* tag.hpp */, ); path = aux_; sourceTree = ""; }; BFFCD0440890389E00044EBA /* preprocessed */ = { isa = PBXGroup; children = ( BFFCD0450890389E00044EBA /* plain */, ); path = preprocessed; sourceTree = ""; }; BFFCD0450890389E00044EBA /* plain */ = { isa = PBXGroup; children = ( BFFCD0460890389E00044EBA /* list10.hpp */, BFFCD0470890389E00044EBA /* list10_c.hpp */, BFFCD0480890389E00044EBA /* list20.hpp */, BFFCD0490890389E00044EBA /* list20_c.hpp */, BFFCD04A0890389E00044EBA /* list30.hpp */, BFFCD04B0890389E00044EBA /* list30_c.hpp */, BFFCD04C0890389E00044EBA /* list40.hpp */, BFFCD04D0890389E00044EBA /* list40_c.hpp */, BFFCD04E0890389E00044EBA /* list50.hpp */, BFFCD04F0890389E00044EBA /* list50_c.hpp */, ); path = plain; sourceTree = ""; }; BFFCD0660890389F00044EBA /* map */ = { isa = PBXGroup; children = ( BFFCD0670890389F00044EBA /* aux_ */, BFFCD08D0890389F00044EBA /* map0.hpp */, BFFCD08E0890389F00044EBA /* map10.hpp */, BFFCD08F0890389F00044EBA /* map20.hpp */, BFFCD0900890389F00044EBA /* map30.hpp */, BFFCD0910890389F00044EBA /* map40.hpp */, BFFCD0920890389F00044EBA /* map50.hpp */, ); path = map; sourceTree = ""; }; BFFCD0670890389F00044EBA /* aux_ */ = { isa = PBXGroup; children = ( BFFCD0680890389F00044EBA /* at_impl.hpp */, BFFCD0690890389F00044EBA /* begin_end_impl.hpp */, BFFCD06A0890389F00044EBA /* clear_impl.hpp */, BFFCD06B0890389F00044EBA /* contains_impl.hpp */, BFFCD06C0890389F00044EBA /* empty_impl.hpp */, BFFCD06D0890389F00044EBA /* erase_impl.hpp */, BFFCD06E0890389F00044EBA /* erase_key_impl.hpp */, BFFCD06F0890389F00044EBA /* has_key_impl.hpp */, BFFCD0700890389F00044EBA /* include_preprocessed.hpp */, BFFCD0710890389F00044EBA /* insert_impl.hpp */, BFFCD0720890389F00044EBA /* item.hpp */, BFFCD0730890389F00044EBA /* iterator.hpp */, BFFCD0740890389F00044EBA /* key_type_impl.hpp */, BFFCD0750890389F00044EBA /* map0.hpp */, BFFCD0760890389F00044EBA /* numbered.hpp */, BFFCD0770890389F00044EBA /* preprocessed */, BFFCD08A0890389F00044EBA /* size_impl.hpp */, BFFCD08B0890389F00044EBA /* tag.hpp */, BFFCD08C0890389F00044EBA /* value_type_impl.hpp */, ); path = aux_; sourceTree = ""; }; BFFCD0770890389F00044EBA /* preprocessed */ = { isa = PBXGroup; children = ( BFFCD0780890389F00044EBA /* no_ctps */, BFFCD07E0890389F00044EBA /* plain */, BFFCD0840890389F00044EBA /* typeof_based */, ); path = preprocessed; sourceTree = ""; }; BFFCD0780890389F00044EBA /* no_ctps */ = { isa = PBXGroup; children = ( BFFCD0790890389F00044EBA /* map10.hpp */, BFFCD07A0890389F00044EBA /* map20.hpp */, BFFCD07B0890389F00044EBA /* map30.hpp */, BFFCD07C0890389F00044EBA /* map40.hpp */, BFFCD07D0890389F00044EBA /* map50.hpp */, ); path = no_ctps; sourceTree = ""; }; BFFCD07E0890389F00044EBA /* plain */ = { isa = PBXGroup; children = ( BFFCD07F0890389F00044EBA /* map10.hpp */, BFFCD0800890389F00044EBA /* map20.hpp */, BFFCD0810890389F00044EBA /* map30.hpp */, BFFCD0820890389F00044EBA /* map40.hpp */, BFFCD0830890389F00044EBA /* map50.hpp */, ); path = plain; sourceTree = ""; }; BFFCD0840890389F00044EBA /* typeof_based */ = { isa = PBXGroup; children = ( BFFCD0850890389F00044EBA /* map10.hpp */, BFFCD0860890389F00044EBA /* map20.hpp */, BFFCD0870890389F00044EBA /* map30.hpp */, BFFCD0880890389F00044EBA /* map40.hpp */, BFFCD0890890389F00044EBA /* map50.hpp */, ); path = typeof_based; sourceTree = ""; }; BFFCD0940890389F00044EBA /* math */ = { isa = PBXGroup; children = ( BFFCD0950890389F00044EBA /* fixed_c.hpp */, BFFCD0960890389F00044EBA /* is_even.hpp */, BFFCD0970890389F00044EBA /* rational_c.hpp */, ); path = math; sourceTree = ""; }; BFFCD0A00890389F00044EBA /* multiset */ = { isa = PBXGroup; children = ( BFFCD0A10890389F00044EBA /* aux_ */, BFFCD0A70890389F00044EBA /* multiset0.hpp */, ); path = multiset; sourceTree = ""; }; BFFCD0A10890389F00044EBA /* aux_ */ = { isa = PBXGroup; children = ( BFFCD0A20890389F00044EBA /* count_impl.hpp */, BFFCD0A30890389F00044EBA /* insert_impl.hpp */, BFFCD0A40890389F00044EBA /* item.hpp */, BFFCD0A50890389F00044EBA /* multiset0.hpp */, BFFCD0A60890389F00044EBA /* tag.hpp */, ); path = aux_; sourceTree = ""; }; BFFCD0CF0890389F00044EBA /* set */ = { isa = PBXGroup; children = ( BFFCD0D00890389F00044EBA /* aux_ */, BFFCD0EF089038A000044EBA /* set0.hpp */, BFFCD0F0089038A000044EBA /* set0_c.hpp */, BFFCD0F1089038A000044EBA /* set10.hpp */, BFFCD0F2089038A000044EBA /* set10_c.hpp */, BFFCD0F3089038A000044EBA /* set20.hpp */, BFFCD0F4089038A000044EBA /* set20_c.hpp */, BFFCD0F5089038A000044EBA /* set30.hpp */, BFFCD0F6089038A000044EBA /* set30_c.hpp */, BFFCD0F7089038A000044EBA /* set40.hpp */, BFFCD0F8089038A000044EBA /* set40_c.hpp */, BFFCD0F9089038A000044EBA /* set50.hpp */, BFFCD0FA089038A000044EBA /* set50_c.hpp */, ); path = set; sourceTree = ""; }; BFFCD0D00890389F00044EBA /* aux_ */ = { isa = PBXGroup; children = ( BFFCD0D10890389F00044EBA /* at_impl.hpp */, BFFCD0D20890389F00044EBA /* begin_end_impl.hpp */, BFFCD0D30890389F00044EBA /* clear_impl.hpp */, BFFCD0D4089038A000044EBA /* empty_impl.hpp */, BFFCD0D5089038A000044EBA /* erase_impl.hpp */, BFFCD0D6089038A000044EBA /* erase_key_impl.hpp */, BFFCD0D7089038A000044EBA /* has_key_impl.hpp */, BFFCD0D8089038A000044EBA /* include_preprocessed.hpp */, BFFCD0D9089038A000044EBA /* insert_impl.hpp */, BFFCD0DA089038A000044EBA /* item.hpp */, BFFCD0DB089038A000044EBA /* iterator.hpp */, BFFCD0DC089038A000044EBA /* key_type_impl.hpp */, BFFCD0DD089038A000044EBA /* numbered.hpp */, BFFCD0DE089038A000044EBA /* numbered_c.hpp */, BFFCD0DF089038A000044EBA /* preprocessed */, BFFCD0EB089038A000044EBA /* set0.hpp */, BFFCD0EC089038A000044EBA /* size_impl.hpp */, BFFCD0ED089038A000044EBA /* tag.hpp */, BFFCD0EE089038A000044EBA /* value_type_impl.hpp */, ); path = aux_; sourceTree = ""; }; BFFCD0DF089038A000044EBA /* preprocessed */ = { isa = PBXGroup; children = ( BFFCD0E0089038A000044EBA /* plain */, ); path = preprocessed; sourceTree = ""; }; BFFCD0E0089038A000044EBA /* plain */ = { isa = PBXGroup; children = ( BFFCD0E1089038A000044EBA /* set10.hpp */, BFFCD0E2089038A000044EBA /* set10_c.hpp */, BFFCD0E3089038A000044EBA /* set20.hpp */, BFFCD0E4089038A000044EBA /* set20_c.hpp */, BFFCD0E5089038A000044EBA /* set30.hpp */, BFFCD0E6089038A000044EBA /* set30_c.hpp */, BFFCD0E7089038A000044EBA /* set40.hpp */, BFFCD0E8089038A000044EBA /* set40_c.hpp */, BFFCD0E9089038A000044EBA /* set50.hpp */, BFFCD0EA089038A000044EBA /* set50_c.hpp */, ); path = plain; sourceTree = ""; }; BFFCD111089038A000044EBA /* vector */ = { isa = PBXGroup; children = ( BFFCD112089038A000044EBA /* aux_ */, BFFCD148089038A000044EBA /* vector0.hpp */, BFFCD149089038A000044EBA /* vector0_c.hpp */, BFFCD14A089038A000044EBA /* vector10.hpp */, BFFCD14B089038A000044EBA /* vector10_c.hpp */, BFFCD14C089038A000044EBA /* vector20.hpp */, BFFCD14D089038A000044EBA /* vector20_c.hpp */, BFFCD14E089038A000044EBA /* vector30.hpp */, BFFCD14F089038A000044EBA /* vector30_c.hpp */, BFFCD150089038A000044EBA /* vector40.hpp */, BFFCD151089038A000044EBA /* vector40_c.hpp */, BFFCD152089038A000044EBA /* vector50.hpp */, BFFCD153089038A000044EBA /* vector50_c.hpp */, ); path = vector; sourceTree = ""; }; BFFCD112089038A000044EBA /* aux_ */ = { isa = PBXGroup; children = ( BFFCD113089038A000044EBA /* at.hpp */, BFFCD114089038A000044EBA /* back.hpp */, BFFCD115089038A000044EBA /* begin_end.hpp */, BFFCD116089038A000044EBA /* clear.hpp */, BFFCD117089038A000044EBA /* empty.hpp */, BFFCD118089038A000044EBA /* front.hpp */, BFFCD119089038A000044EBA /* include_preprocessed.hpp */, BFFCD11A089038A000044EBA /* item.hpp */, BFFCD11B089038A000044EBA /* iterator.hpp */, BFFCD11C089038A000044EBA /* numbered.hpp */, BFFCD11D089038A000044EBA /* numbered_c.hpp */, BFFCD11E089038A000044EBA /* O1_size.hpp */, BFFCD11F089038A000044EBA /* pop_back.hpp */, BFFCD120089038A000044EBA /* pop_front.hpp */, BFFCD121089038A000044EBA /* preprocessed */, BFFCD143089038A000044EBA /* push_back.hpp */, BFFCD144089038A000044EBA /* push_front.hpp */, BFFCD145089038A000044EBA /* size.hpp */, BFFCD146089038A000044EBA /* tag.hpp */, BFFCD147089038A000044EBA /* vector0.hpp */, ); path = aux_; sourceTree = ""; }; BFFCD121089038A000044EBA /* preprocessed */ = { isa = PBXGroup; children = ( BFFCD122089038A000044EBA /* no_ctps */, BFFCD12D089038A000044EBA /* plain */, BFFCD138089038A000044EBA /* typeof_based */, ); path = preprocessed; sourceTree = ""; }; BFFCD122089038A000044EBA /* no_ctps */ = { isa = PBXGroup; children = ( BFFCD123089038A000044EBA /* vector10.hpp */, BFFCD124089038A000044EBA /* vector10_c.hpp */, BFFCD125089038A000044EBA /* vector20.hpp */, BFFCD126089038A000044EBA /* vector20_c.hpp */, BFFCD127089038A000044EBA /* vector30.hpp */, BFFCD128089038A000044EBA /* vector30_c.hpp */, BFFCD129089038A000044EBA /* vector40.hpp */, BFFCD12A089038A000044EBA /* vector40_c.hpp */, BFFCD12B089038A000044EBA /* vector50.hpp */, BFFCD12C089038A000044EBA /* vector50_c.hpp */, ); path = no_ctps; sourceTree = ""; }; BFFCD12D089038A000044EBA /* plain */ = { isa = PBXGroup; children = ( BFFCD12E089038A000044EBA /* vector10.hpp */, BFFCD12F089038A000044EBA /* vector10_c.hpp */, BFFCD130089038A000044EBA /* vector20.hpp */, BFFCD131089038A000044EBA /* vector20_c.hpp */, BFFCD132089038A000044EBA /* vector30.hpp */, BFFCD133089038A000044EBA /* vector30_c.hpp */, BFFCD134089038A000044EBA /* vector40.hpp */, BFFCD135089038A000044EBA /* vector40_c.hpp */, BFFCD136089038A000044EBA /* vector50.hpp */, BFFCD137089038A000044EBA /* vector50_c.hpp */, ); path = plain; sourceTree = ""; }; BFFCD138089038A000044EBA /* typeof_based */ = { isa = PBXGroup; children = ( BFFCD139089038A000044EBA /* vector10.hpp */, BFFCD13A089038A000044EBA /* vector10_c.hpp */, BFFCD13B089038A000044EBA /* vector20.hpp */, BFFCD13C089038A000044EBA /* vector20_c.hpp */, BFFCD13D089038A000044EBA /* vector30.hpp */, BFFCD13E089038A000044EBA /* vector30_c.hpp */, BFFCD13F089038A000044EBA /* vector40.hpp */, BFFCD140089038A000044EBA /* vector40_c.hpp */, BFFCD141089038A000044EBA /* vector50.hpp */, BFFCD142089038A000044EBA /* vector50_c.hpp */, ); path = typeof_based; sourceTree = ""; }; BFFCD15A089038A000044EBA /* preprocessor */ = { isa = PBXGroup; children = ( BFFCD15B089038A000044EBA /* arithmetic */, BFFCD165089038A000044EBA /* arithmetic.hpp */, BFFCD166089038A000044EBA /* array */, BFFCD172089038A100044EBA /* array.hpp */, BFFCD173089038A100044EBA /* assert_msg.hpp */, BFFCD174089038A100044EBA /* cat.hpp */, BFFCD175089038A100044EBA /* comma.hpp */, BFFCD176089038A100044EBA /* comma_if.hpp */, BFFCD177089038A100044EBA /* comparison */, BFFCD17E089038A100044EBA /* comparison.hpp */, BFFCD17F089038A100044EBA /* config */, BFFCD182089038A100044EBA /* control */, BFFCD191089038A100044EBA /* control.hpp */, BFFCD192089038A100044EBA /* debug */, BFFCD196089038A100044EBA /* debug.hpp */, BFFCD197089038A100044EBA /* dec.hpp */, BFFCD198089038A100044EBA /* detail */, BFFCD1A2089038A100044EBA /* empty.hpp */, BFFCD1A3089038A100044EBA /* enum.hpp */, BFFCD1A4089038A100044EBA /* enum_params.hpp */, BFFCD1A5089038A100044EBA /* enum_params_with_a_default.hpp */, BFFCD1A6089038A100044EBA /* enum_params_with_defaults.hpp */, BFFCD1A7089038A100044EBA /* enum_shifted.hpp */, BFFCD1A8089038A100044EBA /* enum_shifted_params.hpp */, BFFCD1A9089038A100044EBA /* expand.hpp */, BFFCD1AA089038A100044EBA /* expr_if.hpp */, BFFCD1AB089038A100044EBA /* facilities */, BFFCD1B4089038A100044EBA /* facilities.hpp */, BFFCD1B5089038A100044EBA /* for.hpp */, BFFCD1B6089038A100044EBA /* identity.hpp */, BFFCD1B7089038A100044EBA /* if.hpp */, BFFCD1B8089038A100044EBA /* inc.hpp */, BFFCD1B9089038A100044EBA /* iterate.hpp */, BFFCD1BA089038A100044EBA /* iteration */, BFFCD1DA089038A200044EBA /* iteration.hpp */, BFFCD1DB089038A200044EBA /* library.hpp */, BFFCD1DC089038A200044EBA /* limits.hpp */, BFFCD1DD089038A200044EBA /* list */, BFFCD1F7089038A200044EBA /* list.hpp */, BFFCD1F8089038A200044EBA /* logical */, BFFCD204089038A200044EBA /* logical.hpp */, BFFCD205089038A200044EBA /* max.hpp */, BFFCD206089038A200044EBA /* min.hpp */, BFFCD207089038A200044EBA /* punctuation */, BFFCD20C089038A200044EBA /* punctuation.hpp */, BFFCD20D089038A200044EBA /* repeat.hpp */, BFFCD20E089038A200044EBA /* repeat_2nd.hpp */, BFFCD20F089038A200044EBA /* repeat_3rd.hpp */, BFFCD210089038A200044EBA /* repeat_from_to.hpp */, BFFCD211089038A200044EBA /* repeat_from_to_2nd.hpp */, BFFCD212089038A200044EBA /* repeat_from_to_3rd.hpp */, BFFCD213089038A200044EBA /* repetition */, BFFCD22B089038A200044EBA /* repetition.hpp */, BFFCD22C089038A200044EBA /* selection */, BFFCD22F089038A200044EBA /* selection.hpp */, BFFCD230089038A200044EBA /* seq */, BFFCD24C089038A200044EBA /* seq.hpp */, BFFCD24D089038A200044EBA /* slot */, BFFCD257089038A300044EBA /* slot.hpp */, BFFCD258089038A300044EBA /* stringize.hpp */, BFFCD259089038A300044EBA /* tuple */, BFFCD260089038A300044EBA /* tuple.hpp */, BFFCD261089038A300044EBA /* while.hpp */, BFFCD262089038A300044EBA /* wstringize.hpp */, ); path = preprocessor; sourceTree = ""; }; BFFCD15B089038A000044EBA /* arithmetic */ = { isa = PBXGroup; children = ( BFFCD15C089038A000044EBA /* add.hpp */, BFFCD15D089038A000044EBA /* dec.hpp */, BFFCD15E089038A000044EBA /* detail */, BFFCD160089038A000044EBA /* div.hpp */, BFFCD161089038A000044EBA /* inc.hpp */, BFFCD162089038A000044EBA /* mod.hpp */, BFFCD163089038A000044EBA /* mul.hpp */, BFFCD164089038A000044EBA /* sub.hpp */, ); path = arithmetic; sourceTree = ""; }; BFFCD15E089038A000044EBA /* detail */ = { isa = PBXGroup; children = ( BFFCD15F089038A000044EBA /* div_base.hpp */, ); path = detail; sourceTree = ""; }; BFFCD166089038A000044EBA /* array */ = { isa = PBXGroup; children = ( BFFCD167089038A000044EBA /* data.hpp */, BFFCD168089038A000044EBA /* elem.hpp */, BFFCD169089038A100044EBA /* insert.hpp */, BFFCD16A089038A100044EBA /* pop_back.hpp */, BFFCD16B089038A100044EBA /* pop_front.hpp */, BFFCD16C089038A100044EBA /* push_back.hpp */, BFFCD16D089038A100044EBA /* push_front.hpp */, BFFCD16E089038A100044EBA /* remove.hpp */, BFFCD16F089038A100044EBA /* replace.hpp */, BFFCD170089038A100044EBA /* reverse.hpp */, BFFCD171089038A100044EBA /* size.hpp */, ); path = array; sourceTree = ""; }; BFFCD177089038A100044EBA /* comparison */ = { isa = PBXGroup; children = ( BFFCD178089038A100044EBA /* equal.hpp */, BFFCD179089038A100044EBA /* greater.hpp */, BFFCD17A089038A100044EBA /* greater_equal.hpp */, BFFCD17B089038A100044EBA /* less.hpp */, BFFCD17C089038A100044EBA /* less_equal.hpp */, BFFCD17D089038A100044EBA /* not_equal.hpp */, ); path = comparison; sourceTree = ""; }; BFFCD17F089038A100044EBA /* config */ = { isa = PBXGroup; children = ( BFFCD180089038A100044EBA /* config.hpp */, BFFCD181089038A100044EBA /* limits.hpp */, ); path = config; sourceTree = ""; }; BFFCD182089038A100044EBA /* control */ = { isa = PBXGroup; children = ( BFFCD183089038A100044EBA /* deduce_d.hpp */, BFFCD184089038A100044EBA /* detail */, BFFCD18C089038A100044EBA /* expr_if.hpp */, BFFCD18D089038A100044EBA /* expr_iif.hpp */, BFFCD18E089038A100044EBA /* if.hpp */, BFFCD18F089038A100044EBA /* iif.hpp */, BFFCD190089038A100044EBA /* while.hpp */, ); path = control; sourceTree = ""; }; BFFCD184089038A100044EBA /* detail */ = { isa = PBXGroup; children = ( BFFCD185089038A100044EBA /* dmc */, BFFCD187089038A100044EBA /* edg */, BFFCD189089038A100044EBA /* msvc */, BFFCD18B089038A100044EBA /* while.hpp */, ); path = detail; sourceTree = ""; }; BFFCD185089038A100044EBA /* dmc */ = { isa = PBXGroup; children = ( BFFCD186089038A100044EBA /* while.hpp */, ); path = dmc; sourceTree = ""; }; BFFCD187089038A100044EBA /* edg */ = { isa = PBXGroup; children = ( BFFCD188089038A100044EBA /* while.hpp */, ); path = edg; sourceTree = ""; }; BFFCD189089038A100044EBA /* msvc */ = { isa = PBXGroup; children = ( BFFCD18A089038A100044EBA /* while.hpp */, ); path = msvc; sourceTree = ""; }; BFFCD192089038A100044EBA /* debug */ = { isa = PBXGroup; children = ( BFFCD193089038A100044EBA /* assert.hpp */, BFFCD194089038A100044EBA /* error.hpp */, BFFCD195089038A100044EBA /* line.hpp */, ); path = debug; sourceTree = ""; }; BFFCD198089038A100044EBA /* detail */ = { isa = PBXGroup; children = ( BFFCD199089038A100044EBA /* auto_rec.hpp */, BFFCD19A089038A100044EBA /* check.hpp */, BFFCD19B089038A100044EBA /* dmc */, BFFCD19D089038A100044EBA /* is_binary.hpp */, BFFCD19E089038A100044EBA /* is_nullary.hpp */, BFFCD19F089038A100044EBA /* is_unary.hpp */, BFFCD1A0089038A100044EBA /* null.hpp */, BFFCD1A1089038A100044EBA /* split.hpp */, ); path = detail; sourceTree = ""; }; BFFCD19B089038A100044EBA /* dmc */ = { isa = PBXGroup; children = ( BFFCD19C089038A100044EBA /* auto_rec.hpp */, ); path = dmc; sourceTree = ""; }; BFFCD1AB089038A100044EBA /* facilities */ = { isa = PBXGroup; children = ( BFFCD1AC089038A100044EBA /* apply.hpp */, BFFCD1AD089038A100044EBA /* empty.hpp */, BFFCD1AE089038A100044EBA /* expand.hpp */, BFFCD1AF089038A100044EBA /* identity.hpp */, BFFCD1B0089038A100044EBA /* intercept.hpp */, BFFCD1B1089038A100044EBA /* is_1.hpp */, BFFCD1B2089038A100044EBA /* is_empty.hpp */, BFFCD1B3089038A100044EBA /* is_empty_or_1.hpp */, ); path = facilities; sourceTree = ""; }; BFFCD1BA089038A100044EBA /* iteration */ = { isa = PBXGroup; children = ( BFFCD1BB089038A100044EBA /* detail */, BFFCD1D7089038A200044EBA /* iterate.hpp */, BFFCD1D8089038A200044EBA /* local.hpp */, BFFCD1D9089038A200044EBA /* self.hpp */, ); path = iteration; sourceTree = ""; }; BFFCD1BB089038A100044EBA /* detail */ = { isa = PBXGroup; children = ( BFFCD1BC089038A100044EBA /* bounds */, BFFCD1C7089038A100044EBA /* finish.hpp */, BFFCD1C8089038A100044EBA /* iter */, BFFCD1D3089038A100044EBA /* local.hpp */, BFFCD1D4089038A200044EBA /* rlocal.hpp */, BFFCD1D5089038A200044EBA /* self.hpp */, BFFCD1D6089038A200044EBA /* start.hpp */, ); path = detail; sourceTree = ""; }; BFFCD1BC089038A100044EBA /* bounds */ = { isa = PBXGroup; children = ( BFFCD1BD089038A100044EBA /* lower1.hpp */, BFFCD1BE089038A100044EBA /* lower2.hpp */, BFFCD1BF089038A100044EBA /* lower3.hpp */, BFFCD1C0089038A100044EBA /* lower4.hpp */, BFFCD1C1089038A100044EBA /* lower5.hpp */, BFFCD1C2089038A100044EBA /* upper1.hpp */, BFFCD1C3089038A100044EBA /* upper2.hpp */, BFFCD1C4089038A100044EBA /* upper3.hpp */, BFFCD1C5089038A100044EBA /* upper4.hpp */, BFFCD1C6089038A100044EBA /* upper5.hpp */, ); path = bounds; sourceTree = ""; }; BFFCD1C8089038A100044EBA /* iter */ = { isa = PBXGroup; children = ( BFFCD1C9089038A100044EBA /* forward1.hpp */, BFFCD1CA089038A100044EBA /* forward2.hpp */, BFFCD1CB089038A100044EBA /* forward3.hpp */, BFFCD1CC089038A100044EBA /* forward4.hpp */, BFFCD1CD089038A100044EBA /* forward5.hpp */, BFFCD1CE089038A100044EBA /* reverse1.hpp */, BFFCD1CF089038A100044EBA /* reverse2.hpp */, BFFCD1D0089038A100044EBA /* reverse3.hpp */, BFFCD1D1089038A100044EBA /* reverse4.hpp */, BFFCD1D2089038A100044EBA /* reverse5.hpp */, ); path = iter; sourceTree = ""; }; BFFCD1DD089038A200044EBA /* list */ = { isa = PBXGroup; children = ( BFFCD1DE089038A200044EBA /* adt.hpp */, BFFCD1DF089038A200044EBA /* append.hpp */, BFFCD1E0089038A200044EBA /* at.hpp */, BFFCD1E1089038A200044EBA /* cat.hpp */, BFFCD1E2089038A200044EBA /* detail */, BFFCD1EA089038A200044EBA /* enum.hpp */, BFFCD1EB089038A200044EBA /* filter.hpp */, BFFCD1EC089038A200044EBA /* first_n.hpp */, BFFCD1ED089038A200044EBA /* fold_left.hpp */, BFFCD1EE089038A200044EBA /* fold_right.hpp */, BFFCD1EF089038A200044EBA /* for_each.hpp */, BFFCD1F0089038A200044EBA /* for_each_i.hpp */, BFFCD1F1089038A200044EBA /* for_each_product.hpp */, BFFCD1F2089038A200044EBA /* rest_n.hpp */, BFFCD1F3089038A200044EBA /* reverse.hpp */, BFFCD1F4089038A200044EBA /* size.hpp */, BFFCD1F5089038A200044EBA /* to_tuple.hpp */, BFFCD1F6089038A200044EBA /* transform.hpp */, ); path = list; sourceTree = ""; }; BFFCD1E2089038A200044EBA /* detail */ = { isa = PBXGroup; children = ( BFFCD1E3089038A200044EBA /* dmc */, BFFCD1E5089038A200044EBA /* edg */, BFFCD1E8089038A200044EBA /* fold_left.hpp */, BFFCD1E9089038A200044EBA /* fold_right.hpp */, ); path = detail; sourceTree = ""; }; BFFCD1E3089038A200044EBA /* dmc */ = { isa = PBXGroup; children = ( BFFCD1E4089038A200044EBA /* fold_left.hpp */, ); path = dmc; sourceTree = ""; }; BFFCD1E5089038A200044EBA /* edg */ = { isa = PBXGroup; children = ( BFFCD1E6089038A200044EBA /* fold_left.hpp */, BFFCD1E7089038A200044EBA /* fold_right.hpp */, ); path = edg; sourceTree = ""; }; BFFCD1F8089038A200044EBA /* logical */ = { isa = PBXGroup; children = ( BFFCD1F9089038A200044EBA /* and.hpp */, BFFCD1FA089038A200044EBA /* bitand.hpp */, BFFCD1FB089038A200044EBA /* bitnor.hpp */, BFFCD1FC089038A200044EBA /* bitor.hpp */, BFFCD1FD089038A200044EBA /* bitxor.hpp */, BFFCD1FE089038A200044EBA /* bool.hpp */, BFFCD1FF089038A200044EBA /* compl.hpp */, BFFCD200089038A200044EBA /* nor.hpp */, BFFCD201089038A200044EBA /* not.hpp */, BFFCD202089038A200044EBA /* or.hpp */, BFFCD203089038A200044EBA /* xor.hpp */, ); path = logical; sourceTree = ""; }; BFFCD207089038A200044EBA /* punctuation */ = { isa = PBXGroup; children = ( BFFCD208089038A200044EBA /* comma.hpp */, BFFCD209089038A200044EBA /* comma_if.hpp */, BFFCD20A089038A200044EBA /* paren.hpp */, BFFCD20B089038A200044EBA /* paren_if.hpp */, ); path = punctuation; sourceTree = ""; }; BFFCD213089038A200044EBA /* repetition */ = { isa = PBXGroup; children = ( BFFCD214089038A200044EBA /* deduce_r.hpp */, BFFCD215089038A200044EBA /* deduce_z.hpp */, BFFCD216089038A200044EBA /* detail */, BFFCD21E089038A200044EBA /* enum.hpp */, BFFCD21F089038A200044EBA /* enum_binary_params.hpp */, BFFCD220089038A200044EBA /* enum_params.hpp */, BFFCD221089038A200044EBA /* enum_params_with_a_default.hpp */, BFFCD222089038A200044EBA /* enum_params_with_defaults.hpp */, BFFCD223089038A200044EBA /* enum_shifted.hpp */, BFFCD224089038A200044EBA /* enum_shifted_params.hpp */, BFFCD225089038A200044EBA /* enum_trailing.hpp */, BFFCD226089038A200044EBA /* enum_trailing_binary_params.hpp */, BFFCD227089038A200044EBA /* enum_trailing_params.hpp */, BFFCD228089038A200044EBA /* for.hpp */, BFFCD229089038A200044EBA /* repeat.hpp */, BFFCD22A089038A200044EBA /* repeat_from_to.hpp */, ); path = repetition; sourceTree = ""; }; BFFCD216089038A200044EBA /* detail */ = { isa = PBXGroup; children = ( BFFCD217089038A200044EBA /* dmc */, BFFCD219089038A200044EBA /* edg */, BFFCD21B089038A200044EBA /* for.hpp */, BFFCD21C089038A200044EBA /* msvc */, ); path = detail; sourceTree = ""; }; BFFCD217089038A200044EBA /* dmc */ = { isa = PBXGroup; children = ( BFFCD218089038A200044EBA /* for.hpp */, ); path = dmc; sourceTree = ""; }; BFFCD219089038A200044EBA /* edg */ = { isa = PBXGroup; children = ( BFFCD21A089038A200044EBA /* for.hpp */, ); path = edg; sourceTree = ""; }; BFFCD21C089038A200044EBA /* msvc */ = { isa = PBXGroup; children = ( BFFCD21D089038A200044EBA /* for.hpp */, ); path = msvc; sourceTree = ""; }; BFFCD22C089038A200044EBA /* selection */ = { isa = PBXGroup; children = ( BFFCD22D089038A200044EBA /* max.hpp */, BFFCD22E089038A200044EBA /* min.hpp */, ); path = selection; sourceTree = ""; }; BFFCD230089038A200044EBA /* seq */ = { isa = PBXGroup; children = ( BFFCD231089038A200044EBA /* cat.hpp */, BFFCD232089038A200044EBA /* detail */, BFFCD234089038A200044EBA /* elem.hpp */, BFFCD235089038A200044EBA /* enum.hpp */, BFFCD236089038A200044EBA /* filter.hpp */, BFFCD237089038A200044EBA /* first_n.hpp */, BFFCD238089038A200044EBA /* fold_left.hpp */, BFFCD239089038A200044EBA /* fold_right.hpp */, BFFCD23A089038A200044EBA /* for_each.hpp */, BFFCD23B089038A200044EBA /* for_each_i.hpp */, BFFCD23C089038A200044EBA /* for_each_product.hpp */, BFFCD23D089038A200044EBA /* insert.hpp */, BFFCD23E089038A200044EBA /* pop_back.hpp */, BFFCD23F089038A200044EBA /* pop_front.hpp */, BFFCD240089038A200044EBA /* push_back.hpp */, BFFCD241089038A200044EBA /* push_front.hpp */, BFFCD242089038A200044EBA /* remove.hpp */, BFFCD243089038A200044EBA /* replace.hpp */, BFFCD244089038A200044EBA /* rest_n.hpp */, BFFCD245089038A200044EBA /* reverse.hpp */, BFFCD246089038A200044EBA /* seq.hpp */, BFFCD247089038A200044EBA /* size.hpp */, BFFCD248089038A200044EBA /* subseq.hpp */, BFFCD249089038A200044EBA /* to_array.hpp */, BFFCD24A089038A200044EBA /* to_tuple.hpp */, BFFCD24B089038A200044EBA /* transform.hpp */, ); path = seq; sourceTree = ""; }; BFFCD232089038A200044EBA /* detail */ = { isa = PBXGroup; children = ( BFFCD233089038A200044EBA /* split.hpp */, ); path = detail; sourceTree = ""; }; BFFCD24D089038A200044EBA /* slot */ = { isa = PBXGroup; children = ( BFFCD24E089038A200044EBA /* detail */, BFFCD256089038A300044EBA /* slot.hpp */, ); path = slot; sourceTree = ""; }; BFFCD24E089038A200044EBA /* detail */ = { isa = PBXGroup; children = ( BFFCD24F089038A200044EBA /* def.hpp */, BFFCD250089038A200044EBA /* shared.hpp */, BFFCD251089038A200044EBA /* slot1.hpp */, BFFCD252089038A200044EBA /* slot2.hpp */, BFFCD253089038A200044EBA /* slot3.hpp */, BFFCD254089038A200044EBA /* slot4.hpp */, BFFCD255089038A300044EBA /* slot5.hpp */, ); path = detail; sourceTree = ""; }; BFFCD259089038A300044EBA /* tuple */ = { isa = PBXGroup; children = ( BFFCD25A089038A300044EBA /* eat.hpp */, BFFCD25B089038A300044EBA /* elem.hpp */, BFFCD25C089038A300044EBA /* rem.hpp */, BFFCD25D089038A300044EBA /* reverse.hpp */, BFFCD25E089038A300044EBA /* to_list.hpp */, BFFCD25F089038A300044EBA /* to_seq.hpp */, ); path = tuple; sourceTree = ""; }; BFFCD266089038A300044EBA /* type_traits */ = { isa = PBXGroup; children = ( BFFCD267089038A300044EBA /* add_const.hpp */, BFFCD268089038A300044EBA /* add_cv.hpp */, BFFCD269089038A300044EBA /* add_pointer.hpp */, BFFCD26A089038A300044EBA /* add_reference.hpp */, BFFCD26B089038A300044EBA /* add_volatile.hpp */, BFFCD26C089038A300044EBA /* aligned_storage.hpp */, BFFCD26D089038A300044EBA /* alignment_of.hpp */, BFFCD26E089038A300044EBA /* alignment_traits.hpp */, BFFCD26F089038A300044EBA /* arithmetic_traits.hpp */, BFFCD270089038A300044EBA /* array_traits.hpp */, BFFCD271089038A300044EBA /* broken_compiler_spec.hpp */, BFFCD272089038A300044EBA /* composite_traits.hpp */, BFFCD273089038A300044EBA /* config.hpp */, BFFCD274089038A300044EBA /* conversion_traits.hpp */, BFFCD275089038A300044EBA /* cv_traits.hpp */, BFFCD276089038A300044EBA /* decay.hpp */, BFFCD277089038A300044EBA /* detail */, BFFCD28B089038A300044EBA /* extent.hpp */, BFFCD28C089038A300044EBA /* function_traits.hpp */, BFFCD28D089038A300044EBA /* has_nothrow_assign.hpp */, BFFCD28E089038A300044EBA /* has_nothrow_constructor.hpp */, BFFCD28F089038A300044EBA /* has_nothrow_copy.hpp */, BFFCD290089038A300044EBA /* has_nothrow_destructor.hpp */, BFFCD291089038A300044EBA /* has_trivial_assign.hpp */, BFFCD292089038A300044EBA /* has_trivial_constructor.hpp */, BFFCD293089038A300044EBA /* has_trivial_copy.hpp */, BFFCD294089038A300044EBA /* has_trivial_destructor.hpp */, BFFCD295089038A300044EBA /* has_virtual_destructor.hpp */, BFFCD296089038A300044EBA /* ice.hpp */, BFFCD297089038A300044EBA /* integral_constant.hpp */, BFFCD298089038A300044EBA /* intrinsics.hpp */, BFFCD299089038A300044EBA /* is_abstract.hpp */, BFFCD29A089038A300044EBA /* is_arithmetic.hpp */, BFFCD29B089038A300044EBA /* is_array.hpp */, BFFCD29C089038A300044EBA /* is_base_and_derived.hpp */, BFFCD29D089038A300044EBA /* is_base_of.hpp */, BFFCD29E089038A300044EBA /* is_class.hpp */, BFFCD29F089038A300044EBA /* is_compound.hpp */, BFFCD2A0089038A300044EBA /* is_const.hpp */, BFFCD2A1089038A300044EBA /* is_convertible.hpp */, BFFCD2A2089038A300044EBA /* is_empty.hpp */, BFFCD2A3089038A300044EBA /* is_enum.hpp */, BFFCD2A4089038A300044EBA /* is_float.hpp */, BFFCD2A5089038A300044EBA /* is_floating_point.hpp */, BFFCD2A6089038A300044EBA /* is_function.hpp */, BFFCD2A7089038A300044EBA /* is_fundamental.hpp */, BFFCD2A8089038A300044EBA /* is_integral.hpp */, BFFCD2A9089038A300044EBA /* is_member_function_pointer.hpp */, BFFCD2AA089038A300044EBA /* is_member_object_pointer.hpp */, BFFCD2AB089038A300044EBA /* is_member_pointer.hpp */, BFFCD2AC089038A300044EBA /* is_object.hpp */, BFFCD2AD089038A300044EBA /* is_pod.hpp */, BFFCD2AE089038A300044EBA /* is_pointer.hpp */, BFFCD2AF089038A300044EBA /* is_polymorphic.hpp */, BFFCD2B0089038A400044EBA /* is_reference.hpp */, BFFCD2B1089038A400044EBA /* is_same.hpp */, BFFCD2B2089038A400044EBA /* is_scalar.hpp */, BFFCD2B3089038A400044EBA /* is_signed.hpp */, BFFCD2B4089038A400044EBA /* is_stateless.hpp */, BFFCD2B5089038A400044EBA /* is_union.hpp */, BFFCD2B6089038A400044EBA /* is_unsigned.hpp */, BFFCD2B7089038A400044EBA /* is_void.hpp */, BFFCD2B8089038A400044EBA /* is_volatile.hpp */, BFFCD2B9089038A400044EBA /* object_traits.hpp */, BFFCD2BA089038A400044EBA /* rank.hpp */, BFFCD2BB089038A400044EBA /* reference_traits.hpp */, BFFCD2BC089038A400044EBA /* remove_all_extents.hpp */, BFFCD2BD089038A400044EBA /* remove_bounds.hpp */, BFFCD2BE089038A400044EBA /* remove_const.hpp */, BFFCD2BF089038A400044EBA /* remove_cv.hpp */, BFFCD2C0089038A400044EBA /* remove_extent.hpp */, BFFCD2C1089038A400044EBA /* remove_pointer.hpp */, BFFCD2C2089038A400044EBA /* remove_reference.hpp */, BFFCD2C3089038A400044EBA /* remove_volatile.hpp */, BFFCD2C4089038A400044EBA /* same_traits.hpp */, BFFCD2C5089038A400044EBA /* transform_traits.hpp */, BFFCD2C6089038A400044EBA /* transform_traits_spec.hpp */, BFFCD2C7089038A400044EBA /* type_with_alignment.hpp */, ); path = type_traits; sourceTree = ""; }; BFFCD277089038A300044EBA /* detail */ = { isa = PBXGroup; children = ( BFFCD278089038A300044EBA /* bool_trait_def.hpp */, BFFCD279089038A300044EBA /* bool_trait_undef.hpp */, BFFCD27A089038A300044EBA /* cv_traits_impl.hpp */, BFFCD27B089038A300044EBA /* false_result.hpp */, BFFCD27C089038A300044EBA /* ice_and.hpp */, BFFCD27D089038A300044EBA /* ice_eq.hpp */, BFFCD27E089038A300044EBA /* ice_not.hpp */, BFFCD27F089038A300044EBA /* ice_or.hpp */, BFFCD280089038A300044EBA /* is_function_ptr_helper.hpp */, BFFCD281089038A300044EBA /* is_function_ptr_tester.hpp */, BFFCD282089038A300044EBA /* is_mem_fun_pointer_impl.hpp */, BFFCD283089038A300044EBA /* is_mem_fun_pointer_tester.hpp */, BFFCD284089038A300044EBA /* size_t_trait_def.hpp */, BFFCD285089038A300044EBA /* size_t_trait_undef.hpp */, BFFCD286089038A300044EBA /* template_arity_spec.hpp */, BFFCD287089038A300044EBA /* type_trait_def.hpp */, BFFCD288089038A300044EBA /* type_trait_undef.hpp */, BFFCD289089038A300044EBA /* wrap.hpp */, BFFCD28A089038A300044EBA /* yes_no_type.hpp */, ); path = detail; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ BFFCCB59089028E500044EBA /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( BF11E81D2440C1EB009C104D /* wxScatteringPowerSphere.h in Headers */, BF11E8332440C200009C104D /* GridResult.h in Headers */, BF11E82F2440C200009C104D /* WXFoxServer.h in Headers */, BF11E7BD2440AA42009C104D /* LSQNumObj.h in Headers */, BF11E8342440C200009C104D /* FoxServer.h in Headers */, BF11E7FB2440C1D6009C104D /* VFNDebug.h in Headers */, BF11E7DC2440C1BF009C104D /* ReflectionProfile.h in Headers */, BF11E7EE2440C1BF009C104D /* Indexing.h in Headers */, BF11E81E2440C1EB009C104D /* MCTable.h in Headers */, BF11E7E12440C1BF009C104D /* IO.h in Headers */, BF11E7BA2440AA42009C104D /* GlobalOptimObj.h in Headers */, BF11E7F92440C1D6009C104D /* ci_string.h in Headers */, BF11E8182440C1EB009C104D /* mpVector.h in Headers */, BF11E8122440C1EB009C104D /* wxTrackerGraph.h in Headers */, BF11E82D2440C200009C104D /* IOSocket.h in Headers */, BF11E8172440C1EB009C104D /* wxLSQ.h in Headers */, BF11E7E82440C1BF009C104D /* Scatterer.h in Headers */, BF11E7F72440C1D6009C104D /* VFNStreamFormat.h in Headers */, BF11E7BF2440AA42009C104D /* IO.h in Headers */, BF11E8142440C1EB009C104D /* wxScatteringPower.h in Headers */, BF11E7E52440C1BF009C104D /* ZScatterer.h in Headers */, BF11E81C2440C1EB009C104D /* wxScatterer.h in Headers */, BF11E7BE2440AA42009C104D /* Tracker.h in Headers */, BF11E8162440C1EB009C104D /* wxRefinableObj.h in Headers */, BF11E8112440C1EB009C104D /* wxZScatterer.h in Headers */, BF11E8312440C200009C104D /* WXFoxClient.h in Headers */, BF11E7E72440C1BF009C104D /* Colours.h in Headers */, BF11E7E32440C1BF009C104D /* DiffractionDataSingleCrystal.h in Headers */, BF11E8132440C1EB009C104D /* wxMultiGraph.h in Headers */, BF11E7F82440C1D6009C104D /* sse_mathfun.h in Headers */, BF11E82E2440C200009C104D /* FoxJob.h in Headers */, BF11E7F12440C1BF009C104D /* UnitCell.h in Headers */, BF11E7E92440C1BF009C104D /* PDF.h in Headers */, BF11E7DA2440C1BF009C104D /* ScatteringData.h in Headers */, BF11E7C12440C199009C104D /* CrystVector.h in Headers */, BF11E7F02440C1BF009C104D /* GeomStructFactor.h in Headers */, BF11E8102440C1EB009C104D /* wxAtom.h in Headers */, BF11E7EA2440C1BF009C104D /* Atom.h in Headers */, BF11E7E62440C1BF009C104D /* Molecule.h in Headers */, BF11E81F2440C1EB009C104D /* wxPowderPattern.h in Headers */, BF11E7BB2440AA42009C104D /* Simplex.h in Headers */, BF11E7DE2440C1BF009C104D /* ScatteringCorr.h in Headers */, BF11E8202440C1EB009C104D /* wxGlobalOptimObj.h in Headers */, BF11E8222440C1EB009C104D /* wxCryst.h in Headers */, BF11E7EC2440C1BF009C104D /* CIF.h in Headers */, BFCB29CD258F7484008A8CCB /* include.h in Headers */, BF11E7DB2440C1BF009C104D /* Crystal.h in Headers */, BF11E7E02440C1BF009C104D /* ScatteringPower.h in Headers */, BF11E8232440C1EB009C104D /* trackball.h in Headers */, BF11E8152440C1EB009C104D /* wxDiffractionSingleCrystal.h in Headers */, BF11E7E22440C1BF009C104D /* test.h in Headers */, BF11E8352440C200009C104D /* FoxClient.h in Headers */, BF11E8322440C200009C104D /* WXGridWindow.h in Headers */, BF11E7DF2440C1BF009C104D /* PowderPattern.h in Headers */, BF11E7ED2440C1BF009C104D /* PowderPatternBackgroundBayesianMinimiser.h in Headers */, BF11E7E42440C1BF009C104D /* ScatteringPowerSphere.h in Headers */, BF11E81A2440C1EB009C104D /* wxRadiation.h in Headers */, BF11E8192440C1EB009C104D /* wxCrystal.h in Headers */, BF11E81B2440C1EB009C104D /* MC.h in Headers */, BF11E7EB2440C1BF009C104D /* General.h in Headers */, BF11E7EF2440C1BF009C104D /* Polyhedron.h in Headers */, BF11E7FA2440C1D6009C104D /* Chronometer.h in Headers */, BF11E7DD2440C1BF009C104D /* SpaceGroup.h in Headers */, BF11E7BC2440AA42009C104D /* RefinableObj.h in Headers */, BF11E8212440C1EB009C104D /* wxMolecule.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; BFFCCBE10890309900044EBA /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ BF1DDDE80D228DCF00A3939D /* Fox */ = { isa = PBXNativeTarget; buildConfigurationList = BF1DDDED0D228DD000A3939D /* Build configuration list for PBXNativeTarget "Fox" */; buildPhases = ( BF1DDDE50D228DCF00A3939D /* Resources */, BF1DDDE60D228DCF00A3939D /* Sources */, BF1DDDE70D228DCF00A3939D /* Frameworks */, ); buildRules = ( ); dependencies = ( BF1DE1890D229E1B00A3939D /* PBXTargetDependency */, BF1DE18B0D229E1B00A3939D /* PBXTargetDependency */, ); name = Fox; productName = FoxCocoa; productReference = BF1DDDE90D228DCF00A3939D /* Fox.app */; productType = "com.apple.product-type.application"; }; BFFCCB5C089028E500044EBA /* newmat */ = { isa = PBXNativeTarget; buildConfigurationList = BFFCCB5F089028E600044EBA /* Build configuration list for PBXNativeTarget "newmat" */; buildPhases = ( BFFCCB59089028E500044EBA /* Headers */, BFFCCB5A089028E500044EBA /* Sources */, BFFCCB5B089028E500044EBA /* Frameworks */, ); buildRules = ( ); dependencies = ( ); name = newmat; productName = Untitled; productReference = BFFCCB5D089028E500044EBA /* libnewmat.a */; productType = "com.apple.product-type.library.static"; }; BFFCCBE40890309900044EBA /* cctbx */ = { isa = PBXNativeTarget; buildConfigurationList = BFFCCBE6089030B800044EBA /* Build configuration list for PBXNativeTarget "cctbx" */; buildPhases = ( BFFCCBE10890309900044EBA /* Headers */, BFFCCBE20890309900044EBA /* Sources */, BFFCCBE30890309900044EBA /* Frameworks */, ); buildRules = ( ); dependencies = ( ); name = cctbx; productName = cctbx; productReference = BFFCCBE50890309900044EBA /* libcctbx.a */; productType = "com.apple.product-type.library.static"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ BFFCCB51089028D300044EBA /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0710; }; buildConfigurationList = BFFCCB52089028D300044EBA /* Build configuration list for PBXProject "Fox" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = BFFCCB4F089028D300044EBA; productRefGroup = BFFCCB5E089028E500044EBA /* Products */; projectDirPath = ""; projectRoot = ..; targets = ( BFFCCB5C089028E500044EBA /* newmat */, BFFCCBE40890309900044EBA /* cctbx */, BF1DDDE80D228DCF00A3939D /* Fox */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ BF1DDDE50D228DCF00A3939D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( BF1DDE260D228E4100A3939D /* Fox.icns in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ BF1DDDE60D228DCF00A3939D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( BF1DDDEE0D228E3700A3939D /* Fox.cpp in Sources */, BF1DDDEF0D228E3700A3939D /* Atom.cpp in Sources */, BF1DDDF00D228E3700A3939D /* Crystal.cpp in Sources */, BF1DDDF10D228E3700A3939D /* CrystVector.cpp in Sources */, BF1DDDF20D228E3700A3939D /* DiffractionDataSingleCrystal.cpp in Sources */, BF1DDDF30D228E3700A3939D /* Exception.cpp in Sources */, BF1DDDF40D228E3700A3939D /* geomStructFactor_001.cpp in Sources */, BF1DDDF50D228E3700A3939D /* geomStructFactor_002.cpp in Sources */, BF1DDDF60D228E3700A3939D /* geomStructFactor_067.cpp in Sources */, BF1DDDF70D228E3700A3939D /* geomStructFactor_097.cpp in Sources */, BF1DDDF80D228E3700A3939D /* geomStructFactor_230.cpp in Sources */, BF1DDDF90D228E3700A3939D /* geomStructFactor_centro.cpp in Sources */, BF1DDDFA0D228E3700A3939D /* geomStructFactor.cpp in Sources */, BF1DDDFB0D228E3700A3939D /* GlobalOptimObj.cpp in Sources */, BF1DDDFC0D228E3700A3939D /* IO.cpp in Sources */, BF1DDDFD0D228E3700A3939D /* IO.cpp in Sources */, BF1DDDFE0D228E3700A3939D /* LSQNumObj.cpp in Sources */, BF1DDDFF0D228E3700A3939D /* MC.cpp in Sources */, BF1DDE000D228E3700A3939D /* Molecule.cpp in Sources */, BF1DDE010D228E3700A3939D /* mpVector.cpp in Sources */, BF1DDE020D228E3700A3939D /* Polyhedron.cpp in Sources */, BF1DDE030D228E3700A3939D /* PowderPattern.cpp in Sources */, BF1DDE040D228E3700A3939D /* PowderPatternBackgroundBayesianMinimiser.cpp in Sources */, BF1DDE050D228E3700A3939D /* RefinableObj.cpp in Sources */, BF1DDE060D228E3700A3939D /* ReflectionProfile.cpp in Sources */, BF1DDE070D228E3700A3939D /* Scatterer.cpp in Sources */, BF1DDE080D228E3700A3939D /* ScatteringCorr.cpp in Sources */, BF1DDE090D228E3700A3939D /* ScatteringData.cpp in Sources */, BF1DDE0A0D228E3700A3939D /* ScatteringPower.cpp in Sources */, BF1DDE0B0D228E3700A3939D /* ScatteringPowerSphere.cpp in Sources */, BF1DDE0C0D228E3700A3939D /* Simplex.cpp in Sources */, BF1DDE0D0D228E3700A3939D /* SpaceGroup.cpp in Sources */, BF1DDE0E0D228E3700A3939D /* test.cpp in Sources */, BF1DDE0F0D228E3700A3939D /* Tracker.cpp in Sources */, BF1DDE100D228E3700A3939D /* UnitCell.cpp in Sources */, BF1DDE110D228E3700A3939D /* VFNDebug.cpp in Sources */, BF1DDE120D228E3700A3939D /* VFNStreamFormat.cpp in Sources */, BF1DDE130D228E3700A3939D /* wxAtom.cpp in Sources */, BF1DDE140D228E3700A3939D /* wxCryst.cpp in Sources */, BF1DDE150D228E3700A3939D /* wxCrystal.cpp in Sources */, BF1DDE160D228E3700A3939D /* wxDiffractionSingleCrystal.cpp in Sources */, BF1DDE170D228E3700A3939D /* wxGlobalOptimObj.cpp in Sources */, BF1DDE180D228E3700A3939D /* wxMolecule.cpp in Sources */, BF1DDE190D228E3700A3939D /* wxMultiGraph.cpp in Sources */, BF1DDE1A0D228E3700A3939D /* wxPowderPattern.cpp in Sources */, BF1DDE1B0D228E3700A3939D /* wxRefinableObj.cpp in Sources */, BF1DDE1C0D228E3700A3939D /* wxScatterer.cpp in Sources */, BF1DDE1D0D228E3700A3939D /* wxScatteringPower.cpp in Sources */, BF1DDE1E0D228E3700A3939D /* wxScatteringPowerSphere.cpp in Sources */, BF1DDE1F0D228E3700A3939D /* wxTrackerGraph.cpp in Sources */, BF1DDE200D228E3700A3939D /* wxZScatterer.cpp in Sources */, BF92D5CF259F2D50005FD5D7 /* Undo.cpp in Sources */, BF1DDE210D228E3700A3939D /* ZScatterer.cpp in Sources */, BF1DDE220D228E3700A3939D /* trackball.c in Sources */, BF1DDE230D228E3700A3939D /* CIF.cpp in Sources */, BF1DDE240D228E3700A3939D /* ci_string.cpp in Sources */, BF1DDE250D228E3700A3939D /* Indexing.cpp in Sources */, BFFB474E0E5E0E620027591E /* wxLSQ.cpp in Sources */, BF69C4D1124F8C310035CF57 /* FoxClient.cpp in Sources */, BF69C4D2124F8C310035CF57 /* FoxJob.cpp in Sources */, BF69C4D3124F8C310035CF57 /* FoxServer.cpp in Sources */, BF69C4D5124F8C310035CF57 /* GridResult.cpp in Sources */, BF69C4D6124F8C310035CF57 /* IOSocket.cpp in Sources */, BF69C4D7124F8C310035CF57 /* WXFoxClient.cpp in Sources */, BF69C4D8124F8C310035CF57 /* WXFoxServer.cpp in Sources */, BF69C4D9124F8C310035CF57 /* WXGridWindow.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; BFFCCB5A089028E500044EBA /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( BFFCCB670890296D00044EBA /* bandmat.cpp in Sources */, BFFCCBA0089029F400044EBA /* cholesky.cpp in Sources */, BFFCCBA1089029F400044EBA /* evalue.cpp in Sources */, BFFCCBA3089029F400044EBA /* fft.cpp in Sources */, BFFCCBA5089029F400044EBA /* hholder.cpp in Sources */, BFFCCBA6089029F400044EBA /* jacobi.cpp in Sources */, BFFCCBA7089029F400044EBA /* myexcept.cpp in Sources */, BFFCCBA8089029F400044EBA /* newfft.cpp in Sources */, BFFCCBA9089029F400044EBA /* newmat1.cpp in Sources */, BFFCCBAA089029F400044EBA /* newmat2.cpp in Sources */, BFFCCBAB089029F400044EBA /* newmat3.cpp in Sources */, BFFCCBAC089029F400044EBA /* newmat4.cpp in Sources */, BFFCCBAD089029F400044EBA /* newmat5.cpp in Sources */, BFFCCBAE089029F400044EBA /* newmat6.cpp in Sources */, BFFCCBAF089029F400044EBA /* newmat7.cpp in Sources */, BFFCCBB0089029F400044EBA /* newmat8.cpp in Sources */, BFFCCBB1089029F400044EBA /* newmat9.cpp in Sources */, BFFCCBB2089029F400044EBA /* newmatex.cpp in Sources */, BFFCCBB3089029F400044EBA /* newmatnl.cpp in Sources */, BFFCCBB4089029F400044EBA /* newmatrm.cpp in Sources */, BFFCCBB8089029F400044EBA /* nm_misc.cpp in Sources */, BFFCCBBA089029F400044EBA /* solution.cpp in Sources */, BFFCCBBB089029F400044EBA /* sort.cpp in Sources */, BFFCCBBC089029F400044EBA /* submat.cpp in Sources */, BFFCCBBD089029F400044EBA /* svd.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; BFFCCBE20890309900044EBA /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( BFFCCC0E089031B000044EBA /* basic.cpp in Sources */, BFFCCC10089031B000044EBA /* fp_fdp.cpp in Sources */, BFFCCC12089031B000044EBA /* henke_tables_01_12.cpp in Sources */, BFFCCC13089031B000044EBA /* henke_tables_13_24.cpp in Sources */, BFFCCC14089031B000044EBA /* henke_tables_25_36.cpp in Sources */, BFFCCC15089031B000044EBA /* henke_tables_37_48.cpp in Sources */, BFFCCC16089031B000044EBA /* henke_tables_49_60.cpp in Sources */, BFFCCC17089031B000044EBA /* henke_tables_61_72.cpp in Sources */, BFFCCC18089031B000044EBA /* henke_tables_73_84.cpp in Sources */, BFFCCC19089031B000044EBA /* henke_tables_85_92.cpp in Sources */, BFFCCC1A089031B000044EBA /* henke.cpp in Sources */, BFFCCC1C089031B000044EBA /* icsd_radii.cpp in Sources */, BFFCCC1D089031B000044EBA /* it1992.cpp in Sources */, BFFCCC1E089031B000044EBA /* n_gaussian_raw.cpp in Sources */, BFFCCC1F089031B000044EBA /* n_gaussian.cpp in Sources */, BFFCCC21089031B000044EBA /* neutron.cpp in Sources */, BFFCCC23089031B000044EBA /* sasaki_tables_01_12.cpp in Sources */, BFFCCC24089031B000044EBA /* sasaki_tables_13_24.cpp in Sources */, BFFCCC25089031B000044EBA /* sasaki_tables_25_36.cpp in Sources */, BFFCCC26089031B000044EBA /* sasaki_tables_37_48.cpp in Sources */, BFFCCC27089031B000044EBA /* sasaki_tables_49_60.cpp in Sources */, BFFCCC28089031B000044EBA /* sasaki_tables_61_72.cpp in Sources */, BFFCCC29089031B000044EBA /* sasaki_tables_73_82.cpp in Sources */, BFFCCC2A089031B000044EBA /* sasaki.cpp in Sources */, BFFCCC2C089031B000044EBA /* tiny_pse.cpp in Sources */, BFFCCC2E089031B000044EBA /* wavelengths.cpp in Sources */, BFFCCC2F089031B000044EBA /* wk1995.cpp in Sources */, BFFCCC620890324D00044EBA /* bricks.cpp in Sources */, BFFCCC630890324D00044EBA /* change_of_basis_op.cpp in Sources */, BFFCCC660890324D00044EBA /* find_affine.cpp in Sources */, BFFCCC670890324D00044EBA /* group_codes.cpp in Sources */, BFFCCC680890324D00044EBA /* hall_in.cpp in Sources */, BFFCCC690890324D00044EBA /* hall_symbol_table.cpp in Sources */, BFFCCC6B0890324D00044EBA /* lattice_symmetry.cpp in Sources */, BFFCCC6C0890324D00044EBA /* lattice_tr.cpp in Sources */, BFFCCC6D0890324D00044EBA /* matrix_group_code_table.cpp in Sources */, BFFCCC6E0890324D00044EBA /* miller.cpp in Sources */, BFFCCC6F0890324D00044EBA /* normalizer.cpp in Sources */, BFFCCC720890324D00044EBA /* reciprocal_space_asu.cpp in Sources */, BFFCCC730890324D00044EBA /* reciprocal_space_ref_asu.cpp in Sources */, BFFCCC740890324D00044EBA /* rot_mx_info.cpp in Sources */, BFFCCC760890324D00044EBA /* rot_mx.cpp in Sources */, BFFCCC770890324D00044EBA /* row_echelon_solve.cpp in Sources */, BFFCCC790890324D00044EBA /* rt_mx.cpp in Sources */, BFFCCC7B0890324D00044EBA /* select_generators.cpp in Sources */, BFFCCC7D0890324D00044EBA /* seminvariant.cpp in Sources */, BFFCCC800890324D00044EBA /* site_symmetry.cpp in Sources */, BFFCCC820890324D00044EBA /* space_group_type.cpp in Sources */, BFFCCC840890324D00044EBA /* space_group.cpp in Sources */, BFFCCC870890324D00044EBA /* symbols.cpp in Sources */, BFFCCC890890324D00044EBA /* tensor_rank_2.cpp in Sources */, BFFCCC8A0890324D00044EBA /* tr_group.cpp in Sources */, BFFCCC8C0890324D00044EBA /* tr_vec.cpp in Sources */, BFFCCC8D0890324D00044EBA /* utils.cpp in Sources */, BFFCCC8F0890324D00044EBA /* wyckoff.cpp in Sources */, BFFCCC900890324D00044EBA /* wyckoff.cpp in Sources */, BFFCCC990890328F00044EBA /* asu.cpp in Sources */, BFFCCC9A0890328F00044EBA /* bins.cpp in Sources */, BFFCCC9B0890328F00044EBA /* index_generator.cpp in Sources */, BFFCCC9C0890328F00044EBA /* match_bijvoet_mates.cpp in Sources */, BFFCCC9D0890328F00044EBA /* match_indices.cpp in Sources */, BF49CDF01B0BC56E0012BF3B /* covalent_radii.cpp in Sources */, BFFCCC9E0890328F00044EBA /* sym_equiv.cpp in Sources */, BF3EB05508968F5500E02367 /* uctbx.cpp in Sources */, BF3EB063089690D200E02367 /* spoil_optimization.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ BF1DE1890D229E1B00A3939D /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = BFFCCB5C089028E500044EBA /* newmat */; targetProxy = BF1DE1880D229E1B00A3939D /* PBXContainerItemProxy */; }; BF1DE18B0D229E1B00A3939D /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = BFFCCBE40890309900044EBA /* cctbx */; targetProxy = BF1DE18A0D229E1B00A3939D /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ BF1DDDEC0D228DD000A3939D /* Deployment */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_CXX_LIBRARY = "libc++"; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEPLOYMENT_LOCATION = NO; DEPLOYMENT_POSTPROCESSING = NO; GCC_AUTO_VECTORIZATION = YES; GCC_ENABLE_SSE3_EXTENSIONS = YES; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_INLINES_ARE_PRIVATE_EXTERN = NO; GCC_OPTIMIZATION_LEVEL = fast; GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_UNROLL_LOOPS = YES; GCC_VERSION = ""; HEADER_SEARCH_PATHS = ( "$(SRCROOT)/../static-libs/include", "$(SRCROOT)/../static-libs/include/wx-3.1", "$(SRCROOT)/../static-libs/lib/wx/include/osx_cocoa-unicode-static-3.1", "$(SRCROOT)/../ObjCryst", "$(SRCROOT)/../cctbx/include", "$(SRCROOT)/../", ); INFOPLIST_FILE = "Fox-Info.plist"; INSTALL_PATH = "$(HOME)/Applications"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)/../static-libs/lib", ); MACOSX_DEPLOYMENT_TARGET = 10.10; OTHER_CFLAGS = ( "-DUSE_SSE2", "-DHAVE_SSE_MATHFUN", "-D_FILE_OFFSET_BITS=64", "-D_LARGE_FILES", "-D__WXMAC__", "-DHAVE_FFTW", "-D__WX__CRYST__", "-DOBJCRYST_GL", "-DHAVE_GLUT", "-D__WXOSX__", "-D__WXOSX_COCOA__", "-D__FOX_COD__", "-DwxDEBUG_LEVEL=0", ); OTHER_LDFLAGS = ( "-framework", Foundation, "-framework", AppKit, "-lz", "-lpthread", "-liconv", ); PRODUCT_BUNDLE_IDENTIFIER = objcryst.sourceforge.net; PRODUCT_NAME = Fox; SDKROOT = macosx; SEPARATE_STRIP = NO; SKIP_INSTALL = YES; STRIP_STYLE = all; WRAPPER_EXTENSION = app; ZERO_LINK = NO; }; name = Deployment; }; BF1DE1810D229D0800A3939D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; CLANG_CXX_LIBRARY = "libc++"; COPY_PHASE_STRIP = NO; DEPLOYMENT_LOCATION = NO; DEPLOYMENT_POSTPROCESSING = NO; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = "compiler-default"; GCC_ENABLE_SSE3_EXTENSIONS = YES; GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS = YES; GCC_FAST_MATH = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_STRICT_ALIASING = NO; "INSTALL_PATH[sdk=*]" = ""; MACOSX_DEPLOYMENT_TARGET = 10.10; ONLY_ACTIVE_ARCH = YES; "OTHER_CPLUSPLUSFLAGS[arch=*]" = ( "$(OTHER_CFLAGS)", "-D__DEBUG__", ); SKIP_INSTALL = YES; }; name = Debug; }; BF1DE1820D229D0800A3939D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; CLANG_CXX_LIBRARY = "libc++"; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; GCC_C_LANGUAGE_STANDARD = "compiler-default"; GCC_ENABLE_SSE3_EXTENSIONS = YES; GCC_FAST_MATH = YES; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_INLINES_ARE_PRIVATE_EXTERN = NO; GCC_MODEL_TUNING = G3; GCC_OPTIMIZATION_LEVEL = fast; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h"; GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_UNROLL_LOOPS = YES; GCC_VERSION = ""; INSTALL_PATH = /usr/local/lib; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "\"$(SRCROOT)/../static-libs/lib\"", ); LIBRARY_STYLE = STATIC; MACOSX_DEPLOYMENT_TARGET = 10.10; OTHER_CFLAGS = ""; OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; "OTHER_CPLUSPLUSFLAGS[arch=*]" = "$(OTHER_CFLAGS)"; OTHER_LDFLAGS = ""; OTHER_REZFLAGS = ""; PRODUCT_NAME = newmat; SDKROOT = macosx; SECTORDER_FLAGS = ""; SEPARATE_STRIP = NO; STRIP_STYLE = all; WARNING_CFLAGS = ( "-Wmost", "-Wno-four-char-constants", "-Wno-unknown-pragmas", ); }; name = Debug; }; BF1DE1830D229D0800A3939D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; GCC_ENABLE_SSE3_EXTENSIONS = YES; GCC_FAST_MATH = YES; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_INLINES_ARE_PRIVATE_EXTERN = NO; GCC_MODEL_TUNING = G3; GCC_OPTIMIZATION_LEVEL = 3; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h"; GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_UNROLL_LOOPS = YES; GCC_VERSION = ""; HEADER_SEARCH_PATHS = ( "$(SRCROOT)/../cctbx/include", "$(SRCROOT)/../static-libs/include", ); INSTALL_PATH = /usr/local/lib; LIBRARY_STYLE = STATIC; MACOSX_DEPLOYMENT_TARGET = 10.10; OTHER_CFLAGS = ""; OTHER_LDFLAGS = ""; OTHER_REZFLAGS = ""; PRODUCT_NAME = cctbx; SDKROOT = macosx; SECTORDER_FLAGS = ""; SEPARATE_STRIP = NO; STRIP_STYLE = all; WARNING_CFLAGS = ( "-Wmost", "-Wno-four-char-constants", "-Wno-unknown-pragmas", ); }; name = Debug; }; BF1DE1840D229D0800A3939D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_CXX_LIBRARY = "libc++"; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; DEPLOYMENT_LOCATION = NO; DEPLOYMENT_POSTPROCESSING = NO; GCC_ENABLE_SSE3_EXTENSIONS = YES; GCC_INLINES_ARE_PRIVATE_EXTERN = NO; GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_UNROLL_LOOPS = YES; GCC_VERSION = ""; HEADER_SEARCH_PATHS = ( "$(SRCROOT)/../", "$(SRCROOT)/../static-libs/include", "$(SRCROOT)/../static-libs/include/wx-3.1", "$(SRCROOT)/../static-libs/lib/wx/include/osx_cocoa-unicode-static-3.1", "$(SRCROOT)/../ObjCryst", "$(SRCROOT)/../cctbx/include", "$(SRCROOT)/../cctbx/scitbx/include", ); INFOPLIST_FILE = "Fox-Info.plist"; INSTALL_PATH = "$(HOME)/Applications"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)/../static-libs/lib", ); MACOSX_DEPLOYMENT_TARGET = 10.10; OTHER_CFLAGS = ( "-DUSE_SSE2", "-DHAVE_SSE_MATHFUN", "-D_FILE_OFFSET_BITS=64", "-D_LARGE_FILES", "-D__WXMAC__", "-DHAVE_FFTW", "-D__WX__CRYST__", "-DOBJCRYST_GL", "-DHAVE_GLUT", "-D__WXOSX__", "-D__WXOSX_COCOA__", "-D__FOX_COD__", "-DwxDEBUG_LEVEL=0", ); OTHER_LDFLAGS = ( "-framework", Foundation, "-framework", AppKit, "-lz", "-lpthread", "-liconv", ); PRODUCT_BUNDLE_IDENTIFIER = objcryst.sourceforge.net; PRODUCT_NAME = Fox; SDKROOT = macosx; SEPARATE_STRIP = NO; SKIP_INSTALL = YES; STRIP_STYLE = all; WRAPPER_EXTENSION = app; ZERO_LINK = NO; }; name = Debug; }; BF48AEF808924F3F0060B5BE /* Deployment */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; CLANG_CXX_LIBRARY = "libc++"; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = dwarf; GCC_C_LANGUAGE_STANDARD = "compiler-default"; GCC_ENABLE_SSE3_EXTENSIONS = YES; GCC_FAST_MATH = YES; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_INLINES_ARE_PRIVATE_EXTERN = NO; GCC_MODEL_TUNING = G3; GCC_OPTIMIZATION_LEVEL = fast; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h"; GCC_UNROLL_LOOPS = YES; GCC_VERSION = ""; INSTALL_PATH = /usr/local/lib; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "\"$(SRCROOT)/../static-libs/lib\"", ); LIBRARY_STYLE = STATIC; MACOSX_DEPLOYMENT_TARGET = 10.10; OTHER_CFLAGS = ""; OTHER_CPLUSPLUSFLAGS = ""; OTHER_LDFLAGS = ""; OTHER_REZFLAGS = ""; PRODUCT_NAME = newmat; SDKROOT = macosx; SECTORDER_FLAGS = ""; SEPARATE_STRIP = NO; STRIP_STYLE = all; WARNING_CFLAGS = ( "-Wmost", "-Wno-four-char-constants", "-Wno-unknown-pragmas", ); }; name = Deployment; }; BF48AEF908924F3F0060B5BE /* Deployment */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = dwarf; GCC_ENABLE_SSE3_EXTENSIONS = YES; GCC_FAST_MATH = YES; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_INLINES_ARE_PRIVATE_EXTERN = NO; GCC_MODEL_TUNING = G3; GCC_OPTIMIZATION_LEVEL = 3; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h"; GCC_UNROLL_LOOPS = YES; GCC_VERSION = ""; HEADER_SEARCH_PATHS = ( "$(SRCROOT)/../cctbx/include", "$(SRCROOT)/../static-libs/include", ); INSTALL_PATH = /usr/local/lib; LIBRARY_STYLE = STATIC; MACOSX_DEPLOYMENT_TARGET = 10.10; OTHER_CFLAGS = ""; OTHER_LDFLAGS = ""; OTHER_REZFLAGS = ""; PRODUCT_NAME = cctbx; SDKROOT = macosx; SECTORDER_FLAGS = ""; SEPARATE_STRIP = NO; STRIP_STYLE = all; WARNING_CFLAGS = ( "-Wmost", "-Wno-four-char-constants", "-Wno-unknown-pragmas", ); }; name = Deployment; }; BF48AEFB08924F3F0060B5BE /* Deployment */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; CLANG_CXX_LIBRARY = "libc++"; COPY_PHASE_STRIP = YES; DEPLOYMENT_LOCATION = NO; DEPLOYMENT_POSTPROCESSING = NO; GCC_C_LANGUAGE_STANDARD = "compiler-default"; GCC_ENABLE_SSE3_EXTENSIONS = YES; GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS = YES; GCC_FAST_MATH = YES; GCC_MODEL_TUNING = ""; GCC_OPTIMIZATION_LEVEL = 3; GCC_STRICT_ALIASING = NO; MACOSX_DEPLOYMENT_TARGET = 10.10; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ""; SKIP_INSTALL = YES; }; name = Deployment; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ BF1DDDED0D228DD000A3939D /* Build configuration list for PBXNativeTarget "Fox" */ = { isa = XCConfigurationList; buildConfigurations = ( BF1DDDEC0D228DD000A3939D /* Deployment */, BF1DE1840D229D0800A3939D /* Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Deployment; }; BFFCCB52089028D300044EBA /* Build configuration list for PBXProject "Fox" */ = { isa = XCConfigurationList; buildConfigurations = ( BF48AEFB08924F3F0060B5BE /* Deployment */, BF1DE1810D229D0800A3939D /* Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Deployment; }; BFFCCB5F089028E600044EBA /* Build configuration list for PBXNativeTarget "newmat" */ = { isa = XCConfigurationList; buildConfigurations = ( BF48AEF808924F3F0060B5BE /* Deployment */, BF1DE1820D229D0800A3939D /* Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Deployment; }; BFFCCBE6089030B800044EBA /* Build configuration list for PBXNativeTarget "cctbx" */ = { isa = XCConfigurationList; buildConfigurations = ( BF48AEF908924F3F0060B5BE /* Deployment */, BF1DE1830D229D0800A3939D /* Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Deployment; }; /* End XCConfigurationList section */ }; rootObject = BFFCCB51089028D300044EBA /* Project object */; } objcryst-2022.1/Fox/Fox_vc12.sln000066400000000000000000000061251430515525000163040ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.30804.86 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Fox", "Fox_vc12.vcxproj", "{2775CD9F-FFF3-4373-A229-94DD4B6D7747}" ProjectSection(ProjectDependencies) = postProject {BA6FA16F-837D-4869-90B9-44ACCD4EC001} = {BA6FA16F-837D-4869-90B9-44ACCD4EC001} {39353CCC-A61A-47C9-8C1F-30FA52D3A1A2} = {39353CCC-A61A-47C9-8C1F-30FA52D3A1A2} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "newmat", "newmat_vc12.vcxproj", "{39353CCC-A61A-47C9-8C1F-30FA52D3A1A2}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cctbx", "cctbx_vc12.vcxproj", "{BA6FA16F-837D-4869-90B9-44ACCD4EC001}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release (profile-guided optim generate)|Win32 = Release (profile-guided optim generate)|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {2775CD9F-FFF3-4373-A229-94DD4B6D7747}.Debug|Win32.ActiveCfg = Debug|Win32 {2775CD9F-FFF3-4373-A229-94DD4B6D7747}.Debug|Win32.Build.0 = Debug|Win32 {2775CD9F-FFF3-4373-A229-94DD4B6D7747}.Release (profile-guided optim generate)|Win32.ActiveCfg = Release (profile-guided optim generate)|Win32 {2775CD9F-FFF3-4373-A229-94DD4B6D7747}.Release (profile-guided optim generate)|Win32.Build.0 = Release (profile-guided optim generate)|Win32 {2775CD9F-FFF3-4373-A229-94DD4B6D7747}.Release|Win32.ActiveCfg = Release|Win32 {2775CD9F-FFF3-4373-A229-94DD4B6D7747}.Release|Win32.Build.0 = Release|Win32 {39353CCC-A61A-47C9-8C1F-30FA52D3A1A2}.Debug|Win32.ActiveCfg = Debug|Win32 {39353CCC-A61A-47C9-8C1F-30FA52D3A1A2}.Debug|Win32.Build.0 = Debug|Win32 {39353CCC-A61A-47C9-8C1F-30FA52D3A1A2}.Release (profile-guided optim generate)|Win32.ActiveCfg = Release (profile-guided optim generate)|Win32 {39353CCC-A61A-47C9-8C1F-30FA52D3A1A2}.Release (profile-guided optim generate)|Win32.Build.0 = Release (profile-guided optim generate)|Win32 {39353CCC-A61A-47C9-8C1F-30FA52D3A1A2}.Release|Win32.ActiveCfg = Release|Win32 {39353CCC-A61A-47C9-8C1F-30FA52D3A1A2}.Release|Win32.Build.0 = Release|Win32 {BA6FA16F-837D-4869-90B9-44ACCD4EC001}.Debug|Win32.ActiveCfg = Debug|Win32 {BA6FA16F-837D-4869-90B9-44ACCD4EC001}.Debug|Win32.Build.0 = Debug|Win32 {BA6FA16F-837D-4869-90B9-44ACCD4EC001}.Release (profile-guided optim generate)|Win32.ActiveCfg = Release (profile-guided optim generate)|Win32 {BA6FA16F-837D-4869-90B9-44ACCD4EC001}.Release (profile-guided optim generate)|Win32.Build.0 = Release (profile-guided optim generate)|Win32 {BA6FA16F-837D-4869-90B9-44ACCD4EC001}.Release|Win32.ActiveCfg = Release|Win32 {BA6FA16F-837D-4869-90B9-44ACCD4EC001}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {92D2EBD0-0BED-4254-8D3C-BB238046D064} EndGlobalSection EndGlobal objcryst-2022.1/Fox/Fox_vc12.vcxproj000066400000000000000000000457311430515525000172110ustar00rootroot00000000000000 Debug Win32 Release (profile-guided optim generate) Win32 Release_XP_NoCOD Win32 Release Win32 {2775CD9F-FFF3-4373-A229-94DD4B6D7747} Win32Proj Fox Fox 10.0 Application true v142 Unicode Application false v142 true Unicode Application false v142 true Unicode Application false v141_xp true Unicode true $(Configuration)\$(ProjectName)\ $(ProjectName)_$(Configuration) false $(Configuration)\$(ProjectName)\ false false $(Configuration)\$(ProjectName)\ false false $(Configuration)\$(ProjectName)\ $(ProjectName)_XP_NoCOD NotUsing Level3 Disabled WIN32;_CRT_SECURE_NO_WARNINGS;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);__WX__CRYST__;HAVE_SSE_MATHFUN;USE_SSE2;OBJCRYST_GL;HAVE_FFTW;__FOX_COD__;__DEBUG__ false $(SolutionDir)..\;$(SolutionDir)..\cctbx\include;$(SolutionDir)..\ObjCryst;$(SolutionDir)..\wxWidgets\include\msvc;$(SolutionDir)..\wxWidgets\lib\vc_lib\mswu;$(SolutionDir)..\wxWidgets\include;$(SolutionDir)..\fftw\api;$(ProjectDir)\..\boost;%(AdditionalIncludeDirectories) $(IntDir)\%(RelativeDir) MultiThreadedDebug StreamingSIMDExtensions2 Fast true false Windows true $(SolutionDir)..\wxWidgets\lib\vc_lib;$(SolutionDir)$(Configuration);$(SolutionDir)..\fftw\fftw-3.3-libs\Static-Release;$(ProjectDir)\..\boost\stage\lib;%(AdditionalLibraryDirectories) newmat.lib;cctbx.lib;libfftwf-3.3.lib;%(AdditionalDependencies) MSVCRT.lib;LIBCMT.lib $(SolutionDir)..\wxWidgets\include\msvc;$(SolutionDir)..\wxWidgets\include;%(AdditionalIncludeDirectories) Level3 NotUsing MaxSpeed true true WIN32;_CRT_SECURE_NO_WARNINGS;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);__WX__CRYST__;HAVE_SSE_MATHFUN;USE_SSE2;OBJCRYST_GL;HAVE_FFTW;__FOX_COD__ false $(SolutionDir)..\;$(SolutionDir)..\cctbx\include;$(SolutionDir)..\ObjCryst;$(SolutionDir)..\wxWidgets\include\msvc;$(SolutionDir)..\wxWidgets\include;$(SolutionDir)..\fftw\api;$(ProjectDir)\..\boost;%(AdditionalIncludeDirectories) $(IntDir)\%(RelativeDir) MultiThreaded StreamingSIMDExtensions2 Fast true Speed true AnySuitable false Windows false true true $(SolutionDir)..\wxWidgets\lib\vc_lib;$(SolutionDir)$(Configuration);$(SolutionDir)..\fftw\fftw-3.3-libs\Static-Release;$(ProjectDir)\..\boost\stage\lib;%(AdditionalLibraryDirectories) newmat.lib;cctbx.lib;libfftwf-3.3.lib;%(AdditionalDependencies) LinkVerbose UseLinkTimeCodeGeneration $(SolutionDir)..\wxWidgets\include\msvc;$(SolutionDir)..\wxWidgets\include;%(AdditionalIncludeDirectories) Level3 NotUsing MaxSpeed true true WIN32;_CRT_SECURE_NO_WARNINGS;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);__WX__CRYST__;HAVE_SSE_MATHFUN;USE_SSE2;OBJCRYST_GL;HAVE_FFTW;__FOX_COD__ false $(SolutionDir)..\;$(SolutionDir)..\cctbx\include;$(SolutionDir)..\ObjCryst;$(SolutionDir)..\wxWidgets\include\msvc;$(SolutionDir)..\wxWidgets\include;$(SolutionDir)..\fftw\api;$(ProjectDir)\..\boost;%(AdditionalIncludeDirectories) $(IntDir)\%(RelativeDir) MultiThreaded StreamingSIMDExtensions2 Fast true Speed true AnySuitable false Windows false true true $(SolutionDir)..\wxWidgets\lib\vc_lib;$(SolutionDir)$(Configuration);$(SolutionDir)..\fftw\fftw-3.3-libs\Static-Release;$(ProjectDir)\..\boost\stage\lib;%(AdditionalLibraryDirectories) newmat.lib;cctbx.lib;libfftwf-3.3.lib;%(AdditionalDependencies) LinkVerbose UseLinkTimeCodeGeneration /GENPROFILE %(AdditionalOptions) $(SolutionDir)..\wxWidgets\include\msvc;$(SolutionDir)..\wxWidgets\include;%(AdditionalIncludeDirectories) Level3 NotUsing MaxSpeed true true WIN32;_CRT_SECURE_NO_WARNINGS;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);__WX__CRYST__;HAVE_SSE_MATHFUN;USE_SSE2;OBJCRYST_GL;HAVE_FFTW false $(SolutionDir)..\;$(SolutionDir)..\cctbx\include;$(SolutionDir)..\ObjCryst;$(SolutionDir)..\wxWidgets\include\msvc;$(SolutionDir)..\wxWidgets\include;$(SolutionDir)..\fftw\api;$(SolutionDir)..\mysql-connector-c-src\include;%(AdditionalIncludeDirectories) $(IntDir)\%(RelativeDir) MultiThreaded StreamingSIMDExtensions2 Fast true Windows true true true $(SolutionDir)..\wxWidgets\lib\vc_lib;$(SolutionDir)$(Configuration);$(SolutionDir)..\fftw\fftw-3.3-libs\Static-Release;$(SolutionDir)..\mysql-connector-c-src\libmysql\Release;%(AdditionalLibraryDirectories) libboost_date_time-vc100-mt-s-1_47.lib newmat.lib;cctbx.lib;libfftwf-3.3.lib;%(AdditionalDependencies) $(SolutionDir)..\wxWidgets\include\msvc;$(SolutionDir)..\wxWidgets\include;%(AdditionalIncludeDirectories) objcryst-2022.1/Fox/Fox_vc12.vcxproj.filters000066400000000000000000000236701430515525000206560ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms {efec9bf6-742c-47ab-9d58-824fbbf7f02f} {aac0ffa9-cb92-4507-811d-69ed19eeadd7} {dd435419-8afa-43c3-9ed3-2cdfa0992ab2} {75f49389-5c92-4dd1-ba54-f607eae108dd} {ce5c0e26-779e-4439-bbbd-1df7ea7ac45a} {9df5b357-4498-40ed-9fb3-a376703d7fde} Source Files\Quirks Source Files\Quirks Source Files\Quirks Source Files\CrystVector Source Files\wxCryst Source Files\wxCryst Source Files\wxCryst Source Files\wxCryst Source Files\wxCryst Source Files\wxCryst Source Files\wxCryst Source Files\wxCryst Source Files\wxCryst Source Files\wxCryst Source Files\wxCryst Source Files\wxCryst Source Files\wxCryst Source Files\wxCryst Source Files\wxCryst Source Files\wxCryst Source Files\wxCryst Source Files\wxCryst Source Files\RefinableObj Source Files\RefinableObj Source Files\RefinableObj Source Files\RefinableObj Source Files\RefinableObj Source Files\RefinableObj Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\ObjCryst Source Files\Fox Source Files\Fox Source Files\Fox Source Files\Fox Source Files\Fox Source Files\Fox Source Files\Fox Source Files\Fox Source Files\Fox Source Files\ObjCryst Resource Files Resource Files Resource Files objcryst-2022.1/Fox/ObjCryst-Fox.spec000066400000000000000000000050131430515525000173370ustar00rootroot00000000000000#------------------------------------------------------------------------------ # INFO #------------------------------------------------------------------------------ Summary: F.O.X., Free Objects for Crystallography, a program for crystal structure analysis, and ab initio structure determination from powder diffraction Name: ObjCryst-Fox Version: FOXVERSION Release: FOXRELEASE Copyright: GPL Packager: Vincent Favre-Nicolin Group: Sciences/Chemistry Source: Fox.tar.bz2 #Patch: ObjCryst-Fox.patch BuildRoot: %{_tmppath}/%{name}-buildroot URL: http://objcryst.sourceforge.net/Fox/ #Provides: (what does it provide - binaries and/or libraries) Prefix: /usr/local DOCDIR: /usr/local/doc #------------------------------------------------------------------------------ # REQUIRES #------------------------------------------------------------------------------ #Requires: /usr/lib/libGL.so /usr/lib/libgtk-x11-2.0.so BuildRequires: gcc /usr/include/GL/gl.h /usr/include/gtk-2.0/gtk/gtk.h #------------------------------------------------------------------------------ # DESCRIPTION #------------------------------------------------------------------------------ %description FOX is an open-source program for crystallographers who wish to solve crystal structures from powder diffraction data (X-ray, neutron, neutron TOF). Additionally, it can be used to create crystal structures and display them in 3D, simulate powder patterns and calculate structure factors. It can also import crystal structures from CIF (Crystallographic Information File) files. FOX is built on top of an object-oriented crystallographic library (ObjCryst++), which can be used for other purposes than structure determination. #------------------------------------------------------------------------------ # BUILD #------------------------------------------------------------------------------ %prep %setup -q -n Fox #%patch -p1 -b .buildroot %build make -C Fox RPM_OPT_FLAGS="$RPM_OPT_FLAGS" %install [ "$RPM_BUILD_ROOT" != "/" ] && rm -rf ${RPM_BUILD_ROOT}%{prefix} mkdir -p ${RPM_BUILD_ROOT}%{prefix}/bin #mkdir -p ${RPM_BUILD_ROOT}%{prefix}/man/man1 install -s -m 755 Fox/src/Fox ${RPM_BUILD_ROOT}%{prefix}/bin/Fox %clean [ "${RPM_BUILD_ROOT}%{prefix}" != "/" ] && rm -rf ${RPM_BUILD_ROOT}%{prefix} %files %defattr(-,root,root) %doc README LICENSE ChangeLog %{prefix}/bin/Fox %changelog * Sun Feb 11 2007 Vincent Favre-Nicolin - Release 1.7 * Thu Jul 06 2005 Vincent Favre-Nicolin - First rpm package ! objcryst-2022.1/Fox/README-Fox.txt000066400000000000000000000007271430515525000164310ustar00rootroot00000000000000FOX, Free Objects for Xtallography is open-source software. Please read the LICENSE file for more information. The documentation for Fox is available online on the Fox wiki at: https://fox.vincefn.net If this is your first use of Fox, please start with the tutorials : https://fox.vincefn.net/Tutorials A static (pdf) version of the online documentation can also be downloaded from: https://sourceforge.net/project/showfiles.php?group_id=27546&package_id=19521 objcryst-2022.1/Fox/cctbx_vc12.vcxproj000066400000000000000000000330051430515525000175470ustar00rootroot00000000000000 Debug Win32 Release (profile-guided optim generate) Win32 Release_XP_NoCOD Win32 Release Win32 {BA6FA16F-837D-4869-90B9-44ACCD4EC001} cctbx cctbx 10.0 StaticLibrary true v142 MultiByte StaticLibrary false v142 true MultiByte StaticLibrary false v142 true MultiByte StaticLibrary false v141_xp true MultiByte .lib $(SolutionDir)$(Configuration)\ $(Configuration)\$(ProjectName)\ .lib $(SolutionDir)$(Configuration)\ $(Configuration)\$(ProjectName)\ .lib $(SolutionDir)$(Configuration)\ $(Configuration)\$(ProjectName)\ .lib $(SolutionDir)$(Configuration)\ $(Configuration)\$(ProjectName)\ Level3 Disabled false $(ProjectDir)\..\boost;$(ProjectDir)\..\cctbx\include _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) MultiThreadedDebug true false $(IntDir)\%(RelativeDir) true Level3 MaxSpeed true true false $(ProjectDir)\..\boost;$(ProjectDir)\..\cctbx\include _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) MultiThreaded true $(IntDir)\%(RelativeDir) true StreamingSIMDExtensions2 Fast true true true Level3 MaxSpeed true true false $(ProjectDir)\..\boost;$(ProjectDir)\..\cctbx\include _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) MultiThreaded true $(IntDir)\%(RelativeDir) Fast true true true Level3 MaxSpeed true true false $(ProjectDir)\..\cctbx\include _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) MultiThreaded true $(IntDir)\%(RelativeDir) true true true objcryst-2022.1/Fox/cctbx_vc12.vcxproj.filters000066400000000000000000000233161430515525000212220ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms {0973d8e0-7c3e-4a1a-97ab-d3a81e184698} {69d0e41e-ab3f-4df9-b9b3-ee6e1c9de679} {b4a8a378-bde2-465f-bf0b-0045f9d06893} {8845c27e-1be7-4f7f-a374-eddc788d0499} {98b58b94-2ea0-4789-992c-b3dae45a1e1c} Source Files\eltbx Source Files\eltbx Source Files\eltbx Source Files\eltbx Source Files\eltbx Source Files\eltbx Source Files\eltbx Source Files\eltbx Source Files\eltbx Source Files\eltbx Source Files\eltbx Source Files\eltbx Source Files\eltbx Source Files\eltbx Source Files\eltbx Source Files\eltbx Source Files\eltbx Source Files\eltbx Source Files\eltbx Source Files\eltbx Source Files\eltbx Source Files\eltbx Source Files\eltbx Source Files\eltbx Source Files\miller Source Files\miller Source Files\miller Source Files\miller Source Files\miller Source Files\miller Source Files\miller Source Files\uctbx Source Files\uctbx Source Files\sgtbx Source Files\sgtbx Source Files\sgtbx Source Files\sgtbx Source Files\sgtbx Source Files\sgtbx Source Files\sgtbx Source Files\sgtbx Source Files\sgtbx Source Files\sgtbx Source Files\sgtbx Source Files\sgtbx Source Files\sgtbx Source Files\sgtbx Source Files\sgtbx Source Files\sgtbx Source Files\sgtbx Source Files\sgtbx Source Files\sgtbx Source Files\sgtbx Source Files\sgtbx Source Files\sgtbx Source Files\sgtbx Source Files\sgtbx Source Files\sgtbx Source Files\eltbx Source Files\eltbx Source Files\eltbx Source Files\eltbx Source Files\sgtbx\reference_settings Source Files\sgtbx\reference_settings Source Files\sgtbx\reference_settings Source Files\sgtbx\reference_settings objcryst-2022.1/Fox/example/000077500000000000000000000000001430515525000156265ustar00rootroot00000000000000objcryst-2022.1/Fox/example/Cimetidine-powder.xml000066400000000000000000011673351430515525000217400ustar00rootroot00000000000000 10.3942 18.819 6.82503 90 106.437 90 0.00415153 0.00119514 0.00105758 objcryst-2022.1/Fox/example/Cimetidine.xml000066400000000000000000000336061430515525000204320ustar00rootroot00000000000000 10.3941 18.8189 6.82493 90 106.437 90 0 objcryst-2022.1/Fox/example/brucite-textured.xml000066400000000000000000006162421430515525000216620ustar00rootroot00000000000000 3.148 10 4.76862 90 90 120 -0.037 0 0 objcryst-2022.1/Fox/example/ktartrate-textured.xml000066400000000000000000015574221430515525000222330ustar00rootroot00000000000000 7.78621 10.6465 7.61506 90 90 90 -0.001 0 0 objcryst-2022.1/Fox/example/ktartrate.xml000066400000000000000000011322251430515525000203570ustar00rootroot00000000000000 7.78447 10.6468 7.61401 90 90 90 0.0154529 -0.00522651 0.0241964 objcryst-2022.1/Fox/example/pbso4-joint.xml000066400000000000000000004331641430515525000205330ustar00rootroot00000000000000 8.482 5.398 6.959 90 90 90 -0.043 0 0 -0.051 0 0 objcryst-2022.1/Fox/example/tutorial-cimetidine/000077500000000000000000000000001430515525000216015ustar00rootroot00000000000000objcryst-2022.1/Fox/example/tutorial-cimetidine/cime.dat000066400000000000000000001716631430515525000232260ustar00rootroot00000000000000 8.01 0.01 84.99 2707 2648 2666 2639 2620 2726 2619 2691 2631 2685 2670 2720 2672 2599 2645 2663 2640 2630 2624 2628 2648 2595 2635 2639 2547 2577 2603 2645 2588 2588 2699 2596 2615 2599 2645 2627 2535 2643 2487 2577 2663 2558 2599 2536 2606 2530 2484 2474 2577 2506 2469 2477 2548 2538 2591 2518 2453 2523 2455 2507 2490 2411 2521 2455 2533 2397 2504 2459 2398 2452 2486 2491 2378 2463 2518 2434 2498 2371 2432 2527 2438 2414 2341 2478 2371 2395 2375 2385 2371 2363 2357 2358 2351 2432 2381 2283 2361 2396 2349 2343 2439 2370 2332 2324 2419 2363 2305 2366 2356 2347 2385 2330 2265 2334 2400 2453 2451 2412 2377 2416 2462 2368 2501 2424 2469 2678 2834 3227 4123 5684 7811 9486 9109 6811 4367 2872 2569 2365 2330 2241 2225 2300 2182 2158 2248 2263 2289 2154 2248 2221 2278 2264 2265 2217 2248 2196 2269 2209 2150 2221 2195 2214 2175 2107 2157 2176 2200 2167 2158 2255 2121 2083 2081 2165 2137 2176 2212 2158 2127 2170 2165 2119 2138 2124 2189 2117 2140 2235 2153 2195 2255 2331 2493 2919 3228 3525 3343 2932 2300 2183 2179 2122 2150 2041 2125 2013 2046 2081 2100 2115 2048 2096 2066 2052 2061 2084 2064 2061 2061 2004 1998 2042 1994 2038 1976 1984 2043 2043 1964 1962 1975 1968 2003 1920 1917 2026 2012 2068 2012 1987 1954 2090 2042 2017 2023 1935 1933 1926 1936 2018 2073 2018 1906 1950 1934 2008 1992 1955 2005 1898 1864 1944 1990 1911 1885 1922 1894 1986 1873 1930 1886 1803 1982 1947 1870 1864 1946 1901 1923 1884 1853 1873 1893 1899 1976 1872 1752 1950 1912 1891 1851 1902 1881 1811 1769 1878 1847 1861 1833 1832 1764 1827 1846 1775 1820 1810 1837 1773 1800 1859 1774 1765 1781 1820 1855 1752 1756 1838 1841 1793 1864 1776 1752 1823 1796 1824 1750 1807 1774 1810 1832 1777 1726 1714 1739 1799 1717 1734 1715 1798 1767 1730 1751 1775 1727 1703 1718 1686 1765 1694 1786 1653 1705 1739 1737 1701 1701 1746 1715 1680 1733 1647 1714 1639 1692 1712 1722 1723 1721 1655 1676 1676 1675 1717 1658 1692 1559 1649 1685 1658 1668 1685 1635 1673 1652 1595 1666 1667 1655 1582 1682 1606 1646 1628 1622 1673 1639 1593 1659 1651 1679 1675 1565 1668 1640 1600 1609 1605 1606 1634 1606 1604 1596 1610 1573 1584 1667 1632 1612 1654 1599 1576 1550 1630 1600 1650 1627 1601 1577 1642 1709 1608 1612 1630 1563 1690 1622 1589 1618 1613 1573 1601 1672 1614 1607 1636 1670 1703 1677 1704 1702 1754 1649 1708 1745 1709 1662 1715 1759 1725 1778 1831 1839 1818 1866 1856 1955 1923 1913 2026 2022 2005 2167 2130 2197 2291 2542 3281 4844 8647 15934 25738 32966 31321 21800 11057 4702 2786 2144 2019 1841 1859 1753 1747 1703 1762 1604 1672 1615 1636 1657 1631 1631 1550 1557 1552 1573 1512 1505 1540 1576 1517 1469 1544 1513 1495 1506 1536 1497 1433 1444 1420 1493 1509 1480 1481 1469 1476 1455 1519 1517 1493 1527 1433 1487 1485 1556 1572 1574 1791 1892 1978 1838 1630 1519 1553 1453 1438 1490 1450 1464 1458 1424 1457 1402 1470 1478 1437 1416 1433 1420 1478 1387 1430 1460 1516 1452 1500 1414 1481 1401 1395 1402 1340 1438 1441 1514 1472 1342 1393 1441 1354 1460 1434 1479 1409 1431 1457 1415 1442 1408 1423 1415 1395 1533 1429 1398 1495 1395 1418 1446 1438 1499 1444 1403 1461 1375 1463 1420 1448 1437 1435 1468 1498 1503 1480 1541 1618 1803 1887 2003 1917 1762 1620 1602 1546 1541 1582 1566 1537 1611 1570 1681 1670 1682 1688 1722 1790 1801 1842 1901 1817 1899 1996 2001 2109 2046 2125 2123 2221 2350 2669 3440 5422 9921 19572 33074 44366 44887 33269 18099 7305 3508 2563 2259 1939 1817 1729 1676 1595 1603 1660 1564 1565 1495 1532 1544 1503 1551 1492 1442 1385 1413 1397 1411 1332 1376 1388 1390 1384 1331 1427 1370 1330 1341 1341 1324 1333 1327 1334 1339 1295 1303 1332 1325 1310 1303 1343 1351 1316 1348 1322 1349 1378 1359 1299 1374 1323 1392 1331 1358 1302 1229 1345 1319 1357 1352 1300 1356 1305 1327 1255 1278 1290 1292 1307 1300 1307 1354 1283 1281 1327 1373 1246 1344 1301 1327 1309 1268 1281 1359 1268 1300 1271 1289 1329 1305 1297 1241 1327 1355 1317 1325 1300 1287 1304 1335 1277 1308 1301 1327 1352 1280 1347 1288 1343 1305 1317 1299 1251 1347 1300 1299 1341 1340 1298 1395 1320 1417 1346 1376 1398 1434 1350 1388 1362 1394 1448 1464 1497 1500 1436 1465 1470 1546 1576 1504 1663 1698 1579 1686 1630 1713 1683 1754 1770 1919 1935 2004 2008 2146 2199 2299 2310 2352 2318 2430 2628 2815 3190 4343 7152 13787 27418 44136 54843 51739 36235 18298 7541 4145 3252 2809 2642 2491 2423 2414 2421 2544 2625 3049 3785 5700 9544 14506 18006 16176 11141 6320 3911 3202 3130 3574 4831 8520 17933 34977 53992 62458 55348 34711 15919 6205 3464 2601 2256 2040 1812 1771 1660 1693 1613 1663 1598 1608 1590 1494 1500 1418 1463 1469 1433 1437 1358 1381 1414 1427 1321 1358 1284 1328 1335 1284 1312 1313 1319 1297 1348 1299 1300 1343 1344 1336 1294 1273 1306 1267 1216 1281 1261 1314 1279 1327 1295 1353 1302 1325 1357 1299 1353 1347 1370 1368 1384 1433 1413 1422 1457 1482 1476 1554 1516 1499 1540 1643 1637 1707 1849 1781 1825 1858 1896 2009 2043 2014 2119 2266 2433 2804 3936 7125 14498 27285 39832 44466 37085 22477 10073 4438 2755 2218 1882 1783 1630 1603 1529 1526 1448 1495 1574 1467 1461 1488 1411 1333 1374 1338 1410 1330 1382 1375 1452 1360 1353 1390 1371 1396 1429 1443 1402 1500 1448 1475 1505 1466 1656 1619 1581 1654 1604 1760 1807 1806 1864 1906 1869 1965 2080 2225 2554 3327 5084 10069 19561 31842 40886 38176 26636 13011 5480 2954 2191 1933 1730 1647 1513 1506 1521 1425 1440 1407 1396 1409 1400 1306 1409 1403 1293 1295 1323 1339 1319 1306 1295 1301 1271 1306 1323 1416 1387 1597 1980 2643 3295 3646 3456 2846 2974 3774 5170 5604 4599 3164 2048 1589 1391 1302 1258 1305 1279 1343 1340 1331 1312 1344 1326 1458 1639 2020 3001 4940 6589 7298 6259 4319 2599 1720 1476 1368 1283 1293 1260 1306 1323 1238 1247 1277 1315 1362 1297 1295 1307 1339 1361 1333 1368 1343 1457 1411 1458 1458 1496 1559 1595 1603 1584 1670 1654 1742 1837 1930 1960 1999 2052 2076 2112 2295 2516 3046 4245 6920 12462 18906 22699 20682 15707 13184 17153 26212 33856 33317 24586 13278 6273 3779 2977 2691 2609 2460 2508 2395 2318 2367 2527 2655 3135 4405 7945 16932 32523 48860 54736 43436 24924 10605 4559 2859 2306 1939 1772 1672 1557 1545 1482 1527 1564 1412 1389 1434 1434 1449 1325 1320 1348 1380 1478 1774 2315 2766 2715 2196 1765 1359 1279 1249 1234 1278 1232 1177 1223 1184 1169 1190 1221 1196 1204 1232 1183 1185 1229 1241 1231 1269 1247 1284 1289 1286 1338 1354 1631 2086 3356 5881 8420 9639 8077 5234 2829 1726 1432 1301 1214 1180 1180 1170 1140 1156 1145 1130 1127 1077 1080 1056 1080 1174 1130 1103 1121 1044 1086 1163 1064 1053 1076 1159 1116 1148 1232 1372 1493 1482 1427 1301 1128 1110 1065 1067 1079 1066 1074 1056 1086 1062 1029 1064 1050 1029 1018 1077 1054 1050 1039 1067 1097 1080 1102 1119 1063 1055 1019 1086 1089 1085 1122 1032 1072 1057 1101 1087 1170 1326 1573 1728 1801 1592 1441 1252 1126 1027 1101 1065 1046 1060 1048 1030 1038 1050 1012 1049 1066 1022 1064 1047 1039 1041 1025 1081 1036 1036 1091 1085 1050 1086 1017 1100 1098 1068 1026 1031 1040 1049 1040 1019 1057 1065 1053 1040 1012 1043 1008 1060 1053 1075 1034 1054 1063 1041 1024 998 1044 1076 1068 1024 1033 1076 1089 1030 1068 1125 989 1098 1059 994 1069 1022 1045 1022 1081 1093 1076 1069 1055 1043 1115 1106 1070 1104 1095 1094 1083 1077 1117 1052 1082 998 1042 1042 1074 1076 1090 1081 1072 1065 1110 1096 1095 1061 1101 1114 1088 1065 1063 1092 1077 1064 1124 1051 1055 1127 1109 1154 1099 1124 1107 1079 1079 1096 1174 1190 1144 1102 1168 1148 1137 1115 1127 1183 1174 1187 1137 1193 1206 1215 1219 1201 1259 1411 1523 1785 1838 1721 1489 1420 1356 1265 1322 1306 1339 1340 1373 1423 1415 1411 1383 1423 1447 1520 1559 1588 1610 1585 1655 1700 1728 1801 1899 2173 2695 3649 5253 6606 6404 5110 3926 2920 2701 2592 2585 2503 2729 2788 3031 3360 4147 6348 11898 23014 35400 44503 41375 27822 14472 7212 5066 4441 4337 4199 4483 4663 4873 4887 4994 4912 5192 5620 6304 8249 12998 26771 58200 108579 153815 167364 137019 83603 37620 14109 7820 5598 4356 3781 3293 3013 2935 2764 2742 2800 2605 2695 2621 2674 2458 2514 2573 2528 2745 3272 4921 9180 17233 26514 32264 30557 21171 11169 5036 2979 2329 1957 1784 1747 1534 1548 1484 1508 1425 1393 1399 1370 1317 1375 1315 1343 1290 1276 1215 1235 1188 1230 1186 1233 1232 1195 1218 1193 1164 1218 1189 1175 1167 1168 1100 1145 1101 1137 1097 1142 1077 1196 1096 1102 1048 1115 1057 1163 1125 1106 1082 1140 1103 1112 1110 1060 1104 1113 1080 1075 1015 1042 1036 1085 1093 1067 1077 1079 1102 1063 1036 983 1067 1112 1033 1120 1087 1065 1028 1026 1097 1023 1016 1085 1028 1007 1031 1061 1094 1066 1001 1062 1055 998 1080 1028 1011 1023 980 992 1022 1039 1083 1046 1002 1005 978 1018 1043 1013 1021 1023 1067 1020 1038 1043 1033 1044 1070 1039 1009 1013 1013 1093 1073 1095 994 1043 1063 1044 1028 997 1030 1076 1025 1060 1152 1143 1211 1350 1544 1564 1849 2233 2787 2987 2418 1849 1391 1172 1129 1106 1129 1131 1116 1129 1120 1079 1124 1070 1104 1134 1182 1166 1150 1159 1159 1190 1232 1262 1232 1315 1301 1362 1312 1344 1346 1433 1446 1457 1437 1541 1583 1734 2018 2974 5118 9272 13250 14958 12636 8077 4474 2616 2090 1917 1920 1873 1905 1966 1985 2037 2147 2097 2208 2252 2283 2488 2780 3363 5005 9009 18282 33764 48815 53209 43512 26599 12262 5745 3450 2586 2244 1901 1718 1664 1552 1535 1501 1467 1503 1443 1423 1333 1417 1374 1399 1409 1628 2147 3316 5053 7150 7384 6178 3974 2301 1535 1360 1258 1158 1213 1166 1149 1146 1105 1081 1135 1136 1131 1067 1125 1088 1143 1223 1447 1622 1837 1875 1692 1530 1275 1190 1212 1143 1207 1147 1215 1229 1279 1214 1245 1316 1374 1316 1247 1330 1385 1527 1743 2136 3093 5085 7805 10908 11430 9448 6199 3638 2340 1836 1655 1766 2070 2548 2927 2879 2481 1873 1566 1525 1500 1584 1848 2577 4059 6009 7507 7285 5569 3537 2202 1866 1782 1714 1839 1839 1883 1961 2352 3113 5131 9347 15702 21172 21368 15671 8999 5115 4590 7095 11744 15368 15792 12009 7154 3598 2127 1693 1500 1443 1293 1350 1318 1185 1236 1175 1184 1207 1247 1313 1437 1606 1751 1620 1403 1238 1213 1176 1175 1145 1213 1230 1382 1580 1723 1728 1564 1383 1296 1273 1272 1280 1238 1259 1350 1357 1487 1733 2388 3724 5789 7230 7360 6227 4135 2694 1907 1640 1572 1565 1510 1582 1622 1590 1726 1617 1758 1983 2359 3136 4838 8504 14357 20249 22049 18717 12525 6970 4002 2617 2032 1778 1523 1478 1491 1468 1508 1460 1432 1407 1453 1452 1498 1539 1683 1664 1655 1657 1873 1955 2056 2239 2368 2569 2566 2759 2831 2926 3734 5743 10141 18511 30346 40468 43347 36380 24378 13436 6829 3842 2619 2048 1852 1609 1519 1458 1369 1361 1312 1250 1247 1243 1189 1162 1165 1153 1093 1096 1064 1015 1072 1086 1033 1063 1059 1031 1037 986 1050 1078 1078 1075 1142 1264 1492 1520 1525 1379 1210 1168 1101 1014 1058 1086 1111 1160 1111 1122 1193 1149 1254 1205 1280 1430 1802 2787 4799 8197 11403 12433 10063 6278 3293 1828 1359 1228 1152 1043 1037 990 988 987 976 999 948 949 942 882 962 994 934 943 921 866 906 958 915 964 938 896 938 870 901 915 912 963 913 918 947 910 925 892 907 951 958 946 905 945 982 1036 1138 1292 1293 1324 1149 964 993 983 958 995 1027 1041 1041 1068 1132 1322 1619 2366 3198 3904 3618 2756 1975 1406 1139 1088 1056 1014 1088 1134 1217 1489 2174 3580 5220 6326 6021 4407 2728 1645 1317 1080 1139 1124 1117 1051 1009 949 950 989 979 976 979 913 960 978 964 930 952 979 999 1003 1015 1047 1006 1094 1063 1153 1111 1075 1119 1165 1179 1270 1455 1817 2785 4830 7807 10372 10452 8090 5226 2892 1835 1560 1591 2039 2940 4933 6960 8336 7258 5049 2920 1718 1301 1175 983 996 1014 868 888 935 947 915 907 879 859 874 866 856 853 886 865 838 872 824 866 851 825 840 830 836 867 879 860 864 838 763 801 855 838 879 852 841 829 821 796 802 778 860 793 806 822 882 850 810 802 831 806 837 841 844 820 901 825 864 853 883 870 891 791 870 845 910 891 889 842 906 901 937 930 947 1058 1241 1524 2094 2745 3569 3448 2645 1929 1403 1219 1217 1488 1750 2280 2591 2307 1861 1446 1260 1355 1799 2697 3493 3638 3166 2154 1394 1088 1018 924 866 901 912 925 984 1009 1124 1437 1823 2404 2966 2934 2416 1712 1162 952 933 821 849 852 830 832 858 812 839 830 869 828 805 851 858 869 849 836 897 885 830 877 838 919 910 869 909 858 814 864 807 918 932 877 908 981 957 981 989 1003 1011 1031 1084 1103 1117 1167 1092 1125 1142 1234 1281 1571 1995 3270 5752 8823 10706 10486 7656 4576 2698 1944 2082 2759 4044 5564 6782 6459 4962 3327 2277 1604 1559 1540 1787 2522 4119 6712 9783 11408 10051 6570 3716 2087 1446 1265 1105 1057 1004 967 932 929 891 904 903 864 933 975 963 971 944 936 893 853 855 839 851 872 853 921 942 1004 1059 1012 969 955 852 854 815 817 875 817 818 882 904 826 827 834 871 833 889 837 852 866 845 870 882 947 902 881 913 960 988 1215 1655 2144 2789 2938 2515 1837 1280 1169 1019 939 940 970 946 962 915 915 948 997 985 992 1002 929 1064 1048 1092 1131 1117 1140 1182 1144 1225 1265 1337 1355 1365 1363 1452 1614 1823 2248 3198 5358 8756 12471 14804 13185 9088 5360 3178 2588 2890 4089 6342 9418 11696 12130 10900 11404 13838 16010 14797 10998 6820 4228 3116 2948 3112 4114 6011 8542 10542 10372 7935 4773 2638 1823 1418 1287 1239 1090 1051 1046 1043 1031 967 957 989 940 960 992 949 987 1040 1069 1085 1131 1247 1100 1117 1035 1007 996 1043 1103 1076 1053 1096 1068 1137 1145 1221 1373 1736 2387 3766 5240 6108 5630 4635 4231 5115 7070 8466 8389 6588 4040 2349 1672 1312 1174 1099 1144 1191 1374 1670 2113 2474 2578 2317 1784 1390 1178 1010 1010 922 976 978 935 979 923 931 983 1012 1029 1165 1266 1497 1909 2357 2594 2373 1845 1534 1180 1244 1291 1580 2275 3162 4258 4840 4582 3485 2325 1580 1167 1075 1030 906 857 839 819 872 813 814 816 827 844 850 811 843 802 853 841 810 823 834 801 854 871 804 822 881 889 807 802 854 815 860 863 891 845 891 897 936 905 951 1062 1116 1201 1163 1316 1503 2040 3084 4427 5442 5158 3924 2836 1729 1227 1044 897 994 935 956 1071 1232 1486 1630 1564 1321 1081 896 905 844 813 886 851 872 828 838 823 839 875 837 849 821 884 837 879 939 1023 1241 1557 2258 3127 3770 3673 3163 2345 1599 1240 1042 924 887 925 870 862 829 779 813 832 797 804 764 788 775 818 833 963 997 1013 1028 945 873 879 936 1052 1247 1473 1465 1330 1120 957 895 879 837 808 774 822 764 777 799 792 819 837 803 830 849 911 1133 1522 2036 2500 2379 2003 1507 1073 956 810 828 751 773 740 732 737 738 737 749 743 780 717 747 773 769 758 775 833 847 842 857 885 835 814 783 746 757 762 733 741 770 755 724 743 741 781 745 714 745 763 745 730 735 781 745 780 801 802 842 835 985 1101 1141 1020 934 835 798 778 789 751 729 725 734 744 779 751 710 746 714 754 727 801 739 741 699 720 726 721 705 722 747 780 716 757 717 765 811 758 785 761 775 852 933 1095 1316 1479 1403 1320 1033 948 781 830 699 781 720 770 787 709 790 803 781 778 735 753 772 818 913 986 1022 940 842 813 770 734 761 768 748 790 768 742 805 791 791 812 801 769 826 821 832 879 902 1078 1319 1667 2065 2431 2333 1877 1309 1061 881 960 1067 1187 1308 1375 1395 1432 1345 1305 977 917 884 830 790 806 824 862 767 815 796 809 867 932 1089 1308 1704 2186 2299 2123 1587 1179 1057 960 919 902 953 834 894 969 904 993 986 1029 1050 1356 1783 2760 4286 5876 6470 5481 4181 3397 3197 3012 2597 1938 1357 1055 912 875 876 848 881 887 969 1104 1228 1344 1259 1095 983 872 865 853 820 794 819 831 884 958 979 1039 1028 1020 911 905 846 855 871 863 892 859 860 847 887 945 1075 1364 1966 2663 3402 3532 2793 2096 1421 1119 925 958 990 1013 1138 1218 1505 1924 1971 1902 1504 1252 1260 1334 1322 1235 1147 1018 1070 1349 1764 2545 3393 3824 3633 2724 1755 1275 1011 956 862 870 864 837 862 849 917 914 1053 984 995 915 849 851 861 854 899 892 956 1184 1553 2211 2733 2808 2379 1663 1281 982 945 860 923 905 961 1136 1149 1406 1470 1339 1242 1068 998 997 1048 1016 1027 961 924 940 955 935 1004 1087 1276 1623 2341 3243 3993 4181 3734 2861 1878 1347 1090 991 1004 949 914 924 941 912 917 904 876 918 924 1004 1108 1454 2024 3011 4030 4443 3936 2733 1853 1426 1286 1183 1172 1054 1059 1084 1047 1107 1154 1262 1492 1844 2373 3283 4081 4021 3362 2461 1596 1284 1054 963 912 883 883 910 863 877 892 894 983 986 989 875 878 879 879 895 839 837 1008 1051 1279 1704 2287 2715 2690 2236 1659 1370 1446 1807 2103 2220 1860 1528 1175 987 919 849 858 839 837 834 890 794 842 816 827 863 844 885 816 872 875 865 945 941 928 981 997 1023 1200 1369 1724 2410 3285 3876 4004 3586 2967 2941 2995 2861 2636 2405 2108 1792 1460 1184 1022 976 898 849 846 883 804 835 848 828 817 823 830 768 803 809 870 843 843 934 888 999 980 939 998 1139 1324 1383 1351 1232 982 934 797 842 763 815 820 766 826 776 763 809 837 789 817 785 810 812 780 829 830 787 799 815 841 832 766 814 785 833 830 896 788 854 770 827 834 883 860 880 906 913 954 897 937 880 943 927 1015 968 1023 1097 1209 1267 1372 1354 1307 1319 1403 1456 1553 1789 2436 3375 4547 5505 5492 4588 3268 2332 1817 1674 1545 1741 1764 1978 2185 2526 3403 5454 8415 10584 10489 8036 5061 3113 2307 2243 2765 3438 4210 4446 3916 2851 2072 1491 1225 1079 1101 1062 1050 1070 1023 1023 1011 987 1070 1155 1091 1084 1119 1140 1399 1714 2111 2992 3478 3555 3004 2253 1680 1298 1166 1065 1102 1054 1059 1084 1174 1417 1880 2389 2712 2589 2132 1640 1271 1071 979 982 967 1003 938 953 933 1019 1132 1285 1791 2592 3885 4869 4963 4059 2785 1919 1338 1100 1039 942 979 983 1040 1112 1144 1233 1144 1110 1016 936 844 888 913 958 1004 1112 1302 1601 1666 1659 1408 1225 1005 906 861 877 893 883 848 899 906 886 916 922 1006 1078 1124 1457 1853 2182 2349 2228 1973 1645 1591 1533 1423 1252 1096 959 925 954 914 945 999 1070 1102 1062 961 900 894 882 854 864 830 822 825 880 861 875 862 905 924 987 922 953 868 925 958 886 953 953 1077 1226 1588 2225 3073 3964 4169 3789 2848 1919 1527 1200 1164 998 936 915 828 884 903 922 832 909 878 841 914 901 919 896 951 991 1090 1200 1380 1367 1266 1148 1080 998 1021 1052 1086 1035 1183 1154 1225 1446 1684 2383 3423 4903 6049 5849 4852 3535 2477 2058 2410 3303 4638 6497 7461 6810 5175 2978 1860 1363 1132 1063 1028 994 990 882 925 958 876 895 911 830 918 901 858 876 1026 1117 1389 1736 2132 2342 2099 1624 1250 1073 1005 1033 1014 972 994 877 896 856 858 846 883 844 858 828 806 834 811 821 789 796 767 728 800 770 823 806 799 816 818 780 813 795 850 855 818 816 875 903 815 920 919 994 964 913 898 859 875 825 916 855 904 928 919 940 998 1053 1043 1216 1398 1969 2900 3889 4614 4457 3668 2622 1803 1393 1360 1410 1483 1467 1299 1176 1084 896 896 893 910 901 852 863 896 897 929 980 1051 1098 1384 1510 1894 2032 1895 1593 1340 1129 1003 940 943 981 925 953 1054 1174 1542 2008 2554 2904 2592 2053 1496 1223 1032 982 1049 964 1004 1051 1115 1201 1472 1876 2439 3121 3829 3963 3551 2855 2188 1626 1341 1085 1029 990 937 960 1068 1059 1219 1426 1548 1453 1346 1120 1027 938 891 940 928 893 917 1070 1351 1592 1716 1668 1513 1192 1059 964 882 917 884 871 864 892 899 880 874 891 893 924 898 1019 1202 1482 1958 2510 2998 2644 2148 1592 1211 1131 1044 1029 1105 1119 1155 1203 1268 1584 2130 2987 3829 4069 3631 2963 2295 2072 2304 2673 3148 3284 3161 2684 2203 1865 1780 1753 1625 1598 1458 1368 1324 1296 1219 1303 1125 1097 1087 998 916 930 905 861 862 867 853 777 811 819 856 820 839 805 839 846 888 880 965 1050 1253 1608 1898 2023 1854 1577 1300 1193 1309 1506 1865 2034 2055 1750 1294 997 924 844 844 855 840 824 861 772 796 810 761 784 861 795 809 805 820 798 788 809 897 950 1040 1184 1303 1380 1397 1292 1114 964 963 880 877 859 949 962 1049 1204 1233 1149 1032 1025 1114 1221 1452 1940 2341 2419 2157 1921 1533 1311 1202 1010 914 870 818 815 877 927 958 968 1005 920 969 895 827 810 818 757 751 781 822 830 769 800 785 785 823 771 795 818 801 792 792 820 752 766 769 833 757 838 789 830 848 821 838 952 1037 1140 1236 1277 1147 1045 936 883 786 805 809 812 837 854 900 928 883 883 854 870 818 820 821 868 924 1007 1181 1503 1842 2124 2114 1694 1388 1140 1006 967 845 808 853 878 867 892 875 905 871 857 925 928 1020 1065 1328 1590 2070 2520 2810 2647 2232 2017 1952 2112 2455 2446 2253 1769 1299 1066 966 881 884 855 848 859 826 822 833 777 858 834 847 859 954 1077 1187 1324 1382 1266 1124 1006 916 934 888 982 975 1038 983 931 870 831 810 838 850 832 808 844 846 811 779 807 820 832 809 800 872 940 1009 1043 1079 1024 1167 1202 1253 1259 1190 1017 911 868 841 817 883 811 882 921 935 1068 1125 1106 1079 1102 1067 1072 1237 1287 1339 1255 1176 1082 1015 1064 1154 1261 1352 1411 1322 1210 1046 993 938 876 988 932 961 1016 1058 1278 1462 1751 1987 2060 1963 1629 1376 1234 1201 1207 1366 1654 2311 3222 3953 4168 3603 2760 2050 1636 1359 1218 1125 1024 934 868 838 873 850 787 877 889 846 806 878 865 878 803 831 868 898 893 940 891 925 867 895 888 860 870 849 896 930 915 943 993 979 1047 1170 1242 1419 1590 1886 2070 2417 2853 3393 3848 3826 2951 2293 1600 1271 1149 1149 1134 1096 1116 1096 1110 1015 1079 1099 1279 1641 2110 2415 2495 2240 1686 1325 1153 1129 975 989 1029 1109 1220 1559 2230 3055 4140 4926 4695 3772 2615 1809 1310 1135 1028 970 917 927 888 871 899 874 919 891 889 866 869 892 924 929 997 920 954 947 904 920 1006 1052 1081 1279 1496 1701 1906 1837 1596 1353 1244 1131 1074 1116 1193 1353 1725 2102 2589 2691 2683 2900 3160 3131 2788 2256 1814 1544 1417 1322 1342 1400 1498 1712 2225 3135 4445 5665 6694 6506 5151 3603 2381 1646 1373 1059 1054 926 947 948 913 907 860 805 949 894 934 906 945 868 890 859 879 877 908 856 934 977 967 957 979 1046 1138 1286 1343 1410 1406 1274 1354 1548 1943 2333 2423 2237 1686 1338 1063 900 889 888 834 856 836 831 824 868 888 827 835 847 899 828 849 918 935 994 1057 1085 1090 1116 1254 1411 1577 1501 1454 1324 1132 1064 1128 1246 1356 1428 1574 1630 1563 1538 1683 1973 2105 1986 1751 1339 1095 984 944 880 943 890 880 921 943 900 923 955 1014 1204 1479 1875 2449 3093 3195 2898 2419 1717 1207 1064 942 859 848 849 796 817 800 825 873 790 845 885 813 786 809 790 749 819 794 839 767 773 836 798 826 824 845 873 841 817 826 790 796 794 843 763 806 807 903 882 863 926 974 1191 1219 1245 1249 1022 943 900 835 782 786 826 849 828 743 762 765 762 765 776 841 772 828 826 809 777 793 844 850 867 898 995 978 954 977 1003 1057 1018 1005 1023 914 848 910 928 947 1034 1191 1314 1556 1523 1303 1187 1089 981 937 872 848 878 869 933 926 1003 1017 1150 1181 1412 1807 2264 2904 3096 3134 2734 2158 1689 1341 1107 1015 958 1028 1045 1146 1191 1305 1253 1261 983 934 902 831 846 916 911 882 887 835 904 790 853 820 796 862 818 819 838 833 836 801 865 822 838 849 944 881 970 1169 1315 1567 1513 1414 1226 1063 929 908 841 847 864 895 934 900 887 976 977 984 1001 1017 1037 1188 1294 1377 1508 1399 1425 1358 1399 1322 1143 1003 937 893 823 904 870 852 878 805 836 884 907 989 1025 1101 1178 1071 1083 994 904 967 976 935 909 867 813 854 851 870 826 885 936 914 1021 1025 1006 1107 1163 1206 1336 1274 1111 1024 968 986 935 943 922 937 921 928 956 985 990 903 1019 1111 1284 1485 2064 2834 3678 4423 4643 4360 3554 2720 1989 1533 1229 1128 1118 1196 1150 1066 1176 1183 1219 1175 1137 1249 1223 1334 1468 1441 1365 1286 1169 1141 1028 981 1005 1122 1364 1603 1936 2289 2890 2982 2768 2560 2149 1971 1949 1767 1628 1532 1688 1788 1836 1774 1503 1233 1086 996 974 1036 964 1031 1148 1194 1250 1139 999 957 975 957 896 1019 921 996 988 933 945 967 881 860 943 993 1012 1092 1192 1381 1602 1904 2254 2378 2378 2019 1605 1253 1081 962 920 885 894 945 933 885 925 965 1019 1185 1318 1713 1858 2164 2073 1788 1596 1248 1092 930 925 873 924 868 851 886 829 844 837 832 896 871 912 910 939 947 1144 1308 1402 1448 1399 1318 1186 1047 1007 897 887 925 834 832 852 862 880 880 889 898 893 893 1049 1080 1352 1469 1934 2095 2221 1911 1564 1327 1190 1037 1000 927 960 923 1002 965 1028 1236 1444 1828 2277 2658 2715 2295 1827 1398 1155 962 1027 946 909 873 851 862 827 843 837 834 881 786 799 836 793 772 799 820 842 779 827 852 832 884 994 1011 956 927 921 826 836 883 814 822 850 912 818 890 820 885 951 912 962 930 1047 1056 1120 1164 1121 1027 946 931 902 851 906 901 931 1004 1094 1165 1274 1453 1438 1398 1394 1311 1199 1073 1040 945 973 920 957 877 888 888 859 910 981 883 916 946 1071 1033 1139 1278 1485 2001 2477 2965 3133 3010 2757 2233 1679 1379 1335 1324 1421 1494 1487 1351 1340 1350 1489 1591 1657 1720 1614 1493 1437 1526 1739 1797 1885 1767 1645 1349 1118 983 962 1045 948 1093 1124 1222 1264 1244 1157 980 930 901 899 857 874 790 833 782 792 794 757 843 813 797 743 820 832 809 808 781 821 754 759 815 758 750 743 830 843 797 817 768 750 784 808 788 821 767 847 810 873 879 868 830 811 879 870 941 964 1224 1292 1508 1531 1404 1454 1440 1303 1399 1194 1077 1079 979 910 947 846 913 887 939 973 986 1045 1020 1022 933 922 901 877 855 882 803 816 842 833 897 908 873 956 1033 1026 1140 1160 1396 1425 1613 1669 1696 1522 1441 1274 1280 1197 1214 1118 1128 1093 1282 1404 1575 1689 1602 1569 1372 1244 1241 1332 1526 1756 1916 1976 2005 1951 1703 1432 1223 1103 971 924 878 838 890 839 777 786 844 814 774 822 822 853 868 935 994 993 940 955 868 862 864 880 853 908 948 1054 1119 1174 1224 1191 1207 1189 1135 1123 1107 1001 891 860 866 834 894 817 879 877 904 981 1005 1121 1124 1191 1255 1220 1185 1001 962 935 906 830 801 827 896 811 877 804 822 810 827 893 933 828 900 866 892 879 804 859 839 789 836 833 841 853 1044 1184 1355 1455 1392 1454 1351 1266 1339 1301 1166 1058 1013 851 864 863 792 798 833 880 744 827 799 810 773 829 871 794 838 810 809 875 951 958 1014 1124 1191 1347 1201 1082 1034 935 925 815 926 900 1041 1154 1322 1478 1550 1288 1190 992 952 988 954 983 1024 996 981 973 876 910 911 895 1018 1122 1256 1252 1314 1344 1215 1188 1085 957 968 880 829 791 815 849 797 829 777 815 836 829 874 859 841 863 877 867 897 1033 1055 1099 1221 1220 1189 1151 1129 1187 1338 1280 1293 1189 1114 1070 1064 1127 1256 1353 1418 1397 1142 969 977 917 885 824 862 886 990 1085 1237 1251 1206 1126 1084 1049 1003 967 941 870 866 808 820 838 925 963 973 1142 1161 1123 1097 1026 880 927 855 895 835 817 846 861 803 873 809 823 823 832 826 782 836 832 831 936 932 1032 1160 1399 1520 1590 1466 1262 1156 1066 935 983 992 1000 1103 1174 1392 1763 1877 1997 1791 1608 1393 1165 1031 993 905 894 931 915 942 971 957 979 956 908 923 912 946 965 974 1016 979 960 1011 967 979 999 1114 1405 1444 1722 1942 2110 2076 1801 1564 1346 1283 1281 1224 1175 1061 1120 1075 1169 1146 1033 1011 997 925 926 932 1076 1147 1219 1390 1381 1459 1386 1347 1324 1225 1262 1237 1107 1171 1116 1026 1058 1048 938 959 864 871 793 753 791 736 824 753 779 831 793 735 753 767 795 798 761 793 739 807 794 811 830 859 792 839 903 885 795 802 771 838 827 829 838 973 952 979 1191 1237 1087 1086 937 846 825 824 831 819 849 915 860 897 933 889 941 982 1074 1171 1335 1444 1438 1374 1292 1264 1102 1064 1035 895 887 932 926 845 803 864 844 798 828 744 768 794 748 835 742 755 876 791 836 849 847 920 1022 1146 1090 1211 1290 1319 1256 1163 1081 988 956 937 840 808 852 825 857 788 844 827 811 775 797 758 834 751 734 809 800 826 750 803 798 756 818 834 784 825 884 815 909 958 990 986 1040 1092 1221 1275 1312 1517 1495 1533 1430 1454 1429 1251 1318 1271 1317 1376 1399 1460 1342 1348 1209 1155 1052 1051 1056 1033 1026 1038 990 1036 905 871 929 867 928 970 965 996 964 961 921 858 832 814 829 860 811 878 907 818 828 755 813 759 816 818 791 907 819 852 939 912 1013 893 932 915 1045 1250 1344 1596 1535 1377 1276 1134 977 890 880 857 848 856 881 884 843 861 934 857 887 906 929 964 1029 1035 1208 1264 1321 1335 1200 1091 1054 1056 1142 1183 1349 1544 1869 2114 2232 2053 1879 1643 1533 1478 1395 1394 1333 1450 1537 1660 1691 1525 1422 1224 1095 947 932 886 799 846 817 843 889 854 871 893 825 924 920 913 888 963 897 885 862 886 878 828 864 851 849 844 811 887 878 865 825 929 892 977 1043 1246 1455 1828 2067 2307 2242 2028 1660 1348 1094 948 970 858 881 831 851 862 786 823 880 857 833 813 818 809 732 796 746 863 768 827 798 848 807 781 826 748 788 762 788 762 817 839 888 870 830 827 837 854 808 787 737 783 851 729 826 774 809 822 870 846 831 833 891 867 1029 1111 1130 1292 1363 1430 1471 1467 1374 1282 1153 1092 1063 993 886 874 885 836 866 819 889 873 894 871 833 835 829 790 818 809 822 801 844 786 965 894 1021 1099 1223 1314 1264 1202 1072 974 918 890 936 997 977 1029 1055 1062 1062 1064 964 933 915 885 887 904 919 837 909 827 825 801 739 817 777 862 755 750 792 782 816 845 878 829 825 786 894 863 895 843 898 832 896 795 891 906 960 1044 1158 1122 1098 1021 978 960 1003 1010 1104 1062 1205 1216 1266 1218 1070 1025 959 958 889 985 954 1016 976 860 976 882 856 894 945 1026 1175 1412 1472 1636 1635 1580 1330 1106 1029 919 838 796 848 874 862 856 869 818 851 769 787 775 766 800 792 759 751 813 845 784 808 859 903 998 969 945 911 920 875 856 857 820 866 976 988 1160 1171 1130 1192 1141 1290 1294 1184 1178 1096 906 893 786 750 809 809 766 765 720 773 755 803 732 828 796 750 722 711 746 757 728 719 781 760 748 780 797 787 826 751 788 830 793 859 864 809 835 874 876 972 942 910 895 933 884 845 846 775 836 808 741 790 741 742 753 833 878 915 890 942 878 884 822 756 765 788 774 754 742 756 765 826 860 851 861 928 949 866 937 946 966 1017 1153 1240 1307 1371 1247 1212 1099 996 962 919 873 837 912 857 899 864 885 879 895 908 904 870 853 830 823 789 804 804 881 806 845 839 885 810 909 924 928 866 863 832 802 827 902 886 950 1037 1187 1425 1542 1590 1652 1641 1387 1239 1102 986 964 902 890 854 875 886 901 889 882 922 908 949 966 993 981 1032 1040 1091 1212 1222 1316 1674 1840 1816 1989 1741 1485 1274 1240 1105 969 942 861 852 815 818 773 879 848 854 861 854 870 933 881 881 990 929 916 1020 1011 1162 1116 1066 1011 920 861 814 831 839 799 800 890 838 816 803 793 844 852 851 919 942 947 953 970 961 901 823 815 828 721 828 858 800 846 822 944 966 1013 1077 1192 1096 925 1001 821 840 870 894 853 921 919 966 1085 1054 1049 1092 1139 1165 1287 1464 1556 1626 1552 1281 1181 1032 1028 951 953 826 878 906 875 932 925 999 990 1001 912 911 838 904 895 905 909 994 1036 923 932 1109 1070 1007 970 1029 875 873 851 830 803 797 834 831 873 919 940 960 946 894 928 945 892 901 886 909 955 908 917 911 948 953 953 988 1064 1138 1145 1112 1031 1040 923 890 885 897 876 869 803 848 863 877 819 841 801 848 875 909 991 887 989 1079 1019 1113 962 940 867 852 828 860 940 855 899 940 915 942 891 862 883 931 965 1024 1134 1251 1290 1469 1458 1267 1171 1058 978 954 894 869 944 963 1006 1074 1150 1258 1268 1340 1232 1247 1165 1117 1112 1051 985 1083 1068 1137 1251 1178 1119 1067 1028 881 828 862 812 868 825 835 843 864 946 950 997 1062 1002 1004 1009 968 940 941 933 955 883 868 845 878 830 871 883 858 929 1006 1041 1041 1012 934 863 913 859 842 830 887 929 906 937 834 926 927 874 958 865 856 811 794 859 840 858 842 878 960 1106 1232 1258 1276 1133 1054 930 927 869 946 886 898 875 897 777 851 819 802 828 817 817 898 844 836 800 802 830 848 838 909 913 932 885 834 887 813 821 865 804 799 794 797 763 755 792 780 720 778 809 817 766 758 805 850 748 815 794 848 849 895 966 962 954 1022 983 961 879 967 1017 948 978 968 918 895 851 868 773 829 874 886 930 951 1004 1074 1110 1163 1068 1121 953 880 866 813 817 805 794 790 804 768 765 815 777 796 793 812 798 795 835 807 857 846 865 882 867 952 933 1040 1051 989 1004 1031 969 1098 1190 1224 1300 1157 1146 1025 948 931 980 1021 1029 1042 1101 1148 1164 1131 1214 1210 1164 996 954 857 929 811 772 870 862 836 796 848 907 848 925 923 930 896 863 883 833 830 776 809 828 799 832 840 858 894 856 906 914 936 823 944 862 865 849 831 900 837 873 856 883 903 943 915 962 991 1108 1127 1245 1213 1269 1171 1074 968 929 845 857 832 869 840 885 832 803 862 885 850 932 946 920 937 945 901 874 853 923 858 863 875 869 885 840 881 890 872 832 801 861 846 843 861 945 912 957 952 981 944 1013 1053 1078 1095 1075 1168 1105 1061 989 872 827 901 993 845 838 836 898 922 845 823 825 809 794 827 842 824 790 836 830 897 901 1015 984 1106 1078 1135 1176 1146 1177 1192 1146 1081 998 1035 1031 1010 1091 1095 1026 1030 1023 1051 1169 1166 1243 1200 1139 1046 1036 982 1084 1039 1050 1055 1103 1030 948 971 971 871 898 835 895 842 848 804 777 821 802 832 754 793 778 792 785 803 827 849 869 855 855 879 947 924 1037 1028 962 938 911 967 921 906 948 1051 965 1074 908 961 938 959 910 879 974 997 955 1036 1041 982 1016 937 869 900 872 827 895 861 896 891 844 848 867 807 833 816 829 787 849 845 862 849 838 870 847 926 915 930 941 960 861 904 858 892 963 942 1005 1086 997 995 1024 1080 1067 1128 989 926 999 912 853 918 993 965 992 956 960 909 924 999 933 963 949 931 957 1031 1000 1056 1059 1186 1376 1504 1512 1614 1473 1256 1143 1029 951 991 937 959 910 950 900 940 957 954 1073 1147 1191 1390 1402 1410 1469 1403 1342 1325 1331 1249 1177 1265 1341 1282 1334 1360 1255 1331 1315 1197 1165 1121 1123 1130 1044 1076 1129 1208 1288 1404 1604 1637 1699 1762 1646 1477 1243 1117 1025 966 1033 955 1134 1232 1261 1379 1387 1347 1298 1184 1161 1137 1024 951 939 917 887 945 1001 969 1000 1126 1112 1185 1184 1127 1068 1073 1062 1006 889 926 858 893 856 898 866 835 929 896 884 932 828 899 928 983 975 1006 951 992 975 993 1078 1062 966 850 898 913 903 863 945 925 980 1070 1137 1132 1192 1188 1336 1402 1385 1482 1484 1462 1259 1169 1077 1018 972 944 891 829 929 886 823 849 882 885 858 873 917 885 964 996 966 1048 1010 1033 1026 951 975 929 884 829 837 893 869 895 869 854 865 881 856 858 846 896 857 823 884 874 932 936 917 995 1104 1271 1282 1410 1381 1313 1195 1137 1021 906 883 858 915 858 818 838 783 807 848 801 817 784 800 812 838 837 792 828 786 827 802 883 844 804 838 848 841 903 819 896 866 897 908 844 846 910 888 864 862 864 894 873 882 853 900 942 956 1063 1149 1101 1196 1055 1020 943 938 847 811 868 872 841 925 955 974 1059 1045 1117 1063 1029 961 908 874 927 815 873 849 829 841 796 917 865 887 964 974 963 929 943 934 940 940 995 949 1009 977 1044 1009 1073 1045 1050 1040 1050 1090 1033 1032 987 952 959 932 886 969 982 1043 972 986 992 948 994 1009 972 997 1066 1034 962 910 917 989 945 932 939 908 895 905 883 865 833 909 871 821 891 799 916 987 1066 1121 1207 1024 1125 994 976 896 882 923 942 928 830 827 893 896 785 835 868 835 874 850 887 897 897 897 973 946 937 958 1024 1093 1186 1224 1289 1278 1233 1135 1067 1083 973 965 956 944 937 982 914 942 853 855 887 936 929 944 970 994 953 908 918 809 920 858 838 878 777 832 857 821 888 859 898 789 862 861 849 882 819 803 792 823 765 769 835 841 812 837 828 819 831 843 854 884 838 831 890 891 851 846 869 953 860 938 931 999 1054 1116 1167 1179 1094 1113 1070 1031 980 901 1012 904 890 875 831 897 881 881 863 891 821 833 844 839 831 862 823 760 818 818 836 805 812 821 838 830 828 786 854 830 853 922 880 939 870 946 951 870 840 864 870 899 843 955 858 898 866 886 892 901 889 937 998 1038 1057 1003 967 961 981 905 925 905 920 847 840 851 875 927 806 871 861 862 797 859 833 837 869 840 907 912 913 938 974 895 916 966 918 953 970 1006 1047 1112 1225 1310 1266 1151 1103 1093 1051 956 997 1017 1048 1138 1188 1262 1290 1244 1273 1283 1150 1067 1031 960 980 914 895 866 870 870 795 839 820 867 855 826 855 850 892 870 870 884 885 876 964 883 902 841 855 849 895 822 835 899 899 881 926 922 873 947 905 937 886 960 944 946 954 997 1034 1147 1160 1212 1185 1286 1357 1446 1413 1277 1241 1065 1097 979 955 1031 1027 1036 1058 1037 1048 906 949 900 847 861 780 780 803 845 867 830 834 855 898 902 861 863 849 909 890 946 951 1006 1133 1128 1210 1177 1179 1313 1200 1283 1344 1403 1426 1468 1365 1261 1194 1086 968 965 965 970 924 959 985 922 940 912 933 993 953 895 944 933 902 870 908 856 851 845 850 893 893 825 850 847 879 890 922 932 909 887 928 857 910 832 840 909 930 913 913 923 936 947 970 1069 1087 1235 1216 1293 1317 1209 1131 1155 1119 1218 1190 1428 1578 1663 1596 1558 1409 1186 1155 1096 1112 1138 1115 1181 1194 1207 1182 1153 1172 1063 1143 1119 1057 1030 949 988 905 917 876 908 877 867 877 913 1003 967 999 997 1041 1081 1063 1112 1028 1002 949 1063 1037 1002 1026 1065 990 974 989 939 objcryst-2022.1/Fox/example/tutorial-cimetidine/cime.fhz000066400000000000000000000007741430515525000232370ustar00rootroot00000000000000KEYWORDS GO HERE 17 C 1 N 1 1.465 C 2 1.366 1 119.987 N 3 1.321 2 120.030 1 6.0 C 4 1.355 3 119.982 2 6.8 N 5 1.136 4 180.000 3 46.3 N 3 1.366 2 120.022 1 186.0 C 7 1.466 3 119.988 2 354.9 C 8 1.529 7 109.482 3 185.0 S 9 1.814 8 109.456 7 180.0 C 10 1.815 9 99.984 8 180.0 C 11 1.507 10 109.466 9 180.0 N 12 1.341 11 126.014 10 90.0 C 13 1.305 12 109.239 11 180.0 N 14 1.349 13 108.723 12 360.0 C 15 1.344 14 107.593 13 359.1 C 16 1.515 15 127.952 14 179.1 objcryst-2022.1/Fox/example/tutorial-cimetidine/cime.pdb000066400000000000000000000105471430515525000232140ustar00rootroot00000000000000HEADER NONAME 16-Apr-00 NONE 1 TITLE NONE 2 AUTHOR SVR4 nobody uid NONE 3 REVDAT 1 16-Apr-00 0 NONE 4 ATOM 1 C 0 -5.282 -1.101 1.291 0.00 0.00 C+0 ATOM 2 N 0 -3.941 -0.740 0.825 0.00 0.00 N+0 ATOM 3 C 0 -3.792 0.071 -0.264 0.00 0.00 C+0 ATOM 4 N 0 -4.852 0.625 -0.826 0.00 0.00 N+0 ATOM 5 C 0 -6.069 0.503 -0.243 0.00 0.00 C+0 ATOM 6 N 0 -7.089 0.401 0.247 0.00 0.00 N+0 ATOM 7 N 0 -2.547 0.310 -0.773 0.00 0.00 N+0 ATOM 8 C 0 -1.362 -0.212 -0.086 0.00 0.00 C+0 ATOM 9 C 0 -0.101 0.297 -0.786 0.00 0.00 C+0 ATOM 10 S 0 1.365 -0.349 0.065 0.00 0.00 S+0 ATOM 11 C 0 2.672 0.395 -0.951 0.00 0.00 C+0 ATOM 12 C 0 4.019 -0.016 -0.416 0.00 0.00 C+0 ATOM 13 N 0 4.716 -1.101 -0.784 0.00 0.00 N+0 ATOM 14 C 0 5.836 -1.140 -0.115 0.00 0.00 C+0 ATOM 15 N 0 5.887 -0.071 0.707 0.00 0.00 N+0 ATOM 16 H 0 6.607 0.151 1.319 0.00 0.00 H+0 ATOM 17 C 0 4.767 0.645 0.512 0.00 0.00 C+0 ATOM 18 C 0 4.345 1.923 1.208 0.00 0.00 C+0 ATOM 19 H 0 -5.849 -1.532 0.467 0.00 0.00 H+0 ATOM 20 H 0 -5.202 -1.830 2.098 0.00 0.00 H+0 ATOM 21 H 0 -5.792 -0.210 1.656 0.00 0.00 H+0 ATOM 22 H 0 -3.159 -1.076 1.290 0.00 0.00 H+0 ATOM 23 H 0 -2.446 0.825 -1.588 0.00 0.00 H+0 ATOM 24 H 0 -1.365 0.127 0.950 0.00 0.00 H+0 ATOM 25 H 0 -1.378 -1.301 -0.112 0.00 0.00 H+0 ATOM 26 H 0 -0.099 -0.041 -1.822 0.00 0.00 H+0 ATOM 27 H 0 -0.086 1.387 -0.760 0.00 0.00 H+0 ATOM 28 H 0 2.570 0.053 -1.981 0.00 0.00 H+0 ATOM 29 H 0 2.583 1.481 -0.918 0.00 0.00 H+0 ATOM 30 H 0 6.596 -1.902 -0.205 0.00 0.00 H+0 ATOM 31 H 0 4.715 2.776 0.639 0.00 0.00 H+0 ATOM 32 H 0 3.259 1.979 1.282 0.00 0.00 H+0 ATOM 33 H 0 4.778 1.939 2.209 0.00 0.00 H+0 CONECT 1 2 19 20 21 NONE 38 CONECT 2 1 3 22 0 NONE 39 CONECT 3 2 4 7 0 NONE 40 CONECT 4 3 5 0 0 NONE 41 CONECT 5 4 6 0 0 NONE 42 CONECT 6 5 0 0 0 NONE 43 CONECT 7 3 8 23 0 NONE 44 CONECT 8 7 9 24 25 NONE 45 CONECT 9 8 10 26 27 NONE 46 CONECT 10 9 11 0 0 NONE 47 CONECT 11 10 12 28 29 NONE 48 CONECT 12 11 13 17 0 NONE 49 CONECT 13 12 14 0 0 NONE 50 CONECT 14 13 15 30 0 NONE 51 CONECT 15 14 16 17 0 NONE 52 CONECT 17 15 12 18 0 NONE 53 CONECT 18 17 31 32 33 NONE 54 END NONE 55 objcryst-2022.1/Fox/example/tutorial-cimetidine/test.xml000066400000000000000000000224071430515525000233070ustar00rootroot00000000000000 10.394 18.819 6.825 90 106.44 90 objcryst-2022.1/Fox/example/tutorial-pbso4/000077500000000000000000000000001430515525000205165ustar00rootroot00000000000000objcryst-2022.1/Fox/example/tutorial-pbso4/neutron.dat000066400000000000000000000427561430515525000227200ustar00rootroot0000000000000010.000 0.050 155.95 PbSO4 D1A(ILL)(Rietveld Refinement Round Robin,R.J. Hill,JApC 25,589) 220 214 219 224 198 229 224 216 202 229 202 215 215 196 235 207 205 238 202 213 226 198 222 186 216 218 225 200 196 224 199 204 189 211 190 184 204 204 219 207 227 211 193 206 208 191 194 185 200 203 197 203 200 200 205 208 205 201 221 218 218 216 202 206 197 210 199 219 192 211 199 196 195 203 202 200 199 191 204 191 200 199 197 202 210 202 198 191 194 198 194 193 212 214 197 195 205 209 203 197 191 192 215 194 189 188 202 201 198 208 197 187 187 190 197 200 193 180 194 206 195 193 205 194 196 194 199 207 188 203 188 180 198 200 201 210 206 189 194 187 195 201 197 206 208 199 192 193 204 201 200 177 193 199 201 194 184 192 199 190 183 189 196 196 198 210 212 219 198 195 198 191 193 197 194 187 209 187 198 206 197 191 200 207 205 198 196 209 211 203 200 192 208 213 221 216 226 228 228 215 224 226 213 239 250 247 240 231 236 223 231 226 214 208 214 196 204 199 186 192 199 200 184 184 189 182 184 185 195 190 194 185 183 193 194 193 188 191 189 188 201 195 205 200 200 192 197 204 207 192 201 190 195 194 182 189 196 196 200 190 183 199 187 196 191 191 195 194 192 182 188 203 187 192 206 201 184 192 205 196 193 194 195 194 201 193 176 187 188 196 192 185 195 198 205 200 208 195 187 193 197 202 193 196 202 201 197 204 208 206 212 207 207 212 216 218 221 218 207 203 204 202 206 202 202 181 193 205 198 196 197 195 201 205 195 196 196 205 198 200 199 180 187 193 197 197 196 194 197 204 201 187 191 205 200 198 200 204 196 195 194 200 198 201 208 205 211 211 220 220 212 208 214 226 235 233 237 242 242 245 239 226 232 238 226 218 218 214 205 200 193 195 196 195 207 215 207 218 218 220 220 229 236 254 264 280 289 289 303 302 297 281 278 280 265 258 243 240 232 231 233 246 248 249 256 272 289 311 340 363 393 440 474 482 492 508 494 475 439 413 368 331 299 286 262 241 238 252 267 276 278 300 325 336 359 405 458 501 564 640 719 783 837 851 866 828 763 697 634 541 465 391 351 301 284 260 248 257 242 246 263 271 281 302 309 335 342 345 356 351 341 334 321 286 268 256 238 229 218 223 216 203 203 194 205 196 193 206 201 201 201 200 194 196 203 195 196 211 216 207 215 221 237 248 261 279 319 337 364 423 489 557 630 729 822 943 1059 1196 1235 1220 1209 1128 1001 864 729 601 496 418 355 313 263 246 226 214 222 222 211 211 202 198 192 193 196 201 203 203 201 198 196 206 210 197 204 200 205 196 195 205 204 200 203 208 207 202 203 198 204 210 216 210 229 239 247 278 302 324 371 420 465 538 630 739 851 976 1076 1161 1222 1227 1187 1096 964 833 708 587 512 436 391 384 370 391 419 448 490 567 626 687 735 780 782 745 721 662 595 527 446 393 335 301 276 251 242 229 209 215 218 214 209 208 212 210 209 210 205 209 211 211 216 205 204 202 201 200 207 205 202 209 202 203 206 206 200 194 199 204 205 210 207 205 210 204 203 202 205 201 201 207 197 198 203 209 209 208 204 209 199 204 206 201 205 202 204 198 198 213 210 212 214 215 217 210 214 215 215 215 217 222 231 247 252 273 304 332 366 408 463 532 619 734 828 944 1003 1055 1070 1018 944 833 725 633 507 445 379 347 316 282 267 269 281 288 300 327 346 380 400 430 453 459 451 427 402 375 344 309 277 265 246 246 230 223 227 225 217 217 223 223 220 223 226 248 258 274 297 324 355 393 458 528 589 688 781 840 876 874 832 765 682 613 524 455 408 384 366 375 392 426 470 519 588 639 681 704 693 650 600 540 478 412 376 345 330 337 350 383 426 493 571 676 803 920 1071 1183 1247 1255 1251 1183 1068 945 861 811 813 872 969 1120 1309 1527 1706 1856 1888 1837 1713 1500 1289 1103 904 749 627 568 551 560 586 634 691 751 799 792 820 774 736 680 627 562 514 459 424 362 333 318 300 287 265 266 262 263 255 270 278 289 317 343 400 468 561 695 873 1100 1372 1660 1954 2224 2400 2459 2435 2245 1986 1671 1358 1086 868 682 578 521 512 537 600 704 855 1032 1232 1466 1693 1866 1966 2024 2016 1846 1667 1429 1179 950 763 599 484 404 351 304 284 273 259 251 251 252 245 259 250 253 256 264 285 301 346 390 458 528 624 733 829 916 988 994 929 843 742 638 527 434 377 320 282 273 256 243 240 240 230 220 230 227 224 219 227 227 224 222 223 217 213 216 219 219 218 220 220 220 223 233 237 249 258 261 283 304 324 347 353 359 363 352 341 330 308 291 271 254 245 245 239 228 217 217 218 223 207 218 222 215 210 216 213 212 215 212 214 211 214 217 205 207 213 208 211 205 214 213 212 212 213 207 203 211 211 214 214 207 203 212 212 214 213 202 210 211 211 214 221 217 212 214 219 223 225 227 235 240 243 252 249 249 255 262 282 308 351 398 470 525 596 646 681 665 615 563 484 421 364 317 289 261 245 233 228 219 219 217 216 221 215 215 210 212 212 204 209 206 216 207 214 207 209 218 215 222 226 230 239 249 263 275 292 317 323 341 350 330 320 307 284 275 265 269 275 292 311 338 387 413 463 510 534 559 539 533 500 471 455 410 373 342 307 288 286 281 292 291 312 326 336 346 341 327 305 277 267 249 229 221 220 217 211 204 203 220 217 217 214 205 205 211 206 208 201 208 214 212 206 216 219 215 217 211 214 215 224 217 215 218 218 228 227 228 225 219 216 219 218 214 212 221 214 208 204 209 209 208 212 213 218 212 205 207 204 206 211 216 214 210 219 222 224 231 227 237 235 238 245 242 248 246 243 253 259 278 281 297 310 324 322 311 295 281 259 250 239 233 227 226 223 211 209 217 214 213 217 220 210 209 215 218 215 217 221 217 219 220 228 229 230 234 251 261 288 313 362 424 524 646 781 920 1024 1120 1187 1187 1166 1114 1044 991 927 823 717 619 520 421 353 308 273 256 245 234 230 224 232 226 222 222 227 225 226 227 229 235 233 243 238 237 236 232 231 227 225 220 218 215 219 224 225 222 231 243 250 269 286 310 325 332 337 329 303 278 268 252 236 228 219 225 222 214 228 221 217 221 222 226 237 246 255 269 284 302 313 327 321 333 331 332 358 402 460 557 660 769 859 934 955 921 824 694 578 474 402 344 306 300 292 292 302 304 306 305 303 299 278 259 257 245 237 240 233 232 235 241 257 274 292 309 333 360 381 387 387 386 382 368 363 352 337 321 297 281 265 255 251 237 238 237 228 240 234 226 229 228 233 243 241 257 279 305 345 410 455 545 622 673 725 717 661 592 518 443 371 336 290 265 252 250 244 242 241 243 248 253 252 264 266 282 291 313 346 374 415 430 433 430 406 384 349 318 307 298 296 304 313 328 346 341 335 324 336 341 341 370 414 442 490 520 532 548 561 567 585 584 558 527 481 424 370 333 312 301 307 314 340 379 427 467 535 584 602 580 532 481 426 379 329 303 288 271 269 267 263 267 260 260 263 263 270 278 293 318 364 424 512 643 817 982 1163 1289 1373 1393 1348 1244 1157 1077 1020 965 907 858 771 647 555 468 405 348 316 291 277 278 270 262 268 270 279 287 300 319 347 378 420 469 536 645 773 925 1115 1254 1367 1400 1327 1188 1038 879 738 644 594 601 643 697 786 842 847 791 702 592 508 418 362 328 299 279 270 257 253 258 257 249 245 257 260 284 296 322 343 382 405 411 416 406 372 353 330 317 313 312 309 303 288 276 264 246 249 241 251 243 246 246 249 244 252 252 258 265 263 284 299 320 344 363 372 358 351 354 330 322 334 339 345 357 360 358 372 425 511 626 770 946 1118 1205 1227 1157 1041 873 715 562 446 377 332 297 282 276 264 261 266 261 253 258 262 260 283 307 344 402 453 529 604 661 672 629 588 510 440 377 330 301 280 269 258 252 251 252 256 253 253 253 262 265 284 291 323 374 431 511 602 678 743 756 717 657 581 490 418 364 335 306 290 286 283 283 274 262 266 261 261 264 269 278 288 306 319 330 343 341 325 318 298 299 288 309 344 382 422 470 512 514 515 488 440 396 366 332 311 305 300 293 286 306 313 317 327 343 330 320 307 298 282 274 266 274 271 274 290 302 321 350 367 386 394 370 356 332 310 288 279 281 274 284 280 270 278 269 273 268 267 265 257 258 267 267 277 287 302 332 360 411 457 524 608 699 861 1096 1377 1685 1901 2069 2016 1800 1500 1181 937 728 629 576 556 535 519 486 465 429 385 361 342 312 293 279 277 265 257 256 250 260 261 258 263 268 284 306 325 337 337 344 340 337 328 321 306 295 289 281 267 266 270 263 256 266 264 259 261 261 258 253 248 244 249 251 245 245 247 247 254 259 250 251 258 252 255 259 256 264 268 281 303 331 371 420 484 532 576 582 563 527 490 465 467 449 416 393 366 331 316 297 294 292 286 295 306 315 334 373 406 447 499 507 506 488 432 391 342 315 292 275 274 259 250 258 252 255 254 253 254 252 257 250 255 251 254 260 249 253 254 259 268 270 284 305 322 364 417 470 573 678 771 847 854 794 720 611 520 463 412 399 416 428 432 420 402 364 348 334 321 330 342 380 385 420 441 465 444 406 383 345 332 321 308 292 303 314 333 379 438 505 594 659 717 738 710 642 547 492 421 386 344 337 350 364 415 506 586 674 750 787 753 682 597 499 417 362 340 302 286 280 283 276 282 284 295 310 319 321 304 298 293 283 277 269 265 277 283 283 293 303 320 316 331 346 327 328 306 291 286 278 273 267 272 257 260 265 264 272 270 268 269 287 292 295 317 335 364 410 477 556 642 755 864 946 970 941 870 759 647 540 468 418 379 381 405 446 476 523 561 555 529 485 436 398 355 322 304 285 270 278 260 268 264 265 263 267 286 293 291 319 366 411 461 489 521 555 550 511 486 436 392 368 330 328 343 371 394 441 468 469 456 416 394 361 330 312 293 285 286 275 274 281 279 298 312 331 375 406 452 506 546 568 589 588 537 498 463 402 386 361 350 330 338 359 364 385 436 474 544 647 695 763 802 812 756 669 606 527 452 409 376 368 391 400 444 481 518 556 577 575 557 552 562 592 596 583 552 512 482 439 385 342 316 300 287 279 267 269 269 271 261 261 265 252 260 263 265 260 274 267 271 274 269 264 277 272 277 282 290 293 294 300 325 348 382 412 466 513 562 585 608 619 594 567 526 518 501 480 470 465 469 458 438 448 470 470 500 505 519 517 517 502 460 410 375 347 347 318 310 302 311 326 320 334 374 444 484 561 647 699 747 767 749 723 664 619 578 553 541 530 530 525 517 493 482 456 423 383 380 343 326 314 302 303 290 290 293 277 286 309 327 357 396 468 529 590 649 699 720 705 672 635 604 564 548 537 564 588 611 636 636 606 600 560 512 473 453 428 390 393 401 395 440 479 549 618 675 746 803 805 788 748 671 621 544 460 421 384 343 321 298 278 287 280 268 281 272 287 282 284 300 303 309 322 340 347 370 401 420 451 491 508 530 531 522 484 468 427 379 365 344 321 294 291 284 264 281 261 256 261 266 264 258 262 250 261 257 253 247 259 259 256 253 256 257 261 246 247 250 270 254 245 254 274 272 253 260 272 265 267 276 280 289 318 331 366 386 426 461 495 532 591 627 616 634 668 645 620 607 560 518 470 445 398 376 336 325 301 303 275 273 288 278 274 273 260 268 276 276 294 293 277 292 284 273 291 287 303 306 315 333 367 387 404 440 480 533 601 620 647 663 652 665 630 628 577 520 472 453 413 412 396 361 370 402 389 423 452 469 498 535 538 564 572 585 574 543 495 484 460 428 375 341 340 312 309 288 271 273 267 255 266 261 269 257 249 245 259 258 259 268 279 256 259 287 269 281 268 277 278 287 277 285 284 278 288 279 287 289 308 308 288 302 295 301 303 294 287 279 279 276 275 264 274 269 269 268 261 256 284 279 280 296 297 296 308 301 300 297 300 289 290 274 275 264 262 249 251 248 252 249 249 262 251 239 263 265 240 236 250 248 248 254 262 252 246 250 251 247 248 254 236 251 247 254 248 259 259 274 263 287 283 281 296 292 323 330 339 358 349 365 399 406 428 413 439 418 425 411 417 391 393 386 359 381 363 364 375 379 392 402 436 451 463 452 449 479 485 484 472 508 518 523 561 559 573 545 561 568 573 562 573 565 499 496 488 449 442 391 387 390 359 338 321 322 327 338 306 290 320 308 300 307 306 314 318 298 313 303 302 333 285 312 312 285 290 288 294 314 300 306 293 299 328 325 328 317 292 321 291 302 291 297 301 270 262 277 258 258 243 269 257 257 240 282 245 243 260 255 275 255 270 286 271 258 309 299 297 304 319 314 290 338 316 341 384 360 367 383 366 369 363 332 325 334 373 336 313 339 325 307 277 286 305 277 262 262 241 251 260 245 249 260 256 242 258 248 235 245 248 281 228 230 212 237 244 231 266 231 234 247 264 247 261 223 242 271 247 249 251 232 225 255 209 266 255 273 250 234 257 250 270 262 281 257 260 257 242 255 250 274 288 275 277 278 264 298 312 282 314 341 314 295 326 347 336 444 393 375 425 413 415 450 326 objcryst-2022.1/Fox/example/tutorial-pbso4/xray.dat000066400000000000000000001370601430515525000222020ustar00rootroot0000000000000010.000 0.025 160.000 PbSO4 XrayDif (Rietveld Round Robin, R.J. Hill, JApC 2 179 147 165 172 150 165 150 158 134 146 167 159 139 145 165 150 149 156 143 166 154 131 144 131 140 147 155 148 140 138 127 146 147 114 129 129 128 136 148 132 141 135 141 145 131 142 148 151 127 133 131 125 129 128 134 142 115 138 125 120 130 118 118 116 119 101 117 142 112 114 111 122 131 107 121 123 120 126 125 120 103 121 109 115 122 123 107 126 133 120 100 130 130 109 116 121 99 107 110 136 113 102 117 111 105 92 110 116 124 111 91 106 122 121 119 114 129 95 117 102 102 117 99 124 107 108 99 113 104 92 98 107 88 96 104 81 111 78 104 119 106 105 96 81 95 96 103 91 112 107 87 112 92 79 92 103 97 102 86 97 103 93 111 95 96 93 85 104 98 108 76 92 95 89 105 95 92 105 89 99 101 97 93 99 100 83 93 96 69 101 97 85 95 85 111 85 86 100 88 98 92 93 94 93 81 98 78 79 93 81 88 73 85 106 88 94 96 91 101 89 87 95 87 97 81 87 93 90 73 98 86 80 82 97 80 81 80 81 73 106 92 101 98 104 106 98 114 97 129 112 141 167 157 200 215 321 397 434 445 313 197 155 110 118 86 110 95 93 98 80 85 106 86 103 92 88 94 79 92 106 82 104 94 88 97 93 90 120 93 106 89 92 100 91 99 81 89 79 91 84 92 107 99 92 87 88 67 81 86 85 103 85 77 105 93 96 93 85 75 105 85 89 86 76 86 71 101 100 89 74 101 103 95 100 87 94 84 102 92 80 82 105 84 83 93 92 105 94 88 97 88 110 110 84 89 98 92 86 110 98 93 94 104 96 105 99 117 111 100 125 99 107 107 98 84 112 99 93 108 100 91 98 124 98 121 114 93 87 95 95 121 102 127 119 118 107 100 95 116 136 92 127 127 115 124 130 123 137 136 165 150 173 190 211 212 255 264 305 353 415 507 623 833 1076 1417 1958 2624 3927 5466 7996 11062 12925 12506 10327 8178 6771 5910 4886 3432 2110 1182 802 623 527 435 393 356 333 295 316 280 248 264 216 202 211 187 168 208 160 171 149 166 138 168 129 147 134 125 137 112 128 134 121 138 103 124 115 119 109 119 116 127 133 121 109 114 113 120 118 102 110 118 123 116 112 107 121 104 124 105 128 115 128 99 130 109 125 138 141 135 125 140 152 177 177 191 195 225 258 301 337 468 618 837 1082 1507 2283 3235 4791 6588 8176 8122 6687 5078 3206 1822 1101 712 566 470 381 302 277 259 259 212 198 189 153 182 178 175 164 139 176 159 147 172 167 159 180 168 162 166 147 149 161 173 145 210 201 257 262 342 451 598 796 1089 1648 2386 3203 3155 2711 1970 1292 729 450 289 285 218 211 202 168 165 177 176 197 164 141 160 160 157 145 165 158 158 197 179 203 194 216 282 282 364 456 632 854 1213 1815 2863 4063 4649 4165 3168 2329 1423 738 438 367 295 246 246 191 179 178 170 182 158 182 179 184 181 169 171 191 175 216 195 224 209 251 257 298 297 378 406 499 590 746 983 1402 2108 3097 4641 7229 10690 13494 13106 10401 7908 5365 2857 1575 947 697 595 529 450 423 344 319 309 252 257 252 266 275 257 285 285 270 280 347 282 362 426 461 637 693 1051 1425 2158 3198 5190 8004 10350 9724 7797 6126 4329 2276 1177 756 591 486 352 340 314 270 256 253 245 206 212 183 205 185 164 197 167 175 159 152 162 168 151 153 128 167 147 140 139 153 153 154 145 147 134 160 137 134 131 157 137 145 151 164 171 172 165 168 162 193 169 199 186 208 196 182 246 245 284 340 364 382 519 665 837 1080 1566 2321 3438 5181 8141 12608 15702 14432 12071 9687 7137 4123 2094 1334 1013 780 668 467 438 379 355 263 287 299 247 253 236 223 193 198 184 204 185 174 201 168 185 175 171 153 162 135 159 139 147 127 143 140 115 142 123 156 133 135 128 130 127 120 121 106 134 114 107 123 111 92 134 87 130 97 101 113 119 122 114 117 84 105 111 104 119 119 101 117 122 105 128 116 126 115 121 116 144 141 128 148 165 172 182 174 193 230 247 312 325 423 589 755 1130 1670 2522 3976 5312 5540 4806 3984 3579 2684 1672 977 645 451 390 317 305 278 234 264 246 263 239 271 260 299 300 332 411 497 630 918 1214 1839 2852 4745 6636 7831 7010 5926 5069 4251 2900 1743 1167 841 646 517 412 354 301 282 234 204 235 226 207 200 180 180 179 172 180 157 154 173 198 147 168 157 199 209 242 257 328 467 631 994 1449 1522 1193 977 947 796 548 358 251 190 164 159 137 134 136 126 122 128 108 100 120 106 123 117 113 108 121 104 104 100 105 107 108 103 108 123 92 122 97 101 92 114 89 81 113 76 89 99 89 98 98 104 120 100 99 89 111 98 96 95 84 115 106 100 86 110 86 98 97 109 112 105 86 102 91 98 111 89 95 95 84 114 108 96 94 94 102 91 106 103 82 121 101 109 112 104 103 105 112 119 116 119 115 106 122 116 120 130 107 137 132 131 140 150 149 161 190 210 234 297 378 583 909 1431 2164 2620 2390 1970 1772 1685 1327 891 543 352 292 230 177 182 207 158 143 129 161 133 119 120 128 118 121 132 135 134 132 135 156 182 207 266 351 368 312 269 260 249 219 174 157 146 135 137 136 103 107 99 133 129 147 130 115 123 109 106 115 136 119 126 131 135 116 112 123 116 121 136 147 130 156 138 133 144 163 171 198 191 196 226 243 294 352 472 630 984 1383 2157 2946 2947 2469 1988 2056 1767 1317 793 524 362 282 264 227 186 194 168 177 199 174 169 183 194 204 189 213 296 350 476 746 894 816 615 549 596 524 395 306 223 164 206 198 162 173 163 144 169 160 156 143 187 146 146 157 177 173 171 197 214 254 333 505 760 1047 1074 910 689 698 717 570 382 273 291 231 278 239 272 257 316 315 377 419 593 709 1116 1749 2604 3739 4133 3642 2835 2622 2580 2147 1381 844 578 447 351 339 309 260 268 240 250 233 275 281 285 381 450 601 801 895 881 726 644 608 589 498 386 283 277 254 276 249 224 213 196 234 186 215 191 211 189 204 193 227 221 225 199 187 193 214 235 241 232 239 254 252 264 251 260 320 375 379 442 425 492 574 693 816 1046 1286 1773 2593 4047 6544 9907 12440 12196 9815 8006 7742 7431 5975 3773 2148 1465 1080 849 683 579 560 480 481 470 468 450 469 498 468 528 615 632 765 985 1263 1833 2821 4290 5647 5682 5372 5802 7664 7744 5866 4103 3552 3442 2855 1843 1102 771 578 517 456 381 379 335 326 303 286 287 274 272 282 267 236 255 238 218 224 209 228 244 234 221 237 224 217 187 261 216 246 244 282 276 314 333 385 413 609 855 1397 2190 3180 3151 2427 1819 1843 2058 1720 1115 716 480 364 297 300 267 227 215 189 213 174 175 193 183 178 166 171 171 172 161 151 143 141 139 172 153 169 141 125 135 142 134 142 138 152 159 140 143 136 147 144 148 153 112 148 138 119 121 160 136 164 137 166 142 158 176 175 183 249 309 389 541 720 682 600 452 443 453 437 329 289 226 201 182 160 178 146 181 142 201 182 174 168 174 233 275 331 464 712 969 1093 984 752 624 651 695 597 460 284 261 211 196 175 167 165 143 153 155 137 161 131 138 125 114 154 114 118 120 130 117 126 132 122 133 122 113 128 139 126 140 120 122 122 136 116 113 103 120 129 112 118 140 135 101 128 115 126 120 119 107 122 124 123 159 132 136 115 142 132 144 140 131 112 147 129 129 106 129 127 122 155 130 121 131 173 157 146 153 168 199 204 212 232 255 319 410 629 1090 1814 2668 2463 1752 1187 1257 1542 1549 1066 624 387 314 267 208 211 210 181 170 154 155 143 171 156 134 142 142 136 139 139 132 152 123 137 125 132 133 137 148 121 150 139 127 127 146 147 155 131 144 148 138 149 154 142 141 181 185 169 181 203 236 232 335 428 600 826 1143 1282 1262 1070 962 964 871 886 728 557 468 370 267 235 203 187 181 188 189 166 167 175 191 184 181 226 228 258 216 233 250 287 332 441 506 459 447 383 372 397 408 434 419 346 392 441 622 912 1096 1359 1605 1949 1937 1843 2020 1980 1741 1467 1209 1080 998 719 548 393 314 277 248 204 179 180 168 160 170 160 184 179 164 149 156 140 161 149 134 126 143 138 142 163 131 161 131 147 150 160 128 126 128 152 134 158 135 162 157 173 156 162 158 164 155 194 195 196 253 262 350 464 665 937 1141 1055 834 657 648 638 752 672 543 404 370 386 469 560 465 360 285 276 355 364 291 228 190 194 195 180 163 154 156 184 181 152 176 177 160 178 185 175 206 214 244 255 254 373 514 623 827 875 884 951 1181 1887 2582 2875 2303 1613 1270 1312 1510 1599 1288 890 794 643 683 884 1207 1571 1762 1506 1186 969 975 1015 1048 938 733 494 392 292 276 254 229 216 203 194 189 192 181 191 163 175 186 149 175 142 180 136 151 177 156 159 174 148 147 141 145 156 144 149 145 127 143 159 129 161 138 145 165 172 184 217 266 272 313 288 275 321 323 439 573 743 906 960 812 566 541 535 554 567 599 473 359 290 254 189 184 196 210 190 179 148 160 147 122 148 141 140 142 114 150 151 132 153 140 118 128 140 136 122 130 135 133 165 160 163 166 190 264 331 334 297 215 205 212 268 226 256 199 165 148 159 132 154 139 121 144 131 136 139 120 129 130 143 127 150 156 154 153 162 208 247 207 192 179 148 154 204 186 208 175 141 111 124 132 127 125 124 147 143 135 136 143 145 143 148 151 139 142 135 161 143 139 136 158 164 167 165 181 147 160 195 209 190 226 195 241 278 302 344 427 563 789 990 1317 1792 2342 2479 2083 1541 1233 1186 1301 1408 1348 1086 761 509 405 349 309 273 269 244 252 286 309 289 316 317 259 228 223 259 237 212 212 201 184 201 170 165 182 182 183 199 200 208 190 185 230 275 352 448 647 956 1241 1280 1063 730 559 576 678 833 919 838 736 578 449 352 332 306 308 321 300 245 216 201 182 162 147 163 193 149 171 166 202 155 141 162 155 166 190 174 189 211 169 195 197 235 250 286 344 394 561 722 930 1317 1481 1358 1037 813 746 717 877 916 896 663 502 396 302 255 280 238 238 233 267 258 267 346 468 667 897 976 870 617 478 483 485 541 636 625 465 354 276 231 232 190 216 192 191 172 178 212 172 174 183 142 176 174 159 196 194 202 246 258 272 227 206 220 234 235 252 241 246 280 326 391 456 640 670 639 521 515 493 632 854 1153 1468 1384 1196 879 770 660 705 773 815 766 626 469 409 338 280 267 303 290 315 308 375 471 637 830 1073 1024 833 639 528 502 569 667 732 600 516 444 417 430 431 409 399 319 289 333 368 368 375 332 257 253 244 250 251 239 260 202 234 236 222 268 246 261 301 352 434 507 687 891 929 869 744 766 883 1213 1390 1383 1276 1228 1172 1129 970 905 839 745 632 628 600 552 393 307 265 275 215 233 208 186 180 200 182 178 170 180 177 190 173 203 200 185 218 207 244 220 243 266 280 324 394 567 690 853 934 815 877 894 888 744 665 674 693 634 583 589 572 455 501 497 637 833 1120 968 776 526 397 372 472 548 682 632 479 341 304 211 213 199 185 190 194 183 193 204 201 264 298 373 364 306 270 271 259 298 371 433 565 625 581 460 365 291 270 311 317 411 435 426 481 415 358 268 245 239 204 246 236 272 241 203 182 189 163 165 161 145 149 163 166 138 141 158 145 131 135 147 133 140 144 155 157 196 193 175 172 174 148 164 177 183 250 310 439 401 356 276 178 216 209 222 263 281 270 217 181 183 174 171 151 142 130 147 146 148 124 129 128 135 143 135 145 134 131 154 135 139 155 143 151 154 160 141 160 155 171 166 159 187 205 212 230 313 346 402 511 535 696 717 624 520 421 399 344 380 468 482 453 373 267 229 209 176 193 210 179 173 207 225 265 315 289 229 197 204 221 249 258 290 401 434 421 368 358 396 462 547 580 497 442 397 313 316 296 341 355 373 333 274 262 290 329 333 356 280 237 214 238 243 204 239 255 249 226 191 222 193 236 264 308 340 330 282 229 235 204 203 252 249 232 222 217 226 222 238 265 341 339 338 302 275 242 218 232 297 360 399 423 365 273 254 262 216 316 339 402 509 598 700 742 619 470 398 379 352 351 379 443 466 438 357 289 258 233 216 241 235 277 309 358 356 323 273 243 224 243 250 220 267 291 282 252 255 328 357 411 375 323 267 240 208 209 236 248 261 256 244 203 173 170 174 168 167 181 159 195 168 180 186 175 191 213 274 266 323 421 552 799 1129 1277 1123 820 610 504 408 478 543 708 817 736 641 568 413 433 373 314 321 244 262 251 232 241 216 240 212 196 173 187 175 173 152 163 143 135 122 139 128 134 140 117 150 134 152 127 170 158 155 173 161 136 128 177 165 140 154 143 168 189 130 160 151 182 221 238 260 315 327 311 246 211 204 196 211 191 234 225 255 200 186 186 162 140 153 147 143 153 154 133 145 148 165 155 155 147 176 149 165 136 163 163 198 215 249 304 377 414 339 322 284 301 311 380 550 624 660 617 461 363 284 266 268 289 340 375 363 327 259 216 172 180 208 177 157 189 192 222 222 188 184 164 173 182 153 158 158 183 190 178 169 145 170 138 169 133 134 122 126 153 112 125 127 147 125 125 142 143 138 145 166 165 156 154 169 130 173 155 178 211 247 289 310 276 303 376 468 665 803 829 683 570 507 383 335 352 412 522 575 652 681 634 466 368 301 214 226 205 239 226 271 279 280 247 223 201 199 198 206 191 154 174 144 155 161 172 178 192 155 171 155 160 138 156 178 163 191 200 208 186 167 183 157 148 163 174 187 182 189 190 190 199 240 247 334 391 512 618 663 593 456 395 343 288 292 310 392 389 437 361 351 262 250 233 197 195 171 174 171 159 158 120 128 140 148 156 133 156 144 163 158 158 154 165 196 206 256 278 255 253 223 190 196 176 171 212 204 252 224 192 180 172 166 159 155 148 167 137 178 161 180 156 169 178 174 181 172 238 209 240 343 384 500 673 704 763 656 551 406 354 352 301 357 414 440 502 459 425 378 418 427 467 441 400 327 278 259 240 213 206 241 263 287 291 245 243 198 195 195 164 178 161 161 183 177 177 177 192 219 260 310 337 312 290 275 243 192 200 212 205 180 219 274 271 200 205 195 179 171 171 147 147 167 159 157 145 164 142 143 164 157 153 145 168 159 169 137 182 196 218 216 223 269 295 288 280 281 187 264 216 220 242 264 272 326 362 407 468 432 443 383 393 367 415 471 595 626 583 491 456 411 322 328 289 271 302 377 369 373 347 296 292 257 269 241 218 212 239 254 295 314 356 301 277 252 251 186 197 162 192 231 223 207 238 196 196 176 171 178 146 169 161 149 173 156 143 154 152 139 184 185 161 159 152 159 176 164 168 193 195 187 237 228 265 291 347 409 454 552 524 552 502 483 433 382 363 322 328 389 469 485 438 491 415 377 375 322 288 280 263 275 245 243 239 247 216 204 210 196 220 209 212 226 201 225 228 210 244 298 405 445 534 579 538 495 466 410 389 387 429 460 573 607 740 853 781 733 593 499 398 368 334 370 358 391 376 394 414 383 300 294 275 246 259 235 239 243 277 363 383 434 436 378 373 386 438 464 491 539 539 523 499 478 472 383 345 354 352 383 370 410 453 416 396 392 319 335 407 461 587 741 875 863 754 619 485 429 336 321 296 316 385 474 539 571 493 420 345 272 242 219 229 203 220 211 190 171 195 176 218 208 212 230 265 314 278 306 262 281 209 235 222 223 246 268 316 307 316 273 247 229 201 198 173 202 173 212 185 197 193 193 194 169 169 157 167 175 140 174 146 171 142 152 171 150 142 161 150 163 154 149 157 192 185 184 205 231 238 263 324 365 388 380 421 418 408 385 374 346 329 297 319 322 328 298 290 304 311 312 319 292 241 239 202 206 202 227 236 307 309 385 341 324 290 208 241 201 202 181 217 264 229 326 303 345 304 296 241 242 210 187 206 194 221 216 245 242 251 258 232 215 189 192 163 158 162 174 182 169 151 187 179 167 169 146 149 146 158 142 164 142 153 147 163 160 163 127 150 159 140 136 159 171 178 159 162 193 156 176 161 155 146 179 208 186 194 252 230 219 182 179 174 147 189 166 142 144 177 178 215 182 160 196 200 159 163 150 175 144 132 160 169 138 171 129 167 172 135 170 172 169 199 221 233 283 291 299 257 239 226 185 195 194 175 192 182 189 210 252 217 230 223 192 205 179 185 155 193 190 214 215 230 223 212 233 221 242 216 261 265 370 406 501 447 488 473 365 279 283 285 282 239 267 263 309 349 345 322 338 308 238 221 215 197 205 208 222 206 204 230 240 284 313 331 344 297 275 267 216 230 194 195 234 196 198 240 255 287 314 318 255 232 213 186 193 156 168 155 154 187 181 194 183 206 191 179 174 158 176 183 184 188 222 211 242 267 330 363 390 397 332 288 273 199 218 198 206 228 206 216 256 259 301 265 240 206 224 183 160 190 158 161 161 143 144 177 175 142 129 140 166 156 126 156 144 146 136 145 160 147 142 150 168 164 168 195 207 229 260 263 294 291 279 245 211 240 218 197 226 253 249 289 329 377 412 419 371 310 258 236 243 235 224 241 236 239 302 286 295 329 390 376 405 380 376 363 361 296 313 279 295 248 253 273 273 275 305 282 295 295 304 318 331 336 336 371 349 315 280 286 238 265 226 238 222 224 254 303 311 297 319 302 295 299 325 347 294 264 265 239 227 226 250 203 229 202 234 220 206 230 228 259 221 276 276 271 278 298 341 366 384 388 410 433 388 382 298 327 266 250 252 252 262 270 257 249 251 336 305 284 293 236 224 207 200 174 177 180 163 150 181 174 141 156 143 166 148 174 153 160 159 160 155 141 148 157 157 161 171 164 169 170 167 189 220 252 328 298 286 290 266 220 171 193 194 170 235 195 207 227 261 320 343 339 411 416 350 350 288 343 300 286 283 249 258 232 229 233 215 250 258 250 251 245 233 220 257 219 207 208 191 187 198 176 184 190 192 159 176 166 196 172 180 208 219 202 177 175 170 167 175 153 145 178 168 153 159 179 196 175 174 168 180 139 157 143 156 157 151 155 158 155 141 152 145 158 153 149 153 150 144 150 143 172 141 166 170 162 206 182 172 183 175 178 179 157 163 182 184 177 163 172 185 159 185 176 169 161 173 190 193 150 175 151 176 166 171 187 180 216 212 269 301 313 319 328 299 252 252 228 200 209 202 225 199 251 236 263 299 302 338 248 259 262 213 211 206 210 168 191 159 183 202 211 205 206 205 223 200 184 189 186 185 205 197 210 206 202 174 175 190 165 173 179 192 168 168 181 170 200 198 219 211 238 222 205 221 204 219 196 210 196 234 212 191 250 230 226 277 263 296 319 338 385 408 381 356 290 284 268 222 245 214 211 204 227 254 236 290 305 290 337 276 281 238 243 231 205 205 193 180 171 185 191 191 190 179 169 175 199 179 189 210 191 206 212 210 235 205 182 185 177 171 153 154 152 170 155 156 153 171 188 181 180 201 183 191 184 187 163 161 165 160 185 198 164 176 182 172 172 186 189 181 231 209 211 227 226 193 216 211 211 193 175 192 209 196 195 230 231 239 311 285 263 289 262 214 212 218 186 191 199 183 190 168 194 191 195 207 218 222 241 242 219 189 202 202 190 225 204 223 262 258 317 312 304 299 278 265 221 205 225 211 203 192 201 197 227 184 205 216 256 253 288 249 280 219 217 249 229 198 193 178 205 210 185 179 213 233 225 232 264 271 285 273 342 326 401 358 432 331 361 330 283 282 263 245 232 219 251 241 241 265 237 251 266 291 301 300 280 332 285 276 261 262 264 280 291 292 284 266 240 219 232 218 192 181 184 219 187 174 184 204 197 217 215 213 212 218 210 224 183 178 205 184 185 180 197 154 171 181 155 145 184 180 173 168 190 169 161 174 158 167 182 165 183 168 159 161 155 189 186 150 168 186 194 155 171 151 165 175 156 163 164 166 185 163 202 186 183 183 155 199 176 188 177 165 198 170 186 188 193 190 207 234 205 212 216 213 266 257 269 300 330 339 357 382 326 325 282 284 305 353 293 354 327 397 378 367 341 307 311 274 313 351 347 326 307 293 260 283 272 272 302 307 313 332 337 327 331 343 329 371 392 418 493 471 481 485 486 422 425 387 379 330 338 327 321 327 386 375 412 398 371 398 377 382 419 397 373 325 333 311 301 293 291 268 279 289 278 266 268 284 258 251 258 247 251 211 209 220 218 191 186 214 213 216 227 196 202 213 186 198 224 177 197 160 191 209 217 216 215 200 207 202 234 218 252 249 281 270 287 318 319 370 397 434 494 424 485 464 454 461 371 326 309 280 332 297 277 293 303 342 293 322 350 360 343 387 437 442 460 486 451 433 459 369 415 340 328 323 291 265 305 279 298 320 299 306 340 314 329 324 367 378 335 338 293 299 293 263 285 277 283 326 291 311 315 351 367 353 387 404 365 354 382 318 310 342 355 334 382 359 322 317 322 315 322 260 275 282 290 318 296 276 281 309 281 305 298 276 252 303 282 308 302 293 288 268 300 319 297 302 304 346 392 454 519 565 590 593 601 563 482 500 403 417 386 328 293 321 300 313 294 318 294 329 329 364 360 385 412 426 405 418 417 358 384 387 312 316 304 295 296 294 273 325 330 345 300 370 350 381 297 316 300 270 271 292 249 263 269 273 252 250 225 241 245 268 276 264 282 294 314 303 269 295 283 293 286 264 255 259 252 270 255 304 293 311 285 332 321 350 358 431 433 427 380 413 422 348 388 355 370 353 322 348 325 320 369 351 400 379 399 406 396 397 415 439 438 437 478 495 511 450 497 498 433 477 484 430 431 454 399 382 384 351 334 347 336 330 306 330 311 298 301 344 335 334 303 326 359 397 356 347 310 347 332 312 335 334 316 309 294 334 342 332 279 267 257 292 288 273 245 269 248 228 250 249 230 238 217 238 212 246 246 239 262 265 264 240 250 246 226 227 235 226 256 190 215 236 223 227 203 206 190 232 230 201 219 203 216 213 208 224 210 202 212 205 236 220 194 199 201 216 237 212 225 203 241 232 260 253 257 282 291 283 325 333 335 293 315 297 310 285 285 276 258 251 269 228 215 259 235 257 241 289 229 267 270 284 265 274 275 279 277 269 267 263 299 262 263 268 235 232 261 236 224 251 249 247 217 238 231 251 261 251 308 300 333 311 283 279 289 281 273 244 299 263 257 209 284 256 270 280 276 282 293 282 285 309 299 295 307 253 258 255 297 296 248 286 288 259 276 256 257 268 246 273 271 306 287 286 303 283 335 330 366 380 334 362 408 432 479 440 484 478 479 513 472 445 466 437 414 396 374 314 326 326 323 316 354 315 351 329 370 366 415 444 423 414 412 463 464 424 427 411 394 383 394 330 360 359 303 294 289 271 288 264 284 262 274 278 293 289 309 292 313 286 291 303 279 298 301 278 261 314 299 316 353 319 339 335 341 306 303 298 290 317 318 296 336 295 284 241 276 245 247 263 270 261 239 247 250 209 238 247 257 255 273 272 319 274 307 253 284 254 274 278 237 257 249 261 242 256 255 236 234 250 233 250 231 252 244 256 226 267 246 257 255 278 292 308 274 375 361 344 361 347 352 322 337 267 268 286 279 276 252 242 277 271 275 272 295 281 338 320 350 381 404 451 441 452 417 450 436 437 440 474 453 457 438 387 386 366 341 337 308 329 283 296 289 297 240 268 282 297 291 281 305 336 324 307 332 328 309 315 330 291 290 344 314 324 327 259 268 305 304 300 285 292 289 294 278 261 297 252 280 245 266 283 238 266 262 249 255 240 239 221 251 212 233 238 249 256 216 262 249 248 263 281 234 290 269 284 233 286 275 263 245 259 276 229 261 273 272 231 212 233 256 241 228 234 238 216 207 221 233 238 217 238 251 268 259 230 276 257 260 255 244 258 279 291 290 295 289 273 306 307 264 289 270 234 252 243 244 251 235 234 246 239 257 218 234 230 253 248 257 248 255 261 275 288 301 283 308 268 300 305 254 251 256 280 290 267 278 302 264 263 289 231 271 289 268 310 278 280 262 234 278 288 265 302 278 273 279 303 318 317 312 303 312 311 308 304 284 281 287 262 273 284 261 241 238 276 276 274 262 279 274 238 278 273 274 260 245 293 307 304 266 287 292 295 295 305 300 281 287 299 268 292 267 236 248 272 274 237 251 245 285 252 272 258 269 268 299 240 263 260 315 315 295 279 295 333 322 338 383 339 311 323 295 275 295 289 294 287 275 249 232 269 258 268 290 253 266 234 233 223 231 252 275 267 251 284 281 254 265 309 269 296 290 301 297 300 345 298 347 345 374 366 387 392 438 465 470 443 511 473 474 455 473 452 460 440 386 385 402 418 382 348 344 360 366 351 322 327 318 352 341 308 357 325 367 383 381 376 381 434 410 412 411 393 427 429 441 407 412 456 389 386 382 368 352 367 366 364 366 352 312 345 336 284 310 289 318 287 303 306 320 330 334 345 367 407 379 410 396 429 425 449 416 394 390 394 404 356 350 378 369 362 311 297 307 293 291 338 300 290 317 312 270 313 278 321 327 332 337 328 301 322 334 330 315 311 302 338 321 317 331 335 345 317 306 309 336 309 299 319 310 287 281 268 260 279 279 289 265 261 264 260 271 265 270 280 304 283 289 294 325 269 282 293 275 283 281 283 277 284 275 277 278 273 284 267 270 287 316 261 283 294 275 324 306 302 276 392 339 309 315 322 359 308 335 315 318 319 328 315 303 296 300 304 283 292 266 279 295 258 289 272 251 305 263 261 299 291 276 294 259 254 297 287 257 284 255 260 259 300 264 300 287 298 283 279 271 291 304 299 272 316 298 322 306 268 257 279 262 269 291 258 269 295 293 268 264 272 272 288 270 267 277 310 292 276 290 319 322 316 343 345 379 383 389 437 371 405 427 442 424 438 396 384 381 329 322 319 274 318 304 316 324 275 319 259 272 262 270 263 266 242 265 251 276 277 260 256 240 278 252 286 295 268 301 296 268 299 298 305 293 327 343 362 367 358 324 322 330 356 353 351 324 359 339 289 330 295 293 293 300 296 319 302 276 293 271 283 256 258 269 272 213 257 274 242 245 252 212 261 281 259 253 280 255 229 241 242 248 259 257 256 253 281 292 254 273 278 277 264 219 271 279 246 268 282 272 270 221 262 286 267 254 267 259 267 276 269 251 256 228 248 243 254 254 245 242 250 264 274 255 281 229 263 250 241 259 268 285 241 255 268 257 263 266 298 281 271 261 280 296 283 341 280 304 282 258 262 279 285 319 293 322 316 348 341 339 321 373 376 366 402 391 405 407 422 395 434 419 426 385 390 375 357 343 359 344 285 324 317 345 303 315 288 301 281 327 316 260 299 302 249 293 271 296 258 283 268 271 305 268 234 286 278 274 274 253 238 291 274 300 282 303 285 323 340 283 355 288 335 350 313 303 338 326 359 372 325 325 352 345 348 330 336 310 343 321 329 325 329 330 311 316 327 320 306 348 345 330 325 371 381 421 388 403 413 417 391 385 376 382 420 374 352 328 368 objcryst-2022.1/Fox/example/tutorial-ylid/000077500000000000000000000000001430515525000204305ustar00rootroot00000000000000objcryst-2022.1/Fox/example/tutorial-ylid/ylid.fhz000066400000000000000000000013151430515525000221020ustar00rootroot00000000000000 24 S 1 O 1 3.259 O 1 3.259 2 92.876 C 1 1.765 2 46.434 3 360.0 C 4 2.361 1 162.691 2 1.3 C 5 1.405 4 72.688 1 178.7 C 2 1.205 1 62.666 3 359.8 C 3 1.206 1 62.666 2 0.2 C 5 1.380 4 165.670 1 358.7 C 6 1.380 5 121.637 4 180.0 C 1 1.811 2 142.957 3 359.6 C 1 1.811 2 89.566 3 99.4 C 9 1.398 5 117.288 4 180.0 C 10 1.398 6 117.290 5 0.0 H 9 1.084 5 121.902 4 360.0 H 10 1.084 6 121.894 5 180.0 H 11 1.092 1 113.213 2 62.7 H 11 1.092 1 110.667 2 293.0 H 11 1.096 1 105.997 2 178.3 H 12 1.093 1 108.857 2 148.8 H 12 1.093 1 108.682 2 30.1 H 12 1.093 1 111.229 2 269.6 H 13 1.087 9 119.600 5 180.0 H 14 1.087 10 119.603 6 180.0 objcryst-2022.1/Fox/example/tutorial-ylid/ylid1.hkl000066400000000000000000000122301430515525000221500ustar00rootroot00000000000000 0 0 2 42215.3 2497.62 0 0 3 142.962 871.678 0 0 4 68110.7 4603.18 0 0 5 1112.92 854.587 0 0 6 18995.2 2963.84 0 0 7 1093.32 913.570 0 0 8 43154.5 5355.04 0 0 -9 -4883.34 2348.14 0 0 -10 105673. 10312.5 0 1 0 170.550 566.063 0 1 1 48398.5 3259.25 0 1 -1 50843.5 1791.60 0 1 2 166221. 7029.44 0 -1 -2 176705. 3775.70 0 -1 -3 79442.0 3435.62 0 1 3 81180.1 5442.23 0 -1 -4 23033.5 2311.51 0 1 4 26130.7 3701.55 0 -1 -5 45817.6 3921.01 0 1 5 49341.3 5027.33 0 1 6 118022. 8696.38 0 -1 -6 114964. 6904.97 0 -1 -7 71556.1 6125.83 0 1 7 69004.7 6994.43 0 1 8 12857.4 3444.74 0 -1 -8 10164.5 2916.38 0 -1 -9 -1684.85 1815.19 0 1 9 1888.47 1300.99 0 2 0 1092.47 624.704 0 2 1 89032.6 5835.76 0 2 -1 91415.4 4258.15 0 2 -2 382036. 6174.93 0 2 2 383564. 12903.5 0 2 3 38.1316 872.695 0 -2 -4 22184.8 1498.92 0 2 4 19636.3 3840.09 0 2 5 78506.4 7278.14 0 -2 -6 3261.80 1350.11 0 2 6 1689.12 2987.59 0 2 7 5289.25 2421.44 0 2 8 -566.357 913.292 0 3 0 617.552 2010.59 0 3 1 16133.0 3440.75 0 3 1 16707.6 1743.48 0 3 -1 20309.1 2873.99 0 3 2 6540.94 2307.87 0 3 3 2745.34 1888.73 0 3 4 26500.3 5058.00 0 3 5 2596.70 2929.52 0 3 6 23019.5 4963.74 0 4 0 117356. 8340.26 0 4 1 182929. 11214.4 0 4 2 15836.8 5243.96 0 4 3 49237.9 6650.28 0 4 4 24549.5 6451.22 1 0 0 388.758 1167.46 1 0 -1 52703.0 4315.94 1 0 2 19994.6 2950.67 1 0 3 141924. 7607.84 1 0 4 3114.02 1376.54 -1 0 -5 90011.3 7473.28 -1 0 -6 3933.53 2409.88 -1 0 -7 131256. 10121.6 -1 0 7 149163. 9411.43 -1 0 8 21712.4 4536.28 -1 0 -8 19358.9 4374.54 -1 0 -9 60854.3 7780.10 -1 0 9 42015.8 6520.53 -1 1 9 28914.4 5547.67 -1 1 8 52968.7 6575.59 -1 1 7 94599.3 8482.43 -1 -1 -4 140930. 7971.77 -1 -1 -3 313889. 11403.1 1 -1 3 359520. 12546.2 -1 -1 -2 205007. 8704.05 1 -1 2 256461. 9688.20 -1 -1 -1 117331. 6837.17 -1 1 1 119300. 6298.80 1 -1 1 132831. 6759.80 -1 1 0 7304.12 1652.06 1 1 0 7976.07 1905.11 1 -1 -1 141951. 6418.84 1 1 1 138235. 6966.67 1 -1 -2 242423. 8443.42 1 -1 -3 352265. 11300.3 1 1 3 347849. 11428.7 1 1 4 144428. 7483.60 -1 1 -6 46611.8 6304.27 -1 1 -6 41799.9 4696.64 -1 1 -7 95573.4 9191.08 -1 -1 7 98310.3 6721.30 -1 1 -8 52716.6 7537.46 -1 2 7 21846.9 4962.85 -1 -2 -6 3188.04 1552.63 -1 2 6 57.4338 2393.38 -1 -2 -5 150139. 8240.65 -1 -2 -4 179637. 8720.93 -1 -2 -3 12041.4 2444.09 -1 2 1 62003.0 4414.80 1 -2 1 63956.9 4819.34 1 2 0 6069.82 1781.46 -1 -2 0 7099.40 1788.29 -1 2 0 4781.88 1398.12 1 -2 0 4099.10 1126.78 1 -2 -1 70656.9 4572.11 1 2 1 56516.7 4709.83 1 2 2 236578. 9221.32 1 -2 -2 242979. 7596.17 1 2 3 9633.15 1793.85 -1 2 -3 11603.7 2941.32 -1 2 -4 166260. 10840.5 1 2 4 179348. 8174.00 1 -2 -4 183944. 7146.64 1 -2 -5 151780. 7207.60 -1 2 -5 151484. 10964.4 1 2 5 131045. 7272.03 -1 2 -6 6006.20 3846.89 -1 2 -7 11885.3 3392.57 -1 3 6 1283.20 3262.74 -1 3 5 16312.9 4983.02 -1 3 1 6721.90 1806.58 1 3 0 108688. 7826.69 1 3 1 3561.50 2397.61 1 3 2 148722. 7661.27 -1 3 -2 155379. 9523.49 -1 -3 2 153044. 7279.36 -1 3 -3 48409.3 5915.75 -1 3 -4 88542.1 8453.38 -1 3 -5 12968.4 4121.08 -1 3 -6 -322.168 3193.24 -1 4 3 31556.2 6073.60 -1 4 2 42606.4 6281.42 -1 4 1 23990.0 4281.15 -1 4 0 3363.34 1810.82 -1 4 -1 13672.0 3968.76 -1 4 -2 35136.4 5144.33 -1 4 -3 19811.6 4046.54 -1 4 -4 61378.9 7827.91 -1 4 -5 7881.31 4143.64 -2 0 0 200557. 12197.9 -2 0 -2 113247. 8973.59 -2 0 -3 196649. 12332.0 -2 0 -4 19828.9 5046.32 -2 0 -5 37.0310 1529.80 -2 0 -6 29961.2 6785.58 -2 0 -7 10007.2 4577.67 -2 -1 -7 67349.5 8141.84 -2 -1 -6 103020. 9769.05 -2 -1 -5 41631.9 6200.74 -2 -1 -4 37857.5 5658.39 -2 -1 -3 3763.67 2524.51 -2 -1 -2 126184. 10194.9 -2 1 0 39881.4 5492.51 -2 1 -1 5847.40 2178.58 -2 1 -2 120743. 9545.44 -2 1 -3 9627.55 2916.26 -2 1 -4 54844.1 7207.35 -2 -2 -6 23463.9 6301.57 -2 -2 -5 112185. 10308.6 -2 -2 -4 76270.7 8141.52 -2 2 1 24386.7 4358.13 -2 2 0 22479.1 4681.78 -2 2 -1 24371.4 4956.44 -2 2 -2 28387.5 5371.66 -2 2 -3 53654.6 6716.23 -2 3 1 2786.72 2244.31 -2 3 0 118077. 9623.45 -2 3 -1 1509.37 3297.88 -2 3 -2 5840.97 3358.59 -2 3 -3 10377.2 5533.04 objcryst-2022.1/Fox/example/ylid.xml.gz000066400000000000000000000124671430515525000177420ustar00rootroot00000000000000‹í\ÛrG’}÷WÔòɳlÖý2A1B&eɱ¢e‹š˜ÝÇÙ"1Ôˆþú9§ º«€óäl‘@"³*/'O 8~÷ño§³‡»¹8«çÍ‹-•:”éP™JþY¦?ÛøúüÃxß|ݦ“JGypòÇùuõXü\ßâ•ÿÿö§³qñ¹¾l^Ϧ÷Ÿ_ü"´jÿfy¼â—zMŸF“æêÅ<oG·£9Vâ|4iÿ­¿â_‰g[½õÁ‰«’ ÇGxõz>œ¤Jµ«žËƒ+íïR¤cåmHKuAU1†Ç-Ž?ß`›IîOåÇf¾g×õíí@å»Ïs$ÅBât:¹›ÏêÑD¼­çóÑe#æÓNBˆ‹‡ÛÛf>{8§7S<Ñþ¸H¡æN|Ö|ªïÇóÿ>8:ùn‘¿Ü5âìaRߎ.‘zï./ï?דËq:ÍšK nTÿótƒÎ³ÑÝçqý ^Mê ¾mfOÒqq‰m6³Ñäú—é?›ÙËùôv¡ð‛ý8óÇÖUOñ¿¬–ùæ–^ÿat7EÂu|þ-Er©hÂ¥šó·âÕl6œÈ'ªR¥*¹ÒuøóÇ×7Ó»ùï×v¨†ú~œÎnÊÓ›zvÝ T¾ýÃét<½Ÿ(¡ž\=ÐFáhMN¶èÝ*@ïþÐÞ$÷ ÓU€NÿО$+'ÿí)LoVazóG˜ötê©jŸ;ŸŽ›Ëûq³°¤LtÚWŸn°†³óé—æÇYóv‹ù×W“fvýðâÀréÓë·£¿7ãÑÍtzc¾~Ë_ïÁ g6Ë_%ö…Ü ^zìóW•µ  ÚãW͸JçcòüÕäg}ÒØñÓÝ_&£ùJm­w§zJœ¿Â•TÞc«ßÍ“t=P—ñAY»«ªßZUΙ§fò ý–ª2µYUÄRQ¸ü8n¾Ž>ŽÆ£ùƒ8Ÿ^5ã¼åå=²¥)Ÿf¨Þ÷MËÔæwÿ#f͸þÚ\‰CñþÕé»óóW?Ÿ½:ë§g‘z¹ýÖˆ‹y=›#Á¾&Ÿ˜Ý}þ¥Öq§uZ¾›šÉ¼þ&Kܤçý´}­8…–o°¸×Í”L4SÈË,*¾{œ‚ŸN®š«÷„.­Ã†r¢þ2ÉûÊB¯ÿ4õt¨+íûñ[9eDòçPö3¾ËEtW뻬U¡ptzTª’I1+EI)-e0[µš¡V¬5XMV«X>Æ/µÊä’Œ~›ÚSÛU{ÚªEÊ[i•j—+1­9Í}/Ö‹A"mõ©*Ær¥’)«…ž¥ ë5²U¶¨õCµ@%Ì5Q-Ü ¼Òjå«£ßnµJ'['à«RzôôšOmÑ×:×l|á§‚–« yLÜ®7 õšJZ«ÝR-”Ú•Ú‚òÛ}ËÖ6tnBX¬Wc½.®œ‹ !u·¯W©5Ž€2—…†ªS¹íüFÇ›]Ø®U¯×jŒKËJ“6†EæB­Œqk¡*³Î»ÆEç†lÓz R²EÚ¨·ë]SjºâbÓ¹18_:×:4æ­…öFõ*íÍb½Q¥˜–¬uò&>®ØÃ¤ÜZo”*†.fV«ÙT:(©‹ÂHí¶ú÷ Cµ‡¦²Ä”6d›yµÉšÈôÙ¦4®QŠðKeÃÒ ÞyåÔ"ÅðfkнQi­Úht`¼uY+~Vz{†½Ñr­Pû:.µF‡"xL\dßÔªµj%À@=º6åm·jµ1j{h½F-h—¨@?ûåb5“Mn˜6C­…oÜjTÔÎ-²@;ë¶wÞ7Ú•êÊ+µh½¦J:¬VÂÉZ­WûÃtr%¨[µ{|6úôiVçÛßgõ¼¾ÑÆðã ‡ãé?Ŭ¹›Žïó-¡+Ȉ…Üâ k[oª¦sůùÓê–_¾B'>a5¼…h1Pkï»wæß×W£|KiæåÓïQýßáûúaÓ¨‹ÏÍå|v»ñîÓùt2½¼™µ·Á:ZÞb¯õì—鸞½¯ç ¯'–ýŽû|Ç"ûF?:æ¯õ—fœÏ·ú÷< <åvey[îz<ýXÛK¤›?¡Ð~ªÇíGî¶ÜóÏ` õᦙ×ï¾¼­o?^Õ'²²HÈ5O,îc¾ùß·?M?Þå\þk3º¾™¿ÝÍ—”ø£…Õ *•Ú¦Py-ëNºæPñ(È;Õ* œpÞWÒax,Èù®œ6š+'PV©ÒNÌ• ‚±+x¨„“ÑHª`••³¦´Œ%yEŠ 1$X+t%µ ¾¯ê!|0‚«‚•TÖ›¾ F(«1Òho¸EìÙ(¯º[Q­dDÝ8<¯|¨¬‡Bc|òݪֶÓAa \™¬€?}´n¸B#B²V c£³#oíÉPúƈ¨T”ôBºÒô6vllWPåð©”’…óR<Ï0P¨îóGD0ä½éxó*½7Éö7“S@ˆ¡*õ)>pº<Ìy»Ì)á­qcd¬ª»ÈlT2R ¯‘bNK›ú›i%ŽúR‡r*Fk } Ë*JFÀ€)j0n÷U¶£6N jžîáÎ¥IeJX(⤄ÅÓ0+l°æ"2šÑ‘ Û Ø D$÷ìðcQšKLðŽ«,*ÌÅJ¡rx MùR¥1I£C‘±¬’ñÆ üƒ×…cY¬Vj?ô$·kðHaÊIïìGBP:‰ÀFìp™K!%W&šÉ¡ÖV/C­ÐPB°eæÂ^:Ò©ˆ<4Œ6 k¢FÖ¿6`ÊH#U¡ ]ìVˆ:4ØŽPŽ‚<²SºD•©çr ji¼ð*XøŽpx=t$ Êál‹•@?ìɨŒz©'IÁ„l…mg=<é+¼2‚YÎl ­Ž{¼ó2våm#)ce®Q4µåº9ÉÅ)¤PÂÙÊEÖ6ÐGû§,bÞ”3@¢rÄÆÆ”Ž„e$" цkRm¡¯‘Yî¥GP£"òaN rHÁ @™rȳ”»‚O%üPÐRS–²;†-.„U²$U²Âµ¯ÎMpôY6ΣšX²X‡’EC‘¾ˆv.Å€ô÷UlކÒp”F¥€ÄV2’¢x+4CWbZ–Ô’oáúÈÝðⲜ°ÉXx½N³{ÀAÐ_ö$:¢.ªÀ>˜H²aûAŸ(1 ζè p :-ÄQ‰Ñ¹¸¦¸))¼DtH1\@>=”%…$¼Xiû…†ê*D¼ÁÚÂ%jÞ¤¾ ¡(BŽî Fûq‰-4´™¹²®[ªÐsˆŒV jÙ¡Zæöº‘! @L#` zDtTêÚRP1!-©ˆõ±HL“Ý >È‚ÔNOÜ´VÒ0MyBZPϪ”»m &–UA¹(5€ m¹2™i­cihë,ïÒ²Sr‡6•À†.ô šÐ…þÎwë{‰¡ÛŒäkôoøÄÐáØ Ø‹¦Í¼Ó³ã3‡é!‡—=¢•DlÁLèfÅFÅOŠ'SVÍ9† Î)_õ{÷᣾€¼aSÖ’}Œ0m£-v“ûrŠhðÄÄ[îä‰,÷ݲíhSPnBÆŒ·Ã*#±-s$ °æ*CÒ©"'Œýžù-hhÙ÷¦×öô[At-ÊÍYGÏK¡_ºŒ9¬ú”ì›M<‚ôÓd&Ánzô Ÿkb~rC0òìÍÚvp>ë‹ÎÌ‚ð'÷0ŒTr,Ì9)–†ñŸó*ÓNL*cer¡@ªh=IÁ™š§¨zí;“^xÜz\‹è>(ÍÂAkSC&MQäFbƒbíx6(gÐb Q“=î/x\óž:íKíB™p¬3å`8Wšžo«§dÓYÎò3 p€Î]BšPò+M¤]NÐ-×mZSdYÐæp =#8jÝ/2V8²JZÇ%UX`Íi]õP¥Ëù[‘ãqÈ*ös’د ¿€i0 ís;sÑ®Étd&°Ó¤ÊÈöÜNÆÏìKÅT*ðð„f Y²MKÛ‘'E:”¶Ù‰"æ T¨û*åS*ãí 03KK¤:q–Ÿê,1‘‰l ܘi*>²ÍH¬ÂÕFúŠÏá‡íÓ9qŠÎ”M;.`@…€> ª®ˆî¤(wΜj&lMGÕÕåO1ä¨ÒŒ@‘‘NÁó8\ßÌx—3}l³ìW¡T™«Èi†Çðmò13?¡%•[SÄlFj)Rð©=®“?DŽ ÔiIrÓ}9ÓBNÃß‹ê ¤±\£Å,ÄCBëøö;jp™q,`~è‘]P#×Q¿H”d| “ž4¨N ‹DJË’«d† Þ¦…w šV¶!ÛÎ$Q±÷[Ò*”ºç±Ãš”ãq!©*]ž÷`±œ|Jæ—ÚÉ’\ß1§;r:UòNµò%JÍÁÝ,5c­%*RJnL"ü¼ÑŠË !‘HYŽ03+‡GÐ*•ÊÊÈ‘ô’'šF ø¼àŠ7A‰Iµ€…ÄÁˆ‡Wy0Šz ›y…&G>·ƒ|æÂc¤-;‡W uP‹Ù(–—€è‹eSn‚ÎÙìf@ÒÅÝÊyÔa Ì }~ß‹? Šè§‘#=ºšœ'̃Rutm~çîøè[o3g‰×ù]Èümï>þ­ûÅxëÞ|9¾žÎFó›ÛïôþRÏêñ¸‹ÍíçüÍ/ïJö4µO×óûY#..oš«ûq³RjûJ/nëÙ|½ž‹úK#~hîæù =F×â}s}?®gãÎw¶¹¾¶W_šÙƒx?ß¿/¾AcÍŽ¿…ämSÃÊÅ?îëYs·x³/otÅ˹˜ß4ÚÅô“hêË1»Ÿ<š¡Îë¯ç£É‰jþãçÖÕñQçñ5ëi¿øí2[/o?Góû«u.4Ŧ¿~žNðšQ=þ†#? WþÞ\ñ›ëo¼ÑÜûê‘ÿZyîü¾ý2“Åò£àW¸ã£âñVxñv9²®¹œ‹öŸŸù=m~,ìääÑÖ×~+ᇠ×^¯8jK§_'ß-¿xòä_ºÎEëƒRobjcryst-2022.1/Fox/gnu.mak000066400000000000000000000025601430515525000154610ustar00rootroot00000000000000BUILD_DIR := $(CURDIR)/.. DESTDIR ?= /usr/local/bin ifeq ($(shared),1) shared-newmat=1 shared-wxgtk=1 shared-fftw=1 shared-glut=1 shared-mysql=1 endif all: Fox default: all Fox: $(MAKE) -f gnu.mak wxcryst=1 opengl=1 fftw=1 debug=$(debug) unicode=$(unicode) cod=$(cod) shared=$(shared) shared-wxgtk=$(shared-wxgtk) shared-glut=$(shared-glut) shared-newmat=$(shared-newmat) shared-fftw=$(shared-fftw) shared-mysql=$(shared-mysql) -C src Fox Fox-nogui: $(MAKE) -f gnu.mak wxcryst=0 opengl=0 fftw=0 cod=0 debug=$(debug) -C src Fox-nogui doc: python wiki2pdf.py rm -Rf wikihtml mv FoxWiki.pdf ../ clean: tidy $(MAKE) -f gnu.mak -C src clean $(MAKE) -f gnu.mak -C $(BUILD_DIR)/ObjCryst clean ${RM} -Rf ${BUILD_DIR}/static-libs/* tidy: $(MAKE) -f gnu.mak -C src tidy $(MAKE) -f gnu.mak -C ${BUILD_DIR}/ObjCryst tidy ${RM} -Rf ${BUILD_DIR}/fftw-3.3.4 ${BUILD_DIR}/newmat ${BUILD_DIR}/wxWidgets-3.1.6 #install Fox in /usr/local/bin install: install -Dm 755 src/Fox $(DESTDIR) update: cd $(BUILD_DIR) && git pull dist: cd ../.. && tar -cjf Fox.tar.bz2 --exclude "*.o" --exclude "Fox-LastOptimizationStop.xml" --exclude ".#*" --exclude "*.a" --exclude "*.dep" --exclude "*.exe" --exclude "Obj*.xml" --exclude "profile*" --exclude "Fox/src/Fox" --exclude "*~" --exclude "cctbx" --exclude "newmat" --exclude "static-libs" --exclude "doc" --exclude "*.bak" --exclude "*.pdf" Fox objcryst-2022.1/Fox/macosx.mak000066400000000000000000000046311430515525000161630ustar00rootroot00000000000000# NOTE: beware of multiple installed libraries, when using homebrew or macports. # For example iconv in /usr/lib and /opt/local/lib, leading to link errors... # For a clean compile exluding non-system libraries, use "PATH=/usr/bin:/bin:/usr/sbin:/sbin make Fox" # Which command to use for download ? CURL=$(shell which curl 2>/dev/null) ifneq ($(CURL),) DOWNLOAD_COMMAND=curl -L -O else DOWNLOAD_COMMAND=wget endif ../cctbx.tar.bz2: cd .. && $(DOWNLOAD_COMMAND) https://github.com/vincefn/objcryst/releases/download/v2021-3rdPartyLibs/cctbx.tar.bz2 ../cctbx: ../cctbx.tar.bz2 cd .. && tar -xjf cctbx.tar.bz2 ../newmat.tar.bz2: cd .. && $(DOWNLOAD_COMMAND) https://github.com/vincefn/objcryst/releases/download/v2021-3rdPartyLibs/newmat.tar.bz2 ../newmat: ../newmat.tar.bz2 cd .. && tar -xjf newmat.tar.bz2 ../fftw-3.3.4.tar.gz: cd .. && curl -O http://fftw.org/fftw-3.3.4.tar.gz ../static-libs/lib/libfftw3f.a: ../fftw-3.3.4.tar.gz rm -f $(PWD)/../static-libs/lib/*fftw* cd .. && tar -xzf fftw-3.3.4.tar.gz && mv fftw-3.3.4 fftw cd ../fftw && MACOSX_DEPLOYMENT_TARGET=10.5 ./configure --enable-single --prefix $(PWD)/../static-libs && MACOSX_DEPLOYMENT_TARGET=10.5 make clean && MACOSX_DEPLOYMENT_TARGET=10.5 make -j4 install rm -Rf ../fftw libfftw: ../static-libs/lib/libfftw3f.a ../wxWidgets-3.1.6.tar.bz2: cd .. && $(DOWNLOAD_COMMAND) https://github.com/wxWidgets/wxWidgets/releases/download/v3.1.6/wxWidgets-3.1.6.tar.bz2 ../static-libs/bin/wx-config: ../wxWidgets-3.1.6.tar.bz2 cd .. && tar -xjf wxWidgets-3.1.6.tar.bz2 cd ../wxWidgets-3.1.6 && ./configure --with-opengl --disable-debug --disable-webviewwebkit --enable-optimise --disable-shared --enable-monolithic --disable-mediactrl --without-libtiff --enable-cxx11 --prefix=$(PWD)/../static-libs && make -j4 install rm -Rf ../wxWidgets-3.1.6 libwx: ../static-libs/bin/wx-config default: Fox Fox: libfftw libwx ../cctbx ../newmat xcodebuild -project Fox.xcodeproj -target Fox -configuration Deployment Fox-nogui: ../cctbx ../newmat make -f gnu.mak Fox-nogui dist:Fox rm -Rf Fox-`date "+%Y-%m-%d"` Fox-`date "+%Y-%m-%d"`.dmg mkdir Fox-`date "+%Y-%m-%d"` cp -R build/Deployment/Fox.app example ../LICENSE.txt ../ChangeLog.txt ../README.rst README-Fox.txt Fox-`date "+%Y-%m-%d"`/ hdiutil create -srcfolder Fox-`date "+%Y-%m-%d"` Fox-`date "+%Y-%m-%d"`.dmg rm -Rf Fox-`date "+%Y-%m-%d"` all: Fox Fox-nogui clean: rm -Rf build/Fox.build make -f gnu.mak clean objcryst-2022.1/Fox/newmat_vc12.vcxproj000066400000000000000000000241611430515525000177420ustar00rootroot00000000000000 Debug Win32 Release (profile-guided optim generate) Win32 Release_XP_NoCOD Win32 Release Win32 {39353CCC-A61A-47C9-8C1F-30FA52D3A1A2} Project1 newmat 10.0 StaticLibrary true v142 MultiByte StaticLibrary false v142 true MultiByte StaticLibrary false v142 true MultiByte StaticLibrary false v141_xp true MultiByte .lib $(Configuration)\$(ProjectName)\ .lib $(Configuration)\$(ProjectName)\ .lib $(Configuration)\$(ProjectName)\ .lib $(Configuration)\$(ProjectName)\ Level3 Disabled true MultiThreadedDebug _USING_V110_SDK71_;%(PreprocessorDefinitions); _CRT_SECURE_NO_WARNINGS true false $(IntDir)\%(RelativeDir) true Level3 MaxSpeed true true false MultiThreaded _USING_V110_SDK71_;%(PreprocessorDefinitions); _CRT_SECURE_NO_WARNINGS true $(IntDir)\%(RelativeDir) true true true Level3 MaxSpeed true true false MultiThreaded _USING_V110_SDK71_;%(PreprocessorDefinitions); _CRT_SECURE_NO_WARNINGS true $(IntDir)\%(RelativeDir) None AnySuitable Speed Fast true true true Level3 MaxSpeed true true false MultiThreaded _USING_V110_SDK71_;%(PreprocessorDefinitions); _CRT_SECURE_NO_WARNINGS true $(IntDir)\%(RelativeDir) true true true objcryst-2022.1/Fox/newmat_vc12.vcxproj.filters000066400000000000000000000103011430515525000214000ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files objcryst-2022.1/Fox/src/000077500000000000000000000000001430515525000147625ustar00rootroot00000000000000objcryst-2022.1/Fox/src/.cvsignore000066400000000000000000000001771430515525000167670ustar00rootroot00000000000000*.o *.exe *.out *.old *.dep *.a .directory .systemG.Desktop tags html latex *.oxy *.xml profile.0.0.0 *.pov Makefile rules.mak objcryst-2022.1/Fox/src/Fox.cpp000066400000000000000000004100401430515525000162210ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000- Vincent Favre-Nicolin vincent.favre-nicolin@ujf-grenoble.fr 2000-2001 University of Geneva (Switzerland) 2002- Univ. Grenoble Alpes 2008-2010 Jan Rohlicek - Inst. of Chemical Technology, Prague This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef __WX__CRYST__ // For compilers that support precompilation, includes "wx/wx.h". #ifndef __DARWIN__ // work around MacOSX type_info bug (??) #include "wx/wxprec.h" #endif #ifdef __BORLANDC__ #pragma hdrstop #endif // for all others, include the necessary headers (this file is usually all you // need because it includes almost all "standard" wxWindows headers) #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "wx/tooltip.h" #include "wx/notebook.h" #include "wx/wfstream.h" #include "wx/zstream.h" #include "wx/fileconf.h" #include "wx/filesys.h" #include #include #include #include #include #include "wx/progdlg.h" #include "wx/tokenzr.h" #endif #include #include #include #include #include #include #ifdef __FOX_COD__ #include #include #endif #include "ObjCryst/ObjCryst/General.h" #include "ObjCryst/Quirks/Chronometer.h" #include "ObjCryst/ObjCryst/IO.h" #include "ObjCryst/ObjCryst/Undo.h" #include "ObjCryst/ObjCryst/Crystal.h" #include "ObjCryst/ObjCryst/PowderPattern.h" #include "ObjCryst/ObjCryst/DiffractionDataSingleCrystal.h" #include "ObjCryst/ObjCryst/Polyhedron.h" #include "ObjCryst/ObjCryst/test.h" #include "ObjCryst/ObjCryst/CIF.h" //#include "ObjCryst/ObjCryst/PDF.h" #include "ObjCryst/RefinableObj/GlobalOptimObj.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" #ifdef __WX__CRYST__ #include "ObjCryst/wxCryst/wxCrystal.h" //FOXGrid #include "WXGridWindow.h" #if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__) #include "Fox.xpm" #endif #if !wxUSE_UNICODE #define _T(x) x #endif #else #define _T(x) x #endif using namespace ObjCryst; using namespace std; // Rough version number - must be updated at least for every major version or critical update // This is used to check for updates... // Now using YYYY### (4-digit year + 3 number for the version) #define __FOXREVISION__ 2022001 static std::string foxVersion; // ---------------------------------------------------------------------------- // Speed test // ---------------------------------------------------------------------------- void standardSpeedTest(); /** Load CIF data (crystal structure, powder and single crystal diffraction data). * \param in: the input stream (can be an ifstream, stringstream, etc..) * \param connectAtoms: if true, will connect the atoms after import. This is ignored * in the GUI version, as the option is read from the Fox preferences. * \note: this function will disable automatic UI update when loading the Crystal structure, * until after the scattering powers have been merged and the atoms connected. */ void FoxLoadCIF(std::istream &in, const bool verbose=true, bool connectAtoms=true) { Chronometer chrono; chrono.start(); gCrystalRegistry.AutoUpdateUI(false); ObjCryst::CIF cif(in,true,verbose); bool oneScatteringPowerPerElement=true; #ifdef __WX__CRYST__ wxConfigBase::Get()->Read(_T("Fox/BOOL/CIF import: automatically convert to molecules"), &connectAtoms); wxConfigBase::Get()->Read(_T("Fox/BOOL/CIF import: only one scattering power per element"), &oneScatteringPowerPerElement); #endif // In case several Crystal structures are loaded, record the number of crystal structures rather than rely on the last one returned by the function const int nb0 = gCrystalRegistry.GetNb(); CreateCrystalFromCIF(cif, verbose, true, false, false); for(int i=nb0;iMergeEqualScatteringPowers(oneScatteringPowerPerElement); if(connectAtoms) pCryst->ConnectAtoms(); #ifdef __WX__CRYST__ if(pCryst->GetNbScatterer()>20) (*fpObjCrystInformUser)((boost::format("CIF: updating graphical user interface for Crystal. This could take a while, there are %d independent scatterers...") % pCryst->GetNbScatterer()).str()); else (*fpObjCrystInformUser)("CIF: updating graphical user interface for Crystal"); #endif } gCrystalRegistry.AutoUpdateUI(true); gCrystalRegistry.UpdateUI(); #ifdef __WX__CRYST__ (*fpObjCrystInformUser)((boost::format("CIF: finished updating graphical user interface for Crystal (Crystal creation=%6.3fs total)") % chrono.seconds()).str()); #endif CreatePowderPatternFromCIF(cif); CreateSingleCrystalDataFromCIF(cif); } #ifdef __WX__CRYST__ // ---------------------------------------------------------------------------- // private classes // ---------------------------------------------------------------------------- // WXCrystScr class WXCrystScrolledWindow:public wxScrolledWindow { public: WXCrystScrolledWindow(wxWindow* parent); virtual bool Layout(); void SetChild(wxWindow* pChild); void OnWXCrystChildFocus(wxChildFocusEvent& event); private: wxWindow* mpChild; int mHeight,mWidth; wxBoxSizer *mpSizer; DECLARE_EVENT_TABLE() }; BEGIN_EVENT_TABLE(WXCrystScrolledWindow, wxScrolledWindow) EVT_CHILD_FOCUS(WXCrystScrolledWindow::OnWXCrystChildFocus) END_EVENT_TABLE() #ifdef __FOX_COD__ /* +------------------+----------------------------------------------------------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +------------------+----------------------------------------------------------------------+------+-----+---------+-------+ | file | mediumint(7) unsigned | NO | PRI | 0 | | | a | double unsigned | YES | MUL | NULL | | | siga | float unsigned | YES | | NULL | | | b | double unsigned | YES | MUL | NULL | | | sigb | float unsigned | YES | | NULL | | | c | double unsigned | YES | MUL | NULL | | | sigc | float unsigned | YES | | NULL | | | alpha | float unsigned | YES | MUL | NULL | | | sigalpha | float unsigned | YES | | NULL | | | beta | float unsigned | YES | MUL | NULL | | | sigbeta | float unsigned | YES | | NULL | | | gamma | float unsigned | YES | MUL | NULL | | | siggamma | float unsigned | YES | | NULL | | | vol | float unsigned | YES | MUL | NULL | | | sigvol | float unsigned | YES | | NULL | | | celltemp | float unsigned | YES | | NULL | | | sigcelltemp | float unsigned | YES | | NULL | | | diffrtemp | float unsigned | YES | | NULL | | | sigdiffrtemp | float unsigned | YES | | NULL | | | cellpressure | float unsigned | YES | | NULL | | | sigcellpressure | float unsigned | YES | | NULL | | | diffrpressure | float unsigned | YES | | NULL | | | sigdiffrpressure | float unsigned | YES | | NULL | | | thermalhist | varchar(255) | YES | | NULL | | | pressurehist | varchar(255) | YES | | NULL | | | nel | varchar(4) | YES | MUL | NULL | | | sg | varchar(32) | YES | MUL | NULL | | | sgHall | varchar(64) | YES | MUL | NULL | | | commonname | varchar(1024) | YES | MUL | NULL | | | chemname | varchar(2048) | YES | MUL | NULL | | | mineral | varchar(255) | YES | MUL | NULL | | | formula | varchar(255) | YES | MUL | NULL | | | calcformula | varchar(255) | YES | MUL | NULL | | | Z | smallint(5) unsigned | YES | MUL | NULL | | | Zprime | float unsigned | YES | MUL | NULL | | | acce_code | char(6) | YES | MUL | NULL | | | authors | text | YES | | NULL | | | title | text | YES | | NULL | | | journal | varchar(255) | YES | MUL | NULL | | | year | smallint(4) unsigned | YES | | NULL | | | volume | smallint(5) unsigned | YES | | NULL | | | issue | varchar(10) | YES | | NULL | | | firstpage | varchar(20) | YES | | NULL | | | lastpage | varchar(20) | YES | | NULL | | | doi | varchar(127) | YES | MUL | NULL | | | method | enum('single crystal','powder diffraction','theoretical prediction') | YES | MUL | NULL | | | radiation | varchar(32) | YES | | NULL | | | wavelength | float unsigned | YES | | NULL | | | radType | varchar(80) | YES | | NULL | | | radSymbol | varchar(20) | YES | | NULL | | | Rall | float unsigned | YES | | NULL | | | Robs | float unsigned | YES | | NULL | | | Rref | float unsigned | YES | | NULL | | | wRall | float unsigned | YES | | NULL | | | wRobs | float unsigned | YES | | NULL | | | wRref | float unsigned | YES | | NULL | | | RFsqd | float unsigned | YES | | NULL | | | RI | float unsigned | YES | | NULL | | | gofall | float | YES | | NULL | | | gofobs | float | YES | | NULL | | | gofgt | float | YES | | NULL | | | duplicateof | mediumint(7) unsigned | YES | | NULL | | | optimal | mediumint(7) unsigned | YES | | NULL | | | status | enum('warnings','errors','retracted') | YES | | NULL | | | flags | set('has coordinates','has disorder','has Fobs') | YES | | NULL | | | text | text | NO | MUL | NULL | | | svnrevision | int(11) | YES | MUL | NULL | | | date | date | YES | MUL | NULL | | | time | time | YES | MUL | NULL | | | onhold | date | YES | | NULL | | +------------------+----------------------------------------------------------------------+------+-----+---------+-------+ */ struct cod_record { float a,b,c,alpha,beta,gamma,vol; std::string sg,sgHall; long file; std::string nel; std::string commonname,chemname,mineral,formula,calcformula; std::string authors,title,journal; long volume,year; string firstpage; std::string cif; }; #endif // main frame class WXCrystMainFrame : public wxFrame { public: WXCrystMainFrame(const wxString& title, const wxPoint& pos, const wxSize& size, const bool splashscreen=true); void OnQuit(wxCommandEvent& WXUNUSED(event)); void OnAbout(wxCommandEvent& WXUNUSED(event)); void OnLoad(wxCommandEvent& event); void Load(const wxString &filename); void OnBrowse(wxCommandEvent& event); void OnBrowseSelect(wxCommandEvent& event); void OnMenuClose(wxCommandEvent& event); void Close(const bool safe=true); void OnClose(wxCloseEvent& event); void SafeQuit(); void OnSave(wxCommandEvent& WXUNUSED(event)); void OnAddCrystal(wxCommandEvent& WXUNUSED(event)); void OnAddPowderPattern(wxCommandEvent& WXUNUSED(event)); void OnAddSingleCrystalData(wxCommandEvent& WXUNUSED(event)); void OnAddGlobalOptimObj(wxCommandEvent& WXUNUSED(event)); void OnAddGeneticAlgorithm(wxCommandEvent& WXUNUSED(event)); void OnUndo(wxCommandEvent &ev); void OnRedo(wxCommandEvent &ev); void OnDebugTest(wxCommandEvent& event); void OnSetDebugLevel(wxCommandEvent& event); void OnUpdateUI(wxUpdateUIEvent& event); void OnToggleTooltips(wxCommandEvent& event); void OnPreferences(wxCommandEvent& event); void OnCheckUpdate(wxCommandEvent& event); //FoxGrid//////////////////////////////////////// void OnStartGridServer(wxCommandEvent &event); void OnStartGridClient(wxCommandEvent &event); virtual void OnSize(wxSizeEvent &event); /// Handle event to pass a user message from a secondary thread. void OnUserMessage(wxCommandEvent &event); wxTextCtrl* GetLogWindow(); #ifdef __FOX_COD__ void OnCOD(wxCommandEvent &event); void OnButton(wxCommandEvent &event); void OnCODSelect(wxGridEvent &event); #endif //FoxGrid//////////////////////////////////////// WXGrigWindow *mpGridWindow; private: DECLARE_EVENT_TABLE() RefinableObjClock mClockLastSave; wxNotebook *mpNotebook; /// List of available updates std::map > mvUpdates; /// Are we during an autocheck ? bool mvUpdatesAutoCheck; /// Browsing dir wxString mBrowseDir; /// List of files in browsing dir wxListBox *mpBrowseList; #ifdef __FOX_COD__ std::list mvpCOD_Elements; std::list mvpCOD_NElements; wxTextCtrl* mvpCOD_Formula; wxTextCtrl* mvpCOD_SMARTS; wxTextCtrl* mvpCOD_Text1; wxTextCtrl* mvpCOD_Text2; wxTextCtrl* mpCOD_MinNel; wxTextCtrl* mpCOD_MaxNel; wxTextCtrl* mpCOD_MinVol; wxTextCtrl* mpCOD_MaxVol; wxTextCtrl* mvpCOD_ID; wxListBox* mpCOD_List; wxFrame *mpCODFrame; wxGrid *mpCODGrid; std::vector mvCOD_Record; #endif /// Log window for the main FOX frame wxTextCtrl *mpLog; }; class MyApp : public wxApp { public: virtual bool OnInit(); virtual int OnExit(); #ifdef __WXMAC__ virtual void MacOpenFile(const wxString &fileName); #endif private: WXCrystMainFrame *mpFrame; wxLocale mLocale; }; // ---------------------------------------------------------------------------- // For messaging the user // ---------------------------------------------------------------------------- wxTextCtrl *pLogWindowForUserMessage; wxDEFINE_EVENT(ID_FOX_USER_MESSAGE, wxCommandEvent); void WXCrystInformUserStdOut(const string &str) { if(wxThread::IsMain()) { pLogWindowForUserMessage->AppendText(wxString::Format(_T("%s\n"), str.c_str())); wxSafeYield(wxTheApp->GetTopWindow(), true); } else { wxCommandEvent event(ID_FOX_USER_MESSAGE); event.SetString(str); wxPostEvent(pLogWindowForUserMessage,event); } cout< > &vUpdates) { vUpdates.clear(); std::list vurl; vurl.push_back(wxString("http://vincefn.net/FoxUpdates.txt")); vurl.push_back(wxString("http://objcryst.sourceforge.net/FoxUpdates.txt")); wxInputStream *fstream=NULL; wxFileSystem fs; wxFSFile *fp= NULL; bool ok=false; for(std::list::const_iterator pos=vurl.begin();pos!=vurl.end();++pos) { if(wxFileSystem::HasHandlerForPath(*pos)) { fp= fs.OpenFile(*pos,wxFS_READ); if(fp!=NULL) fstream = fp->GetStream(); if(fstream!=NULL) ok = (fstream->IsOk()) && (!fstream->Eof()); if(ok) { (*fpObjCrystInformUser)(wxString::Format("Fetching updates from: %s", *pos).ToStdString()); break; } } (*fpObjCrystInformUser)(wxString("Failed fetching updates from: "+ *pos).ToStdString()); } if(ok) { wxTextInputStream txtis(*fstream); txtis.ReadLine();//first line while(!fstream->Eof()) { unsigned long revisionfix=txtis.Read32(); unsigned long revisionbug=txtis.Read32(); unsigned long severity=txtis.Read32(); wxString reason=txtis.ReadLine(); if((revisionfix>__FOXREVISION__)&&(__FOXREVISION__>revisionbug)) { //cout<<"Revision:"< > *mpvUpdates; WXCrystMainFrame *mpCaller; }; // ---------------------------------------------------------------------------- // event tables and other macros for wxWindows // ---------------------------------------------------------------------------- BEGIN_EVENT_TABLE(WXCrystMainFrame, wxFrame) EVT_MENU(MENU_FILE_QUIT, WXCrystMainFrame::OnQuit) EVT_MENU(MENU_HELP_ABOUT, WXCrystMainFrame::OnAbout) EVT_MENU(MENU_HELP_TOGGLETOOLTIP, WXCrystMainFrame::OnToggleTooltips) EVT_MENU(MENU_HELP_UPDATE, WXCrystMainFrame::OnCheckUpdate) EVT_MENU(ID_FOX_UPDATES_RESULT, WXCrystMainFrame::OnCheckUpdate) EVT_MENU(MENU_PREFS_PREFERENCES, WXCrystMainFrame::OnPreferences) EVT_MENU(MENU_FILE_LOAD, WXCrystMainFrame::OnLoad) EVT_MENU(MENU_FILE_BROWSE, WXCrystMainFrame::OnBrowse) EVT_LISTBOX(ID_FOX_BROWSE, WXCrystMainFrame::OnBrowseSelect) EVT_LISTBOX_DCLICK(ID_FOX_BROWSE, WXCrystMainFrame::OnBrowseSelect) EVT_MENU(MENU_FILE_CLOSE, WXCrystMainFrame::OnMenuClose) EVT_CLOSE( WXCrystMainFrame::OnClose) EVT_MENU(MENU_FILE_SAVE, WXCrystMainFrame::OnSave) EVT_MENU(MENU_OBJECT_CREATE_CRYSTAL, WXCrystMainFrame::OnAddCrystal) EVT_MENU(MENU_OBJECT_CREATE_POWDERSPECTRUM, WXCrystMainFrame::OnAddPowderPattern) EVT_MENU(MENU_OBJECT_CREATE_SINGLECRYSTALDATA, WXCrystMainFrame::OnAddSingleCrystalData) EVT_MENU(MENU_OBJECT_CREATE_GLOBALOPTOBJ, WXCrystMainFrame::OnAddGlobalOptimObj) EVT_MENU(MENU_OBJECT_CREATE_GENETICALGORITHM, WXCrystMainFrame::OnAddGeneticAlgorithm) EVT_MENU(wxID_UNDO, WXCrystMainFrame::OnUndo) EVT_MENU(wxID_REDO, WXCrystMainFrame::OnRedo) EVT_MENU(MENU_DEBUG_LEVEL0, WXCrystMainFrame::OnSetDebugLevel) EVT_MENU(MENU_DEBUG_LEVEL1, WXCrystMainFrame::OnSetDebugLevel) EVT_MENU(MENU_DEBUG_LEVEL2, WXCrystMainFrame::OnSetDebugLevel) EVT_MENU(MENU_DEBUG_LEVEL3, WXCrystMainFrame::OnSetDebugLevel) EVT_MENU(MENU_DEBUG_LEVEL4, WXCrystMainFrame::OnSetDebugLevel) EVT_MENU(MENU_DEBUG_LEVEL5, WXCrystMainFrame::OnSetDebugLevel) EVT_MENU(MENU_DEBUG_LEVEL6, WXCrystMainFrame::OnSetDebugLevel) EVT_MENU(MENU_DEBUG_LEVEL7, WXCrystMainFrame::OnSetDebugLevel) EVT_MENU(MENU_DEBUG_LEVEL8, WXCrystMainFrame::OnSetDebugLevel) EVT_MENU(MENU_DEBUG_LEVEL9, WXCrystMainFrame::OnSetDebugLevel) EVT_MENU(MENU_DEBUG_LEVEL10, WXCrystMainFrame::OnSetDebugLevel) EVT_MENU(MENU_DEBUG_TEST1, WXCrystMainFrame::OnDebugTest) EVT_MENU(MENU_DEBUG_TEST2, WXCrystMainFrame::OnDebugTest) EVT_MENU(MENU_DEBUG_TEST3, WXCrystMainFrame::OnDebugTest) #ifdef __FOX_COD__ EVT_MENU(MENU_COD, WXCrystMainFrame::OnCOD) EVT_BUTTON(ID_FOX_BUTTON_COD, WXCrystMainFrame::OnButton) EVT_GRID_CELL_LEFT_DCLICK( WXCrystMainFrame::OnCODSelect) #endif EVT_UPDATE_UI(ID_CRYST_UPDATEUI, WXCrystMainFrame::OnUpdateUI) //FoxGrid/////////////////////////////////////////////////////////////////////////////// EVT_MENU(MENU_GRID_SERVER_RUN, WXCrystMainFrame::OnStartGridServer) EVT_MENU(MENU_GRID_CLIENT_START, WXCrystMainFrame::OnStartGridClient) EVT_SIZE(WXCrystMainFrame::OnSize) EVT_COMMAND(wxID_ANY, ID_FOX_USER_MESSAGE, WXCrystMainFrame::OnUserMessage) END_EVENT_TABLE() IMPLEMENT_APP(MyApp) // ============================================================================ // implementation // ============================================================================ int STRCMP(const char* s1,const char* s2) {return wxStrcmp(wxString(s1),wxString(s2));} int STRCMP(const char* s1,wxChar* s2) {return wxStrcmp(wxString(s1),wxString(s2));} #ifdef __WXMAC__ /// Set of files to ignore in MacOpenFile, because they were given on the command line and thus already loaded in OnInit() std::set vMacOpenFile_Ignore; #endif // 'Main program' equivalent: the program execution "starts" here bool MyApp::OnInit() #else int STRCMP(const char* s1,const char* s2){ return strcmp(s1,s2);} int main (int argc, char *argv[]) #endif { TAU_PROFILE("main()","int()",TAU_DEFAULT); TAU_PROFILE_SET_NODE(0); //set locale settings to standard //std::locale::global(std::locale("")); #ifdef __WX__CRYST__ mLocale.Init(wxLANGUAGE_DEFAULT); #else setlocale(LC_NUMERIC,"C"); #endif std::cout.imbue(std::locale::classic()); std::cin.imbue(std::locale::classic()); {// Fox version char verBuf[200]; unsigned int foxv0 = __FOXREVISION__ / 1000; unsigned int foxv1 = __FOXREVISION__ % 1000; #ifdef __DEBUG__ sprintf(verBuf,"%u.%u(DEBUG)", foxv0, foxv1); #else sprintf(verBuf,"%u.%u", foxv0, foxv1); #endif foxVersion=verBuf; } bool useGUI(true); long nbTrial(1000000); long nbRun(1); double finalCost=0.; bool silent=false; string outfilename("Fox-out.xml"); string working_dir(""); long filenameInsertCost=-1; bool randomize(false); bool only3D(false); bool loadFourierGRD(false); list vFourierFilenameGRD; bool loadFourierDSN6(false); list vFourierFilenameDSN6; bool cif2pattern=false,cif2patternN=false; double cif2patternWavelength=1.54056; double cif2patternPeakWidth=0.01; long cif2patternNbPoint=1000; double cif2patternMax2Theta=M_PI*.9; bool exportfullprof=false; bool fitprofile=false; //FoxGrid bool runclient(false); long nbCPUs = -1; string IP; bool testLSQ=false; bool testMC=false; bool testSPEED=false; for(int i=1;i> finalCost; #endif cout << "Fox will stop after reaching cost:"<> nbTrial; #endif cout << "Fox will run for "<> nbRun; #endif cout << "Fox will do "<> cif2patternWavelength; #endif } ++i; { #ifdef __WX__CRYST__ wxString(argv[i]).ToDouble(&cif2patternMax2Theta); #else stringstream sstr(argv[i]); sstr >> cif2patternMax2Theta; #endif cif2patternMax2Theta*=DEG2RAD; if(cif2patternMax2Theta>M_PI) cif2patternMax2Theta=M_PI; } ++i; { #ifdef __WX__CRYST__ wxString(argv[i]).ToLong(&cif2patternNbPoint); #else stringstream sstr(argv[i]); sstr >> cif2patternNbPoint; #endif } ++i; { #ifdef __WX__CRYST__ wxString(argv[i]).ToDouble(&cif2patternPeakWidth); #else stringstream sstr(argv[i]); sstr >> cif2patternPeakWidth; #endif cif2patternPeakWidth*=DEG2RAD; } continue; } if(STRCMP("-i",argv[i])==0) {// Obsolete, just ignore ++i; continue; } if(STRCMP("-o",argv[i])==0) { ++i; #ifdef __WX__CRYST__ outfilename=string(wxString(argv[i]).ToAscii()); #else outfilename=argv[i]; #endif filenameInsertCost = outfilename.find("#cost",0); cout <<"Fox:#cost, pos="<::iterator pos=pl.mvHKL.begin();pos!=pl.mvHKL.end();++pos) //{ pos->d2obsmin=(3*pos->d2obs+pos->d2obsmin)/4; pos->d2obsmax=(3*pos->d2obs+pos->d2obsmax)/4;} { pos->d2obsmin=pos->d2obs; pos->d2obsmax=pos->d2obs;} CellExplorer cx(pl,TRICLINIC,0); cx.SetAngleMinMax((float)90*DEG2RAD,(float)120*DEG2RAD); // Use at most 20 lines ? if(pl.GetPeakList().size()>20) pl.GetPeakList().resize(20); unsigned int nb=pl.GetPeakList().size(); if(nb>20) nb=20;// Use at most 20 peaks to estimate cell volume const float dmin=pl.GetPeakList()[nb-1].dobs; const float dmax=pl.GetPeakList()[0].dobs/10;// /10: assume no peaks at lower resolution const float vmin=EstimateCellVolume(dmin,dmax,nb,TRICLINIC ,LATTICE_P,1.2); const float vmax=EstimateCellVolume(dmin,dmax,nb,TRICLINIC ,LATTICE_P,0.2); float lengthmax=pow(vmax,(float)(1/3.0))*4; if(lengthmax<25)lengthmax=25; //if(lengthmax>(2.1/pl.GetPeakList()[0].dobs)) lengthmax=2.1/pl.GetPeakList()[0].dobs; cx.SetVolumeMinMax(vmin,vmax); cx.SetLengthMinMax(3,lengthmax); cx.DicVol(10,4,50,4); /* for(unsigned int i=0;;++i) { cout<40) break; } */ TAU_REPORT_STATISTICS(); exit(0); } if(STRCMP("--index-test",argv[i])==0) { ofstream out("indexing-results.txt"); out.imbue(std::locale::classic()); srand(time(NULL)); for(unsigned int k=0;k<100;++k) { PeakList pl; float a,b,c,alpha,beta,gamma; while(true) { a=4+rand()/float(RAND_MAX)*20, b=4+rand()/float(RAND_MAX)*20, c=4+rand()/float(RAND_MAX)*20, alpha=50+rand()/float(RAND_MAX)*80, beta =50+rand()/float(RAND_MAX)*80, gamma=50+rand()/float(RAND_MAX)*80; //a=21.611; b= 4.407; c=16.848; alpha= 93.27; beta= 71.47; gamma= 87.13; //V= 1514.99 ; if( (alpha<(beta+gamma-5)) && (beta<(alpha+gamma-5)) && (gamma<(beta+alpha-5)) && ((alpha+beta+gamma)<355)) break; } const float missing=0.2; const float sigma=1e-4; const unsigned int nb=20; const unsigned int nbspurious=0; const float v=pl.Simulate(0,a,b,c,alpha,beta,gamma,true,nb,nbspurious,1e-4,missing,true); //v=pl.Simulate(0,10.317,9.414,13.178,87.90,89.76,74.10,true,20,0,0.); //v=pl.Simulate(0,10.451,12.884,7.072,86.91,96.07,83.36,true,20,0,0.); //v=pl.Simulate(21.611,4.407,16.848,93.27,71.47,87.13,1514.99,true,20,0,1e-4,0.2,true); pl.Print(cout); CellExplorer cx(pl,TRICLINIC,LATTICE_P); cx.SetAngleMinMax((float)90*DEG2RAD,(float)120*DEG2RAD); const float dmin=pl.GetPeakList()[nb-1].dobs; const float dmax=pl.GetPeakList()[0].dobs;// /10: assume no peaks at lower resolution const float vmin=EstimateCellVolume(dmin,dmax,nb,TRICLINIC ,LATTICE_P,1.2); const float vmax=EstimateCellVolume(dmin,dmax,nb,TRICLINIC ,LATTICE_P,0.5); float lengthmax=pow(vmax,(float)(1/3.0))*4; if(lengthmax<25)lengthmax=25; //if(lengthmax>(2.1/pl.GetPeakList()[0].dobs)) lengthmax=2.1/pl.GetPeakList()[0].dobs; cout<<"Indexing using TRICLINIC lattice, latt=3.0->"<"< >::const_iterator pos=cx.GetSolutions().begin(); float score=0,vsol=0; if(pos!=cx.GetSolutions().end()) { score=pos->second; vsol=pos->first.DirectUnitCell()[6]; } char buf[200]; sprintf(buf,"a=%6.3f b=%6.3f c=%6.3f alpha=%6.2f beta=%6.2f gamma=%6.2f V=%8.2f Vsol=%8.2f %d Score=%5.0f dt=%6.1fs (V=%5.0f->%5.0f, L=%4.1f->%4.1f, nb=%2d, spurious=%2d, missing=%2.0f%%, sigma=%5.3f%%)", a,b,c,alpha,beta,gamma,v,vsol,int((abs(vsol-v)/v)<0.005),score,chrono.seconds(),vmin,vmax,3.0,lengthmax,nb,nbspurious,missing*100,sigma*100); out<40) break; } */ } TAU_REPORT_STATISTICS(); exit(0); } #ifdef __DEBUG__ if(STRCMP("--debuglevel",argv[i])==0) { long level; ++i; #ifdef __WX__CRYST__ wxString(argv[i]).ToLong(&level); #else stringstream sstr(argv[i]); sstr >> level; #endif VFN_DEBUG_GLOBAL_LEVEL(level); continue; } #endif #ifdef __WX__CRYST__ if(wxString(argv[i]).find(_T(".xml"))!=wxNOT_FOUND) #else if(string(argv[i]).find(string(".xml"))!=string::npos) #endif { #ifdef __WX__CRYST__ cout<<"Loading: "<4) { if(name.Mid(name.size()-4)==wxString(_T(".xml"))) { wxFileInputStream is(name); stringstream sst; if(is.GetSize()>0) { char * tmpbuf=new char[is.GetSize()+1]; is.Read(tmpbuf,is.GetSize()); sst<6) if(name.Mid(name.size()-6)==wxString(_T(".xmlgz"))) gz=true; if(name.size()>7) if(name.Mid(name.size()-7)==wxString(_T(".xml.gz"))) gz=true; if(gz) {//compressed file wxFileInputStream is(name); wxZlibInputStream zstream(is); stringstream sst; while (!zstream.Eof()) sst<<(char)zstream.GetC(); try { XMLCrystFileLoadAllObject(sst); #ifdef __WXMAC__ vMacOpenFile_Ignore.insert(name); #endif } catch(const ObjCrystException &except) { wxMessageDialog d(NULL,_T("Failed loading file:\n")+name,_T("Error"),wxOK|wxICON_ERROR); d.ShowModal(); }; } } } #else cout<<"Loading: "<0) { char * tmpbuf=new char[is.GetSize()+1]; is.Read(tmpbuf,is.GetSize()); in<SetCrystal(gCrystalRegistry.GetObj(j)); diffData->SetReflectionProfilePar(PROFILE_PSEUDO_VOIGT,cif2patternPeakWidth*cif2patternPeakWidth); diffData->GetCrystal().SetUseDynPopCorr(true); data.SetMaxSinThetaOvLambda(50.0); data.AddPowderPatternComponent(*diffData); //we don't have data, so just simulate (0->Pi/2).. //give a constant 'obs pattern of unit intensity CrystVector_REAL obs(cif2patternNbPoint); obs=1; data.SetPowderPatternObs(obs); data.Prepare(); // Save the powder pattern in text format stringstream sst; #ifdef __WX__CRYST__ sst<"<(ttheta,icalc,12,4); out.close(); } // Erase every data in memory ? //gOptimizationObjRegistry.DeleteAll(); //gDiffractionDataSingleCrystalRegistry.DeleteAll(); //gPowderPatternRegistry.DeleteAll(); //gCrystalRegistry.DeleteAll(); break; } cout <<"command-line arguments:"< vpDiff; // Multiple phases ? unsigned int nbcomp=gPowderPatternRegistry.GetObj(i).GetNbPowderPatternComponent(); for(unsigned int k=0;k(&(gPowderPatternRegistry.GetObj(i).GetPowderPatternComponent(k))); if(pDiff!=0) vpDiff.insert(pDiff); } LSQNumObj lsq; lsq.SetRefinedObj(gPowderPatternRegistry.GetObj(i),0,true,true); lsq.PrepareRefParList(true); lsq.SetParIsUsed(gpRefParTypeScatt,false); lsq.SetParIsUsed(gpRefParTypeScattPow,false); bool fitzero=false,fitwidth0=false,fitwidth=false,fiteta=false, fitasym=false,fitdispltransp=false,fitbackgd=false,fitcell=false, fitTOFInstWidth=false,fitTOFBroadening=false; if(gPowderPatternRegistry.GetObj(i).GetRadiation().GetWavelengthType()==WAVELENGTH_TOF) { fitzero=true; fitTOFInstWidth=true; fitTOFBroadening=true; fitbackgd=true; fitcell=true; } else { fitzero=true; fitwidth0=true; fitwidth=true; fiteta=true; fitasym=true; fitdispltransp=true; fitbackgd=true; fitcell=true; } cout<::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) cout<<" "<<(*pos)->GetName()<<"(Crystal:"<<(*pos)->GetCrystal().GetName()<<")"<::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) lsq.SetParIsFixed((*pos)->GetProfile().GetPar("W"),false); if(fitzero||fitwidth0) { lsq.Refine(5,true,true); for(set::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) (*pos)->ExtractLeBail(2); } if(fitwidth) for(set::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) lsq.SetParIsFixed((*pos)->GetProfile().GetPar("U"),false); if(fitwidth) for(set::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) lsq.SetParIsFixed((*pos)->GetProfile().GetPar("V"),false); if(fiteta) for(set::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) lsq.SetParIsFixed((*pos)->GetProfile().GetPar("Eta0"),false); if(fitwidth||fiteta) { lsq.Refine(5,true,true); for(set::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) (*pos)->ExtractLeBail(2); } if(fitTOFInstWidth) {// TOF for(set::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) { lsq.SetParIsFixed((*pos)->GetProfile().GetPar("Alpha1"),false); lsq.SetParIsFixed((*pos)->GetProfile().GetPar("Beta0"),false); lsq.SetParIsFixed((*pos)->GetProfile().GetPar("Beta1"),false); } lsq.Refine(5,true,true); for(set::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) (*pos)->ExtractLeBail(2); } if(fitTOFBroadening) {// TOF for(set::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) { lsq.SetParIsFixed((*pos)->GetProfile().GetPar("GaussianSigma1"),false); //lsq.SetParIsFixed(pos->GetProfile().GetPar("LorentzianGamma2"),false); //lsq.SetParIsFixed(pos->GetProfile().GetPar("GaussianSigma1"),0,1e6); //lsq.SetParIsFixed(pos->GetProfile().GetPar("LorentzianGamma2"),0,1e6); } lsq.Refine(5,true,true); for(set::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) (*pos)->ExtractLeBail(2); for(set::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) lsq.SetParIsFixed((*pos)->GetProfile().GetPar("GaussianSigma1"),true); } if(fiteta) for(set::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) lsq.SetParIsFixed((*pos)->GetProfile().GetPar("Eta1"),false); if(fiteta) { lsq.Refine(5,true,true); for(set::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) (*pos)->ExtractLeBail(2); } if(fitasym) for(set::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) lsq.SetParIsFixed((*pos)->GetProfile().GetPar("Asym0"),false); if(fitasym) for(set::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) lsq.SetParIsFixed((*pos)->GetProfile().GetPar("Asym1"),false); if(fitasym) for(set::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) lsq.SetParIsFixed((*pos)->GetProfile().GetPar("Asym2"),false); if(fitdispltransp) for(set::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) lsq.SetParIsFixed((*pos)->GetParentPowderPattern().GetPar("2ThetaDispl"),false); if(fitdispltransp) for(set::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) lsq.SetParIsFixed((*pos)->GetParentPowderPattern().GetPar("2ThetaTransp"),false); if(fitdispltransp||fitasym) { lsq.Refine(5,true,true); for(set::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) (*pos)->ExtractLeBail(2); } if(fitbackgd) { lsq.SetParIsFixed(gpRefParTypeScattDataBackground,false); // Make sure points beyond max resolution are not optimized for(unsigned int k=0;k (&(gPowderPatternRegistry.GetObj(i).GetPowderPatternComponent(k))); pback->FixParametersBeyondMaxresolution(lsq.GetCompiledRefinedObj()); } lsq.Refine(5,true,true); for(set::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) (*pos)->ExtractLeBail(2); } if(fitcell) { lsq.SetParIsFixed(gpRefParTypeUnitCell,false); lsq.Refine(5,true,true); for(set::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) (*pos)->ExtractLeBail(2); } } catch(const ObjCrystException &except) { cout<<"Oups: automatic profile fit + Le Bail went wrong, please try manual fit within GUI"<OnExit(); #else TAU_REPORT_STATISTICS(); #endif exit(0); */ } if(exportfullprof) { // Find every powder pattern, export to fullprof for(unsigned int i=0;iOnExit(); #endif exit(0); } if(cif2pattern) { #ifdef __WX__CRYST__ this->OnExit(); #endif exit(0); } if(randomize) for(int i=0;i(&(gOptimizationObjRegistry.GetObj(i))); Chronometer chrono; pMonteCarloObj->InitLSQ(false); cout<<"Fox: running LSQ test for profiling"<GetLSQObj().Refine(100,true,true,true); cout<<" LSQ tests - SUCCESS -, elapsed time for 100 cycles (full pattern=true ):"<OnExit(); #endif return 0; } if(testMC) { for(int i=0;iOnExit(); #endif return 0; } if(testSPEED) { standardSpeedTest(); //TAU_REPORT_STATISTICS(); #ifdef __WX__CRYST__ this->OnExit(); #endif return 0; } if(!useGUI) { if(nbTrial!=0) { if(nbRun==1) { for(int i=0;i=0) { char costAsChar[50]; sprintf(costAsChar,"-Cost-%f",gOptimizationObjRegistry.GetObj(0).GetLogLikelihood()); string tmpstr2=costAsChar; tmpstr.replace(filenameInsertCost,5,tmpstr2,0,tmpstr2.length()); } XMLCrystFileSaveGlobal(tmpstr); cout <<"End of Fox execution. Bye !"<OnExit(); #endif exit(0); } #ifdef __WX__CRYST__ wxSocketBase::Initialize();// Need this for threaded check of updates this->SetVendorName(_T("http://fox.vincefn.net/")); this->SetAppName(_T("FOX-Free Objects for Crystallography")); // Read (and automatically create if necessary) global Fox preferences // We explicitely use a wxFileConfig, to avoid the registry under Windows wxConfigBase::Set(new wxFileConfig(_T("FOX-Free Objects for Crystallography"))); if(wxConfigBase::Get()->HasEntry(_T("Fox/BOOL/Enable tooltips"))) { bool tooltip_enabled; wxConfigBase::Get()->Read(_T("Fox/BOOL/Enable tooltips"), &tooltip_enabled); wxToolTip::Enable(tooltip_enabled); wxToolTip::SetDelay(500); } else wxConfigBase::Get()->Write(_T("Fox/BOOL/Enable tooltips"), true); if(!wxConfigBase::Get()->HasEntry(_T("Fox/BOOL/Ask confirmation before exiting Fox"))) wxConfigBase::Get()->Write(_T("Fox/BOOL/Ask confirmation before exiting Fox"), true); if(!wxConfigBase::Get()->HasEntry(_T("Fox/BOOL/Use compressed file format (.xmlgz)"))) wxConfigBase::Get()->Write(_T("Fox/BOOL/Use compressed file format (.xmlgz)"), true); if(!wxConfigBase::Get()->HasEntry(_T("Fox/BOOL/Check for Fox updates"))) wxConfigBase::Get()->Write(_T("Fox/BOOL/Check for Fox updates"), true); if(!wxConfigBase::Get()->HasEntry(_T("Fox/BOOL/CIF import: automatically convert to molecules"))) wxConfigBase::Get()->Write(_T("Fox/BOOL/CIF import: automatically convert to molecules"), true); if(!wxConfigBase::Get()->HasEntry(_T("Fox/BOOL/CIF import: only one scattering power per element"))) wxConfigBase::Get()->Write(_T("Fox/BOOL/CIF import: only one scattering power per element"), true); string title(string("FOX: Free Objects for Xtal structures v")+foxVersion); mpFrame = new WXCrystMainFrame(wxString::FromAscii(title.c_str()), wxPoint(50, 50), wxSize(600, 600), !(loadFourierGRD||loadFourierDSN6||runclient)); // Use the main frame status bar to pass messages to the user pLogWindowForUserMessage=mpFrame->GetLogWindow(); fpObjCrystInformUser=&WXCrystInformUserStdOut; WXCrystal *pWXCryst; if(loadFourierGRD || loadFourierDSN6) { //wxFrame *pWXFrame= new wxFrame((wxFrame *)NULL, -1, "FOX", wxPoint(50, 50), wxSize(550, 400)); //wxScrolledWindow *pWXScWin=new wxScrolledWindow(pWXFrame,-1); //WXCrystal * pWXCrystal=new WXCrystal(pWXScWin,&(gCrystalRegistry.GetObj(0))); pWXCryst=dynamic_cast (gCrystalRegistry.GetObj(0).WXGet()); wxCommandEvent com; pWXCryst->OnMenuCrystalGL(com); } if(loadFourierGRD) { list::iterator pos; for(pos=vFourierFilenameGRD.begin();pos!=vFourierFilenameGRD.end();++pos) { UnitCellMap *pMap=new UnitCellMap(pWXCryst->GetCrystal()); cout<<"Reading Fourier file:"<<*pos<ImportGRD(*pos) == 0) { cout<<"Error reading Fourier file:"<< *pos<GetCrystalGL()->AddFourier(pMap); } } if(loadFourierDSN6) { list::iterator pos; for(pos=vFourierFilenameDSN6.begin();pos!=vFourierFilenameDSN6.end();++pos) { UnitCellMap *pMap=new UnitCellMap(pWXCryst->GetCrystal()); cout<<"Reading Fourier file:"<<*pos<ImportDSN6(*pos) == 0) { cout<<"Error reading Fourier file:"<< *pos<GetCrystalGL()->AddFourier(pMap); } } if(runclient) { wxString dir = wxPathOnly(argv[0]); wxSetWorkingDirectory(dir); wxCommandEvent com; //mpFrame->OnStartGridClient(com); mpFrame->mpGridWindow->m_working_dir = wxString::FromAscii(working_dir.c_str()); mpFrame->mpGridWindow->StartClientWindow(); if(nbCPUs!=-1) { mpFrame->mpGridWindow->m_WXFoxClient->setNbCPU(nbCPUs); } mpFrame->mpGridWindow->m_WXFoxClient->m_IPWindow->SetValue(wxString::FromAscii(IP.c_str())); mpFrame->mpGridWindow->m_WXFoxClient->OnConnectClient(com); } return TRUE; #else return 0; #endif } #ifdef __WX__CRYST__ int MyApp::OnExit() { delete wxConfigBase::Set((wxConfigBase *) NULL); TAU_REPORT_STATISTICS(); return this->wxApp::OnExit(); } #ifdef __WXMAC__ void MyApp::MacOpenFile(const wxString &fileName) { if(vMacOpenFile_Ignore.count(fileName)>0) vMacOpenFile_Ignore.erase(fileName); else mpFrame->Load(fileName); } #endif // ---------------------------------------------------------------------------- // WXCrystScrolledWindow // ---------------------------------------------------------------------------- WXCrystScrolledWindow::WXCrystScrolledWindow(wxWindow* parent): wxScrolledWindow(parent),mpChild((wxWindow*)0),mHeight(-1),mWidth(-1) { mpSizer=new wxBoxSizer(wxHORIZONTAL); this->SetSizer(mpSizer); //this->FitInside(); this->SetScrollRate(10,10); } bool WXCrystScrolledWindow::Layout() { //this->Scroll(0,0);//workaround bug ? return this->wxScrolledWindow::Layout(); } void WXCrystScrolledWindow::SetChild(wxWindow* pChild) { mpChild=pChild; mpSizer->Add(mpChild); // Initialize scrollbars //this->SetScrollbars(40,40,2,2); } void WXCrystScrolledWindow::OnWXCrystChildFocus(wxChildFocusEvent& event) { // Workaround for wx 2.8.8+ bug event.Skip(false); } // ---------------------------------------------------------------------------- // main frame // ---------------------------------------------------------------------------- WXCrystMainFrame::WXCrystMainFrame(const wxString& title, const wxPoint& pos, const wxSize& size, const bool splashscreen) : wxFrame((wxFrame *)NULL, -1, title, pos, size), mpNotebook(NULL), mvUpdatesAutoCheck(false) #ifdef __FOX_COD__ ,mpCODFrame(0) #endif { #ifdef __WXMAC__ // we need this in order to allow the about menu relocation, since ABOUT is // not the default id of the about menu wxApp::s_macAboutMenuItemId = MENU_HELP_ABOUT; #endif // create a menu bar wxMenu *menuFile = new wxMenu;// menuFile->Append(MENU_FILE_LOAD, _T("&Open .xml or .cif\tCtrl-O"), _T("Open Fox (.xml, .xmlgz) or CIF file")); menuFile->Append(MENU_FILE_CLOSE, _T("Close\tCtrl-W"), _T("Close all")); menuFile->Append(MENU_FILE_SAVE, _T("&Save\tCtrl-S"), _T("Save Everything...")); menuFile->Append(MENU_FILE_QUIT, _T("Exit\tCtrl-Q"), _T("Quit ")); menuFile->AppendSeparator(); menuFile->Append(MENU_FILE_BROWSE, _T("&Browse .xml, .xmlgz or .cif files...\tCtrl-B"), _T("Browse .xml, .xmlgz or .cif files...")); wxMenu *objectMenu = new wxMenu(_T(""), wxMENU_TEAROFF); objectMenu->Append(MENU_OBJECT_CREATE_CRYSTAL, _T("&New Crystal\tCtrl-N"), _T("Add a new Crystal structure")); objectMenu->Append(MENU_OBJECT_CREATE_POWDERSPECTRUM, _T("New PowderPattern"), _T("Add a new PowderPattern Object")); objectMenu->Append(MENU_OBJECT_CREATE_SINGLECRYSTALDATA, _T("New Single Crystal Diffraction"), _T("Add a new Single Crystal Diffraction Object")); objectMenu->Append(MENU_OBJECT_CREATE_GLOBALOPTOBJ, _T("New Monte-Carlo Object"), _T("Add a new Monte-Carlo Object")); #ifdef __FOX_UNDO__ wxMenu *menuEdit = new wxMenu;// menuEdit->Append(wxID_UNDO, _T("&Undo\tCtrl-Z"), _T("Undo last change in objects (EXPERIMENTAL)")); menuEdit->Append(wxID_REDO, _T("&Redo\tCtrl-Y"), _T("Redo next change in objects (EXPERIMENTAL)")); #endif //FoxGrid//////////////////////////////////////////////////////////////////// wxMenu *gridMenu = new wxMenu; gridMenu->Append(MENU_GRID_SERVER_RUN, _T("&Run Server"), _T("Start Fox Grid Server")); gridMenu->AppendSeparator(); gridMenu->Append(MENU_GRID_CLIENT_START, _T("&Start Client"), _T("Start Fox Grid Client")); wxMenu *prefsMenu = new wxMenu; prefsMenu->Append(MENU_PREFS_PREFERENCES, _T("&Preferences..."), _T("Fox Preferences...")); wxMenu *helpMenu = new wxMenu; helpMenu->Append(MENU_HELP_ABOUT, _T("&About..."), _T("About ObjCryst...")); helpMenu->Append(MENU_HELP_TOGGLETOOLTIP, _T("Toggle Tooltips"), _T("Set Tooltips on/off")); helpMenu->Append(MENU_HELP_UPDATE, _T("Check for Updates"), _T("Check for a newer version of Fox")); #ifdef __FOX_COD__ wxMenu *codMenu = new wxMenu; codMenu->Append(MENU_COD,_T("Cryst. Open &Database\tCtrl-D"),_T("Search structures on the Crystallographic Open Database (COD)")); #endif wxMenuBar *menuBar = new wxMenuBar(); menuBar->Append(menuFile, _T("&File")); menuBar->Append(objectMenu,_T("&Objects")); #ifdef __FOX_UNDO__ menuBar->Append(menuEdit,_T("Edit")); #endif #ifdef __FOX_COD__ menuBar->Append(codMenu,_T("COD")); #endif //FoxGrid///////////////////////////// menuBar->Append(gridMenu,_T("FOX&Grid")); menuBar->Append(prefsMenu, _T("&Preferences")); menuBar->Append(helpMenu, _T("&Help")); #ifdef __DEBUG__ wxMenu *debugMenu = new wxMenu; debugMenu->Append(MENU_DEBUG_TEST1, _T("Test #1")); debugMenu->Append(MENU_DEBUG_TEST2, _T("Test #2")); debugMenu->Append(MENU_DEBUG_TEST3, _T("Test #3")); debugMenu->Append(MENU_DEBUG_LEVEL0, _T("Debug level 0 (lots of messages)")); debugMenu->Append(MENU_DEBUG_LEVEL1, _T("Debug level 1")); debugMenu->Append(MENU_DEBUG_LEVEL2, _T("Debug level 2")); debugMenu->Append(MENU_DEBUG_LEVEL3, _T("Debug level 3")); debugMenu->Append(MENU_DEBUG_LEVEL4, _T("Debug level 4")); debugMenu->Append(MENU_DEBUG_LEVEL5, _T("Debug level 5")); debugMenu->Append(MENU_DEBUG_LEVEL6, _T("Debug level 6")); debugMenu->Append(MENU_DEBUG_LEVEL7, _T("Debug level 7")); debugMenu->Append(MENU_DEBUG_LEVEL8, _T("Debug level 8")); debugMenu->Append(MENU_DEBUG_LEVEL9, _T("Debug level 9")); debugMenu->Append(MENU_DEBUG_LEVEL10,_T("Debug level 10 (few messages)")); menuBar->Append(debugMenu, _T("&Debug")); #endif SetMenuBar(menuBar); #if 0 // wxUSE_STATUSBAR CreateStatusBar(1); SetStatusText(_T("Welcome to FOX/ObjCryst++!")); #endif // wxUSE_STATUSBAR wxSizer* s0 = new wxBoxSizer(wxVERTICAL); this->SetSizer(s0); this->SetAutoLayout(true); // Create the notebook mpNotebook = new wxNotebook(this, -1); s0->Add(mpNotebook,1,wxEXPAND); //wxSizer* s = new wxBoxSizer(wxHORIZONTAL); //mpNotebook->SetSizer(s); // First window -Crystals WXCrystScrolledWindow *mpWin1 = new WXCrystScrolledWindow(mpNotebook); mpWin1->SetChild(gCrystalRegistry.WXCreate(mpWin1)); mpWin1->Layout(); mpNotebook->AddPage(mpWin1, _T("Crystals"), TRUE); // Second window - PowderPattern WXCrystScrolledWindow *mpWin2 = new WXCrystScrolledWindow(mpNotebook); mpWin2->SetChild(gPowderPatternRegistry.WXCreate(mpWin2)); mpWin2->Layout(); mpNotebook->AddPage(mpWin2,_T("Powder Diffraction"),true); // Third window - SingleCrystal WXCrystScrolledWindow *mpWin3 = new WXCrystScrolledWindow(mpNotebook); mpWin3->SetChild(gDiffractionDataSingleCrystalRegistry.WXCreate(mpWin3)); mpWin3->Layout(); mpNotebook->AddPage(mpWin3,_T("Single Crystal Diffraction"),true); // Fourth window - Global Optimization WXCrystScrolledWindow *mpWin4 = new WXCrystScrolledWindow(mpNotebook); mpWin4->SetChild(gOptimizationObjRegistry.WXCreate(mpWin4)); mpWin4->Layout(); mpNotebook->AddPage(mpWin4,_T("Global Optimization"),true); // Fift window - FoxGrid WXCrystScrolledWindow *mpWin5 = new WXCrystScrolledWindow(mpNotebook); mpGridWindow = new WXGrigWindow(mpWin5); mpWin5->SetChild(mpGridWindow); mpWin5->Layout(); mpNotebook->AddPage(mpWin5,_T("FOXGrid"),true); mpNotebook->SetSelection(0); // Log windows mpLog =new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(600,100),wxTE_MULTILINE|wxTE_READONLY|wxTE_DONTWRAP); mpLog->SetFont(wxFont(10,wxTELETYPE,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL)); s0->Add(mpLog,0,wxEXPAND); mpLog->AppendText(wxString::Format(_T("Welcome to FOX !\n"))); this->SetIcon(wxICON(Fox)); this->Show(TRUE); this->Layout(); // Set tooltip delay wxToolTip::SetDelay(500); // Reset "last save" clock, in the case we loaded an xml file on startup mClockLastSave.Click(); #if 0 // Check for updates in a separate thread bool check; wxConfigBase::Get()->Read("Fox/BOOL/Check for Fox updates", &check); if(check || ((rand()%10)==0)) { WXThreadCheckUpdates *pThreadCheckUpdates = new WXThreadCheckUpdates(mvUpdates,*this); if(pThreadCheckUpdates->Create() != wxTHREAD_NO_ERROR) wxLogError("Can't create updates check thread"); else pThreadCheckUpdates->Run(); mvUpdatesAutoCheck=true; } #endif //Splash Screen if(true==splashscreen) { wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,MENU_HELP_ABOUT); wxPostEvent(this,event); } } void WXCrystMainFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) { this->SafeQuit(); } class WXDialogFoxAbout:public wxDialog { public: WXDialogFoxAbout(wxWindow* parent); void OnButtonCheckUpdate(wxCommandEvent &ev); #ifdef __WXGTK__ void OnWindowCreate(wxWindowCreateEvent &WXUNUSED(evt)); #endif DECLARE_EVENT_TABLE() }; BEGIN_EVENT_TABLE(WXDialogFoxAbout, wxDialog) EVT_BUTTON(ID_ABOUT_FOX_BUTTON_UPDATE, WXDialogFoxAbout::OnButtonCheckUpdate) #ifdef __WXGTK__ EVT_WINDOW_CREATE(WXDialogFoxAbout::OnWindowCreate) #endif END_EVENT_TABLE() WXDialogFoxAbout::WXDialogFoxAbout(wxWindow* parent): wxDialog(parent,-1,_T("About Fox"),wxDefaultPosition,wxDefaultSize,wxCAPTION|wxSTAY_ON_TOP|wxCLOSE_BOX) { wxBoxSizer *sizer=new wxBoxSizer(wxVERTICAL); string msg(string("F.O.X. - Free Objects for Xtallography\n") +"Version "+ foxVersion +" \n\n" +"(c) 2000- Vincent FAVRE-NICOLIN, favre@esrf.fr,\n" +" ESRF and Univ. Grenoble Alpes\n" +" 2000-2001 Radovan CERNY, University of Geneva\n" +" 2009- Jan Rohlicek, Michal Husak (Inst. Chem. Tech, Prague)\n\n" +"http://fox.vincefn.net\n" +"https://github.com/vincefn/objcryst\n\n" +"FOX comes with ABSOLUTELY NO WARRANTY. It is free software, and you are\n" +"welcome to redistribute it under certain conditions. \n" +"See the LICENSE file for details.\n\n"); wxStaticText *txt=new wxStaticText(this,-1,wxString::FromAscii(msg.c_str()),wxDefaultPosition,wxDefaultSize,wxALIGN_LEFT); sizer->Add(txt); wxBoxSizer *sizer2=new wxBoxSizer(wxHORIZONTAL); sizer2->Add(this->CreateButtonSizer(wxOK)); sizer2->Add(new wxButton(this,ID_ABOUT_FOX_BUTTON_UPDATE,_T("Check for Updates")) ); sizer->Add(0,4,0); sizer->Add(sizer2); this->SetSizer(sizer); this->Fit(); } #ifdef __WXGTK__ void WXDialogFoxAbout::OnWindowCreate(wxWindowCreateEvent &WXUNUSED(evt)) { // necessary because of delayed decorations (see wx book, page 61-62) this->Fit(); } #endif void WXDialogFoxAbout::OnButtonCheckUpdate(wxCommandEvent &ev) { this->EndModal(int(ID_ABOUT_FOX_BUTTON_UPDATE)); } void WXCrystMainFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) { WXDialogFoxAbout ab(this); if(ab.ShowModal()==ID_ABOUT_FOX_BUTTON_UPDATE) { wxCommandEvent ev(wxEVT_COMMAND_MENU_SELECTED,MENU_HELP_UPDATE); wxPostEvent(this,ev); } } void WXCrystMainFrame::OnLoad(wxCommandEvent& event) { // First record if any object already in memory need to be saved bool saved=true; for(int i=0;imClockLastSave) { saved=false; break; } wxFileDialog *open; if(event.GetId()==MENU_FILE_LOAD) { open= new wxFileDialog(this,_T("Choose File :"), _T(""),_T(""),_T("FOX files (*.xml,*.xmlgz) or CIF (*.cif)|*.xml;*.xmlgz;*.gz;*.cif"),wxFD_OPEN | wxFD_FILE_MUST_EXIST); if(open->ShowModal() != wxID_OK) return; wxString name=open->GetPath(); this->Load(name); } open->Destroy(); if(saved) mClockLastSave.Click(); } void WXCrystMainFrame::Load(const wxString &filename) { VFN_DEBUG_ENTRY("WXCrystMainFrame::Load("<4) { if(filename.Mid(filename.size()-4)==wxString(_T(".xml"))) { wxFileInputStream is(filename); stringstream in; if(is.GetSize()>0) { char * tmpbuf=new char[is.GetSize()]; is.Read(tmpbuf,is.GetSize()); in.write(tmpbuf,is.GetSize()); delete[] tmpbuf; } else while (!is.Eof()) in<<(char)is.GetC(); try{XMLCrystFileLoadAllObject(in);} catch(const ObjCrystException &except) { wxMessageDialog d(this,_T("Failed loading file1:\n")+filename,_T("Error loading file"),wxOK|wxICON_ERROR); d.ShowModal(); this->PostSizeEvent(); VFN_DEBUG_EXIT("WXCrystMainFrame::Load("<DataLoaded(); } else if(filename.Mid(filename.size()-4)==wxString(_T(".cif"))) { wxFileInputStream is(filename); stringstream in; if(is.GetSize()>0) { char * tmpbuf=new char[is.GetSize()]; is.Read(tmpbuf,is.GetSize()); in.write(tmpbuf,is.GetSize()); delete[] tmpbuf; } else while (!is.Eof()) in<<(char)is.GetC(); FoxLoadCIF(in); //FoxGrid mpGridWindow->DataLoaded(); } else { bool gz=false; if(filename.size()>6) if(filename.Mid(filename.size()-6)==wxString(_T("xml.gz"))) gz=true; if(filename.size()>6) if(filename.Mid(filename.size()-6)==wxString(_T(".xmlgz"))) gz=true; if(gz) {//compressed file wxFileInputStream is(filename); wxZlibInputStream zstream(is); stringstream sst; while (!zstream.Eof()) sst<<(char)zstream.GetC(); try{XMLCrystFileLoadAllObject(sst);} catch(const ObjCrystException &except) { wxMessageDialog d(this,_T("Failed loading file2:\n")+filename,_T("Error loading file"),wxOK|wxICON_ERROR); d.ShowModal(); this->PostSizeEvent(); VFN_DEBUG_EXIT("WXCrystMainFrame::Load("<DataLoaded(); } } } VFN_DEBUG_MESSAGE("WXCrystMainFrame::Load():sending event", 10) this->PostSizeEvent(); VFN_DEBUG_EXIT("WXCrystMainFrame::Load("<Append(filename); } if(wxNOT_FOUND!=filename.Find(_T(".cif"))) { mpBrowseList->Append(filename); } } cont = wxBrowseDir.GetNext(&filename); } frame->Show(true); } void WXCrystMainFrame::OnBrowseSelect(wxCommandEvent &event) { if(false==event.IsSelection()) return; this->Close(false); wxArrayInt selections; mpBrowseList->GetSelections(selections); for(int i=0;iLoad(mBrowseDir+_T("\\")+mpBrowseList->GetString(selections.Item(i))); #else this->Load(mBrowseDir+_T("/")+mpBrowseList->GetString(selections.Item(i))); #endif } this->PostSizeEvent(); } void WXCrystMainFrame::OnMenuClose(wxCommandEvent& event) { bool safe; wxConfigBase::Get()->Read(_T("Fox/BOOL/Ask confirmation before exiting Fox"),&safe); this->Close(safe); } void WXCrystMainFrame::Close(bool safe) { if(safe) { bool saved=true; for(int i=0;imClockLastSave) { saved=false; break; } if(!saved) { wxString msg; msg.Printf( _T("Some objects have not been saved\n") _T("Do you really want to close all ?")); wxMessageDialog d(this,msg, _T("Really Close ?"), wxYES | wxNO); if(wxID_YES!=d.ShowModal()) return; } } cout<<"Removing all Optimization objects..."<SafeQuit(); } void WXCrystMainFrame::SafeQuit() { if(mpGridWindow->m_WXFoxServer!=NULL) { wxMessageDialog d(this,_T("You are trying to close the FOX GRID server. Are you sure?"), _T(""), wxYES | wxNO | wxCENTER | wxSTAY_ON_TOP); if(wxID_YES!=d.ShowModal()) return; } if(mpGridWindow->m_WXFoxClient!=NULL){ wxMessageDialog d(this,_T("You are trying to close the FOX GRID client. Are you sure?"), _T(""), wxYES | wxNO | wxCENTER | wxSTAY_ON_TOP); if(wxID_YES!=d.ShowModal()) return; mpGridWindow->m_WXFoxClient->CloseClient(); } bool safe=true; wxConfigBase::Get()->Read(_T("Fox/BOOL/Ask confirmation before exiting Fox"),&safe); if(!safe) { this->Destroy(); return; } bool saved=true; for(int i=0;imClockLastSave) { saved=false; break; } if(!saved) { wxString msg; msg.Printf( _T("Some objects have not been saved\n") _T("Do you really want to Exit ?")); wxMessageDialog d(this,msg, _T("Really Exit ?"), wxYES | wxNO | wxCENTER | wxSTAY_ON_TOP); if(wxID_YES!=d.ShowModal()) return; } cout<<"Removing all Optimization objects..."<Clear(); mpGridWindow->Destroy(); this->Destroy(); } void WXCrystMainFrame::OnSave(wxCommandEvent& WXUNUSED(event)) { WXCrystValidateAllUserInput(); bool compressed; wxConfigBase::Get()->Read(_T("Fox/BOOL/Use compressed file format (.xmlgz)"),&compressed); if(compressed) { wxFileDialog open(this,_T("Choose File to save all objects:"), _T(""),_T(""),_T("FOX compressed files (*.xmlgz)|*.xmlgz"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if(open.ShowModal() != wxID_OK) return; wxString name=open.GetPath(); if(name.substr(name.size()-6,6)!=_T(".xmlgz")) { cout< "< "<SetName(s.str()); if(!wxConfigBase::Get()->HasEntry(_T("Crystal/BOOL/Default-use Dynamical Occupancy Correction"))) wxConfigBase::Get()->Write(_T("Crystal/BOOL/Default-use Dynamical Occupancy Correction"), true); else { bool doc; wxConfigBase::Get()->Read(_T("Crystal/BOOL/Default-use Dynamical Occupancy Correction"), &doc); if(doc) obj->GetOption(0).SetChoice(0); else obj->GetOption(0).SetChoice(1); } obj->UpdateDisplay(); mpNotebook->SetSelection(0); // Fake pdf for linking ? //PDF pdf; //pdf.GetPDFR(); this->PostSizeEvent(); } void WXCrystMainFrame::OnAddPowderPattern(wxCommandEvent& WXUNUSED(event)) { PowderPattern* obj; obj=new PowderPattern; stringstream s;s<<"Powder Pattern #"<SetName(s.str()); obj->SetMaxSinThetaOvLambda(0.4); obj->UpdateDisplay(); mpNotebook->SetSelection(1); this->PostSizeEvent(); } void WXCrystMainFrame::OnAddSingleCrystalData(wxCommandEvent& WXUNUSED(event)) { WXCrystValidateAllUserInput(); Crystal *cryst; if(gCrystalRegistry.GetNb()==1) cryst=&(gCrystalRegistry.GetObj(0)); else { int choice; cryst=dynamic_cast (WXDialogChooseFromRegistry(gCrystalRegistry,(wxWindow*)this, "Choose a Crystal Structure:",choice)); if(0==cryst) return; } DiffractionDataSingleCrystal* obj; obj=new DiffractionDataSingleCrystal(*cryst); stringstream s;s<<"Diffraction data for "<GetName(); obj->SetName(s.str()); obj->SetMaxSinThetaOvLambda(0.4); obj->UpdateDisplay(); mpNotebook->SetSelection(2); this->PostSizeEvent(); } void WXCrystMainFrame::OnAddGlobalOptimObj(wxCommandEvent& WXUNUSED(event)) { stringstream s;s<<"OptimizationObj #"<SetSelection(3); this->PostSizeEvent(); } void WXCrystMainFrame::OnAddGeneticAlgorithm(wxCommandEvent& WXUNUSED(event)) { //GeneticAlgorithm* obj; //obj=new GeneticAlgorithm("Change Me!"); } void WXCrystMainFrame::OnUndo(wxCommandEvent &ev) { gConfigHistory.Previous(); } void WXCrystMainFrame::OnRedo(wxCommandEvent &ev) { gConfigHistory.Next(); } //FOXGrid void WXCrystMainFrame::OnStartGridServer(wxCommandEvent &event) { if((mpGridWindow->m_WXFoxServer!=NULL)||(mpGridWindow->m_WXFoxClient!=NULL)) { wxMessageDialog d(this,"You have already either a Grid client or server\n running in this instance of Fox !","Error",wxOK|wxICON_ERROR); d.ShowModal(); return; } VFN_DEBUG_ENTRY("WXCrystMainFrame::OnStartGridServer()",10) wxDirDialog dlg(this, _T("Choose working directory (check write and read permissions!)")); if(dlg.ShowModal()!=wxID_OK) return; wxString dirName; #ifdef WIN32 dirName = dlg.GetPath() + _T("\\GridRslt"); #else dirName = dlg.GetPath() + _T("/GridRslt"); #endif if(!wxDirExists(dirName)) wxMkdir(dirName); mpGridWindow->m_working_dir = dlg.GetPath(); if(mpGridWindow->StartServer()==NULL) return; VFN_DEBUG_EXIT("WXCrystMainFrame::OnStartGridServer()",10) mpNotebook->SetSelection(4); } void WXCrystMainFrame::OnStartGridClient(wxCommandEvent &event) { if((mpGridWindow->m_WXFoxServer!=NULL)||(mpGridWindow->m_WXFoxClient!=NULL)) { wxMessageDialog d(this,"You have already either a Grid client or server\n running in this instance of Fox !","Error",wxOK|wxICON_ERROR); d.ShowModal(); return; } wxDirDialog dlg(this, _T("Choose working directory (check write and read permissions!)")); if(dlg.ShowModal()!=wxID_OK) return; mpGridWindow->m_working_dir = dlg.GetPath(); if(mpGridWindow->StartClientWindow()==NULL) return; mpNotebook->SetSelection(4); } void WXCrystMainFrame::OnSetDebugLevel(wxCommandEvent& event) { if(event.GetId()== MENU_DEBUG_LEVEL0 ){VFN_DEBUG_GLOBAL_LEVEL(0);} if(event.GetId()== MENU_DEBUG_LEVEL1 ){VFN_DEBUG_GLOBAL_LEVEL(1);} if(event.GetId()== MENU_DEBUG_LEVEL2 ){VFN_DEBUG_GLOBAL_LEVEL(2);} if(event.GetId()== MENU_DEBUG_LEVEL3 ){VFN_DEBUG_GLOBAL_LEVEL(3);} if(event.GetId()== MENU_DEBUG_LEVEL4 ){VFN_DEBUG_GLOBAL_LEVEL(4);} if(event.GetId()== MENU_DEBUG_LEVEL5 ){VFN_DEBUG_GLOBAL_LEVEL(5);} if(event.GetId()== MENU_DEBUG_LEVEL6 ){VFN_DEBUG_GLOBAL_LEVEL(6);} if(event.GetId()== MENU_DEBUG_LEVEL7 ){VFN_DEBUG_GLOBAL_LEVEL(7);} if(event.GetId()== MENU_DEBUG_LEVEL8 ){VFN_DEBUG_GLOBAL_LEVEL(8);} if(event.GetId()== MENU_DEBUG_LEVEL9 ){VFN_DEBUG_GLOBAL_LEVEL(9);} if(event.GetId()== MENU_DEBUG_LEVEL10){VFN_DEBUG_GLOBAL_LEVEL(10);} } void WXCrystMainFrame::OnDebugTest(wxCommandEvent& event) { WXCrystValidateAllUserInput(); static long saveId=-1; static long saveId2=-1; if(event.GetId()== MENU_DEBUG_TEST1) { if(saveId==-1) saveId=gScattererRegistry.GetObj(0).CreateParamSet(); else gScattererRegistry.GetObj(0).SaveParamSet(saveId); gScattererRegistry.GetObj(0).GlobalOptRandomMove(1); gCrystalRegistry.GetObj(0).UpdateDisplay(); if(saveId2==-1) saveId2=gScattererRegistry.GetObj(0).CreateParamSet(); else gScattererRegistry.GetObj(0).SaveParamSet(saveId2); } if(event.GetId()== MENU_DEBUG_TEST2) { Crystal *cryst=new Crystal(25.,30.,35.,"P1"); ScatteringPowerAtom *ScattPowS=new ScatteringPowerAtom("S" ,"S",0.74); ScatteringPowerAtom *ScattPowO=new ScatteringPowerAtom("O","O",1.87); cryst->AddScatteringPower(ScattPowS); cryst->AddScatteringPower(ScattPowO); Molecule *mol; mol=MakeOctahedron(*cryst,"SO6",ScattPowS,ScattPowO,1.5); cryst->AddScatterer(mol); mol->CreateCopy(); } if(event.GetId()== MENU_DEBUG_TEST3) { Crystal *cryst=new Crystal(25.,30.,35.,"P1"); ScatteringPowerAtom *ScattPowS=new ScatteringPowerAtom("S" ,"S",0.74); ScatteringPowerAtom *ScattPowO=new ScatteringPowerAtom("O","O",1.87); cryst->AddScatteringPower(ScattPowS); cryst->AddScatteringPower(ScattPowO); Molecule *mol; mol=MakeTetrahedron(*cryst,"SO4",ScattPowS,ScattPowO,1.5); mol->RestraintStatus(cout);cryst->AddScatterer(mol); mol=MakeOctahedron(*cryst,"SO6",ScattPowS,ScattPowO,1.5); mol->RestraintStatus(cout);cryst->AddScatterer(mol); mol=MakeSquarePlane(*cryst,"SO6",ScattPowS,ScattPowO,1.5); mol->RestraintStatus(cout);cryst->AddScatterer(mol); mol=MakeCube(*cryst,"SO8",ScattPowS,ScattPowO,1.5); mol->RestraintStatus(cout);cryst->AddScatterer(mol); mol=MakePrismTrigonal(*cryst,"SO6",ScattPowS,ScattPowO,1.5); mol->RestraintStatus(cout);cryst->AddScatterer(mol); mol=MakeIcosahedron(*cryst,"SO12",ScattPowS,ScattPowO,1.5); mol->RestraintStatus(cout);cryst->AddScatterer(mol); mol=MakeTriangle(*cryst,"SO3",ScattPowS,ScattPowO,1.5); mol->RestraintStatus(cout);cryst->AddScatterer(mol); mol=MakeAntiPrismTetragonal(*cryst,"SO8",ScattPowS,ScattPowO,1.5); mol->RestraintStatus(cout);cryst->AddScatterer(mol); cryst->RandomizeConfiguration(); WXCrystal *pWXCryst=dynamic_cast (gCrystalRegistry.GetObj(0).WXGet()); wxCommandEvent com; pWXCryst->OnMenuCrystalGL(com); this->PostSizeEvent(); } } void WXCrystMainFrame::OnUpdateUI(wxUpdateUIEvent& event) { VFN_DEBUG_MESSAGE("WXCrystMainFrame::OnUpdateUI(): Uncaught event !!",10) } void WXCrystMainFrame::OnToggleTooltips(wxCommandEvent& event) { bool tooltip_enabled; wxConfigBase::Get()->Read(_T("Fox/BOOL/Enable tooltips"), &tooltip_enabled); tooltip_enabled = !tooltip_enabled; wxToolTip::Enable(tooltip_enabled); wxConfigBase::Get()->Write(_T("Fox/BOOL/Enable tooltips"), tooltip_enabled); VFN_DEBUG_MESSAGE("WXCrystMainFrame::OnToggleTooltips(): Tooltips= "< > &l) { wxString str; wxString path=wxConfigBase::Get()->GetPath(); if(path==_T(""))path=_T("/")+path; long entry; bool bCont = wxConfigBase::Get()->GetFirstEntry(str, entry); while(bCont) { //cout<<__FILE__<<":"<<__LINE__<<"Entry:"<GetNextEntry(str, entry); } long group; bCont = wxConfigBase::Get()->GetFirstGroup(str, group); while(bCont) { wxConfigBase::Get()->SetPath(path+_T("/")+str); GetRecursiveConfigEntryList(l); wxConfigBase::Get()->SetPath(_T("..")); bCont = wxConfigBase::Get()->GetNextGroup(str, group); } } static const long ID_FOX_PREFS_OK=WXCRYST_ID(); enum FOX_PREF_TYPE {PREF_BOOL,PREF_STRING,PREF_LONG,PREF_REAL} ; struct FoxPref { FoxPref(wxString &comp,FOX_PREF_TYPE &t,wxString &e,wxWindow *w): component(comp),type(t),entry(e),win(w) {} wxString component; FOX_PREF_TYPE type; wxString entry; wxWindow *win; }; class WXFoxPreferences:public wxDialog { public: WXFoxPreferences(wxWindow *parent); ~WXFoxPreferences(); void OnClose(wxCloseEvent& event); void OnButton(wxCommandEvent &event); private: list l; DECLARE_EVENT_TABLE() }; BEGIN_EVENT_TABLE(WXFoxPreferences, wxDialog) EVT_CLOSE(WXFoxPreferences::OnClose) EVT_BUTTON(ID_FOX_PREFS_OK, WXFoxPreferences::OnButton) END_EVENT_TABLE() WXFoxPreferences::WXFoxPreferences(wxWindow *parent): wxDialog(parent,-1,_T("FOX Preferences: "),wxDefaultPosition,wxSize(400,400),wxDEFAULT_DIALOG_STYLE) { #if 1 wxWindow *sw = this; #else wxScrolledWindow *sw=new wxScrolledWindow(this); sw->FitInside(); sw->SetScrollRate(10,10); #endif wxBoxSizer *sizer=new wxBoxSizer(wxVERTICAL); sw->SetSizer(sizer); list > ltmp; GetRecursiveConfigEntryList(ltmp); wxWindow *w; list l2; for(list >::const_iterator pos=ltmp.begin();pos!=ltmp.end();++pos) { wxString component,entry; FOX_PREF_TYPE type; size_t tmp=pos->first.find(_T("/"),1); component=pos->first.substr(1,tmp-1); entry=pos->second; if(pos->first.find(_T("BOOL") ,1)!=wxString::npos) type=PREF_BOOL; if(pos->first.find(_T("STRING"),1)!=wxString::npos) type=PREF_STRING; if(pos->first.find(_T("LONG") ,1)!=wxString::npos) type=PREF_LONG; if(pos->first.find(_T("REAL") ,1)!=wxString::npos) type=PREF_REAL; switch(type) { case PREF_BOOL: { wxCheckBox *win=new wxCheckBox(sw,-1,component+_T(":")+entry); bool val; wxConfigBase::Get()->Read(_T("/")+component+_T("/BOOL/")+entry,&val); win->SetValue(val); sizer->Add(win,0,wxLEFT); w=win; break; } case PREF_STRING: { w=new wxWindow(sw,-1); wxBoxSizer *s=new wxBoxSizer(wxHORIZONTAL); w->SetSizer(s); wxStaticText *txt=new wxStaticText(w,-1,component+_T(":")+entry); wxString val; wxConfigBase::Get()->Read(_T("/")+component+_T("/STRING/")+entry,&val); wxTextCtrl *win=new wxTextCtrl(w,-1,val); s->Add(txt,0,wxALIGN_CENTER); s->Add(win,0,wxALIGN_CENTER); w->Layout(); sizer->Add(w,0,wxLEFT); w=win; break; } case PREF_LONG: { w=new wxWindow(sw,-1); wxBoxSizer *s=new wxBoxSizer(wxHORIZONTAL); w->SetSizer(s); wxStaticText *txt=new wxStaticText(w,-1,component+_T(":")+entry); wxString val; wxConfigBase::Get()->Read(_T("/")+component+_T("/LONG/")+entry,&val); wxTextCtrl *win=new wxTextCtrl(w,-1,val,wxDefaultPosition,wxDefaultSize,0,wxTextValidator(wxFILTER_NUMERIC)); s->Add(txt,0,wxALIGN_CENTER); s->Add(win,0,wxALIGN_CENTER); w->Layout(); sizer->Add(w,0,wxLEFT); w=win; break; } case PREF_REAL: { w=new wxWindow(sw,-1); wxBoxSizer *s=new wxBoxSizer(wxHORIZONTAL); w->SetSizer(s); wxStaticText *txt=new wxStaticText(w,-1,component+_T(":")+entry); wxString val; wxConfigBase::Get()->Read(_T("/")+component+_T("/REAL/")+entry,&val); wxTextCtrl *win=new wxTextCtrl(w,-1,val,wxDefaultPosition,wxDefaultSize,0,wxTextValidator(wxFILTER_NUMERIC)); s->Add(txt,0,wxALIGN_CENTER); s->Add(win,0,wxALIGN_CENTER); w->Layout(); sizer->Add(w,0,wxLEFT); w=win; break; } } l.push_back(FoxPref(component,type,entry,w)); } wxButton *pbut=new wxButton(sw,ID_FOX_PREFS_OK,"OK"); sizer->Add(pbut,0,wxCENTER); sw->Layout(); sizer->Fit(sw); this->Layout(); } WXFoxPreferences::~WXFoxPreferences() { cout<<"WXFoxPreferences::~WXFoxPreferences()"<::const_iterator pos=l.begin();pos!=l.end();++pos) { switch(pos->type) { case PREF_BOOL: { wxString full=_T("/")+pos->component+_T("/BOOL/")+pos->entry; bool val; wxConfigBase::Get()->Read(full,&val); wxCheckBox *w=dynamic_cast(pos->win); val=w->GetValue(); wxConfigBase::Get()->Write(full,val); break; } case PREF_STRING: { wxString full=_T("/")+pos->component+_T("/STRING/")+pos->entry; wxString val; wxConfigBase::Get()->Read(full,&val); wxTextCtrl *w=dynamic_cast(pos->win); val=w->GetValue(); wxConfigBase::Get()->Write(full,val); break; } case PREF_LONG: { wxString full=_T("/")+pos->component+_T("/LONG/")+pos->entry; wxString s; long val; wxConfigBase::Get()->Read(full,&val); wxTextCtrl *w=dynamic_cast(pos->win); s=w->GetValue(); s.ToLong(&val); wxConfigBase::Get()->Write(full,val); break; } case PREF_REAL: { wxString full=_T("/")+pos->component+_T("/REAL/")+pos->entry; wxString s; double val; wxConfigBase::Get()->Read(full,&val); wxTextCtrl *w=dynamic_cast(pos->win); s=w->GetValue(); s.ToDouble(&val); wxConfigBase::Get()->Write(full,val); break; } } } event.Skip(true); } void WXFoxPreferences::OnButton(wxCommandEvent &event) { VFN_DEBUG_MESSAGE("WXFoxPreferences::OnButton()",5); this->Close(); } void WXCrystMainFrame::OnPreferences(wxCommandEvent& event) { event.Skip(true); WXFoxPreferences *prefs= new WXFoxPreferences(this); prefs->ShowModal(); } void WXCrystMainFrame::OnCheckUpdate(wxCommandEvent& event) { VFN_DEBUG_MESSAGE("WXCrystMainFrame::OnCheckUpdate",10); #if 0 // Threaded check for updates if(event.GetId()!=ID_FOX_UPDATES_RESULT) { #if 1 if(false == wxFileSystem::HasHandlerForPath(_T("http://objcryst.sourceforge.net/FoxUpdates.txt"))) wxFileSystem::AddHandler(new wxInternetFSHandler); #endif mvUpdatesAutoCheck=false; WXThreadCheckUpdates *pThreadCheckUpdates = new WXThreadCheckUpdates(mvUpdates,*this); if(pThreadCheckUpdates->Create() != wxTHREAD_NO_ERROR) wxLogError(_T("Can't create updates check thread")); else pThreadCheckUpdates->Run(); } else #else // Avoid thread to check for updates -unreliable ! CheckUpdates(mvUpdates); #endif { unsigned int nbminorfeature=0,nbmajorfeature=0,nbrelease=0,nbminorbug=0,nbmajorbug=0,nbcritical=0; for(map >::const_iterator pos=mvUpdates.begin();pos!=mvUpdates.end();++pos) {//Critical fixes if(pos->second.first==0) nbminorfeature++; if(pos->second.first==1) nbmajorfeature++; if(pos->second.first==2) nbrelease++; if(pos->second.first==10) nbminorbug++; if(pos->second.first==11) nbmajorbug++;// Major bug but calculations are still OK if(pos->second.first==12) nbcritical++;// A mistake was made, giving erroneous results } if(mvUpdatesAutoCheck) {// Autocheck => only critical updates if(nbcritical>0) { wxString msg; msg.Printf( _T("A new version of Fox is available, including CRITICAL bug fixes\n") _T("It is strongly recommended to update to a new version\n\n Major changes: \n")); for(map >::const_iterator pos=mvUpdates.begin();pos!=mvUpdates.end();++pos) { if(pos->second.first==12) msg=msg+wxString::Format(_T("#%d (CRITICAL): %s\n"),pos->first,pos->second.second.c_str()); } wxMessageDialog d(this,msg, _T("! CRITICAL update available !"), wxOK|wxICON_EXCLAMATION); d.ShowModal(); } } else {// User asked for this, so give the full version wxFrame *frame=new wxFrame(this,-1,_T("FOX Updates"),wxDefaultPosition,wxSize(800,250),wxSTAY_ON_TOP | wxRESIZE_BORDER | wxCAPTION | wxCLOSE_BOX | wxCLIP_CHILDREN); wxTextCtrl *wUpdates=new wxTextCtrl(frame,-1,_T(""),wxDefaultPosition,wxDefaultSize,wxTE_MULTILINE|wxTE_READONLY|wxTE_DONTWRAP); wUpdates->SetFont(wxFont(10,wxROMAN,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_BOLD)); if(mvUpdates.size()>0) { if(nbcritical>0) { cout<AppendText(wxString::Format(_T("WARNING: CRITICAL updates are available !\n\n Changes:\n"))); for(map >::const_iterator pos=mvUpdates.begin();pos!=mvUpdates.end();++pos) { if(pos->second.first==12) { wxString mess=wxString::Format(_T(" #%d: %s\n"),pos->first,pos->second.second.c_str()); wUpdates->AppendText(mess); } } } else if(nbrelease>0) { cout<AppendText(wxString::Format(_T("A new Fox RELEASE available !\n\n Changes:\n"))); for(map >::const_iterator pos=mvUpdates.begin();pos!=mvUpdates.end();++pos) { if(pos->second.first==2) wUpdates->AppendText(wxString::Format(_T(" #%d: %s\n"),pos->first,pos->second.second.c_str())); } } else if(nbmajorfeature>0) { cout<AppendText(wxString::Format(_T("A new Fox version with new major features is available !\n\n Changes:\n"))); for(map >::const_iterator pos=mvUpdates.begin();pos!=mvUpdates.end();++pos) { if(pos->second.first==1) wUpdates->AppendText(wxString::Format(_T(" #%d: %s\n"),pos->first,pos->second.second.c_str())); } } else if(nbminorfeature>0) { cout<AppendText(wxString::Format(_T("A new Fox version with new minor features is available.\n\n Changes:\n"))); for(map >::const_iterator pos=mvUpdates.begin();pos!=mvUpdates.end();++pos) { if(pos->second.first==0) wUpdates->AppendText(wxString::Format(_T(" #%d: %s\n"),pos->first,pos->second.second.c_str())); } } wUpdates->AppendText(wxString::Format(_T("\n\n => go to https://github.com/vincefn/objcryst/releases to get the new version"))); } else { wUpdates->AppendText(wxString::Format(_T("No updates found !\n"))); } frame->Show(true); } } } void WXCrystMainFrame::OnSize(wxSizeEvent &event) { if(mpNotebook!=NULL) for(unsigned int i=0;iGetPageCount();i++) mpNotebook->GetPage(i)->PostSizeEvent(); this->wxFrame::OnSize(event); } void WXCrystMainFrame::OnUserMessage(wxCommandEvent &event) { (*fpObjCrystInformUser)(std::string(event.GetString().c_str())); } wxTextCtrl* WXCrystMainFrame::GetLogWindow() { return mpLog; } #ifdef __FOX_COD__ void WXCrystMainFrame::OnCOD(wxCommandEvent &event) { for(unsigned int i=0;iGetPageCount();i++) if(mpNotebook->GetPageText(i)=="COD") { mpNotebook->SetSelection(i); return; } WXCrystScrolledWindow *pWinCOD = new WXCrystScrolledWindow(mpNotebook); mpNotebook->AddPage(pWinCOD,_T("COD"),true); wxBoxSizer *topsizer=new wxBoxSizer(wxVERTICAL); pWinCOD->SetSizer(topsizer); wxBoxSizer *tmpsizer; tmpsizer=new wxBoxSizer(wxHORIZONTAL); topsizer->Add(tmpsizer, 0, wxEXPAND); wxStaticText *pWords=new wxStaticText(pWinCOD,-1,"Free text:"); pWords->SetToolTip(_T("Name, formula, authors, etc...")); tmpsizer->Add(pWords); mvpCOD_Text1 = new wxTextCtrl(pWinCOD,-1); tmpsizer->Add(mvpCOD_Text1,1, wxEXPAND); mvpCOD_Text2 = new wxTextCtrl(pWinCOD,-1); tmpsizer->Add(mvpCOD_Text2,1, wxEXPAND); tmpsizer=new wxBoxSizer(wxHORIZONTAL); topsizer->Add(tmpsizer, 0, wxEXPAND); wxStaticText *pFormula=new wxStaticText(pWinCOD,-1,"Formula (Hill notation):"); tmpsizer->Add(pFormula); mvpCOD_Formula = new wxTextCtrl(pWinCOD,-1); tmpsizer->Add(mvpCOD_Formula,1, wxEXPAND); pFormula->SetToolTip(_T("Ordered formula: C first, then H,\n" "then alphabetical order, separated by 1 space\n" "\nSee https://en.wikipedia.org/wiki/Hill_notation\n" "Example: C2 H5 Br, C18 H18 Cl N O3 S")); tmpsizer=new wxBoxSizer(wxHORIZONTAL); topsizer->Add(tmpsizer, 0, wxEXPAND); wxStaticText *pSMARTS=new wxStaticText(pWinCOD,-1,"SMARTS pattern:"); tmpsizer->Add(pSMARTS); mvpCOD_SMARTS = new wxTextCtrl(pWinCOD,-1); tmpsizer->Add(mvpCOD_SMARTS,1, wxEXPAND); pSMARTS->SetToolTip(_T("SMARTS pattern, e.g. [OH]c1ccccc1 for phenol\n" "See https://www.daylight.com/dayhtml/doc/theory/theory.smarts.html\n" "Characters not allowed (untested): at least &")); tmpsizer=new wxBoxSizer(wxHORIZONTAL); topsizer->Add(tmpsizer, 0, wxEXPAND); wxStaticText *pCODId=new wxStaticText(pWinCOD,-1,"COD id:"); tmpsizer->Add(pCODId); mvpCOD_ID = new wxTextCtrl(pWinCOD,-1); tmpsizer->Add(mvpCOD_ID,1, wxEXPAND); pCODId->SetToolTip(_T("COD id or range, e.g.:\n" "single entry: 1100661\n" "multiple entries: 1100661,1501768")); tmpsizer=new wxBoxSizer(wxHORIZONTAL); topsizer->Add(tmpsizer, 0, wxEXPAND); wxStaticText *pElements=new wxStaticText(pWinCOD,-1,"Elements ('C', 'O6'..):"); tmpsizer->Add(pElements); for(unsigned int i=0;i<6;i++) { mvpCOD_Elements.push_back(new wxTextCtrl(pWinCOD,-1, wxEmptyString, wxDefaultPosition, wxSize(50,-1))); tmpsizer->Add(mvpCOD_Elements.back(),1, wxEXPAND); } tmpsizer=new wxBoxSizer(wxHORIZONTAL); topsizer->Add(tmpsizer, 0, wxEXPAND); pElements=new wxStaticText(pWinCOD,-1,"Excluded Elements:"); tmpsizer->Add(pElements); for(unsigned int i=0;i<4;i++) { mvpCOD_NElements.push_back(new wxTextCtrl(pWinCOD, -1)); tmpsizer->Add(mvpCOD_NElements.back(),1, wxEXPAND); } tmpsizer=new wxBoxSizer(wxHORIZONTAL); topsizer->Add(tmpsizer, 0, wxEXPAND); wxStaticText *pNbElements=new wxStaticText(pWinCOD,-1,"Min and Max number of elements:"); tmpsizer->Add(pNbElements); mpCOD_MinNel=new wxTextCtrl(pWinCOD,-1, wxEmptyString, wxDefaultPosition, wxSize(50,-1)); tmpsizer->Add(mpCOD_MinNel,1, wxEXPAND); mpCOD_MaxNel=new wxTextCtrl(pWinCOD,-1, wxEmptyString, wxDefaultPosition, wxSize(50,-1)); tmpsizer->Add(mpCOD_MaxNel,1, wxEXPAND); tmpsizer=new wxBoxSizer(wxHORIZONTAL); topsizer->Add(tmpsizer, 0, wxEXPAND); wxStaticText *pVolume=new wxStaticText(pWinCOD,-1,"Min and Max unit cell volume (A^3):"); tmpsizer->Add(pVolume); mpCOD_MinVol=new wxTextCtrl(pWinCOD,-1); tmpsizer->Add(mpCOD_MinVol,1, wxEXPAND); mpCOD_MaxVol=new wxTextCtrl(pWinCOD,-1); tmpsizer->Add(mpCOD_MaxVol,1, wxEXPAND); wxButton *pbut=new wxButton(pWinCOD,ID_FOX_BUTTON_COD,"Query COD"); topsizer->Add(pbut); pWinCOD->Layout(); this->PostSizeEvent(); } /// Almost a copy of wxGridCellAutoWrapStringRenderer, just based on a fixed width rather than the golden ratio class WXGridCellAutoWrapStringRendererFixedWidth: public wxGridCellAutoWrapStringRenderer { public: WXGridCellAutoWrapStringRendererFixedWidth(unsigned int w): wxGridCellAutoWrapStringRenderer(),mFixedWidth(w){}; virtual wxSize GetBestSize(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, int row, int col); virtual wxGridCellRenderer *Clone() const { return new WXGridCellAutoWrapStringRendererFixedWidth(mFixedWidth); } private: wxArrayString GetTextLines( wxGrid& grid, wxDC& dc, const wxGridCellAttr& attr, const wxRect& rect, int row, int col); void BreakLine(wxDC& dc, const wxString& logicalLine, wxCoord maxWidth, wxArrayString& lines); wxCoord BreakWord(wxDC& dc, const wxString& word, wxCoord maxWidth, wxArrayString& lines, wxString& line); unsigned int mFixedWidth; }; // Same as WXGridCellAutoWrapStringRenderer::GetTextLines, unfortunately private... wxArrayString WXGridCellAutoWrapStringRendererFixedWidth::GetTextLines(wxGrid& grid, wxDC& dc, const wxGridCellAttr& attr, const wxRect& rect, int row, int col) { dc.SetFont(attr.GetFont()); const wxCoord maxWidth = rect.GetWidth(); // Transform logical lines into physical ones, wrapping the longer ones. const wxArrayString logicalLines = wxSplit(grid.GetCellValue(row, col), '\n', '\0'); // Trying to do anything if the column is hidden anyhow doesn't make sense // and we run into problems in BreakLine() in this case. if ( maxWidth <= 0 ) return logicalLines; wxArrayString physicalLines; for ( wxArrayString::const_iterator it = logicalLines.begin(); it != logicalLines.end(); ++it ) { const wxString& line = *it; if ( dc.GetTextExtent(line).x > maxWidth ) { // Line does not fit, break it up. BreakLine(dc, line, maxWidth, physicalLines); } else // The entire line fits as is { physicalLines.push_back(line); } } return physicalLines; } // Same as WXGridCellAutoWrapStringRenderer::BreakLine, unfortunately private... void WXGridCellAutoWrapStringRendererFixedWidth::BreakLine(wxDC& dc, const wxString& logicalLine, wxCoord maxWidth, wxArrayString& lines) { wxCoord lineWidth = 0; wxString line; // For each word wxStringTokenizer wordTokenizer(logicalLine, wxS(" \t"), wxTOKEN_RET_DELIMS); while ( wordTokenizer.HasMoreTokens() ) { const wxString word = wordTokenizer.GetNextToken(); const wxCoord wordWidth = dc.GetTextExtent(word).x; if ( lineWidth + wordWidth < maxWidth ) { // Word fits, just add it to this line. line += word; lineWidth += wordWidth; } else { // Word does not fit, check whether the word is itself wider that // available width if ( wordWidth < maxWidth ) { // Word can fit in a new line, put it at the beginning // of the new line. lines.push_back(line); line = word; lineWidth = wordWidth; } else // Word cannot fit in available width at all. { if ( !line.empty() ) { lines.push_back(line); line.clear(); lineWidth = 0; } // Break it up in several lines. lineWidth = BreakWord(dc, word, maxWidth, lines, line); } } } if ( !line.empty() ) lines.push_back(line); } // Same as WXGridCellAutoWrapStringRenderer::BreakWord, unfortunately private... wxCoord WXGridCellAutoWrapStringRendererFixedWidth::BreakWord(wxDC& dc, const wxString& word, wxCoord maxWidth, wxArrayString& lines, wxString& line) { wxArrayInt widths; dc.GetPartialTextExtents(word, widths); const unsigned count = widths.size(); unsigned n; for ( n = 0; n < count; n++ ) { if ( widths[n] > maxWidth ) break; } if ( n == 0 ) { n = 1; } lines.push_back(word.substr(0, n)); const wxString rest = word.substr(n); const wxCoord restWidth = dc.GetTextExtent(rest).x; if ( restWidth <= maxWidth ) { line = rest; return restWidth; } return BreakWord(dc, rest, maxWidth, lines, line); } wxSize WXGridCellAutoWrapStringRendererFixedWidth::GetBestSize(wxGrid& grid, wxGridCellAttr& attr,wxDC& dc,int row, int col) { const int lineHeight = dc.GetCharHeight(); // Search for a shape no taller than the golden ratio. wxSize size; size.x=mFixedWidth; const size_t numLines = GetTextLines(grid, dc, attr, size, row, col).size(); size.y = numLines * lineHeight; return size; } void WXCrystMainFrame::OnButton(wxCommandEvent &event) { VFN_DEBUG_MESSAGE("WXCrystMainFrame::OnButton()",10) wxProgressDialog dlgProgress(_T("Querying Crystallographic Open Database"),_T("Building query.............................................................\n\n"), 106,this,wxPD_AUTO_HIDE|wxPD_ELAPSED_TIME);//|wxPD_CAN_ABORT Chronometer chrono; chrono.start(); stringstream query; //query<<"select file,a,b,c,alpha,beta,gamma,vol,sg,sgHall,nel,commonname,chemname,mineral,formula,calcformula,authors,title,journal,volume,year,firstpage from data where "; query<<"http://www.crystallography.net/cod/result.php?"; //Read parameters from GUI wxString v; bool empty_query=true; // text v=mvpCOD_Text1->GetValue(); if(v.IsEmpty()==false) { query<<"&text1="<GetValue(); if(v.IsEmpty()==false) { query<<"&text2="<GetValue(); if(v.IsEmpty()==false) { query<<"&formula="<GetValue(); if(v.IsEmpty()==false) { query<<"&smarts="<GetValue(); if(v.IsEmpty()==false) { query<<"&id="<::iterator pos=mvpCOD_Elements.begin();pos!=mvpCOD_Elements.end();++pos) { v=(*pos)->GetValue(); if(v.IsEmpty()==false) { query<<"&el" << idxel++ <<"="<::iterator pos=mvpCOD_NElements.begin();pos!=mvpCOD_NElements.end();++pos) { v=(*pos)->GetValue(); if(v.IsEmpty()==false) { query<<"&nel" << idxel++ <<"="<GetValue(); if(v.IsEmpty()==false) { query<<"&strictmin=" << v; empty_query = false; } v=mpCOD_MaxNel->GetValue(); if(v.IsEmpty()==false) { query<<"&strictmax=" << v; empty_query = false; } //Volume v=mpCOD_MinVol->GetValue(); if(v.IsEmpty()==false) { query<<"&vmin="<GetValue(); if(v.IsEmpty()==false) { query<<"&vmax="<Close(); // Query using REST API if(false == wxFileSystem::HasHandlerForPath(_T("http://objcryst.sourceforge.net/FoxUpdates.txt"))) wxFileSystem::AddHandler(new wxInternetFSHandler); // First get the number of results if(wxFileSystem::HasHandlerForPath(query.str())) { wxFSFile *fp= NULL; wxFileSystem fs; fp= fs.OpenFile((boost::format("%s&format=count") % query.str()).str(),wxFS_READ); if(fp!=NULL) { wxInputStream *fstream = fp->GetStream(); wxStringOutputStream wxresult; fstream->Read(wxresult); (*fpObjCrystInformUser)((boost::format("COD: number of results= %s") % wxresult.GetString().c_str()).str()); const int ct = std::atoi(wxresult.GetString().c_str()); if(ct>200) { wxMessageDialog d(this,_T("COD: more than 200 results - narrow your search"),_T("Error"),wxOK|wxICON_ERROR); d.ShowModal(); return; } } } // Get the actual results and parse them if(wxFileSystem::HasHandlerForPath(query.str())) { wxFSFile *fp= NULL; wxFileSystem fs; fp= fs.OpenFile((boost::format("%s&format=json") % query.str()).str(),wxFS_READ); if(fp!=NULL) { wxInputStream *fstream = fp->GetStream(); wxStringOutputStream wxresult; fstream->Read(wxresult); // Parse results boost::property_tree::ptree root; stringstream ss; ss <second.size())).str()); //(*fpObjCrystInformUser)((boost::format("COD id: %d")%(pos->second.get("file"))).str()); mvCOD_Record.push_back(cod_record()); cod_record *p=&(mvCOD_Record.back()); p->file = std::atoi(pos->second.get("file").c_str() ); VFN_DEBUG_MESSAGE("COD id="<file<<"("<a = string2floatC(pos->second.get("a")); p->b = string2floatC(pos->second.get("b")); p->c = string2floatC(pos->second.get("c")); p->alpha = string2floatC(pos->second.get("alpha")); p->beta = string2floatC(pos->second.get("beta")); p->gamma = string2floatC(pos->second.get("gamma")); p->vol = string2floatC(pos->second.get("vol")); p->sg = pos->second.get("file"); p->sgHall = pos->second.get("file"); p->nel = std::atoi(pos->second.get("nel").c_str()); p->commonname = pos->second.get("commonname"); p->chemname = pos->second.get("chemname"); p->mineral = pos->second.get("mineral"); p->formula = pos->second.get("formula"); p->calcformula = pos->second.get("calcformula"); p->authors = pos->second.get("authors"); p->title = pos->second.get("title"); p->journal = pos->second.get("journal"); p->volume = string2floatC(pos->second.get("volume")); p->year = std::atoi(pos->second.get("year").c_str()); p->firstpage = std::atoi(pos->second.get("firstpage").c_str()); } // (*fpObjCrystInformUser)(string(wxresult.GetString().c_str())); } } if(mvCOD_Record.size()==0) { wxMessageDialog d(this,_T("COD: No results !"),_T("No results"),wxOK|wxICON_ERROR); d.ShowModal(); return; } dlgProgress.Update(106,"Displaying results"); mpCODFrame= new wxMiniFrame(this,-1, _T("Crystallography Open Database results (double-click on formula to load CIF)"), wxDefaultPosition,wxSize(700,500),wxCLOSE_BOX|wxCAPTION|wxRESIZE_BORDER);//|wxSTAY_ON_TOP wxSizer *pSizer=new wxBoxSizer(wxHORIZONTAL); mpCODFrame->SetSizer(pSizer); mpCODGrid=new wxGrid(mpCODFrame,ID_FOX_COD_LIST,wxDefaultPosition,wxDefaultSize); mpCODGrid->SetDefaultCellFont(wxFont(10,wxTELETYPE,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_BOLD)); //mpCODGrid->SetDefaultRenderer(new WXGridCellAutoWrapStringRendererFixedWidth(200)); mpCODGrid->EnableEditing(false); mpCODFrame->Show(); pSizer->Add(mpCODGrid,wxEXPAND); mpCODGrid->SetColLabelSize(0); mpCODGrid->SetRowLabelSize(0); mpCODGrid->CreateGrid(3*mvCOD_Record.size(),2); mpCODGrid->SetColSize(0,190); mpCODGrid->SetColSize(1,500); mpCODGrid->SetColMinimalWidth(0,120); mpCODGrid->SetColMinimalWidth(1,300); mpCODGrid->DisableDragRowSize(); wxGridCellAttr* cellAttrFormula = new wxGridCellAttr; cellAttrFormula->SetRenderer(new WXGridCellAutoWrapStringRendererFixedWidth(190)); mpCODGrid->SetColAttr(0,cellAttrFormula); wxGridCellAttr* cellAttrInfo = new wxGridCellAttr; cellAttrInfo->SetRenderer(new WXGridCellAutoWrapStringRendererFixedWidth(500)); mpCODGrid->SetColAttr(1,cellAttrInfo); std::vector::const_iterator ps=mvCOD_Record.begin(); for(unsigned int i=0;iSetCellSize(i*3,0,3,1); mpCODGrid->SetCellAlignment(i*3,0, wxALIGN_CENTER, wxALIGN_CENTER); const cod_record *c=(cod_record*)&(*ps); mpCODGrid->SetCellValue(i*3,0,wxString::Format("%s",c->formula.substr(2,c->formula.size()-4).c_str())); mpCODGrid->SetCellValue(i*3,1,wxString::Format("%.3f %.3f %.3f %.1f %.1f %.1f %s",c->a,c->b,c->c,c->alpha,c->beta,c->gamma,c->sg)); mpCODGrid->SetCellValue(i*3+1,1,wxString::Format("%s %ld (%ld), %s: %s",c->journal,c->volume,c->year,c->firstpage,c->authors)); mpCODGrid->SetCellValue(i*3+2,1,wxString::Format("%s",c->title)); //VFN_DEBUG_MESSAGE(i<<":"<GetRowSize(i*3+2),10) ps++; } mpCODGrid->AutoSizeRows(false); mpCODFrame->SetAutoLayout(true); mpCODFrame->PostSizeEvent(); } void WXCrystMainFrame::OnCODSelect(wxGridEvent &ev) { // We don't want to get double-click events from other grids if(ev.GetId()!=ID_FOX_COD_LIST) { VFN_DEBUG_MESSAGE("WXCrystMainFrame::OnCODSelect(): wrong wxGrid !", 10) return; } std::vector::const_iterator pos=mvCOD_Record.begin(); for(unsigned int i=ev.GetRow()/3;i>0;i--) pos++; wxString cifurl=wxString::Format("http://www.crystallography.net/cod/%ld.cif",pos->file); cout<GetStream(); wxStringOutputStream wxcif; fstream->Read(wxcif); cout<Close(false); std::stringstream in; in<DataLoaded(); mpNotebook->SetSelection(0); } cout< vReport; vReport.push_back(SpeedTest(20,4,"P1" ,RAD_NEUTRON,100,0,dt)); vReport.push_back(SpeedTest(20,4,"P-1" ,RAD_NEUTRON,100,0,dt)); vReport.push_back(SpeedTest(20,4,"Pnma",RAD_NEUTRON,100,0,dt)); vReport.push_back(SpeedTest(20,4,"Ia3d",RAD_NEUTRON,100,0,dt)); vReport.push_back(SpeedTest(20,4,"P1" ,RAD_XRAY ,100,0,dt)); vReport.push_back(SpeedTest(20,4,"P-1" ,RAD_XRAY ,100,0,dt)); vReport.push_back(SpeedTest(20,4,"Pnma",RAD_XRAY ,100,0,dt)); vReport.push_back(SpeedTest(20,4,"Ia3d",RAD_XRAY ,100,0,dt)); vReport.push_back(SpeedTest(100,4,"P21",RAD_XRAY ,500,0,dt)); vReport.push_back(SpeedTest(100,4,"P21/n",RAD_XRAY ,500,0,dt)); vReport.push_back(SpeedTest(20,4,"P1" ,RAD_NEUTRON,100,1,dt)); vReport.push_back(SpeedTest(20,4,"P-1" ,RAD_NEUTRON,100,1,dt)); vReport.push_back(SpeedTest(20,4,"Pnma",RAD_NEUTRON,100,1,dt)); vReport.push_back(SpeedTest(20,4,"Ia3d",RAD_NEUTRON,100,1,dt)); vReport.push_back(SpeedTest(20,4,"P1" ,RAD_XRAY ,100,1,dt)); vReport.push_back(SpeedTest(20,4,"P-1" ,RAD_XRAY ,100,1,dt)); vReport.push_back(SpeedTest(20,4,"Pnma",RAD_XRAY ,100,1,dt)); vReport.push_back(SpeedTest(20,4,"Ia3d",RAD_XRAY ,100,1,dt)); vReport.push_back(SpeedTest(100,4,"P21",RAD_XRAY ,500,1,dt)); vReport.push_back(SpeedTest(100,4,"P21/n",RAD_XRAY ,500,1,dt)); // Compared to results on a Core2 Quad Q6600 running @2.4 GHz, gcc 4.6.2 with an old version of Fox 1.9.0.2 CrystVector_REAL vfnBogoMRAPS_n_201001(20); vfnBogoMRAPS_n_201001(0)=47; vfnBogoMRAPS_n_201001(1)=49; vfnBogoMRAPS_n_201001(2)=86; vfnBogoMRAPS_n_201001(3)=106; vfnBogoMRAPS_n_201001(4)=46; vfnBogoMRAPS_n_201001(5)=49; vfnBogoMRAPS_n_201001(6)=85; vfnBogoMRAPS_n_201001(7)=107; vfnBogoMRAPS_n_201001(8)=89; vfnBogoMRAPS_n_201001(9)=105; vfnBogoMRAPS_n_201001(10)=39; vfnBogoMRAPS_n_201001(11)=41; vfnBogoMRAPS_n_201001(12)=79; vfnBogoMRAPS_n_201001(13)=105; vfnBogoMRAPS_n_201001(14)=38; vfnBogoMRAPS_n_201001(15)=42; vfnBogoMRAPS_n_201001(16)=73; vfnBogoMRAPS_n_201001(17)=105; vfnBogoMRAPS_n_201001(18)=86; vfnBogoMRAPS_n_201001(19)=102; cout<<" Spacegroup NbAtoms NbAtType Radiation Type NbRefl BogoSPS BogoMRAPS BogoMRAPS(n) relat%"<::const_iterator pos=vReport.begin(); pos != vReport.end();++pos) { cout<<" "<mSpacegroup,8)<<" " <mNbAtom)<<" " <mNbAtomType,6)<<" "; switch(pos->mRadiation) { case(RAD_NEUTRON): cout<mDataType) { case(0): cout<mBogoMRAPS_reduced/vfnBogoMRAPS_n_201001(i); cout<mNbReflections)<<" " <mBogoSPS)<<" " <mBogoMRAPS)<<" " <mBogoMRAPS_reduced)<<" " <æü37CHg-Ÿÿ»5šûí) ~ÿä•©7+'6Ÿó÷ÛΚ[Q–889fóøy7_ ')røûk°ÿñ)SøóÖºdMD‚æûÛÄÆÂw:R›889›úòo}Í‘&$9°ÿÉC×ÿØ&#$"Yßÿ屨žŽ¡ÞüçÉ¥¸ª=Z­<98ÄÿÔ8oÙT%[ãÿš!Gåÿ£-C@i¤çÿ÷ÞÕÓÐëüòÛϰw.0|¿?;Eæÿ¥*@‘&%vÿÿz‡õôhX‹ Óñþÿÿüùøø÷ðßÎά3;”Ê@=~óûj&/P#"sÿíc(ÅÿÌ“¬ÞðýþþÿÿýûüýêÔÈÂÑ”\"\¦ÍB<±ýéB$$#"[îåU{ñóÆâðüþþüýÿÿþüþûâÆ»½½y+?‰¿Ñ@NÚÿÎ8&&$!<*›ïk HÊóáòýÿþÿýùøüÿÿýýøá·¿¥XY¤ÑÉ?sÁ̬\/-*)&!9™“IH‡Åâùÿþùöõö÷öùúôâŶ·Id¾Ö³D^a\ZX9531.'!VV_нñùù÷ûõô÷õëåÝßéèÜо³§~S+,ÐÁvJE@=99:952,&$$%eÁïîëðòðäñðÝØÕÔÐÒ˹¨—‹Œm‚unªÎ¤UIFC@=;:975/*'€(UE©ïîåâîëáÛæÙÁÁÃÆÂú±£ƒgjr«¸§¬®”vHGC?=<<;;951,&(#jÜ÷æßÚÞÓǼº¸­¢«±¶¸¾¹¯—†u‘ÇÕȲ¦›’JHCA@@€?,>;61+$9­øñáѼº¿¬¦©­Ÿ˜¬¾»ÄÉÃô®•¯Ó×Ï¿±£˜LIEBCC€D\C@:4.=›ðôÚÈ´¥–Š–¥«­©¦¡©»ÅÂÁ¿·­š­ÅÅ·¬£‘‹LIFEHHJIGED?@e¯ïö׸ªŸˆ]@>Or“””–§´µ±²³²®¨¥°¨‘{sx…IGHJLK€MVp—ÁàïçÚ½˜‹u7'=\q‡˜¯¯´¶µ³´¾°–}tkk{‡EGHJNR]|ªÑàêõóèÛÓ¬{m_*&!+Kuˆ–£±¶¸²·¬šr\frƒ„–CGLOXÒâëìéæáÕô±›pp‚ygE9=9Pkr…ŽŒ‡„Š“™ œ’‚„‹®»ÉÏǹ»ÃÁµ¤˜–’QPOMJHGD><3,+ )0*8]‰Š{tyŒ—œ–’ŒŠ˜¤«·ÀÊÓÎľ¶·´¬šŒNMLKHEE@<71+*%( $&T›¤‘zv‚‡””•ªª¥®²½É³¶«¬­¦”…GIKHFEC=<72,($$#(#&Z¤¹¡sqzˆŽŠ• ¯¨›©¶²Ã½¼·¬¯§•?EEB@?;9851+(%"%#*vÐÀ¦”ƒˆ‰Žš °¬Ÿ¤°¶ÈÎÒÏ¿µª›59:97554430,(&%%"#! K™Ñ¸©›ŒŠ™ ž¨µ©°Ë¹¼ÊÂź¬¡™.110.-/010.+'%$%$$#)$6…äϺ£ŒŒ†“¥¥¤´º¹Ëν¯°¾À¶·¦¡..,)((+-0/-*((&$##"$&>šÝÞ˨œ›~f„œ›œš—“«®«§²¸®«°²,,)8'&&(,/0-*('('&&##'Kƒ±åÚ¿²±”^Mmvw|ƒ‘¬¿Ã³ººª§µµ-,*'%%'*-,*'€&P%&&$#&l4##7—Éutj>6T)*+)**#  "Q%"-#!,‚É¯Šƒ‡m44j()+"'   .MI84d¸·}‚ŠL 8r€'   '$$ad`Yn¦°”‡m|t#>+)&  0)G_3&u†{™®‘š•|LVŠ+*$  <]p“s+t©œ–•ŽˆŠ›c &gŽ+)  € Yz¢´t{N¤¤ ~kq„l=?w,*   q«ÀÍ–y«ŸB7 ¯žyalƒ‹P -fŽ’*%  oÇÕÆ…>±³¥Rx°Ÿ€gq‰t5 Cƒ¤Ž*   (»ÒÉ•H@”¨‰J!S–¡‰qwƒ`) Lš¦x.(&%! &&%# 6°ª¹´¢–“¤~idajyˆrvtN*e£ˆF310/,*))(#@€ •¤®° «¨ˆ‚~ykoniAdZTW>FFP„—e)4300.,++*& +e—”‡ƒž£”™Šlquqda\__K6;>asw€xO03310/.€-,+&"I“ Š{s†‡zidbXS`b\Z_bdSHBSs~‚ybB<331011€0(/+'",‰¶ƒl\auYHLOIKbodhichbb\jwusmU@@33€24€53.)%!3†Æ®…p^UGDGQRLLSW\dgb_^]abhg^OK@5421235678762.2\¤Ï½‰bQNC'*9=;CLX^ZSOST\d_L=1)%'/0/3699:-19?E{­¬ª¥“Š}nb_I-,462!'88%&FWWVUFFUS@0!&*7/!"'*3,00-("8pˆ†yk]cjd[NA9>LYNJKFB>=61?HKI@?<6:5($(,.&0( oµº«vhbbgaXSM]j^K?66@GD6+4FMIPM<:4*$(,+,.2IX¸ÐÀ®Ž‹}XFNUhwy|ˆŠrXIDJVQD8;JSOGCID;50.053-2\>@\­Ýʱ¨¢•„bD4Dr›·¼ÉÇ´•†€zznVLLKLQTIGB;=;9553+5O—“•³Ä»­§”Œƒt^HSx›»Öèðëàѽ£€sd[UQKQUNE?=88=>:7.;I”‰•¤¤¥¡šŽtj|—¤¯»¿ÄÑÊı–ƒydMERJIQOKF?836<9414Æ®¡€€’—”ž¨™¢º§©¯¥¢–„gSH!""€(~ÛÁ°˜~~yŒœ›©©¨¼½¨“‘˜“zeNL€" €0•ÕÓÀ‘oY}“‘Š…ƒœš‚ˆ…gUUV ?{ªÝϵ¦¤‡P>`idgošª¤‡‡zZMUX.Y¬äá̹³“cLS_fsƒ‘™§©fUHN0X! "[ºãåÕɸ“lkaiy‹‰™—ŒŽm`SCBN"%%$#! !"!MX6'd2$+#"#&%    !O? ,SO*,3##%%$    :`/)aZ**3)!(&$$"    Y 1\0#! Se4"9G("0$$"!    <(" BcB(2PJ !>!"#   €   %.-(6RB();X4$I"!    &0E:(71QYC%'  8jF)-MT&$   ;`rxK2B? #/5*"      (/OYEFK4+)$&&%     )-2/#'@PO=.'#--#€3   ($ Z£¨‹`D4.12*$#"-1!‚  €+(CQ­É¹¥€oU2"$"7FEHSV6  'V==S¢Ò¬£›‡gC* Q––¥£ˆcTPMK4  ,G•“‹¨¹³¥ŸŽƒwdM7@i§ÀÔÞÖǵ †^B)2A’žƒ‹œœ—›˜Œ‰l^p‹•žª¯·Âº±›{>dQ3 )1K~j^sŽ›™œ˜…zŒ“Ž‘‰†}obbhaB* ‚**,W„XJYiq€„ˆ„‚ˆ‰‡‚uomlnrf]PC7)/73$ **.H„ˆfMCCQY\ca]VMJIS_ffhnm^[XTJJGLYZ?&  )*0:DqkZA417BHB=<6*,A`^YXKŠ>ŠM­M­ 2 2--++((&&&&''))++ , ,**''%%%%$$$$%%$$$$$$##&&#4#4U^gU^g¶¿Æ¶¿ÆÛãëÛãëÝæïÝæïÏÖáÏÖáÄËÖÄËÖµ»Éµ»É¥²¥²Zl{Zl{ao{ao{Q`oQ`oScqScq]o~]o~p€p€€Žž€Žžw†—w†— ² ²y’¦y’¦nŒ¥nŒ¥ Â ÂZŒ¾ZŒ¾&kª&kª`³`³ T¦ T¦D™D™>Š>ŠM­M­++**)) & & % % $ $&&)),,,,**''&&$$''%%%%%%%% # ###'')5C)5CNZcNZc¥¬±¥¬±ßçíßçí×àé×àéÆÎÙÆÎÙ«³¾«³¾«µÅ«µÅ•Ÿª•Ÿªbr€br€5CQ5CQ7L_7L_?Ra?RaQesQesI^qI^qgwŠgwŠv†˜v†˜’¤’¤…š«…š«š±Çš±ÇŒªÎŒªÎ\‹¹\‹¹SˆÃSˆÃ$g­$g­ X¯ X¯GGN«N«Z¼Z¼++**)) & & % % $ $&&)),,,,**''&&$$''%%%%%%%% # ###'')5C)5CNZcNZc¥¬±¥¬±àèîàèî×àé×àéÆÎÙÆÎÙ«³¾«³¾«µÅ«µÅ•Ÿª•Ÿªbr€br€4BP4BP7L_7L_?Ra?RaQesQesH^qH^qgwŠgwŠv†˜v†˜’¤’¤†š«†š«›²È›²È«Ï«Ï\‹¹\‹¹T‰ÄT‰Ä$g­$g­ X° X°GGN¬N¬Z½Z½++++(('' % % % %'',,..!1!1--**))&&''''&&&&%% " "##((N]>N]es{es{ˆ“šˆ“šŒ–¡Œ–¡ƒ’›ƒ’›ƒ’Ÿƒ’Ÿv‡˜v‡˜s…—s…—kŽkŽŽ¢°Ž¢°|“¨|“¨hŠ©hŠ©V£V£c‡±c‡±_†¸_†¸-i®-i® S© S©T¯T¯V²V²----++((((''**,,"0"0!/!/--**((((''$$####""""$$&&#/>#/>ž¥¨ž¥¨ÙàéÙàéÏÒÜÏÒÜÁÄÎÁÄΓ›¦“›¦„˜„˜„‘›„‘›k{Šk{Š=M\=M\iwiw—ž—ž™¤™¤‡•ž‡•ž‡•¢‡•¢y‰šy‰šu‡™u‡™kŽkŽŽ¢°Ž¢°{’§{’§f‰¨f‰¨V£V£c‡±c‡±a‡¸a‡¸/j¯/j¯ Tª TªT¯T¯V²V²..1100..--,,.. 0 0!0!0#0#0..,,((%%%%##%%##$$""++ " ")8)8{ƒˆ{ƒˆàåîàåͻ½Í¬±»¬±»“¨“¨o{Šo{Šp€Žp€Žeu„eu„y†Œy†Œ‹™¡‹™¡”Ÿ¦”Ÿ¦ˆ–¢ˆ–¢ž¦ž¦ ®¼ ®¼š¦¹š¦¹ž¬»ž¬»²ÃÓ²ÃÓª½Ïª½ÏФºŠ¤ºi«i«n‘°n‘°}˜¾}˜¾y•Áy•ÁJy²Jy²j¼j¼M§M§L L ..1100//--,,.. 0 0!0!0#0#0..,,((%%%%##%%##$$"",, " ")8)8x€…x€…áæïáæïº¼Ìº¼Ì«°º«°º“¨“¨mz‰mz‰ooeu„eu„‹‹Žœ¤Žœ¤• §• §ˆ–¢ˆ–¢‘Ÿ§‘Ÿ§£±¿£±¿©¼©¼¢°¾¢°¾¹ÉÙ¹ÉÙ­ÀÒ­ÀÒŒ¦¼Œ¦¼jެjެp“±p“±š¿š¿{—Â{—ÂL{³L{³!l¾!l¾M§M§KŸKŸ44#8#8&9&9$7$7#5#5"4"4"3"3#3#3#3#3#3#300--))%%&&##&&     %%    6@M6@M‡–‡–ËÍÙËÍÙ«¬¸«¬¸œ¢ªœ¢ªŒ– Œ– t~Œt~Œx‚x‚mz†mz†€Ž•€Ž•‰•ž‰•žŒ˜¡Œ˜¡šš™¨±™¨±•¥´•¥´†”¢†”¢ ¬º ¬º±ÁÒ±ÁÒ†®†®“ª½“ª½­Ê­Êž¼ž¼ˆ Ãˆ Ãu”Àu”À_†»_†»2g­2g­T£T£ Iš Iš 5 5$9$9':':%8%8$6$6#5#5#4#4#4#4#3#3#3#300--))%%&&##&&     %%     9CP9CP‰˜‰˜ÉË×ÉËת«¶ª«¶›¡©›¡©Œ–ŸŒ–Ÿuuyƒyƒn{†n{†€–€–‰•ž‰•ž‹—¡‹—¡€š€šš©³š©³”¤³”¤³„’ „’  ¬º ¬º°ÀÒ°ÀÒ‚šª‚šª”«½”«½•±Î•±Îƒ ¾ƒ ¾‰¡Ä‰¡Äu”Àu”Àa‡¼a‡¼4g«4g«U£U£ Iš Iš(=(=!/D!/D.B.B-A-A,>,>+=+='9'9&7&7)7)7&5&5!2!2,,)) % % $ $   ((        ))enwenwÈÏÚÈÏÚ¯³Á¯³Ášž¨šž¨†’›†’›hw‡hw‡kx‡kx‡}†“}†“mz†mz†q‚Œq‚Œ~—~—…– …– „“Ÿ„“Ÿ¢°»¢°»  †”¡†”¡…—¥…—¥‹¡²‹¡²‘¦¸‘¦¸¤¹Ì¤¹Ì™²Î™²ÎŸ¸ÔŸ¸Ô›°Ñ›°Ñ{™Á{™ÁjŠ·jŠ·Is«Is«%]Ÿ%]ŸC‘C‘)>)>#1F#1F/C/C.B.B-?-?,>,>(:(:&7&7*8*8&5&5!2!2,,)) % % $ $   ((        **kt}kt}ÑØãÑØã¬°¾¬°¾˜¦˜¦„š„šcs„cs„jw†jw†~‡”~‡”mz†mz†o€‹o€‹}Ž–}Ž–„– „– …” …” ¤±¼¤±¼|Žž|Žž‡•¢‡•¢‚”£‚”£†®†®“¨º“¨º§»Î§»Îš³Îš³Î£¼×£¼×ž³Óž³Ó|šÁ|šÁl‹·l‹·Lu«Lu«(^Ÿ(^ŸBB!0E!0E$3H$3H%6K%6K!3F!3F2D2D1D1D0B0B*;*;-<-<(7(7"3"3--((%% # #####++    $$8BP8BPœž¨œž¨«±Á«±Á‘™§‘™§|ˆ–|ˆ–XfzXfzN]pN]pWfzWfzjv‡jv‡x†‘x†‘h{‡h{‡qƒŒqƒŒ€”¡€”¡†˜£†˜£›¬¶›¬¶v‰™v‰™}}ŒŸ¯ŒŸ¯‘§º‘§º†Ÿ¯†Ÿ¯œ³Èœ³È‰§Â‰§Â‹¤¿‹¤¿š¼š¼f„­f„­`±`±>n©>n©UœUœ : :"1F"1F$3I$3I&7L&7L"4G"4G3E3E2E2E1C1C+<+<.=.=(7(7"3"3--((%% # #$$""--    %%>IV>IV¤¥¯¤¥¯¥«¼¥«¼–¤–¤x…”x…”Q_uQ_uKZmKZmTcxTcxgt…gt…zˆ“zˆ“gz‡gz‡o‚‹o‚‹€”¢€”¢‡™¤‡™¤š«¶š«¶u‰™u‰™|Ž|ŽŽ¡±Ž¡±“©¼“©¼„ž®„ž®š²Èš²È‡¥À‡¥À‡ ¼‡ ¼z–¹z–¹cªcª^€°^€°O+>O1BQ1BQ/@N/@N7GT7GTCT`CT`>Pa>PaQ^nQ^nXevXevdn~dn~}‡“}‡“ƒ›ƒ›‡‡‹“£‹“£Š’¡Š’¡Š’£Š’£‹•¦‹•¦‹“¦‹“¦Š’¤Š’¤‡•¥‡•¥…Ÿ…Ÿ„‘ž„‘ž€œ€œvˆ—vˆ—`w‹`w‹H`{H`{CZrCZrH_rH_rQhxQhxL_pL_pRi{Ri{f{Šf{Šsˆœsˆœƒ—­ƒ—­ƒœµƒœµz•±z•±{™¸{™¸o’³o’³]…­]…­Iy¨Iy¨;n¤;n¤/bž/bžR”R” 7~ 7~11 0x 0x*7N*7N,:Q,:Q*;O*;O*:L*:L3DR3DR-?P-?P1BQ1BQ1AO1AOPe>Pe4G`4G`0A\0A\5D^5D^Sm>Sm@Wr@WrOfOf\r…\r…Qf{Qf{Sm…Sm…a€›a€›n’¯n’¯p“µp“µs²s²p‘²p‘²Z‡°Z‡°B{­B{­)m¨)m¨a¨a¨Y¤Y¤ Iš Iš ? ? 4| 4| 2| 2|0…0… 5‰ 5‰)6N)6N*6O*6O2@R2@RER^ER^TbjTbjŒ—¢Œ—¢|ˆ—|ˆ—ananUbwUbw4F]4F].B[.B[+;V+;V3B[3B[6Gc6GcRl>RlE]xE]xLd~Ld~Zq†Zq†LczLczJeJeUy˜Uy˜a‹¬a‹¬b‹±b‹±kŠ­kŠ­k²k²N€®N€®1r©1r©d£d£ Z¥ Z¥Q¢Q¢C–C– < <5|5|2{2{ /‚ /‚ 5‡ 5‡*5L*5L*6N*6N.†>†4}4} .t .t ,s ,s.|.|'|'|*‡*‡++*4K*4K*6M*6M-;O-;O]fk]fk‚Š˜‚Š˜Q[lQ[lJRbJRb[dr[drow„ow„o{†o{†~‹”~‹”}Š™}Š™Š˜Š˜†ž†žƒŸƒŸ  €¥€¥‰”ª‰”ª†’©†’©†”¬†”¬€¥€¥Š£Š£}Š¢}Š¢u…›u…›o–o–l‚˜l‚˜k™k™j…j…q‹¢q‹¢e‚¡e‚¡^}›^}›Vw˜Vw˜Cn•Cn•?j”?j”(W‡(W‡+^Š+^Š2b‘2b‘5`’5`’.h¡.h¡d¦d¦U—U—K‘K‘?ˆ?ˆ7…7…///„/„.†.†*‡*‡+‹+‹//)4J)4J*6M*6M.S3>SOXdOXd…‰‘…‰‘hn|hn|^iv^ivrz…rz…‹‘œ‹‘œ™ ª™ ª”ž¨”ž¨§²§²™Ÿ­™Ÿ­£²£²”£”£Œ’¤Œ’¤{†˜{†˜{†™{†™•ž³•ž³›¥¹›¥¹š²š²š±š±›·›·’¢¼’¢¼‡›µ‡›µ‡œµ‡œµ~–±~–±q‰£q‰£bšbšb€žb€žfƒ¥fƒ¥g‡¨g‡¨LvŸLvŸ0_0_!Gx!GxEyEyV‹V‹RŒRŒQ’Q’ \ž \ža§a§Y¡Y¡ Mœ Mœ?‘?‘=”=”2”2”1–1–6¡6¡3¦3¦3£3£5¡5¡)4K)4K9BV9BVbhpbhp—™¤—™¤glxglxs~ˆs~ˆŒ•Œ•ž¤®ž¤®¢©³¢©³Ÿ¨´Ÿ¨´©²¾©²¾©¬¹©¬¹¬°À¬°À‘˜§‘˜§“—ª“—ªxƒ•xƒ•yƒ”yƒ”— µ— µ¡«¾¡«¾‹—¯‹—¯“³“³”¤Á”¤Áœ­Èœ­ÈŽ£¿Ž£¿“©Ä“©ÄŠ¢¿Š¢¿vލvލa|™a|™\{œ\{œi…§i…§mŒ¯mŒ¯Hv¡Hv¡'U…'U…8m8mByByWWMŒMŒO—O—YY_¥_¥]¦]¦O¢O¢?•?•?š?š442œ2œ:­:­8´8´7°7°8¦8¦1;O1;ODL^DL^™› ™› ™˜ ™˜ |ƒŽ|ƒŽ†š†š˜ ª˜ ªœ¤®œ¤®”š§”š§¥°¥°˜ ¬˜ ¬Ÿ¡°Ÿ¡°‰ž‰ž‘–§‘–§{€“{€“alƒalƒco…co…}ˆœ}ˆœ’ž²’ž²”¤¼”¤¼Ÿ°ÉŸ°É¨¹Ó¨¹Ó¬¼Õ¬¼Õ²¿Ò²¿Ò½ÍܽÍܳÄÖ³ÄÖ¬¿Ó¬¿Ó™¯È™¯È}—¸}—¸f„¨f„¨Z¨Z¨;k›;k›&W‹&W‹AzAzMˆMˆSSD„D„N•N•Q™Q™O—O— K— K—E–E–=•=•7•7•2˜2˜4 4 ;¯;¯9³9³4¨4¨1’1’6?Q6?QKRcKRc»»¾»»¾›˜ž›˜žŠ’œŠ’œ’œ¥’œ¥ ¨² ¨²›¤®›¤®Œ’ Œ’ œ¤®œ¤®Ž•¢Ž•¢™›«™›«txŠtxŠ‘–§‘–§ls†ls†T_xT_xVc|Vc|nznzŠ–«Š–«š¬Äš¬Ä§¼×§¼×µÆßµÆß·ÅÝ·ÅÝÈÑÞÈÑÞ×ãì×ãìÌÙäÌÙäÎÞîÎÞî»Ïæ»Ïæ‘©É‘©Éeƒ©eƒ©Nw¥Nw¥4e˜4e˜%Y%YGƒGƒT’T’QQ?€?€N”N”M—M— E E AŽ AŽ??<–<–3“3“1–1–6£6£<°<°:³:³3¤3¤-†-†.6L.6LMTbMTb¦§¯¦§¯‘‘š‘‘š‰“›‰“›£®º£®º´¾Ë´¾Ë°¹Æ°¹Æ¡¨µ¡¨µ¢ª¶¢ª¶—¥—¥‰ ‰ |†›|†›r–r–]lƒ]lƒDTqDTq:Kg:KgRe€Re€|‡Ÿ|‡Ÿ–£¾–£¾ª¿Ùª¿ÙÁÖéÁÖéÐãïÐãïÚêñÚêñÔèõÔèõÇßðÇßð¹Òë¹Òë¤ÀߤÀߎ©ÉŽ©ÉdƒªdƒªKw¦Kw¦0h£0h£ ]› ]›T•T•Q•Q•P–P–GGT›T›RR J™ J™C”C”>’>’<™<™6›6›6¢6¢;«;«>°>°9°9°8¨8¨.†.†(1I(1IOVbOVb˜š¦˜š¦ŠŒ˜ŠŒ˜‰”›‰”›¯»É¯»ÉÂÎÜÂÎÜ¿È׿È×°¸Ä°¸Ä¦¯¼¦¯¼‘˜§‘˜§ˆ™ˆ™‚§‚§]p‹]p‹Tg‚Tg‚9Ml9Ml(;Y(;Y@Ww@Wws~˜s~˜“žº“žº­ÂÛ­ÂÛÊáðÊáðâ÷üâ÷üçüþçüþÓìüÓìüÅãùÅãù«Ëê«Ëê–·Û–·ÛŒ©ÊŒ©Êd„¬d„¬Jw¨Jw¨-k«-k«`£`£]¡]¡P˜P˜ Pš Pš M™ M™Y Y U¡U¡ N  N D˜D˜>”>”=œ=œ9¡9¡:ª:ª?±?±@±@±9®9®;¬;¬.‡.‡(2J(2J]cs]csLM\LM\SVeSVe_it_it¦±º¦±ºÐÛçÐÛçÂÊÙÂÊÙ¬²¾¬²¾£©µ£©µœ£±œ£±‹”¦‹”¦xªxªTq“Tq“=Vx=Vx'>c'>c6\6\0S0Skƒ«kƒ«‹£Ì‹£Ì¡¿â¡¿â¢Åé¢Åé·Öò·Öò³Óð³ÓðœÂèœÂè{¨Õ{¨Õk˜Êk˜ÊcÃcÃ\†·\†·U}®U}®Av¯Av¯#`¢#`¢Q•Q•Q—Q—K’K’ M“ M“ K— K—TTT¤T¤ F– F–GžGž?˜?˜:š:š<¤<¤:ª:ª;¬;¬7¤7¤5¤5¤6 6 ,},})3K)3Khm€hm€&&,/A,/AAJYAJY «° «°ÚæðÚæðÄÌÜÄÌܪ¯ºª¯º¡¥±¡¥±¤«¹¤«¹”ž°”ž°r‹¬r‹¬Mr™Mr™,Jr,Jr4\4\2^2^$P…$P…f‡¹f‡¹†¨Ù†¨Ù˜½ç˜½ç†²ä†²ä˜¿ë˜¿ëŽ¶æŽ¶æt¤Ût¤ÛF}¼F}¼=s³=s³?t²?t²:m©:m©Jy°Jy°;v´;v´YœYœFŒFŒII G G K K J– J–Q›Q›S¦S¦ @ @I£I£@œ@œ8™8™?§?§;«;«8©8©1›1›332—2—*w*w(2K(2KTYlTYl  !!#.#.hqwhqw½ÈѽÈÑÉÑßÉÑß´ºÆ´ºÆª±Àª±ÀŽ—ªŽ—ª~«~«h‰°h‰°Dl›Dl›&Ep&Ep Cs CsF{F{#U”#U”Mw²Mw²Z‡ÆZ‡Æ^ŽÉ^ŽÉ\ŽÌ\ŽÌj›Õj›Õkš×kš×J‚ÅJ‚Å,f«,f«%Xœ%Xœ'S“'S“$S“$S“.a¡.a¡!]¦!]¦OšOš >ƒ >ƒ??BBP’P’O›O›N™N™ G“ G“B“B“K¤K¤AœAœ:œ:œ7š7š3—3—1˜1˜0”0”4š4š4–4–,},}(2K(2KDJ]DJ]  h>h!Bo!Bo$O…$O…'V’'V’#Z¡#Z¡9j­9j­8n·8n·1j²1j²ƒ>ƒN–N– J› J› H™ H™ 8| 8|7v7v?v?vT•T•T T L˜L˜ =… =…C–C–M¦M¦BœBœ<Ÿ<Ÿ1‘1‘-ˆ-ˆ,‹,‹005˜5˜6•6•.‚.‚'0J'0J.1C.1C  #%/#%/q‚’q‚’µÂÒµÂÒ¶ÀÒ¶ÀÒ£·Ï£·Ït“¶t“¶Y‚°Y‚°Hv©Hv©4ež4ež*VŒ*VŒ-\—-\—.b£.b£%\¤%\¤,_¥,_¥+^¥+^¥)W™)W™6i±6i±;t¼;t¼1lº1lºU¥U¥F“F“:…:…6}6}>‰>‰J˜J˜H–H–B‹B‹.h.h0j0j;r;rQ”Q”MšMšK—K—N—N— H– H–?‘?‘>–>–44,Š,Š'}'}))-Š-Š...ƒ.ƒ.€.€'/J'/J..      CZpCZp ±Ä ±Ä°¾Ô°¾Ô—µÒ—µÒlËlËG€¸G€¸3g¡3g¡+bŸ+bŸ2h¦2h¦5g§5g§5m³5m³'^¨'^¨"Vž"Vž P– P–#H…#H…1bª1bª1jµ1jµX«X« E™ E™;Š;Š 2‚ 2‚ 3€ 3€?Ž?Ž Gš GšF“F“=€=€&W&W+`+`7o7oO“O“ H– H–J–J–\¦\¦ L— L— 3 3:’:’.‚.‚(„(„"t"t&y&y+‡+‡(„(„(u(u..(/I(/I&(:&(:%%    !4!4BfBfs™Ás™ÁzžÅzžÅe’¼e’¼G€¶G€¶7j¡7j¡(` (` *f§*f§0g§0g§/d¦/d¦'_¦'_¦P™P™FŠFŠA…A…DˆDˆ#W£#W£#a³#a³O¥O¥ F› F› D• D• <Ž <Ž ; ; >’ >’ Aš Aš @’ @’4s4s0c0c—>—<š<š:‘:‘+h+h:n:nK‹K‹JJ J” J” A‘ A‘ 8‡ 8‡5ƒ5ƒ4†4†4ˆ4ˆ;˜;˜6–6–)„)„jj#s#s'„'„,,0”0”%d%d)/G)/G15H15HIEOIEOJEOJEO49Q49Q5T}5T}C‚ÆC‚Æ9€É9€É5{À5{À.r´.r´$p¹$p¹&e¬&e¬ g· g·)n¸)n¸'d¬'d¬ Y¡ Y¡O™O™FF=…=…7}7}:†:†GšGšV­V­ O© O© P¥ P¥Q¦Q¦ M£ M£ K£ K£>œ>œ8–8–2„2„-f-fD}D}H‰H‰M“M“Q›Q› M  M EœEœD›D›BšBš>˜>˜;•;•0‹0‹$u$uee"r"r'…'…))2™2™ (m (m)/E)/E18L18L_^b_^bgeigeiIVsIVsCt¬Ct¬D“äD“ä*}Ô*}Ô!uÉ!uÉ%sÀ%sÀ"{Ï"{Ï$uÍ$uÍ"uÏ"uÏ(rÂ(rÂb°b°RRM—M—H“H“C‘C‘<…<…44 A˜ A˜T¨T¨W±W±Y­Y­W­W­ U­ U­ S® S®?¡?¡4“4“*w*w/e/eNŒNŒE‡E‡P˜P˜X¢X¢ Z° Z°S±S±T³T³P¯P¯H©H©;“;“++ g gaa!q!q(†(†'Œ'Œ5ž5ž +w +w'.D'.D.5I.5IGKVGKVLQ[LQ[>Kc>KcO}¡O}¡b­çb­çH›äH›ä<Þ<Þ9‡Õ9‡Õ.†Ù.†Ù.€Ö.€Ö,×,×(xÌ(xÌ i» i»Y©Y©SŸSŸPŸPŸ@Ž@Ž1s1s2|2| =’ =’H–H–H’H’=y=y:t:t?}?} GŽ GŽB™B™22 %h %h8t8tR‘R‘Q•Q•SœSœX¦X¦T¬T¬G¤G¤N­N­V¸V¸L°L°<˜<˜,ˆ,ˆ``ZZ j j&&&‡&‡5›5›3‡3‡&-C&-C*1G*1G-7J-7J0;L0;L2@S2@S]‡–]‡–‚Éì‚Éìh½÷h½÷Z®öZ®öNìNì;“ä;“ä9à9à6Šà6Šà)Ø)Ø!qÇ!qÇa¶a¶Z¨Z¨Z¬Z¬>‹>‹%a%a/x/x 8 8;„;„9r9rBB66'J'J;k;k F F0‡0‡ X XC„C„W—W—_¥_¥V¡V¡ Xª XªN©N©:–:–H§H§]Ã]ÃP¸P¸=Ÿ=Ÿ..YYSSbb%w%w&‚&‚6˜6˜<˜<˜&,D&,D)0G)0G+5I+5I/9K/9K1>Q1>QGduGdu]‹¥]‹¥\˜»\˜»g«×g«×lµëlµë`±î`±îO¡êO¡êE™êE™ê7Œã7Œã1×1×'tÉ'tÉ%mÀ%mÀc»c»==&f&f,p,p -s -s %V %V D D * * ( (00(L(L *Z *ZTT F F9w9wMŠMŠV›V›N˜N˜ W¬ W¬O«O«G§G§K¯K¯S¹S¹P¸P¸=Ÿ=Ÿ00`` T T !c !c&s&s)†)†2‹2‹=˜=˜&,E&,E(/H(/H(3H(3H-7J-7J/Q0>QAWdAWdWy…Wy…d¥d¥jŸºjŸºh¤Íh¤Íd°çd°ça²ôa²ôU¤ñU¤ñG“äG“ä8„Ù8„Ù'sÏ'sÏ Bž Bž +y +y ,t ,t$\$\    ""  00 F F4u4uA~A~RšRšPžPž V­ V­WµWµR¸R¸O¸O¸I¯I¯R·R·N°N°?Ÿ?Ÿ"y"y b b %j %j 'm 'm(}(} +| +|::'/G'/G&.F&.F(3I(3I,7J,7J,9M,9M,:L,:L,:N,:N/— >— ; ;7{7{ A A $ $  33LL%g%g +r +r @‰ @‰JJ\®\®\°\°V¯V¯U´U´M²M²R´R´O²O²X³X³ d» d» T« T«4œ4œ)…)…)z)z $m $m g g%u%u1…1…*1K*1K+1G+1G(1E(1E*4F*4F+6J+6J*6H*6H)8L)8L-8J-8J-8H-8H*8G*8G$4F$4F$0A$0A *: *:6JU6JU{§¬{§¬ æú æú†Ìù†Ìùd¢çd¢ç,mÁ,mÁQ©Q© H¢ H¢K›K›:|:|FF / /  )),V,V :Š :Š2Š2Š 8‰ 8‰ E EY¥Y¥a·a· V¬ V¬ X³ X³I¨I¨L°L°T±T±S³S³ _¯ _¯e®e®[¢[¢D®D®3 3 +‰+‰"n"ncc"m"m.….…+1K+1K+1H+1H(1E(1E)3D)3D*4G*4G*5F*5F)7I)7I-7H-7H,7G,7G(7F(7F#2E#2E".?".?)9)9,;G,;GVs{Vs{|²Â|²Â†Î÷†Î÷o°ïo°ï9|Ï9|Ï`¶`¶S«S«PŸPŸEŠEŠ)b)b H H !K !K/Z/ZŒ >Œ.o.oDDW¤W¤U¨U¨K«K«K­K­ U­ U­U¡U¡EŽEŽ]°]° `¾ `¾`À`ÀZºZº^¿^¿UµUµY°Y°^¥^¥*a”*a”e«e«^Á^ÁW¿W¿A¬A¬?¡?¡::/Š/Š0…0…,2J,2J+2H+2H'1D'1D(1A(1A)2C)2C)3B)3B(4D(4D*4C*4C*4C*4C%3B%3B!/A!/A *; *;&6&6#1#1#/#/4JT4JTi¦Ãi¦ÃÇùÇùUœëUœë8Ô8Ô#lÆ#lÆ\²\²T¤T¤G—G—HŒHŒG—G—P¤P¤ R© R©L­L­J¨J¨ Q¥ Q¥V¡V¡Z¤Z¤aµaµfÁfÁ gÅ gÅ^¿^¿`Á`Á]½]½]³]³bªbª(a•(a•i±i±gÈgÈ`Æ`ÆP¸P¸O®O®D¦D¦6”6”5Œ5Œ-2J-2J,1H,1H(0B(0B)1A)1A(1A(1A(2A(2A(2A(2A(1@(1@(2A(2A#1@#1@ -> -> )9 )9$4$4!/!/ + +((9^s9^s‚É÷‚É÷b«öb«öCæCæ%{Ú%{ÚdÇdÇ R« R«U«U«3t½3t½ K¢ K¢D¥D¥M¬M¬N°N° H¡ H¡J™J™X£X£2~Ê2~Êi½i½oÇoÇ rÏ rÏdÇdÇdÆdÆjÊjÊd¹d¹h³h³$a—$a—q¼q¼vÕvÕoÓoÓjÌjÌjÃjÃT¶T¶B¥B¥=—=—-2I-2I,2G,2G(0B(0B(0@(0@'0@'0@'1?'1?'0?'0?'/>'/>&0?&0?"/>"/>+<+<(7(7#3#3,,))%%,EW,EWh°áh°áa­÷a­÷G“êG“ê'}Ü'}ÜhÍhÍ Z¹ Z¹a¹a¹5xÀ5xÀX«X«I¦I¦ L© L© P¯ P¯ K£ K£H—H—W¢W¢)r½)r½eºeºd½d½ kÈ kÈdÆdÆbÀbÀ iÁ iÁ ]­ ]­b«b« YŽ YŽk³k³wÔwÔsÕsÕrÎrÎn¾n¾ Y² Y²@¤@¤?—?—-2G-2G-3F-3F)0B)0B'.>'.>&/>&/>&/<&/<%-=%-=%-;%-;$.<$.'/>%/=%/=%.;%.;$,<$,<$,:$,:#-:#-: ,: ,:'6'6#3#3 / /''''&&**/n /n L¤ôL¤ôKšñKšñ0ƒâ0ƒâ wÝ wÝpÖpÖ4…Ü4…Ü?†Ð?†Ð/xÅ/xÅd¹d¹`¶`¶a¸a¸Z¯Z¯MžMž]¨]¨b­b­_¶_¶ X´ X´\¼\¼b¿b¿ `´ `´d¬d¬MM Jˆ JˆCuCuW—W— uÌ uÌ|Ô|Ô/€É/€ÉAy³Ay³)g©)g© Cž Cž<’<’.3G.3G-2E-2E(/B(/B&0?&0?$.<$.<$,9$,9#*9#*9"+9"+9!+7!+7)6)6"1"1..**%%(( %/ %/!&1!&1AlAl)Œé)ŒéG˜ñG˜ñ;‰ä;‰ä6†ã6†ã~à~àQ ðQ ðJ•äJ•ä8‰Ù8‰Ù>‰Ø>‰Ø4ˆÛ4ˆÛ)zÌ)zÌk¿k¿_²_²'k¶'k¶%m»%m»_¶_¶dÂdÂXºXº]¶]¶c´c´^ ^ D~D~/_/_5b5bF€F€ l½ l½"Ì"ÌG‚¹G‚¹U­U­Hr¢Hr¢O”O”2…2…-3G-3G,2E,2E(/B(/B&0?&0?$-<$-<$,:$,:"*9"*9!*9!*9!*7!*7(5(5!1!1,,((&&''**!-!-;b;b*Õ*ÕJ›òJ›ò=è=è3†ã3†ã$€á$€áQ ïQ ïVžèVžèAÞAÞ?‰×?‰×?’â?’â;ŠØ;ŠØkÁkÁ!j¼!j¼'o¼'o¼&tÄ&tÄc½c½cÃcÃ]¿]¿\µ\µa°a°]]D|D|3d3d&/>$,<$,<#+;#+;!):!): ): ): (6 (6%4%4 0 0(($$))&&$$.L.L,j­,j­P¡õP¡õB•ñB•ñ-†å-†å0…ã0…ãP¡ïP¡ïp²ñp²ñV ëV ëAŠ×AŠ×W©òW©òa®óa®ó!lÆ!lÆ5ƒÓ5ƒÓ&wÊ&wÊ)„Ù)„Ù kÍ kÍbÆbÆgÊgÊ\µ\µ^¨^¨[˜[˜EyEy%.>#+;#+;"*:"*: ): ): )9 )9(5(5$3$3//''##&&$$  %>%>(\•(\•K•âK•âK›ðK›ð6è6è6‹ç6‹çV¤ðV¤ðj¯ñj¯ña©îa©îM”ÝM”ÝU§ðU§ð^­ó^­ó-}Ô-}Ô0ƒÖ0ƒÖ!xÏ!xÏ$€×$€× kÎ kÎgÌgÌlÏlÏ e¾ e¾d®d®`Ÿ`ŸOˆOˆJ~J~S‡S‡6d6d O‘ O‘P„P„6Uu6Uu[¦[¦i•Éi•É.n².n² -^ -^*1H*1H(/E(/E&/@&/@#-=#-= )9 )9'8'8(:(: (8 (8'4'4#1#1--&&""    ;_;_?y·?y·a«îa«îLòLòFšñFšñe­ôe­ô\¨ñ\¨ñ|¾ø|¾øi­ìi­ìQ¥íQ¥íX¬óX¬óH§õH§õ%…ß%…ß|Ý|ÝyÕyÕ kÑ kÑtÛtÛyÛyÛzÔzÔs½s½k²k²h¬h¬#l¥#l¥"e™"e™@o@o 5k 5k*K*K#2F#2F`€ `€ ¨×¨×E‡ÊE‡Ê)O)O)/F)/F#*U#*U"*Q"*Q(N(N$K$K#I#I'8'8'6'6&3&3#1#1..''"" ' ' C C 2 2-i-i1]¦1]¦XžÜXžÜV¦ôV¦ôL óL óm´öm´öb®ób®ór¯ùr¯ùaŸïaŸïN™ðN™ðM›ôM›ôH¨õH¨õ%†å%†åsâsâoÚoÚ cÖ cÖkßkß sâ sâ~Û~Û"}É"}És¾s¾k±k±'qª'qª)kž)kžDsDs/^/^ ; ;%6%6Rn‹Rn‹€¤Ð€¤ÐSÎSÎ9e9e%*A%*A€€~~{{yyww%4%4#2#2#0#0#1#100++##   I I±±dd ƒ ƒ{{A|°A|°pÀüpÀü]±û]±ûÈýÈýr½úr½úXŠþXŠþL}úL}úG|ûG|û1qø1qøHªöHªö$‹õ$‹õ[ï[ïUêUêOæOæTìTìe÷e÷(ˆð(ˆð/™ë/™ëˆßˆßr¾r¾0~·0~·<|­<|­"N~"N~??/@W/@W€›Á€›Áy§Ûy§Û/b/b$*A$*AŸŸhh"1"1!0!0 - - - -,,''     @ @xx P P n n ‰ ‰1]¿1]¿_ªñ_ªñc¶ûc¶û†Ìý†ÌývÂûvÂû^’þ^’þ@hû@hû4\ü4\ü9~ø9~øHªöHªö)ô)ô^ñ^ñ ?ï ?ï:ì:ìCðCðnønø1”ó1”ó-˜ì-˜ìƒÛƒÛo½o½/|¶/|¶?±?±$S‚$S‚"B"B1BY1BY|—¼|—¼€«Ü€«Ü7k¦7k¦#)@#)@||ÿÿÿÿÐÐ@@**))%%##        ±±ÿÿ / /   2 2³³ëë0lÓ0lÓsÄûsÄû•Ùþ•ÙþÑþÑþo¨þo¨þ.þ.þÿÿQ¥ûQ¥ûGªøGªø6 ò6 ò#i÷#i÷ÿÿÿÿþþ0‰ü0‰üK·üK·ü'•ï'•ï wÒ wÒ hº hº-x³-x³I‰½I‰½*`*`*J*J  7Ja7Jarޝrޝ•·ß•·ßM…¿M…¿#)@#)@llùùÿÿÏÏ::))((%%""       / /ÃÃìì ) )   + +““éé$RÝ$RÝ_¨ð_¨ðÔúÔú„Ñý„Ñýu³ýu³ý3Tý3TýþþS¨ûS¨ûI¬øI¬ø;¤ó;¤ó(q÷(q÷ÿÿÿÿ$ý$ý1’ü1’üD³üD³ü"”ð"”ðwÔwÔfºfº*w´*w´JоJо/e–/e–,M,M  4E[4E[l‡§l‡§Ž±ÚޱÚOˆÂOˆÂ")A")A!(w©>w©2V2V    )5J)5J[p[pz¡Ëz¡ËW‘ÌW‘Ì#*A#*A!(#)> ½ ½ÿÿÿÿ@@%%######    ååÿÿ²²        ÿÿÿÿ%\ª%\ªK›ÛK›Ûc¯çc¯çxËüxËübÃýbÃýOþOþ8ý8ý>­û>­û%Vÿ%VÿÿÿÿÿŽûŽû%ªü%ªü0¬þ0¬þ”ø”øgÔgÔ_Ã_Ão»o»@„¼@„¼c”Åc”Å/T/T//!0!0AXzAXzZƒ±Zƒ±S‘ÑS‘Ñ%+A%+A#)=#)= ¯ ¯ÿÿÿÿII%%$$22##     êêÿÿ··        kkùùÿÿK²K²B‹ÆB‹ÆY ÖY Öm¿óm¿ó_¾ù_¾ù)eý)eý2ý2ý:¨û:¨ûIÿIÿÿÿÿÿ‘ú‘ú!¦û!¦û-ªý-ªý•ø•øj×j×bÆbÆp¾p¾@…½@…½f—Éf—É3X‚3X‚$;$;  **:Oo:OoV~«V~«SÏSÏ#)?#)?"(<"(<{{ÿÿÿÿ p p&&&& n n%%##    ÿÿÿÿÌÌ          ååÿÿÓÓ Kt Kt1e–1e–@‘Ó@‘ÓU¬éU¬éa¿ûa¿ûLþLþ*–ý*–ýÿÿÿÿÿÿžúžúšùšù £ü £üšûšûuäuäoÔoÔvÊvÊAˆÃAˆÃt¦Út¦ÚEiEi1Ik1Ik&&  *B*BEi“Ei“TŽÊTŽÊ#)?#)?"(<"(<nnÿÿÿÿ } }&&&& { {%%## ! !  ÿÿÿÿÕÕ          ××ÿÿÚÚ@n@n-[‡-[‡<…Ã<…ÃLœÖLœÖY´ðY´ðYúYú%ý%ýÿÿÿÿ þ þ¡ú¡ú›ù›ù¡û¡û˜ú˜ú|è|èuÙuÙzÍzÍ?ˆÄ?ˆÄr¤×r¤×Hm”Hm”6Os6Os((  '>'>CfCfTÉTÉ#+>#+>#):#):&6&6ÿÿÿÿ ¸ ¸(('' · ·((&&%%!!ÿÿÿÿÿÿ          ——ÿÿÿÿTT1D1D(R|(R|#V‚#V‚3†Ã3†Ã1—é1—é %þ %þÿÿÿÿMýMý=¯û=¯û$¡ù$¡ù™÷™÷’ö’öúú‘ò‘ò‹ß‹ß5ŠÍ5ŠÍhœÌhœÌY«Y«MlšMlš00  **:Y:YTŒÈTŒÈ#+=#+=#):#):&6&6÷÷ÿÿ ¿ ¿))//ÂÂ33&&%%!!óóÿÿÿÿ ! !        ŠŠÿÿÿÿ c c,>,>'Lr'Lr!Mt!Mt/x°/x°/ŒØ/ŒØ-ö-öÿÿÿÿQùQù7¦ó7¦ó#›ò#›ò”ï”ïŽïŽïŸùŸù–ó–óáá6‹Î6‹ÎgœÌgœÌ\ƒ¯\ƒ¯LožLož%>%>  **7U}7U}T‹ÆT‹Æ#*;#*;"(9"(9&7&7ÒÒÿÿçç , ,[[ÿÿpp&&%%  ´´ÿÿÿÿ K K        JJÿÿÿÿ²² .@ .@..2O2O#V„#V„)XÒ)XÒÿÿÿÿfäfäxÎx΀ЀÐyÊyÊyÏyÏ/«ù/«ù5°ý5°ý(™ð(™ð:‘Ø:‘ØdÐdÐm›Èm›ÈIµIµ4X‰4X‰44((+Dg+DgXˆ»Xˆ»#):#):"(9"(9&7&7 Ë Ëÿÿêê66^^øø z z&&&&!!©©ÿÿÿÿ V V        CCÿÿÿÿ¹¹+<+<---H-H Mw Mw'RÐ'RÐÿÿÿÿdÝdÝtÈtÈ|Ê|ÊtÂtÂtÅtÅ0£í0£í8±û8±û)›ñ)›ñ6Ù6Ù]™Î]™Îb’Àb’ÀG~µG~µ8]8]55%%)@a)@aW†¸W†¸!&7!&7&8&8 '8 '8¥¥ÿÿÿÿttttÐÐ ¸ ¸ * ***%% i iÿÿÿÿ˜˜          ÿÿÿÿåå""%%  ++-È-Èÿÿÿÿ\´\´^¥^¥c¦c¦!W‘!W‘+X‡+X‡6w©6w©M¸óM¸ó2ªü2ªü!Œá!Œá6ƒÄ6ƒÄ#\”#\”9|¹9|¹N~·N~·!;!;  (=(=S}©S}©!&7!&7&8&8 '8 '8ÿÿÿÿttll ¼ ¼ » » * *))$$ ` `ûûÿÿ¡¡          øøÿÿèè!!$$  ))(Ì(ÌÿÿúúS¸S¸\¢\¢`Ÿ`Ÿ#U‹#U‹+S~+S~4o4oK°èK°è7®ü7®ü$ã$ã3ƒÆ3ƒÆ$`š$`š9|º9|ºP€¹P€¹'C'C  (=(=Q{§Q{§!(8!(8!(8!(8#+:#+:"d"dÿÿÿÿww(1(1(/(/ÐÐ ) )%%!!ååÿÿåå          ËËÿÿÿÿ  ììÿÿØØ Ü Ü"L"L*Ll*Ll3E^3E^*.>*.>'5D'5Dk˜>k˜#)6#)6#*7#*7!*5!*5"*5"*5ùùÿÿ ¨ ¨)3)3 +2 +2$E$E!+!+ ‹ ‹##JJòòÿÿ ‡ ‡        ²²ÿÿøø   R RÿÿþþC\ªC\ª+8~+8~ Ó Ó'-D'-D%'3%'3&& "( "( 0< 0>   c cõõåå  µµýýªª  ÿÿööf{“f{“?B>?B.3:.3:""""""##!!  "*"*%BS%BSmÂçmÂç.ŒÙ.ŒÙ"g¦"g¦,],]#Mx#Mx"e¡"e¡$*3$*3$*1$*1#*0#*0#*.#*. *- *- +. +. +0 +0",/",/!,.!,.+.+.&,&,#)#) & &""7JR7JRdcddcd>?B>?B.3:.3:""""""##!!  "*"*%BS%BSmÂçmÂç.ŒÙ.ŒÙ"g¦"g¦,],]#Mx#Mx"e¡"e¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿobjcryst-2022.1/Fox/src/Fox.rc000066400000000000000000000000531430515525000160420ustar00rootroot00000000000000Fox ICON "Fox.ico" #include "wx/msw/wx.rc" objcryst-2022.1/Fox/src/Fox.vcproj000066400000000000000000000556421430515525000167570ustar00rootroot00000000000000 objcryst-2022.1/Fox/src/Fox.xcf000066400000000000000000000215551430515525000162300ustar00rootroot00000000000000gimp xcf file22BB gimp-comment‰2"˜22Logoÿ     222F22V4 ÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿþÿÿÿÿÿþÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿ Ä Ä4õ8ªªUªÿÿøªUªªýªªùqUªªqöªÿÿUÿUüUâªâþüâÿªýƪüªÿâøªUÿâüªÿªøÿâUªÿóq8ÿÿqüªÿÿù8ÿÿ88Æø8ÿÿUÆüâÿâüÆÿÿúâÿªÆøÿÿUUƪûUÿÿÿþâûÿÿøÆÿâ8ÿUûªÿÿ8û8ÿÿªûUÿÿ8ÿûªªÿûÿÿ8ûÆÿÿøUÿÿUUÿþÆüâÿÆúâÿâûªÿÿüâÿªûqÿÿøÿÿüâÿÆüqÿªûâÿU÷ª8ÿÿqúUÿÿÆ÷ªÿªâ8ô8ÆÿUÿÿâ8 Uú8ªUqUUýUUþ22Nouveau calqueÿ     Ý22ñ22Û310.-.0/..,)&"RdB:""â#! *SçÙ¦x¡431//12110.*("ï4ÕT/20"  €€+…ßõ—…^4330/01211/)'"†¹?0'**!'oïýÕ¯‰aP{6432201321-)#  À‘PH-%.%!QÓþ渮¡mOx6755422320+'!ú¥4Ö–_[:4%(?Æþö×ÑÅ¡c;˜88:88231/,)%!UÔŠd‚l^>DšýùÕÇÄÉ‚<@—788662..+)**%Ó"%+…δ«¥¦‘‡©óüáÄ”¹·;=©;9744.,-*)&%  Ô@.O„¼ãÒÝÎÐÊÏùýðØÐȵ‰4(g»>:610*('((&%!Ý$D|‚Ãéùüûúûù÷öúòßÍÌ«š0*È?<91/)&&Ï%# 81.(%##úø'HŸÛçüýýÛûþüûúüþøÔû¼Å/0z±ÑA<50*&%$$!ù!Y·îüýýýþûúú×øüýüôÚº¹Á©VJËÌ@;83-(*)%# QÆûþþ€´üþûøòóêðöûüïÒº³½Ja¯ß¿A@=96342010+#!9°üûýúþ÷ùõöôçàÙâóîëß¾·­~?WÁÛHE@=98:841-&"_·îòñôñøìíóõßÝÕÑÛÛÔ½²¬¥™okKF ×ÊOIFB><;::640($)&$L­õñåãïñë×òóÆÓÊÙÍÆÊµ¨˜yn`¡‰©Ã¨eGEB?<99 761.*%(/1léñäãàðäÙØÛÌ¿²¶»¶Âº¶´ ~_b€½Ì¹­¢”…GFB>><=;<<851(&!&¼ûñâÚÒÒǼ©¤®¨”¢§·­¾Äµ³™ž¤ÔÙÒ·­¤™JHBAA€>@A@>94/+(s÷öæÚÇ««½¢¥¬°¡™£Ê½ÇÏÇÆÊ¹³—¼ÕÓÌö¥—KIEBDCFEEDC=731põûåʺ¥ Œo¤¨«­­¡Ž°¾Àº¿µ°¥”«Á¿¬¡Š…KGEFJHLJHGFA:U¬úùçÁ©¢›|F/)VŠŠ‰¥·¬³¨°±³¯®¢® ‰ncm…GFIJMLNMJNj™ÔúùèÔÒªŠ„d Na…‚¨´­¾´·²¶Å²rplj|†EHHJNOSv³êú÷öñëáÝΕlgV )1h{Ž®®»¹­¹ ‘hVenŒ}™CGJLS–ì÷öìäààØÇ¶¨¬‹ax„rB6Jk‡X„—¥¡ª©–§Ã¸ŸYSbw‚˜˜ELbis¬äÔÉÀÏÍϰ—“‘…˜¨±­­€¸®¡“weŒ‡˜¢°±³¯©“gaq†ŒžwIE<5/O©¾¸¨¤Œ ¯©¥›‹yu‹²¡ž š™—š‘hn‹”‘‡ƒ†ˆ˜–„js„”dJ. pÄÔÒ˸¡Ÿ¦§³¨ž–…ªµ«™Š‚€Žš“€W`o“––¦—’‚„ty‡„uK] KºãÐÌŸ§³o…’¡­·²¹ÄÌ´ŸŠ{ƒ–›™|vv• ˜…–¦œŸ‘ˆ‹˜•‚K€&AY°ðܺ±¹°¬™r\^…¹ÙçäëæÛ¼³²©°´œŒ–›¦£œ™§«©›—wIb¦˜›ÉÜ×ļ§™§‹‚lYw˜ºÛðüþüùêÛʬ¨«£¡˜š™ ¡ ˜”œ¡ª±±®¬‡Qc¾žœ¥²® ®¢«Š§†x|«Ä×ßÝÞìäîæÉ©¥˜ƒ’€”—Ž–“–£°³¤†KVp¤xˆ®³´¾¹À§ª•”µ¾¯³ÁȿĿ¨™œ§¯¡…myŒ—¥¦¢•šœ­´°¦JMOq„W[|š”š™žšŸ¢±²¸¯¦§£š˜šž£¡œ››{‚Š «˜“Љ…ŒŽ˜LNOaÀ–q`Zl„™˜ ª£­ž™•”™™˜œ¡¡™’‹£ ››¡¤œ—ކ}ts||‡NOR^j¢—w][V[cifVPKDBOl‰‡‹Œlx~†z˜¬±­²®©£¥¢–|{‚‡OMNLQl˜ŒƒykjdwŠ…†ˆ‡{kqy†ˆ€lod‚…~£·ÁÀ²··µ¯«£“}~MLMKQSUy}zy{Ž£¦£œ››œ£Ÿ¢”‘Žeq…—œ¨»¾·¦¨¦¨—™—œ“šNQOLRPQOXekz~†™œ¢¥£¦ªª¨©¢Ÿš”ˆviqxnv„™©°­·±¥žŸž–sPQPMPKQKIQCJ_f˜œ››œ˜˜æž¢¢—xyy §ºÈÀ»¼ÇǶ }{‡PP€1NLJJIBAB/3%"K`c…‡„}{†‹’ž ’‘††“¨·ÀÎÓdzµÀÅ¿¯¤£•POOLJFFB=;3*/$".)`˜‰ylrŒ˜œœ™“‘‰Žª¡¯¶¿ÊØÕɽ®³´±™ˆLLKJGDE@<73+*'","*W°­šƒuh}tˆœŽ›µ ¥­¬¹Æ¤·¨««¥—†FILGEEC<=73-(%#$"-%V¯¼¤”umx…“‡‹¢¤¶™±¼®ÈÀ¼¹ª°©œ|>FCB?>:7852,)%$ (*}ã¾¦š„†”†‹–  ¼ž¢£®ºÎÎ×ÓÁ·«Ÿ59:86544330-)%&#& % P˜×¶©Ÿ†–ž¡š³³ ºÒª½Î¾ÄÀ¼«£š.10/-,.00€œ.,(%%#%#$","8…ï̺¨‰„¤§¢§¿¼¾ÙÒ¼¬±¿Â³¾§Ÿ--+(('*,0/-*(('$##""$&>¨éÜΦ˜›Š\ž¤ž¢š™Ž°§¨£±¸¯ª¯²++('%%',.1-*)&''&&%"#(T®èÙ½¯±Ÿo@bztz{•³¿Á¯¸¿¨¦¶²+*)&%$&),,*'&$'%%#Ñ'Cc±îéپŪ€P_asqŠ˜¤«ÈϹĭ°¬½2-+(&&')+,*'%%$$%$$â#&4gÆëïáÖɲ{{oq~ž—²¦¥Â¾ª³¦™Š­*+,÷+&# íJc?3å"BÂŒg]Me)*+*)**),+'"Ò.±K',(#h»®va\;Z**+*+*))*+& ¯v™4(#$$ ZÎÁmZ<0O+*+*)()*+)%§yC<'' C´ËotsC.S)**½)&')+(!*²sGF0("2¢Ô¦†…‰t8$k((++*')((&   €ðF \BULE.5vί†’S )o&&')'%%$"!  eŠng^cWXw¸ªŒƒ\|~! (}*(&&%! !  .2V„}ƒx€yy«°™‘›XDˆ+)&%" 1RV†—§®¯¬¯¡™’‘‹Šœl YŒ)('#  %Ke‘¬¿«¨¹·®žš£šuovˆ¦iI *iŽ,)&#   Ô .g›¯Ëð°­Á³¨ ª¬”g_o„”T!Xƒ‘)(&"  ¤ 5zÆÓÖÏÆÈµ³³¥žª¯¦‘vauw2 5p¡‘)''# /ŠÄÙÑ×ÍÓ¹ª ž‰›¯·•whx‰`* JŽ·…*++)%$%##€U  |À±È½Ï¼º©ªœˆv~—™™ˆr~|N@›§b1//-)'(('#;y«š­¨¾­¥¬§…|yktyzskhle@5*2€¨‡)210/,+))(% .j¡•†…¡² Š©®lƒw„kbg\^[E.DWUKKUUE]``Z^UY^ae^WA?:/011ü46688€|40*J§æÌ¢mQHK: ,:28EYaVXILTS_e[D3+""./.379::<<=[‹·Ï¸ …yK11( !<@Y`T^NQLTcO)"'&#(3,/37<%/8;9';F0CW_VXN:H]P=.%&6<:+:KJJA8544;6)#',0%/ Z±¾µ€gbhgm^VPHbjXE;23?GF=&+7OHJ\L3:.("&+((.2JC²Öû‡…ˆhBOVZjnjr€…hTC:>NJH87?TTL=CMB<1-,056.3m/J«æÌ¯¥«ž‹rJ42P‡¨½²¿¶¤}stmyvYFIGKJQS@I@8?;8132*1VšŒ”»Îȸ¯˜ˆpgM;W~žÂá÷üìãË·©„wk`]PPMYUND>=9:?@9;.?R»˜’œ¨¤’¤•›x–s_cz–¬¼ÆÅÑãÙÞÏ©ƒweYGTQ?NMEA?<316<:3-4Bh™l~•¤©¨²¬°˜—ƒƒ «—¤­£©¢Ž|{…ŒvU8BWMOY_]O??42:878464.,.'*+66@Rb—ˆnbFB;BGNI<40()3QsolxyR]dqcey‹‹Š€rdZQC<52/566<=Ed}sgTPI]qkjij\HO^vnndOVHmtn’£§Ÿ•˜’ƒqlXE3134668:CEJpqpjjo••ˆ††ˆƒŠ‰~~wHUnt~y†ŠŒ¡£”‚~vxYJ@<297:;:D?BALXZikuŒŽ””“•˜–•˜’‘Š„rYP^g]buƒ“•˜|ofcV81.:;;Ð@:B<9F1;RZxƒ’Ž‹Œ‹Š‹Œ“˜•‡xzejh—¦²¨Ÿ›£›‡aE526899€ü:787311$BSVwyqify{‰””ƒy{€…›¤¬¹¸®—‘š•„jUSC6678:443/.##S‹raU_““‹†‡~„Ÿ”¢¢ªµÀ»ª—ƒ€ykOB34596341/)"!  QŸ™‡n_Xpfo|„“’§’–ž™¦¬‰—€}rcQB1374321+.(" I¥«–…_Zctˆz‚”™«‰Ž¡©ž²¥ –€mT9)1/.-,(&*&!tذsw‡z€Ž–”±Ž•”¨»³¼³š‹u^B $'%$##ü«CË«¡–ƒ{•—©¤’¬À𫱠¡”‡gUI !#)€æ¼°zu‹œ –Ÿ±©°ÉÀ¦Ž“š—{lMK÷"!¦/¥àÒÄ›‘{Mw—™••‰‡¢’‰‡‡jTTV!Iˆ¨ßͳ£¤”`3Spcffnƒ¡©¢‡ZLTV¬5Z¬èàγµŸrBLRe^w†’𲫋‰gXGNZ  #^¿ãæÖË»¥lo`co€Ž† ’Œ Œk`TD>M$# ó"!ß7d>.%m.",#"#&$#   Æ"‚M(*%6dH%,9##$$#!  £Oy5'# 0tU)4&(%#$"   qe=7&(&cc' 8P*0##!"  È   {R4/)& !Pi8&3QP!>!!#"  Ñ  .e2'&*3*'<\:"-:^8G! !  Ð  => !+6M2!6#9N S#"   ¨  #>*/5(:dmI4+X## (#31:;>6=$5hYM :T#"  Ð  1@Ua6/GC8 AtE1ET&#  Õ )Kcxb=?>SD0%0@c/AZS"!û    Ü 2‚ŠyhdQMI- +50 L> )[zW#!Ñ  =s•Ž€[G64>K' -I* 7r•M%$#€ö  Ap]r„rjIH(# -/0<"/€y/*(&#   ?aLFe\|iQXH% #" #`E,*(&$#! ,PB-0PpVAWa!5&)  ?Y_$ .-(&$$#"! !)G;6QJ8>4)'% "GUH--)'&&%%$!:_N+%:*     #7-,()((€‘# 9‚bC% 3  2 $,+'()*(,+&" F‡N2"   **+(*+*)--*$$ 6{ †d,      '&(,,/°-?ew‚i[A/    &((-/-3OwŒjVHE81     ˜  &*-02]‚hZN;96)!    )1_gICD*!%"$"(   Ð )13- 'BII8&)*/)  Þ' C °—lG3+255'" #11   Ä  (D<§Î½±}n`>!$'#981ELZLJUabkkN1   )*.04U…sfWB=:J]XWX\O7=Ld^YM9?4W`]j~‡{xkI0+  )(*+239ccbZ[^o……‚{~{}w}z}kmc1<\_lhtwyŽx]SIK%*,**3-11¤¥xQKTgzgo€‡šu|Ž“„š‡‡zc^< #  kѬ˜„cj~mo}„…¤|‡‚†“§š£ž|lL(Ú  9‰Éª›Œuyn€‰‹€š”„ °‚”•ƒ‰ua4 €ž xẫ“moeŽ•ˆ‘£¢¹­Œjp{L!#žÙÏÁ“„„k=i‡‡yukŽ{fVca/   =~£ØÉ®›šŠQ'C`OPRZpŒ“„Q^K ® )N¥àׯ««•b47?QHgv†›\T$ U¶ÛÝÏĵZaQS]p€wynZ&  Äÿ22 Arrière-planÿ     #A22#U22#e Äÿ Äÿ Äÿobjcryst-2022.1/Fox/src/Fox.xpm000066400000000000000000001227521430515525000162550ustar00rootroot00000000000000/* XPM */ static const char * Fox_xpm[] = { "50 50 2326 2", " c None", ". c #332A24", "+ c #312A24", "@ c #302A23", "# c #2E2A23", "$ c #2D2A20", "% c #2E2B20", "& c #302B20", "* c #2F2C22", "= c #2E2C21", "- c #2E2B1F", "; c #2C261A", "> c #292317", ", c #262018", "' c #221D15", ") c #1E1B15", "! c #1E1A13", "~ c #1C1710", "{ c #19150F", "] c #181510", "^ c #1A1511", "/ c #191511", "( c #181211", "_ c #181310", ": c #171210", "< c #191412", "[ c #181413", "} c #191513", "| c #1A1615", "1 c #1E1916", "2 c #1B1612", "3 c #1C1613", "4 c #1C1914", "5 c #524A37", "6 c #646364", "7 c #423F3E", "8 c #3A332E", "9 c #221C14", "0 c #221914", "a c #221912", "b c #231B13", "c c #211B12", "d c #201B11", "e c #2A2216", "f c #534225", "g c #E7C26D", "h c #D98C2E", "i c #A66722", "j c #8F5D2C", "k c #784D23", "l c #A16522", "m c #342923", "n c #332A26", "o c #312B24", "p c #5D211B", "q c #A2120E", "r c #BA0E0A", "s c #BB0E0B", "t c #A3120E", "u c #761D15", "v c #FF0000", "w c #9F0E0A", "x c #221A14", "y c #1F1A14", "z c #1D1811", "A c #1A140E", "B c #32110D", "C c #990907", "D c #B30706", "E c #670D0D", "F c #B30606", "G c #B20606", "H c #321111", "I c #1A1516", "J c #191415", "K c #181414", "L c #321110", "M c #980807", "N c #B30605", "O c #BB0F0B", "P c #E86348", "Q c #544B4D", "R c #741A1B", "S c #BB0F0E", "T c #BA0D0C", "U c #840E0C", "V c #201812", "W c #201911", "X c #2B2316", "Y c #856836", "Z c #DFBB64", "` c #F5AE48", " . c #C27625", ".. c #97612C", "+. c #855C39", "@. c #5E3B23", "#. c #8D5A23", "$. c #342A24", "%. c #332B23", "&. c #302A21", "*. c #BA0E0B", "=. c #49251C", "-. c #312A20", ";. c #312B1E", ">. c #741912", ",. c #6F140F", "'. c #1D1712", "). c #1B1510", "!. c #660C09", "~. c #E50202", "{. c #B20605", "]. c #1B1614", "^. c #1C1615", "/. c #1A1312", "(. c #191515", "_. c #1A1414", ":. c #181311", "<. c #17110E", "[. c #D7271A", "}. c #B99979", "|. c #3F3435", "1. c #302827", "2. c #CF0807", "3. c #B80C0C", "4. c #2A2420", "5. c #211B16", "6. c #1F1A13", "7. c #272016", "8. c #6F5A30", "9. c #EFCE74", "0. c #FDC155", "a. c #D57F1F", "b. c #AF6D29", "c. c #895A34", "d. c #613C26", "e. c #50301F", "f. c #7B4F28", "g. c #362B25", "h. c #342A23", "i. c #332B24", "j. c #322A22", "k. c #E80503", "l. c #332A20", "m. c #322B1F", "n. c #31291D", "o. c #2D251A", "p. c #B80A07", "q. c #3B1812", "r. c #201914", "s. c #1D1813", "t. c #680F0C", "u. c #16110E", "v. c #18110F", "w. c #1B1313", "x. c #1A1210", "y. c #B20505", "z. c #191312", "A. c #1B1513", "B. c #191210", "C. c #19110D", "D. c #990806", "E. c #F8130D", "F. c #917965", "G. c #50433D", "H. c #852825", "I. c #B90D0D", "J. c #251D1C", "K. c #2E2728", "L. c #25201D", "M. c #211B15", "N. c #514326", "O. c #D3B463", "P. c #FECB63", "Q. c #E69027", "R. c #B86F20", "S. c #AE7438", "T. c #A17350", "U. c #6D432A", "V. c #4F2E1E", "W. c #785330", "X. c #362923", "Y. c #372A23", "Z. c #352A21", "`. c #352A22", " + c #A3110D", ".+ c #33291F", "++ c #322B20", "@+ c #472419", "#+ c #2B2116", "$+ c #870E0A", "%+ c #211812", "&+ c #1E1712", "*+ c #4E110E", "=+ c #7F0A08", "-+ c #17100C", ";+ c #170F0C", ">+ c #170F0D", ",+ c #170E0D", "'+ c #1A110F", ")+ c #1B120F", "!+ c #1A110E", "~+ c #1A100C", "{+ c #4C0E09", "]+ c #AD5A40", "^+ c #823729", "/+ c #DA100B", "(+ c #3A3029", "_+ c #342826", ":+ c #282220", "<+ c #3F3221", "[+ c #C6A250", "}+ c #FED469", "|+ c #F6A638", "1+ c #D78626", "2+ c #D18533", "3+ c #C58951", "4+ c #A17450", "5+ c #633821", "6+ c #3B2418", "7+ c #986B3E", "8+ c #382821", "9+ c #3A2B23", "0+ c #64221B", "a+ c #771B14", "b+ c #31281E", "c+ c #2F281D", "d+ c #D00806", "e+ c #292016", "f+ c #251A13", "g+ c #211711", "h+ c #E50302", "i+ c #160D0C", "j+ c #180D0C", "k+ c #CB0303", "l+ c #1A120F", "m+ c #1B1410", "n+ c #1C130D", "o+ c #1D130E", "p+ c #EC0805", "q+ c #D81F11", "r+ c #DC0F09", "s+ c #904C22", "t+ c #6C4C2A", "u+ c #5E4533", "v+ c #3E2E2A", "w+ c #443527", "x+ c #9A763C", "y+ c #FDCE5C", "z+ c #F9AF3A", "A+ c #D58622", "B+ c #C7812D", "C+ c #C4813A", "D+ c #C9925E", "E+ c #825338", "F+ c #3C2014", "G+ c #40291A", "H+ c #976F47", "I+ c #372621", "J+ c #38261F", "K+ c #382720", "L+ c #A5120F", "M+ c #741812", "N+ c #B80B08", "O+ c #2A2016", "P+ c #2A1C13", "Q+ c #251811", "R+ c #690F0B", "S+ c #980705", "T+ c #180E0B", "U+ c #170D0B", "V+ c #160C0A", "W+ c #170C0A", "X+ c #170B0A", "Y+ c #E50102", "Z+ c #18100F", "`+ c #221C18", " @ c #251813", ".@ c #1E120C", "+@ c #2B1A11", "@@ c #C82D1B", "#@ c #B45C1C", "$@ c #A55E16", "%@ c #A6631A", "&@ c #915721", "*@ c #87582B", "=@ c #A97736", "-@ c #F3B84D", ";@ c #FCAA32", ">@ c #E18C21", ",@ c #C48336", "'@ c #945C23", ")@ c #B97C39", "!@ c #B77E4E", "~@ c #3B2116", "{@ c #160B0A", "]@ c #3D281A", "^@ c #A97D53", "/@ c #3B2A23", "(@ c #392822", "_@ c #37261F", ":@ c #D20807", "<@ c #E70403", "[@ c #2C2017", "}@ c #5B1A13", "|@ c #70140E", "1@ c #261A10", "2@ c #25160E", "3@ c #20130E", "4@ c #B40705", "5@ c #4B0C08", "6@ c #190E0C", "7@ c #4A0808", "8@ c #B20504", "9@ c #1D130F", "0@ c #402E20", "a@ c #2E1E14", "b@ c #4F3219", "c@ c #845623", "d@ c #D25829", "e@ c #E46612", "f@ c #CE7816", "g@ c #D0801E", "h@ c #CA791B", "i@ c #CF7917", "j@ c #F9AB2F", "k@ c #FDB035", "l@ c #F09928", "m@ c #D8913A", "n@ c #D09D64", "o@ c #C89B6D", "p@ c #B57F49", "q@ c #895834", "r@ c #341E13", "s@ c #281712", "t@ c #67442B", "u@ c #BB8858", "v@ c #3E2B23", "w@ c #3A2923", "x@ c #36261D", "y@ c #281C14", "z@ c #271D16", "A@ c #B70A07", "B@ c #281C13", "C@ c #26180F", "D@ c #25150E", "E@ c #21130E", "F@ c #19100B", "G@ c #180F0B", "H@ c #180E0C", "I@ c #180D0B", "J@ c #170D0A", "K@ c #970504", "L@ c #54110E", "M@ c #44311E", "N@ c #7C5228", "O@ c #825623", "P@ c #C38633", "Q@ c #E99731", "R@ c #FE250D", "S@ c #FD4D18", "T@ c #FBAF3D", "U@ c #F9A124", "V@ c #F7991D", "W@ c #F69210", "X@ c #FA9D18", "Y@ c #F29110", "Z@ c #DF8B1C", "`@ c #CD8A35", " # c #CC9C68", ".# c #AB7F59", "+# c #9A6C4D", "@# c #301B13", "## c #130C0B", "$# c #2A1A13", "%# c #81593A", "&# c #C88C54", "*# c #3F2923", "=# c #3C2822", "-# c #7B1A13", ";# c #70130D", "># c #261913", ",# c #261B14", "'# c #6E120D", ")# c #251A11", "!# c #23170F", "~# c #20120C", "{# c #1D100C", "]# c #CC0403", "^# c #1B110D", "/# c #190F0B", "(# c #150B09", "_# c #190D0C", ":# c #1A0D0B", "<# c #E50101", "[# c #D30805", "}# c #744B20", "|# c #966531", "1# c #D39140", "2# c #E9AC55", "3# c #FBBF61", "4# c #FE4C18", "5# c #FD962A", "6# c #FF1508", "7# c #FF1406", "8# c #FA9E18", "9# c #F99A11", "0# c #FCA320", "a# c #FB9A14", "b# c #E47503", "c# c #D46F04", "d# c #CA760F", "e# c #C38841", "f# c #DAA674", "g# c #8F6945", "h# c #6B4931", "i# c #26150F", "j# c #110908", "k# c #422A1E", "l# c #936945", "m# c #CA8E54", "n# c #422C26", "o# c #3E2923", "p# c #BD0D0A", "q# c #401712", "r# c #251812", "s# c #231813", "t# c #231912", "u# c #231810", "v# c #1F150E", "w# c #1B100C", "x# c #E50201", "y# c #160A09", "z# c #160A0A", "A# c #7F0706", "B# c #AA5C25", "C# c #DB9B4B", "D# c #E7AF63", "E# c #FCCB78", "F# c #FDC362", "G# c #FE4F1B", "H# c #FD9D38", "I# c #FBAD3E", "J# c #FF5625", "K# c #FB8E16", "L# c #FCAA25", "M# c #FEAC30", "N# c #F89412", "O# c #D46702", "P# c #C35F02", "Q# c #BB6F13", "R# c #BC8440", "S# c #C59463", "T# c #7F542F", "U# c #2F1B12", "V# c #110707", "W# c #302119", "X# c #7A5841", "Y# c #B1835A", "Z# c #D19153", "`# c #412922", " $ c #3C2821", ".$ c #E80403", "+$ c #CF0605", "@$ c #261A13", "#$ c #241712", "$$ c #241812", "%$ c #211610", "&$ c #1E130C", "*$ c #1B0E0A", "=$ c #190C0A", "-$ c #7E0706", ";$ c #B10404", ">$ c #170A09", ",$ c #300908", "'$ c #E60201", ")$ c #CF5121", "!$ c #EEC682", "~$ c #FCD38F", "{$ c #FDD68A", "]$ c #FDCF79", "^$ c #FE4223", "/$ c #FEB259", "($ c #FBB551", "_$ c #FAB34D", ":$ c #FB8C39", "<$ c #FD5F18", "[$ c #FDAF35", "}$ c #FCA630", "|$ c #F49114", "1$ c #DA7604", "2$ c #BA6104", "3$ c #B97520", "4$ c #C18D4C", "5$ c #A9773E", "6$ c #56321A", "7$ c #170B09", "8$ c #140C0A", "9$ c #4A3529", "0$ c #8F705B", "a$ c #CBA17A", "b$ c #CC9157", "c$ c #402923", "d$ c #7C1A16", "e$ c #D00705", "f$ c #401913", "g$ c #2A1B15", "h$ c #291B15", "i$ c #251914", "j$ c #231911", "k$ c #20140C", "l$ c #1D0F0A", "m$ c #180B09", "n$ c #160B0B", "o$ c #B10403", "p$ c #2F0907", "q$ c #320B0A", "r$ c #B30504", "s$ c #EB0503", "t$ c #D36C30", "u$ c #FBC473", "v$ c #FED995", "w$ c #FED181", "x$ c #FEA86F", "y$ c #FE2E1D", "z$ c #FBA551", "A$ c #F8AA47", "B$ c #F2A036", "C$ c #F76923", "D$ c #FE1203", "E$ c #FC8930", "F$ c #FCB74B", "G$ c #EF9527", "H$ c #D27709", "I$ c #BA6809", "J$ c #B3782D", "K$ c #BD8949", "L$ c #90602A", "M$ c #4A2A15", "N$ c #100605", "O$ c #614A37", "P$ c #AF8E72", "Q$ c #DFB795", "R$ c #BF854D", "S$ c #412A25", "T$ c #801D18", "U$ c #7E1D17", "V$ c #7B1B15", "W$ c #791913", "X$ c #771813", "Y$ c #34251C", "Z$ c #32231B", "`$ c #30231B", " % c #312319", ".% c #301F14", "+% c #2B1911", "@% c #23130E", "#% c #1C0F0E", "$% c #490A09", "%% c #B10303", "&% c #640806", "*% c #830A07", "=% c #7B150F", "-% c #B07C41", ";% c #FCC070", ">% c #FBB15D", ",% c #FDC881", "'% c #FABD72", ")% c #FE8A58", "!% c #FA7D4C", "~% c #FB7C47", "{% c #F87131", "]% c #F6AA48", "^% c #F58B24", "/% c #EF5B17", "(% c #EA550E", "_% c #E64F08", ":% c #EC5406", "<% c #F76510", "[% c #F08828", "}% c #EB992F", "|% c #DF881A", "1% c #BE7212", "2% c #B77E30", "3% c #AD7C3C", "4% c #7E4E22", "5% c #3F1F10", "6% c #120606", "7% c #0E0506", "8% c #57402F", "9% c #C19B80", "0% c #DBA779", "a% c #9D622F", "b% c #48312A", "c% c #452F28", "d% c #402F26", "e% c #3D2D23", "f% c #392920", "g% c #38271F", "h% c #3A281F", "i% c #382820", "j% c #34271E", "k% c #2D1D13", "l% c #261610", "m% c #22130F", "n% c #1F110E", "o% c #1E1210", "p% c #1F110D", "q% c #5F3B1F", "r% c #B7793F", "s% c #EEAB61", "t% c #F29D4C", "u% c #F19A46", "v% c #F4AD65", "w% c #F1A85C", "x% c #F8BE7C", "y% c #ECAD69", "z% c #EDA551", "A% c #F3AC58", "B% c #F5A748", "C% c #DF8525", "D% c #DD7C15", "E% c #D57917", "F% c #D16B0A", "G% c #DB7405", "H% c #DB7906", "I% c #D47A0F", "J% c #BD731D", "K% c #B26B18", "L% c #AC6819", "M% c #A56C23", "N% c #996522", "O% c #6F4016", "P% c #6B350D", "Q% c #4B2A13", "R% c #463223", "S% c #A08060", "T% c #D7A881", "U% c #CA8745", "V% c #4F2912", "W% c #49322C", "X% c #46312A", "Y% c #423028", "Z% c #3E2F26", "`% c #3C2C24", " & c #3B2B23", ".& c #3A2921", "+& c #3A2920", "@& c #362820", "#& c #34251B", "$& c #302018", "%& c #281A14", "&& c #241713", "*& c #291C17", "=& c #261A15", "-& c #1F1410", ";& c #241611", ">& c #4C2E18", ",& c #AD6A2C", "'& c #F5A150", ")& c #F19542", "!& c #E5862D", "~& c #E38530", "{& c #EFA150", "]& c #F1B270", "^& c #EBA056", "/& c #D78A41", "(& c #F2A957", "_& c #F3AE61", ":& c #C66C21", "<& c #D38335", "[& c #CA7726", "}& c #D98429", "|& c #CD6B0C", "1& c #C66206", "2& c #CA6705", "3& c #B55C07", "4& c #A85E14", "5& c #985B1B", "6& c #794516", "7& c #6E3C13", "8& c #7F4B16", "9& c #603213", "0& c #A15B0A", "a& c #9D611D", "b& c #89643F", "c& c #A97F59", "d& c #C38D5F", "e& c #A86324", "f& c #652F0A", "g& c #47332E", "h& c #45322D", "i& c #422F28", "j& c #3F3026", "k& c #3C2E24", "l& c #392C24", "m& c #392A23", "n& c #392B22", "o& c #372B21", "p& c #36291E", "q& c #312219", "r& c #2E1E18", "s& c #2A1C18", "t& c #251814", "u& c #281E19", "v& c #2F2520", "w& c #312621", "x& c #6C4119", "y& c #E98C29", "z& c #F19847", "A& c #E4893B", "B& c #E38636", "C& c #E07E1F", "D& c #F0A051", "E& c #E4954A", "F& c #D98938", "G& c #D8893E", "H& c #DB8834", "I& c #CC7A29", "J& c #BF6B1C", "K& c #B25F18", "L& c #B66B27", "M& c #BB6D25", "N& c #B65F10", "O& c #C26408", "P& c #BA5804", "Q& c #B65D08", "R& c #B4630F", "S& c #A05E17", "T& c #7E4413", "U& c #5F2F0E", "V& c #623515", "W& c #804613", "X& c #BD6C0A", "Y& c #CC7F22", "Z& c #B98247", "`& c #AD7F55", " * c #A27248", ".* c #944F19", "+* c #853205", "@* c #47322D", "#* c #46332D", "$* c #423029", "%* c #3E2E27", "&* c #3C2F26", "** c #3D2D25", "=* c #3B2D25", "-* c #3C2D21", ";* c #38291C", ">* c #35261D", ",* c #31221B", "'* c #281C17", ")* c #261C16", "!* c #211714", "~* c #261A14", "{* c #BC853A", "]* c #FBB15F", "^* c #F19B4E", "/* c #E2812B", "(* c #DA7015", "_* c #D2690F", ":* c #D27825", "<* c #C77F3A", "[* c #BC6F2A", "}* c #A9510D", "|* c #A44B0E", "1* c #AE5512", "2* c #A8510E", "3* c #94440E", "4* c #A2561B", "5* c #A75C1A", "6* c #B75F12", "7* c #AD520A", "8* c #BE5F05", "9* c #C46505", "0* c #B55F0B", "a* c #B36712", "b* c #99520D", "c* c #9E580C", "d* c #7F4B19", "e* c #A46015", "f* c #D47A0A", "g* c #D97B0B", "h* c #D28023", "i* c #B77737", "j* c #AD6119", "k* c #A43D02", "l* c #994205", "m* c #4A322D", "n* c #48312C", "o* c #413129", "p* c #413128", "q* c #413228", "r* c #403128", "s* c #403123", "t* c #3E2D20", "u* c #34241D", "v* c #2F211C", "w* c #2B201B", "x* c #281E18", "y* c #735E39", "z* c #F7C982", "A* c #F6AB62", "B* c #E68F43", "C* c #DA7B25", "D* c #C76414", "E* c #AB520C", "F* c #AB550F", "G* c #BD7433", "H* c #A24B0D", "I* c #A54404", "J* c #AC4D06", "K* c #B04E06", "L* c #A1480B", "M* c #994A0E", "N* c #A3581A", "O* c #CA7E32", "P* c #BD6919", "Q* c #C76F16", "R* c #CF720B", "S* c #C76405", "T* c #C66406", "U* c #CA6A06", "V* c #B96408", "W* c #B36813", "X* c #976124", "Y* c #BC7116", "Z* c #D57607", "`* c #D36F05", " = c #CC6A07", ".= c #C36A11", "+= c #B65406", "@= c #A54203", "#= c #973D04", "$= c #4B322C", "%= c #49322B", "&= c #453127", "*= c #423128", "== c #443229", "-= c #43342A", ";= c #463528", ">= c #45362C", ",= c #45352B", "'= c #443526", ")= c #433022", "!= c #3D2B20", "~= c #37271E", "{= c #33251D", "]= c #31251F", "^= c #706546", "/= c #F5D287", "(= c #FBC781", "_= c #E5934E", ":= c #CA7632", "<= c #BA6322", "[= c #A5571B", "}= c #A0561A", "|= c #8C3E0D", "1= c #6F2E11", "2= c #904411", "3= c #A45716", "4= c #A85510", "5= c #AB4B05", "6= c #AD4B06", "7= c #AD550C", "8= c #A15517", "9= c #8E4511", "0= c #B05D12", "a= c #BE600B", "b= c #C06007", "c= c #BA5A06", "d= c #BF5E04", "e= c #B55503", "f= c #B05906", "g= c #A55E13", "h= c #94612A", "i= c #AB651A", "j= c #C15E02", "k= c #BF5703", "l= c #AC4101", "m= c #A13F03", "n= c #9D3A03", "o= c #8A2F04", "p= c #853004", "q= c #4B312A", "r= c #47312B", "s= c #453128", "t= c #46342A", "u= c #4A362B", "v= c #48362A", "w= c #4C3829", "x= c #4A382D", "y= c #48382D", "z= c #47382A", "A= c #463424", "B= c #413024", "C= c #3A2A20", "D= c #554A36", "E= c #ACA77B", "F= c #FAE6A0", "G= c #F9CC86", "H= c #E7A264", "I= c #C16D2C", "J= c #A95113", "K= c #A2480C", "L= c #9B4B11", "M= c #7C3A13", "N= c #461B0F", "O= c #2F110B", "P= c #1E0A08", "Q= c #29140E", "R= c #562C13", "S= c #8A3A0A", "T= c #8A3205", "U= c #893809", "V= c #8F450D", "W= c #A55915", "X= c #B76111", "Y= c #AC560B", "Z= c #B3580A", "`= c #A84903", " - c #B04C03", ".- c #B15404", "+- c #B35303", "@- c #AF5F0A", "#- c #AE6515", "$- c #A25B11", "%- c #AE4401", "&- c #A03301", "*- c #892B03", "=- c #6E2207", "-- c #631D06", ";- c #6D2207", ">- c #852E04", ",- c #472F27", "'- c #462E26", ")- c #493328", "!- c #4A372C", "~- c #4D392C", "{- c #4C3A2C", "]- c #4E3A2C", "^- c #4D3C2F", "/- c #4A3C2F", "(- c #4E3D2D", "_- c #6A5B3F", ":- c #998B65", "<- c #D4B777", "[- c #FACF82", "}- c #F9B869", "|- c #E8A05B", "1- c #D48541", "2- c #D2792F", "3- c #AA4B0E", "4- c #8A3108", "5- c #84310A", "6- c #64280E", "7- c #160706", "8- c #0C0204", "9- c #0A0104", "0- c #110507", "a- c #120608", "b- c #190A0C", "c- c #1F0A07", "d- c #4E1C0A", "e- c #61210A", "f- c #853C0B", "g- c #824013", "h- c #A85914", "i- c #B46010", "j- c #AD5407", "k- c #BE5E08", "l- c #B44E03", "m- c #B75102", "n- c #B24C01", "o- c #B65402", "p- c #C56304", "q- c #B24F03", "r- c #8F2901", "s- c #722207", "t- c #70270C", "u- c #6C260D", "v- c #6A230A", "w- c #7C2807", "x- c #863307", "y- c #452C26", "z- c #482F28", "A- c #483328", "B- c #4A372D", "C- c #4E3C2F", "D- c #4F3C2D", "E- c #534233", "F- c #766D4F", "G- c #B3A977", "H- c #EAD18F", "I- c #FAD58C", "J- c #F7B96A", "K- c #F6AB56", "L- c #F19C48", "M- c #EB9545", "N- c #E18A38", "O- c #DD8331", "P- c #CE6F20", "Q- c #953B0B", "R- c #6C270E", "S- c #67290E", "T- c #56210F", "U- c #200B09", "V- c #0F0305", "W- c #0F0407", "X- c #180709", "Y- c #110407", "Z- c #29120F", "`- c #1C0907", " ; c #180705", ".; c #31120A", "+; c #682E10", "@; c #7B421A", "#; c #8F4C18", "$; c #8E440E", "%; c #AE570A", "&; c #AE5107", "*; c #BB5605", "=; c #B94E02", "-; c #AD4702", ";; c #B95002", ">; c #A03D02", ",; c #913302", "'; c #681D06", "); c #561D0F", "!; c #65240E", "~; c #6E280C", "{; c #8C2C05", "]; c #7D2E0A", "^; c #993F04", "/; c #432D26", "(; c #47312A", "_; c #4C3B30", ":; c #534032", "<; c #96875D", "[; c #ECC982", "}; c #F7BD68", "|; c #F6AE5A", "1; c #EC9D4E", "2; c #E4933B", "3; c #E08D39", "4; c #E08A36", "5; c #D87F29", "6; c #C77121", "7; c #B66119", "8; c #A85A1B", "9; c #AC5A1F", "0; c #8B3E11", "a; c #612510", "b; c #782F0E", "c; c #8D380B", "d; c #843B11", "e; c #723912", "f; c #421E0E", "g; c #361B0F", "h; c #4A2714", "i; c #6B3B12", "j; c #90460C", "k; c #873006", "l; c #581F0A", "m; c #844313", "n; c #97571E", "o; c #A55F1E", "p; c #A15614", "q; c #AA580C", "r; c #A94E05", "s; c #963A05", "t; c #A74803", "u; c #C35D02", "v; c #B85002", "w; c #9F3D03", "x; c #902E03", "y; c #591907", "z; c #531907", "A; c #621F08", "B; c #772504", "C; c #822603", "D; c #983603", "E; c #983C05", "F; c #452F29", "G; c #4C3831", "H; c #625E5F", "I; c #696567", "J; c #735649", "K; c #AC7443", "L; c #E49344", "M; c #D47D2A", "N; c #C97521", "O; c #C07325", "P; c #CF7B22", "Q; c #CD7524", "R; c #CF7522", "S; c #C27228", "T; c #B0621F", "U; c #9D5218", "V; c #974D17", "W; c #934815", "X; c #914312", "Y; c #853C14", "Z; c #81340F", "`; c #98410B", " > c #A85413", ".> c #B1570F", "+> c #AD5910", "@> c #AD5711", "#> c #AE5309", "$> c #933403", "%> c #772A08", "&> c #652F14", "*> c #8C4E1B", "=> c #874515", "-> c #985012", ";> c #A25812", ">> c #B05A0B", ",> c #B15308", "'> c #B35406", ")> c #AF5004", "!> c #A94804", "~> c #933B05", "{> c #812B05", "]> c #672007", "^> c #611C05", "/> c #712105", "(> c #862802", "_> c #8C2702", ":> c #9E3502", "<> c #772B0A", "[> c #493029", "}> c #453331", "|> c #3C2C33", "1> c #35252D", "2> c #2F1D20", "3> c #4F3427", "4> c #A97242", "5> c #BE8349", "6> c #B88249", "7> c #A87238", "8> c #A46626", "9> c #8C5629", "0> c #A05A1E", "a> c #AF6B2A", "b> c #A9672F", "c> c #A56129", "d> c #9B521A", "e> c #8B4415", "f> c #793816", "g> c #753315", "h> c #8B4116", "i> c #9D4D17", "j> c #B25917", "k> c #A1470A", "l> c #9E480B", "m> c #A04C0C", "n> c #9A460C", "o> c #99430A", "p> c #973E07", "q> c #9A3C06", "r> c #913A07", "s> c #682B0E", "t> c #6E3A17", "u> c #8B4B1B", "v> c #8F4A0F", "w> c #944A0B", "x> c #91410C", "y> c #873809", "z> c #833508", "A> c #863407", "B> c #883406", "C> c #983B04", "D> c #963604", "E> c #842903", "F> c #6A1D04", "G> c #732305", "H> c #842702", "I> c #8F2C02", "J> c #943002", "K> c #64250E", "L> c #4A2F27", "M> c #2E1C1B", "N> c #0D0204", "O> c #0A0103", "P> c #0F0405", "Q> c #180C0D", "R> c #705A43", "S> c #C4B1A0", "T> c #D4BEB0", "U> c #D2B597", "V> c #CB9D6C", "W> c #B88047", "X> c #A16733", "Y> c #9F622B", "Z> c #A66832", "`> c #A76735", " , c #B36D35", "., c #A85E27", "+, c #9E5622", "@, c #965020", "#, c #854823", "$, c #AA6231", "%, c #B56A31", "&, c #AB5818", "*, c #99450D", "=, c #8A3B0E", "-, c #82320D", ";, c #80330D", ">, c #8E3F0E", ",, c #9A470D", "', c #934611", "), c #803D11", "!, c #572610", "~, c #602B10", "{, c #6F3710", "], c #934F10", "^, c #96480D", "/, c #964A0F", "(, c #A65C13", "_, c #974C0C", ":, c #7F3309", "<, c #923A05", "[, c #822E07", "}, c #842803", "|, c #742204", "1, c #792604", "2, c #872B02", "3, c #842802", "4, c #752806", "5, c #7F2E06", "6, c #4B3228", "7, c #5D4A44", "8, c #080102", "9, c #0D0405", "0, c #4B433C", "a, c #BAB2A7", "b, c #E3D6CE", "c, c #D0C3BD", "d, c #CCBBB1", "e, c #9F877D", "f, c #A7856E", "g, c #B38860", "h, c #9D683E", "i, c #6F4221", "j, c #854F24", "k, c #925627", "l, c #A15A23", "m, c #AD6A39", "n, c #B76E38", "o, c #B26A31", "p, c #B9723C", "q, c #C48047", "r, c #CC854F", "s, c #B46829", "t, c #9F5417", "u, c #8A4313", "v, c #7B3A15", "w, c #833E12", "x, c #964E18", "y, c #9B4A0D", "z, c #99480B", "A, c #7C380C", "B, c #76370F", "C, c #763F14", "D, c #955413", "E, c #A05412", "F, c #984C12", "G, c #853D0D", "H, c #964307", "I, c #A64D06", "J, c #9C4203", "K, c #9F3C02", "L, c #913102", "M, c #882D03", "N, c #8B2C02", "O, c #8F3002", "P, c #983502", "Q, c #953602", "R, c #822E06", "S, c #4B3329", "T, c #806D68", "U, c #261616", "V, c #412F2C", "W, c #594A41", "X, c #B0ABA0", "Y, c #F0E6DA", "Z, c #DCCCC4", "`, c #BAAFAA", " ' c #B1A5A1", ".' c #B9ABA4", "+' c #B09E94", "@' c #AC8B72", "#' c #99724D", "$' c #724A2C", "%' c #5C341A", "&' c #5E3216", "*' c #855024", "=' c #B98766", "-' c #D9A886", ";' c #E7BD98", ">' c #E4B286", ",' c #EBBF98", "'' c #E6B68E", ")' c #DBA474", "!' c #BC7D46", "~' c #B3733D", "{' c #B2743F", "]' c #A96D3A", "^' c #B0794A", "/' c #B4763B", "(' c #9C591C", "_' c #8C460F", ":' c #90490F", "<' c #8F470C", "[' c #8F4B0D", "}' c #964A0B", "|' c #9B5114", "1' c #A6530E", "2' c #8F4009", "3' c #A34904", "4' c #9C4004", "5' c #993802", "6' c #A73F02", "7' c #AB3B01", "8' c #A93801", "9' c #9B3101", "0' c #9D3301", "a' c #973201", "b' c #493128", "c' c #62564F", "d' c #A69A98", "e' c #988C8A", "f' c #9B9489", "g' c #C9BBAF", "h' c #DCCEC2", "i' c #D7C8BF", "j' c #C4B8B0", "k' c #BCAFA6", "l' c #A79891", "m' c #99887F", "n' c #A79082", "o' c #8B705D", "p' c #826754", "q' c #6C4D39", "r' c #593B28", "s' c #775740", "t' c #987E73", "u' c #BA9E93", "v' c #DBC2AD", "w' c #F0E1CA", "x' c #FCF7E2", "y' c #FEFCE7", "z' c #FCECD3", "A' c #F9E3C5", "B' c #EACBAB", "C' c #DBB796", "D' c #CAA98C", "E' c #AC8464", "F' c #A8774A", "G' c #AB6B2D", "H' c #A3601C", "I' c #A15D18", "J' c #985010", "K' c #9A500C", "L' c #994D0D", "M' c #A05919", "N' c #A15515", "O' c #A04E0A", "P' c #984407", "Q' c #943E05", "R' c #9C3D03", "S' c #A13902", "T' c #AA3A01", "U' c #B13F01", "V' c #B14001", "W' c #AE3901", "X' c #AC3B01", "Y' c #872E05", "Z' c #513F36", "`' c #63524B", " ) c #BEBBBB", ".) c #9E989B", "+) c #9C928A", "@) c #A59C92", "#) c #B2A8A0", "$) c #AEA49B", "%) c #A0928C", "&) c #AEA49C", "*) c #A2958E", "=) c #AB9B99", "-) c #8A7874", ";) c #A79691", ">) c #86736C", ",) c #785F54", "') c #7C6356", ")) c #8D7A6E", "!) c #AB968A", "~) c #C4AC9A", "{) c #D7BCA7", "]) c #DFC6B5", "^) c #DDC5B7", "/) c #DED1C8", "() c #ECE3D7", "_) c #E4D9CC", ":) c #EEDECE", "<) c #E6CFBB", "[) c #C9A991", "}) c #A98365", "|) c #A5774E", "1) c #986534", "2) c #8F5925", "3) c #834716", "4) c #925417", "5) c #905114", "6) c #803F11", "7) c #944E16", "8) c #974D12", "9) c #8E4109", "0) c #8F3F07", "a) c #963C03", "b) c #933302", "c) c #963102", "d) c #A33601", "e) c #B03C01", "f) c #B33A01", "g) c #A43301", "h) c #862D05", "i) c #4B3429", "j) c #564239", "k) c #706862", "l) c #A49997", "m) c #786C67", "n) c #887E73", "o) c #9D958C", "p) c #AEA49E", "q) c #B3A9A2", "r) c #B4A89F", "s) c #BEB2A9", "t) c #B9ACA9", "u) c #C0B0AC", "v) c #AA9793", "w) c #958378", "x) c #948379", "y) c #B5A097", "z) c #BEABA1", "A) c #AF978B", "B) c #B39D93", "C) c #C1A494", "D) c #C8AD9C", "E) c #BFA38E", "F) c #C4A993", "G) c #BFA28A", "H) c #A88E76", "I) c #997C61", "J) c #9C7B5C", "K) c #A78569", "L) c #AF8C6D", "M) c #A17648", "N) c #855527", "O) c #6D3814", "P) c #794215", "Q) c #90571B", "R) c #8C4D17", "S) c #974F14", "T) c #9D591D", "U) c #A55F18", "V) c #A65D0F", "W) c #A24F06", "X) c #953F04", "Y) c #9A3F05", "Z) c #9D3402", "`) c #9C3201", " ! c #AD3A01", ".! c #B43801", "+! c #B03701", "@! c #A63802", "#! c #4A3429", "$! c #4D362A", "%! c #4F3C2E", "&! c #716D65", "*! c #84726B", "=! c #574439", "-! c #5B4C45", ";! c #7C7169", ">! c #9A918A", ",! c #948C81", "'! c #9D9589", ")! c #9A8A7D", "!! c #998C82", "~! c #9E8F87", "{! c #9A8A81", "]! c #9F8D80", "^! c #A28D7F", "/! c #B19C92", "(! c #B29B91", "_! c #B8A192", ":! c #AF9589", "~ c #4E3629", ",~ c #4F362A", "'~ c #524032", ")~ c #5E5245", "!~ c #6A6254", "~~ c #A2978C", "{~ c #97887C", "]~ c #816E61", "^~ c #776255", "/~ c #5D4634", "(~ c #5B422E", "_~ c #563B2B", ":~ c #5B4233", "<~ c #634736", "[~ c #694E3C", "}~ c #664938", "|~ c #563C30", "1~ c #503426", "2~ c #4B3022", "3~ c #44281F", "4~ c #422920", "5~ c #4F3328", "6~ c #6C5142", "7~ c #897363", "8~ c #876F5F", "9~ c #816C5A", "0~ c #8B7867", "a~ c #8C7966", "b~ c #6C523E", "c~ c #785D45", "d~ c #7E644C", "e~ c #86715A", "f~ c #7A634C", "g~ c #81654A", "h~ c #987955", "i~ c #AC8B61", "j~ c #B18B62", "k~ c #AD8A6B", "l~ c #B28F6B", "m~ c #AE804E", "n~ c #A97231", "o~ c #A3641B", "p~ c #A55A0D", "q~ c #A25105", "r~ c #8D3C0A", "s~ c #7C350F", "t~ c #7B320F", "u~ c #822F09", "v~ c #87350B", "w~ c #4F3629", "x~ c #4E3C2E", "y~ c #4C3D30", "z~ c #514534", "A~ c #6C6455", "B~ c #988F85", "C~ c #8C7D73", "D~ c #837366", "E~ c #796757", "F~ c #6B5442", "G~ c #6A503D", "H~ c #64493A", "I~ c #775D4A", "J~ c #8A715D", "K~ c #856B58", "L~ c #866A57", "M~ c #886958", "N~ c #876A5C", "O~ c #7B5C4F", "P~ c #6B4837", "Q~ c #714F3D", "R~ c #795E4C", "S~ c #8F7664", "T~ c #866E5E", "U~ c #886E59", "V~ c #80644D", "W~ c #6C4F39", "X~ c #6F563F", "Y~ c #644834", "Z~ c #826D57", "`~ c #857460", " { c #7E6E5D", ".{ c #907F6A", "+{ c #A3927E", "@{ c #B7A38D", "#{ c #C1A790", "${ c #C09F87", "%{ c #B2957B", "&{ c #B79878", "*{ c #B7926B", "={ c #B58349", "-{ c #AF7130", ";{ c #AB6C2B", ">{ c #A35815", ",{ c #93450A", "'{ c #7D3308", "){ c #7E3109", "!{ c #8D3306", "~{ c #903404", "{{ c #4D3629", "]{ c #4C3628", "^{ c #4D382A", "/{ c #4B3A2B", "({ c #514332", "_{ c #534533", ":{ c #554A39", "<{ c #797063", "[{ c #7D7163", "}{ c #7A7062", "|{ c #796A5A", "1{ c #7B6A5B", "2{ c #816F5E", "3{ c #8E7F6F", "4{ c #A39585", "5{ c #A69585", "6{ c #A38F82", "7{ c #9C887B", "8{ c #9B867E", "9{ c #9B867B", "0{ c #9D887D", "a{ c #9C8377", "b{ c #A38A7D", "c{ c #9F897A", "d{ c #A28D7D", "e{ c #947E6B", "f{ c #917E6D", "g{ c #8E7763", "h{ c #654831", "i{ c #71553C", "j{ c #7F6E5C", "k{ c #85745F", "l{ c #8F7E6C", "m{ c #8D7968", "n{ c #978674", "o{ c #9C8A77", "p{ c #A88C79", "q{ c #BBA18E", "r{ c #BEA38F", "s{ c #B79478", "t{ c #A6825D", "u{ c #A87E53", "v{ c #A67649", "w{ c #A8784B", "x{ c #975925", "y{ c #994A11", "z{ c #974006", "A{ c #9C3C05", "B{ c #933202", "C{ c #9A3903", "D{ c #4E372A", "E{ c #513A2C", "F{ c #4F3B2A", "G{ c #4C3A2A", "H{ c #524433", "I{ c #503F2D", "J{ c #514231", "K{ c #4F4131", "L{ c #584C3C", "M{ c #655848", "N{ c #6B5A49", "O{ c #7A695C", "P{ c #7E6B5E", "Q{ c #86756A", "R{ c #998C80", "S{ c #9C8E82", "T{ c #A2948A", "U{ c #A5948A", "V{ c #A3938B", "W{ c #A6958D", "X{ c #AA988E", "Y{ c #AA968E", "Z{ c #A8958D", "`{ c #A99889", " ] c #A29286", ".] c #9F9183", "+] c #9A8A7B", "@] c #948471", "#] c #88725A", "$] c #76593F", "%] c #695039", "&] c #715E46", "*] c #786750", "=] c #6E5D4A", "-] c #76624B", ";] c #84755F", ">] c #99836E", ",] c #A9937E", "'] c #B0957B", ")] c #AD9072", "!] c #B79879", "~] c #B1906D", "{] c #A57C53", "]] c #9E6F3D", "^] c #9F6630", "/] c #9E6330", "(] c #965624", "_] c #7F380B", ":] c #813107", "<] c #732E0A", "[] c #503A2B", "}] c #513B2D", "|] c #503B2B", "1] c #4D3B2B", "2] c #50402E", "3] c #4B3A27", "4] c #4B3C2B", "5] c #493929", "6] c #514634", "7] c #43311D", "8] c #4A3B2D", "9] c #5F5246", "0] c #665A52", "a] c #817873", "b] c #988D86", "c] c #90837E", "d] c #9D928F", "e] c #9C8E8A", "f] c #9B8B83", "g] c #9B8C82", "h] c #9C8B84", "i] c #988A82", "j] c #988B83", "k] c #988C84", "l] c #9E938A", "m] c #A29890", "n] c #A29587", "o] c #978773", "p] c #8D7866", "q] c #8F7A63", "r] c #78654F", "s] c #796A54", "t] c #796852", "u] c #8D7F6A", "v] c #A08F7C", "w] c #A79784", "x] c #BAA695", "y] c #C8B29C", "z] c #C0A894", "A] c #BB9F84", "B] c #BC9B77", "C] c #C7A37D", "D] c #C79B70", "E] c #B6875F", "F] c #A0612D", "G] c #8D450D", "H] c #7D350A", "I] c #7B3208", "J] c #873607", "K] c #503829", "L] c #503928", "M] c #503927", "N] c #4E3928", "O] c #4C3A28", "P] c #4A3724", "Q] c #4A3827", "R] c #493726", "S] c #423323", "T] c #413120", "U] c #42311C", "V] c #2F1E12", "W] c #332418", "X] c #251710", "Y] c #22150F", "Z] c #4B423A", "`] c #605350", " ^ c #635656", ".^ c #857777", "+^ c #877976", "@^ c #84716C", "#^ c #7D6964", "$^ c #7B6660", "%^ c #867971", "&^ c #8B7B72", "*^ c #8D8177", "=^ c #928981", "-^ c #9E9488", ";^ c #A09486", ">^ c #928170", ",^ c #918371", "'^ c #867963", ")^ c #867B67", "!^ c #8D806C", "~^ c #938571", "{^ c #A89B8A", "]^ c #B7A496", "^^ c #C0ACA0", "/^ c #CEB9A5", "(^ c #D3B89E", "_^ c #C7AE8A", ":^ c #B39771", "<^ c #B59169", "[^ c #C09A77", "}^ c #C5956C", "|^ c #BF8448", "1^ c #AF6A23", "2^ c #A45510", "3^ c #A3530E", "4^ c #95430A", "5^ c #503627", "6^ c #4F3626", "7^ c #4F3725", "8^ c #4C3826", "9^ c #4A3A27", "0^ c #463420", "a^ c #423322", "b^ c #3D2F20", "c^ c #3B2E1E", "d^ c #332314", "e^ c #2A1A10", "f^ c #2F1E13", "g^ c #24150D", "h^ c #22130C", "i^ c #2E2319", "j^ c #1A0E0A", "k^ c #180E09", "l^ c #291C15", "m^ c #605352", "n^ c #897265", "o^ c #79614D", "p^ c #6C5545", "q^ c #725F57", "r^ c #8C8179", "s^ c #988F86", "t^ c #9C938B", "u^ c #9C9387", "v^ c #998B80", "w^ c #938677", "x^ c #918775", "y^ c #897E6A", "z^ c #8E8474", "A^ c #AA9F8E", "B^ c #A19480", "C^ c #AFA294", "D^ c #B6A28F", "E^ c #BFAA97", "F^ c #CAB5A2", "G^ c #D8C0A9", "H^ c #D5BB9F", "I^ c #C9AA8E", "J^ c #BD9773", "K^ c #AE8361", "L^ c #B3805F", "M^ c #B47950", "N^ c #B16B36", "O^ c #994F11", "P^ c #88420D", "Q^ c #4C3323", "R^ c #4C3424", "S^ c #4B3523", "T^ c #4A3928", "U^ c #473624", "V^ c #443320", "W^ c #453422", "X^ c #403120", "Y^ c #3C2F1E", "Z^ c #372918", "`^ c #332214", " / c #2B1C11", "./ c #27170F", "+/ c #22150D", "@/ c #2C2117", "#/ c #180D08", "$/ c #221710", "%/ c #2A1B14", "&/ c #190D0B", "*/ c #57514B", "=/ c #B09F9B", "-/ c #AD998F", ";/ c #9A8779", ">/ c #836E5F", ",/ c #755F52", "'/ c #68584F", ")/ c #7D7068", "!/ c #74665C", "~/ c #7F6F63", "{/ c #887C6F", "]/ c #908475", "^/ c #9C9380", "// c #8E816F", "(/ c #9B927F", "_/ c #B5A795", ":/ c #A09282", "( c #1C0E0A", ",( c #2A1A12", "'( c #7D746B", ")( c #E3D8D1", "!( c #BEB0AC", "~( c #A69D98", "{( c #9A9084", "]( c #847363", "^( c #86776A", "/( c #94877E", "(( c #867A6D", "_( c #8B806F", ":( c #968E7D", "<( c #A09684", "[( c #A09485", "}( c #BCB1A4", "|( c #9E8E7C", "1( c #A39482", "2( c #AE9D86", "3( c #BAA893", "4( c #CEBBA7", "5( c #CEB39A", "6( c #D7BCA3", "7( c #D3B39E", "8( c #C19A7C", "9( c #B78B6C", "0( c #AB754C", "a( c #9F5E28", "b( c #904208", "c( c #352016", "d( c #392417", "e( c #3A2716", "f( c #382516", "g( c #362415", "h( c #352313", "i( c #342314", "j( c #342316", "k( c #332316", "l( c #301E10", "m( c #2D1A0E", "n( c #29190E", "o( c #25170E", "p( c #26170F", "q( c #23170E", "r( c #261910", "s( c #1E120A", "t( c #20130C", "u( c #20110C", "v( c #504339", "w( c #988F89", "x( c #D7CBC9", "y( c #B6ABAA", "z( c #A9A19B", "A( c #9F968C", "B( c #8D7F75", "C( c #8D8379", "D( c #867B6E", "E( c #968F80", "F( c #9E9589", "G( c #A1978B", "H( c #9A9080", "I( c #B3A99A", "J( c #B3A494", "K( c #A09284", "L( c #BAACA0", "M( c #D2C0B0", "N( c #AA9A82", "O( c #BDAB94", "P( c #CEB195", "Q( c #BEA083", "R( c #C4A189", "S( c #C09475", "T( c #BC8761", "U( c #AB6734", "V( c #A35512", "W( c #9A490A", "X( c #2E1B11", "Y( c #311D13", "Z( c #301E13", "`( c #2F1F13", " _ c #2D1E12", "._ c #2C1C11", "+_ c #2E1E12", "@_ c #302014", "#_ c #302115", "$_ c #302313", "%_ c #2E1D10", "&_ c #281810", "*_ c #25170F", "=_ c #251810", "-_ c #23160F", ";_ c #241711", ">_ c #221610", ",_ c #2C1D14", "'_ c #22130D", ")_ c #38291D", "!_ c #858078", "~_ c #EFE6E1", "{_ c #CCBCBA", "]_ c #BAB0AB", "^_ c #A89D93", "/_ c #897A6D", "(_ c #8D7F6F", "__ c #847565", ":_ c #908B7F", "<_ c #A49C8E", "[_ c #A7A095", "}_ c #A29688", "|_ c #A79F91", "1_ c #BFB1A3", "2_ c #BCA99D", "3_ c #BEB0A2", "4_ c #D9C9B9", "5_ c #D2C0AD", "6_ c #BCA68C", "7_ c #AC8E6A", "8_ c #B19370", "9_ c #BF9A7F", "0_ c #C2977B", "a_ c #B37B4C", "b_ c #BE6C21", "c_ c #A74D07", "d_ c #9F4B08", "e_ c #2D1910", "f_ c #2D1911", "g_ c #28190F", "h_ c #27170E", "i_ c #2A1A11", "j_ c #2C1C13", "k_ c #302217", "l_ c #2F2114", "m_ c #2D1C0F", "n_ c #2A190F", "o_ c #281910", "p_ c #281912", "q_ c #271911", "r_ c #241912", "s_ c #22150E", "t_ c #24170F", "u_ c #261710", "v_ c #3E2F23", "w_ c #A8A59E", "x_ c #E9E0D9", "y_ c #DCD2CF", "z_ c #CEC4C1", "A_ c #A69B93", "B_ c #988D84", "C_ c #9B9184", "D_ c #8A7B6B", "E_ c #5C4D3D", "F_ c #7F7769", "G_ c #9E978D", "H_ c #A4998F", "I_ c #9E9587", "J_ c #9A8979", "K_ c #998775", "L_ c #8E7F6B", "M_ c #B0A28E", "N_ c #A7927B", "O_ c #A88966", "P_ c #A37F56", "Q_ c #B18763", "R_ c #B88761", "S_ c #AF6A2F", "T_ c #AA540B", "U_ c #AF5405", "V_ c #B25605", "W_ c #2B1810", "X_ c #28170F", "Y_ c #25160D", "Z_ c #27180F", "`_ c #2C1B12", " : c #2E1F13", ".: c #312114", "+: c #2D1B11", "@: c #2A1911", "#: c #291810", "$: c #271A14", "%: c #271B14", "&: c #261810", "*: c #23150E", "=: c #281911", "-: c #54493D", ";: c #90887E", ">: c #AEA8A3", ",: c #E8DFD8", "': c #D9CDC9", "): c #BDB3AE", "!: c #AFA39B", "~: c #B1A49A", "{: c #9F948A", "]: c #6F6051", "^: c #403327", "/: c #625343", "(: c #7A7060", "_: c #74634F", ":: c #7A6650", "<: c #7B6652", "[: c #816E5A", "}: c #958370", "|: c #B3A18C", "1: c #BFA993", "2: c #C1A284", "3: c #AF8151", "4: c #B8875E", "5: c #BF814B", "6: c #A85A15", "7: c #A64C03", "8: c #B25606", "9: c #26160D", "0: c #24140B", "a: c #26170E", "b: c #291B12", "c: c #2C1E15", "d: c #2C1F14", "e: c #2A1B13", "f: c #271710", "g: c #241710", "h: c #271A12", "i: c #251A12", "j: c #25180F", "k: c #23160E", "l: c #271810", "m: c #433529", "n: c #635A4E", "o: c #B1ACA5", "p: c #EEE8E0", "q: c #E9E0D7", "r: c #D9CEC6", "s: c #BEB3AB", "t: c #C5B5AB", "u: c #AA9F95", "v: c #807262", "w: c #504234", "x: c #5F4C37", "y: c #61523F", "z: c #736551", "A: c #715E48", "B: c #8A7767", "C: c #988676", "D: c #A4927F", "E: c #AB9A86", "F: c #C8B29B", "G: c #CFAB8D", "H: c #B98B5C", "I: c #C48954", "J: c #AD6724", "K: c #B0580B", "L: c #9D4706", "M: c #AC4E02", "N: c #BD5A02", "O: c #322018", "P: c #2D1B12", "Q: c #291C13", "R: c #2B1E14", "S: c #2C2016", "T: c #2A1C15", "U: c #271913", "V: c #241A13", "W: c #241913", "X: c #251911", "Y: c #241810", "Z: c #24160E", "`: c #34231A", " < c #675E55", ".< c #C6BFB6", "+< c #EBE3DB", "@< c #EFE6DD", "#< c #E1D6CF", "$< c #D6CBC4", "%< c #C9BBB5", "&< c #B2A59D", "*< c #7B6C5A", "=< c #7B6F61", "-< c #716353", ";< c #7E6F5D", ">< c #8D8070", ",< c #9E8E80", "'< c #978677", ")< c #B2A090", "!< c #A69279", "~< c #A58C6E", "{< c #C2A07F", "]< c #BE8C5A", "^< c #AA6B26", "/< c #B36011", "(< c #A6540A", "_< c #994405", ":< c #8A3E06", "<< c #AD4D02", ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l ", "m n o p q r s t u r v v w x y z A B C D E F G H I J K L M N D O P Q R S T U V V W X Y Z ` ...+.@.#.", "$.. %.&.*.v v =.-.;.>.v ,.x '.).!.~.{.].^./.~.~.H (._.:.<.~.v [.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.", "g.h.i.j.s v k.l.m.n.o.p.q.r.s.t.v ~.u.v.w.x.y.v G z.A.B.C.D.v E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.", "X.Y.Z.`.v v +.+++@+#+$+%+&+*+v v =+-+;+>+,+y.v v '+)+!+~+{+v v ]+^+/+(+_+J.:+<+[+}+|+1+2+3+4+5+6+7+", "8+8+9+0+v v a+b+c+d+e+f+g+&+h+v ~.C.;+>+i+j+k+v v !+l+m+n+o+p+v q+r+s+t+u+v+w+x+y+z+A+B+C+D+E+F+G+H+", "I+J+K+L+v v >.M+d+N+O+P+Q+R+v v S+T+U+V+W+X+v v Y+Z+`+ @.@+@@@v v #@$@%@&@*@=@-@;@>@,@'@)@!@~@{@]@^@", "/@(@_@:@v <@[@}@v |@1@2@3@4@v v 5@T+6@W+W+7@v v 8@9@0@a@b@c@d@v v e@f@g@h@i@j@k@l@m@n@o@p@q@r@s@t@u@", "v@w@x@v v p.y@z@A@B@C@D@E@v v v F@G@H@I@J@K@v v L@M@N@O@P@Q@R@v v S@T@U@V@W@X@Y@Z@`@ #.#+#@###$#%#&#", "*#=#-#v v ;#>#,#'#)#!#~#{#v v ]#^#/#(#_#:#<#v [#}#|#1#2#3#4#5#6#v 7#8#9#0#a#b#c#d#e#f#g#h#i#j#k#l#m#", "n#o#p#v v q#r#s#t#u#v#{#w#x#v 8@U+J@y#z#A#v v B#C#D#E#F#G#H#I#J#v v K#L#M#N#O#P#Q#R#S#T#U#V#W#X#Y#Z#", "`# $.$v +$@$r##$$$%$&$*$=$-$v ;$X+W+>$,$'$v )$!$~${$]$^$/$($_$:$v v <$[$}$|$1$2$3$4$5$6$7$8$9$0$a$b$", "c$d$v v e$f$g$h$i$j$k$l$m$n$o$v p$>$q$r$s$t$u$v$w$x$y$v z$A$B$C$v v D$E$F$G$H$I$J$K$L$M$N$U+O$P$Q$R$", "S$T$U$V$W$X$Y$Z$`$ %.%+%@%#%j+$%%%&%*%=%-%;%>%,%'%)%!%~%{%]%^%/%(%_%:%<%[%}%|%1%2%3%4%5%6%7%8%9%0%a%", "b%c%d%e%f%g%h%i%j% %k%l%m%n%o%!+H@p%q%r%s%t%u%v%w%x%y%z%A%B%C%D%E%F%G%H%I%J%K%L%M%N%O%P%Q%R%S%T%U%V%", "W%X%Y%Z%`% &.&+&@&#&$&%&&&*&=&-&;&>&,&'&)&!&~&{&]&^&/&(&_&:&<&[&}&|&1&2&3&4&5&6&7&8&9&0&a&b&c&d&e&f&", "g&h&i&j&k&l&m&n&o&p&q&r&s&t&u&v&w&x&y&z&A&B&C&D&E&F&G&H&I&J&K&L&M&N&O&P&Q&R&S&T&U&V&W&X&Y&Z&`& *.*+*", "@*#*$*%*Z%&***=*k&-*;*>*,*'*)*!*~*{*]*^*/*(*_*:*<*[*}*|*1*2*3*4*5*6*7*8*9*0*a*b*c*d*e*f*g*h*i*j*k*l*", "m*n*Y%o*p*q*q*r*q*s*t*f%u*v*w*x*y*z*A*B*C*D*E*F*G*H*I*J*K*L*M*N*O*P*Q*R*S*T*U*V*W*X*Y*Z*`* =.=+=@=#=", "$=%=&=*===-=;=>=,='=)=!=~={=]=^=/=(=_=:=<=[=}=|=1=2=3=4=5=6=7=8=9=0=a=b=c=d=e=f=g=h=i=j=k=l=m=n=o=p=", "q=r=s=t=u=v=w=x=y=z=A=B=C=D=E=F=G=H=I=J=K=L=M=N=O=P=Q=R=S=T=U=V=W=X=Y=Z=`= -.-+-@-#-$-%-&-*-=---;->-", ",-'-)-!-~-{-]-^-/-(-_-:-<-[-}-|-1-2-3-4-5-6-7-8-9-0-a-b-c-d-e-f-g-h-i-j-k-l-m-n-o-p-q-r-s-t-u-v-w-x-", "y-z-A-B-C-D-E-F-G-H-I-J-K-L-M-N-O-P-Q-R-S-T-U-V-W-X-Y-Z-`- ;.;+;@;#;$;%;&;*;=;-;;;>;,;';);!;~;{;];^;", "/;(;B-_;:;<;[;};|;1;2;3;4;5;6;7;8;9;0;a;b;c;d;e;f;g;h;i;j;k;l;m;n;o;p;q;r;s;t;u;v;w;x;y;z;A;B;C;D;E;", "F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;W;X;Y;Z;`; >.>+>@>7=#>m=$>%>&>*>=>->;>>>,>'>)>!>~>{>]>^>/>(>_>:><>", "[>}>|>1>2>3>4>5>6>7>8>9>0>a>b>c>d>e>f>g>h>i>j>k>l>m>n>o>p>q>r>s>t>u>v>w>x>y>z>A>B>C>D>E>F>G>H>I>J>K>", "L>M>N>O>P>Q>R>S>T>U>V>W>X>Y>Z>`> ,.,+,@,#,$,%,&,*,=,-,;,>,,,',),!,~,{,],^,/,(,_,:,<,[,},|,1,2,3,4,5,", "6,7,Y-8,9,0,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,", "S,T,U,V,W,X,Y,Z,`, '.'+'@'#'$'%'&'*'='-';'>',''')'!'~'{']'^'/'('_':'<'['}'|'1'2'3'4'5'6'7'8'9'0'a'%>", "b'c'd'e'f'g'h'i'j'k'l'm'n'o'p'q'r's't'u'v'w'x'y'z'A'B'C'D'E'F'G'H'I'J'K'L'M'N'O'P'Q'R'S'T'U'V'W'X'Y'", "Z'`' ).)+)@)#)$)%)&)*)=)-);)>),)')))!)~){)])^)/)()_):)<)[)})|)1)2)3)4)5)6)7)8)V=9)0)a)b)c)d)e)f)g)h)", "i)j)k)l)m)n)o)p)q)r)s)t)u)l'v)w)x)y)z)A)B)C)D)E)F)G)H)I)J)K)L)M)N)O)P)Q)R)S)T)U)V)W)X)Y)Z)`) !.!+!@!", "#!$!%!&!*!=!-!;!>!,!'!)!!!~!{!]!^!/!(!_!:!~,~'~)~!~~~{~]~^~/~(~_~:~<~[~}~|~1~2~3~4~5~6~7~8~9~0~a~b~c~d~e~f~g~h~i~j~k~l~m~n~o~p~q~H,r~s~t~u~v~", "w~$!x~y~z~A~B~C~D~E~F~G~H~I~J~K~L~M~N~O~P~Q~R~S~T~U~V~W~X~Y~Z~`~ {.{+{@{#{${%{&{*{={-{;{>{,{'{){!{~{", "{{]{^{/{({_{:{<{[{}{|{1{2{3{4{5{6{7{8{9{0{a{b{c{d{e{f{g{h{i{j{k{l{m{n{o{p{q{r{s{t{u{v{w{x{y{z{A{B{C{", "D{E{F{G{H{I{J{K{L{M{N{O{P{Q{R{S{T{U{V{W{X{Y{Z{`{ ].]+]@]#]$]%]&]*]=]-];]>],]'])]!]~]{]]]^]/](]_]:]<]", "[]}]|]1]2]3]J{4]5]6]7]8]9]0]a]b]c]d]e]f]g]h]i]j]k]l]m]n]o]p]q]r]s]t]u]v]w]x]y]z]A]B]C]D]E]F]G]H]I]J]", "K]L]M]N]O]P]Q]R]S]T]U]V]W]X]Y]Z]`] ^.^+^@^#^$^%^&^*^=^-^;^>^,^'^)^!^~^{^]^^^/^(^_^:^<^[^}^|^1^2^3^4^", "5^6^7^8^9^0^0^a^b^c^d^e^f^g^h^i^j^k^l^m^j]n^o^p^q^r^s^t^u^v^w^x^y^z^A^B^C^D^E^F^G^H^I^J^K^L^M^N^O^P^", "Q^R^S^T^U^V^W^X^Y^Z^`^ /e^./+/@/#/$/%/&/*/=/-/;/>/,/'/)/!/~/{/]/^///(/_/:/(,('()(!(~({(](^(/(((_(:(<([(}(|(n]1(2(3(4(5(6(7(8(9(0(a(b(", "c(d(e(f(g(h(i(j(k(d^l(m(n(o(p(q(r(s(t(Q+p%u(v(w(x(y(z(A(B(C(D(E(F(G(H(I(J(K(L(M(N(O(P(Q(R(S(T(U(V(W(", "X(Y(Z(`( _._+_@_#_$_%_$(&_*_=_!#=_-_;_>_,_'_)_!_~_{_]_^_/_(___:_<_[_}_|_1_2_3_4_5_6_7_8_9_0_a_b_c_d_", "e_f_+%&_g_h_i_j_k_l_m_n_o_p_q_r_q(!#s_s_t_u_v_w_x_y_z_A_B_C_D_E_F_G_H_I_n]J_K_L_M_N_O_P_Q_R_S_T_U_V_", "W_W_X_./Y_&(Z_`_ :.:+:@:#:u_$:%:&:&:o(+/*:=:-:;:>:,:':):!:~:{:]:^:/:(:_:::<:[:}:|:1:2:3:4:5:6:7:o-8:", "+%@:%(9:Y_0:a:b:c:d:e:f:u_g:h:i:j:*_o(l/k:l:m:n:o:p:q:r:s:t:u:v:w:x:y:z:A:B:C:D:E:F:G:H:I:J:K:L:M:N:", "O:P:+@g_&:a:q_Q:R:S:T:U:X]r#V:W:X:Y:t_Z:-_&:`: <.<+<@<#<$<%<&<*<=<]:-<;<><,<'<)m_exit = true; e->m_pid = pid; e->m_dir = m_dir; e->m_status = status; //m_parent->AddPendingEvent( e ); m_parent->QueueEvent(e); //m_parent->onProcessTerminate(pid, status, m_dir); delete this; } /////////////////////////////////////////////// FoxProcess::FoxProcess(wxString tmpDir) { tmpDIR = tmpDir; running = false; pid = -1; jobID = -1; startingtime = wxDateTime::Now();//just to initiate it } FoxProcess::~FoxProcess() { } void FoxProcess::setPid(int pid) { this->pid = pid; } int FoxProcess::getPid() { return pid; } void FoxProcess::setTmpDir(wxString dir) { tmpDIR = dir; } wxString FoxProcess::getTmpDir() { return tmpDIR; } void FoxProcess::setRunning(bool run) { running = run; } bool FoxProcess::isRunning() { return running; } void FoxProcess::setJobID(int id) { jobID = id; } int FoxProcess::getJobID() { return jobID; } void FoxProcess::setStarted(wxDateTime t) { startingtime = t; } wxDateTime FoxProcess::getStartingTime() { return startingtime; } int FoxProcess::getProgressInPercents(wxTimeSpan avCalcTime) { wxDateTime ct = wxDateTime::Now(); wxTimeSpan duration = ct - startingtime; int p = (int) (100*(duration.GetSeconds().ToDouble() / avCalcTime.GetSeconds().ToDouble())); if(p>100) p=100; return p; } /////////////////////////////////////////////// GrdRslt::GrdRslt(int ID, wxString cost, wxString content) { this->ID = ID; this->cost = cost; this->content = content; sent = false; pending = false; } GrdRslt::~GrdRslt() { } /////////////////////////////////////////////// /////////////////////////////////////////////// FoxClient::FoxClient(wxString working_dir): wxEvtHandler() { m_working_dir = working_dir; wxString dirName = addToPath(getWorkingDir(), _T("processes")); if(!wxDirExists(dirName)) wxMkdir(dirName); //m_DataMutex = new wxMutex(); //m_ResultsMutex = new wxMutex(); //m_ProcessMutex = new wxMutex(); mpClient = new wxSocketClient(); //m_Connecting = false; m_sendingTimer = new wxTimer(this, ID_SEND_TIMER); m_exit = false; m_nbOfAvailCPUs = wxThread::GetCPUCount(); resetProcesses(m_nbOfAvailCPUs); } FoxClient::~FoxClient() { if(m_sendingTimer!=NULL) { m_sendingTimer->Stop(); delete m_sendingTimer; } if (mpClient != 0) { mpClient->Destroy(); mpClient = 0; } } void FoxClient::setNbOfAvailCPUs(int nb) { m_nbOfAvailCPUs = nb; resetProcesses(m_nbOfAvailCPUs); } int FoxClient::getNbOfAvailCPUs() { return m_nbOfAvailCPUs; } void FoxClient::resetProcesses(int nbProcesses) { wxCriticalSectionLocker locker(m_ProcessCriticalSection); m_processes.clear(); for(int i=0;igetWorkingDir(), _T("client.log")); wxFile logfile(filename, wxFile::write_append); wxDateTime datetime = wxDateTime::Now(); logfile.Write(datetime.Format(_T("%X ")) + msg + _T("\n")); logfile.Close(); #endif (*fpObjCrystInformUser)(msg.ToStdString()); } void FoxClient::OnProcessEvent(ProcessMyEvent& pEvent) { onProcessTerminate(pEvent.m_pid, pEvent.m_status, pEvent.m_dir); } void FoxClient::onProcessTerminate(int pid, int status, wxString dir) { int nb=0; //WriteMessageLog(_T("Going to lock")); wxCriticalSectionLocker locker(m_ProcessCriticalSection); //WriteMessageLog(_T("Going to locked")); wxString st = _T(""); st.Printf(_T("pid=%d, status=%d, dir="), pid, status); WriteMessageLog(_T("Process terminated: ") + st + dir); int ID=-1; wxDateTime startingtime; //identify process ID for(int i=0;i empty result will be sent to the server")); SaveResult("", "-1", ID, true); return; } wxString filename = getOutputFile(dir); wxString cost = getCost(filename); #ifdef WIN32 //save result to the memory SaveResult(dir + _T("\\") + filename, cost, ID, false); //delete output and input files wxRemoveFile(dir + _T("\\") + filename); wxRemoveFile(dir + _T("\\input.xml")); #else //save result to the memory SaveResult(dir + _T("/") + filename, cost, ID, false); //delete output and input files wxRemoveFile(dir + _T("/") + filename); wxRemoveFile(dir + _T("/input.xml")); wxRemoveFile(dir + _T("/out.txt")); #endif //WriteMessageLog(_T("Leaving the locked part...")); //wxMutexError qre = mmh.Unlock(); //WriteMessageLog(_T("Mutex unlocked"+wxString::Format("%d", qre))); } wxString FoxClient::getOutputFile(wxString dir) { wxDir tmpDir(dir); wxString filename; if(!tmpDir.IsOpened()) return _T("-1"); //there should be only one file out-Cost-*.xml if(!tmpDir.GetFirst(&filename, _T("out-Cost*.xml"), wxDIR_FILES)) return _T("-1"); return filename; } wxString FoxClient::getCost(wxString filename) { if(filename.size()<=13) return _T("-1"); return filename.SubString(9, filename.size()-5); } void FoxClient::WriteProtocol() { } bool FoxClient::IsClientConnected() { if(mpClient!=0) return mpClient->IsConnected(); else return false; } void FoxClient::KillProcesses() { wxCriticalSectionLocker locker(m_ProcessCriticalSection); WriteMessageLog(_T("Killing processes")); for(int i=0;iStop(); if(mpClient!=0) { mpClient->Destroy(); mpClient = 0; } } bool FoxClient::ConnectClient(int nbOfTrial, wxString hostname) { //m_Connecting = true; WriteMessageLog(_T("Client try to connect")); wxIPV4address ip; int i=0; m_hostname = hostname; ip.Service(2854); if(!ip.Hostname(m_hostname)) { return false; } if(mpClient==0) mpClient = new wxSocketClient(); mpClient->SetEventHandler(*this, GRID_CLIENT_SOCKET_ID); mpClient->SetNotify( wxSOCKET_CONNECTION_FLAG | wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG | wxSOCKET_OUTPUT_FLAG); mpClient->Notify(true); do { i++; mpClient->Connect(ip, false); mpClient->WaitOnConnect(3,0); if(i==nbOfTrial) break; //if(!m_Connecting) break; if(m_exit) break; } while(!mpClient->IsConnected()); //m_Connecting = false; if (mpClient->IsConnected()){ mpClient->SaveState(); //better to run it just once and then start it again after all precedures are done m_sendingTimer->Start(10*1000, true); WriteMessageLog(_T("Client is connected to the server")); return true; } else { mpClient->Close(); return false; } } void FoxClient::OnSocketEvent(wxSocketEvent &event) { //WriteMessageLog(_T("OnSocketEvent Begin")); wxSocketBase *tmpSock = event.GetSocket(); tmpSock->SetNotify(wxSOCKET_LOST_FLAG); switch(event.GetSocketEvent()) { case wxSOCKET_INPUT: { //WriteMessageLog(_T("INPUT - This should never happen!")); //WriteMessageLog(_T("INPUT_END")); break; } case wxSOCKET_LOST: { //ClientEvent("Connection failed.\n"); //WriteMessageLog(_T("LOST - This can sometimes happen!")); //m_sendingTimer->Stop(); if(mpClient!=0) { mpClient->Destroy(); mpClient = NULL; } break; } case wxSOCKET_OUTPUT: { //WriteMessageLog(_T("OUTPUT - This should never happen!")); break; } default: break; } tmpSock->SetNotify(wxSOCKET_LOST_FLAG | wxSOCKET_INPUT_FLAG | wxSOCKET_OUTPUT_FLAG); //WriteMessageLog(_T("OnSocketEvent End")); } bool FoxClient::AnalyzeMessage(wxString msg) { wxString ID, nbTrial, nbRuns, Rand; stringstream in_string; bool newJob = false; vector asks; vector jobs; vector jobRuns; vector trials; vector ids; vector rands; SaveDataAsFile(msg, addToPath(getWorkingDir(), _T("client_msg_in.txt"))); //jobs = getJobs(inmsg); in_string<>tag; if(true==in_string.eof()) break; if( ("ClientJob"==tag.GetName()) && (!tag.IsEndTag()) ){ //WriteMessageLog(_T("New job found")); newJob = true; long runs=0, trial=0, id=0, rand; for(int i=tag.GetNbAttribute()-1;i>=0;i--){ if(tag.GetAttributeName(i)=="ID"){ //WriteMessageLog(_T("ID found")); ID = wxString::FromAscii(tag.GetAttributeValue(i).c_str()); if(!ID.ToLong((long *) &id)) WriteMessageLog(_T("Can't convert ID attribute to long")); } if(tag.GetAttributeName(i)=="nbTrials"){ //WriteMessageLog(_T("nbTrials found")); nbTrial = wxString::FromAscii(tag.GetAttributeValue(i).c_str()); if(!nbTrial.ToLong((long *) &trial)) WriteMessageLog(_T("Can't convert nbTrials attribute to long")); } if(tag.GetAttributeName(i)=="nbOfRuns") { //WriteMessageLog(_T("nbOfRuns found")); wxString nbRuns = wxString::FromAscii(tag.GetAttributeValue(i).c_str()); if(!nbRuns.ToLong((long *) &runs)) WriteMessageLog(_T("Can't convert nbOfRuns attribute to long")); } if(tag.GetAttributeName(i)=="rand") { //WriteMessageLog(_T("rand found")); wxString Rand = wxString::FromAscii(tag.GetAttributeValue(i).c_str()); if(!Rand.ToLong((long *) &rand)) WriteMessageLog(_T("Can't convert rand attribute to long")); } } long pos = in_string.tellg(); wxString tmp = getJob(msg, pos); if(tmp.Cmp(_T(""))!=0) { jobs.push_back(tmp); jobRuns.push_back(runs); trials.push_back(trial); ids.push_back(id); rands.push_back(rand); } else { WriteMessageLog(_T("ERROR: job was not load")); } } } if(newJob){ WriteMessageLog(_T("New job was received from server")); std::vector jobsForRejecting; for(int i=0;i\n \n"); bool newResults = false; //send all result with value sent=false for(int i=0;i\n"); if(newResults) { WriteMessageLog(_T("Sending result(s) to server")); } //WriteMessageLog(_T("Saving answer to the file")); //SaveDataAsFile(out, addToPath(getWorkingDir(), _T("client_out.txt"))); //WriteMessageLog(_T("sending message...")); if(!m_IOSocket.WriteStringToSocket(mpClient, out)) { WriteMessageLog(m_IOSocket.getError()); WriteMessageLog(_T("ERROR: answer was not send")); //change back status of results and send it later... for(int i=0;i")); if(p==-1) return _T(""); //save it job = in.Left(p); return job; } void FoxClient::get_copy_of_processes(vector &FP, vector &CJ) { //WriteMessageLog("get_copy_of_processes: Locking"); FP.clear(); CJ.clear(); wxCriticalSectionLocker locker(m_ProcessCriticalSection); //WriteMessageLog("get_copy_of_processes: Locked"); for(int i=0;iLock()!=wxMUTEX_NO_ERROR) return -1; wxCriticalSectionLocker locker(m_ProcessCriticalSection); FoxProcess *proc = getUnusedProcess(); if(proc!=0) { //WriteMessageLog(_T("process found")); #ifdef WIN32 //saving input file to the temporary directory SaveDataAsFile(job,proc->getTmpDir() + _T("\\input.xml")); //creating bat file //wxFile *batFile = new wxFile(proc->getTmpDir() + _T("\\!run.bat"), wxFile::write); //creating bat file content wxString cmd_content; wxString appname = wxApp::GetInstance()->argv[0]; if(rand) { cmd_content.Printf(_T("%3$s \"%1$s\\input.xml\" --nogui -n %2$d --randomize -o \"%1$s\\out#cost.xml\""), proc->getTmpDir(), nbTrial, appname); } else { cmd_content.Printf(_T("%3$s \"%1$s\\input.xml\" --nogui -n %2$d -o \"%1$s\\out#cost.xml\""), proc->getTmpDir(), nbTrial, appname); } #else //WriteMessageLog(_T("saving data as file - input.xml")); SaveDataAsFile(job, proc->getTmpDir() + _T("/input.xml")); wxFile *batFile = new wxFile(); batFile->Create(proc->getTmpDir() + _T("/run.sh"), true, wxS_IRUSR|wxS_IWUSR|wxS_IXUSR|wxS_IRGRP|wxS_IWGRP|wxS_IXGRP|wxS_IROTH|wxS_IWOTH|wxS_IXOTH); if(!batFile->IsOpened()) { batFile->Open(proc->getTmpDir() + _T("/run.sh"), wxFile::write); } wxString content; wxString appname = wxStandardPaths::Get().GetExecutablePath(); WriteMessageLog(appname); //if(appname(0,1)!=_T("/")) appname=wxGetCwd()+_T("/")+appname; //WriteMessageLog(appname); wxString tr; tr.Printf(_T("%d"), nbTrial); if(rand) { content = appname+_T(" \"")+proc->getTmpDir()+_T("/input.xml\" --nogui -n ")+tr+_T(" --randomize --silent -o \"")+proc->getTmpDir()+_T("/out#cost.xml\" > \"")+proc->getTmpDir()+_T("/out.txt\""); } else { content = appname+_T(" \"")+proc->getTmpDir()+_T("/input.xml\" --nogui -n ")+tr+_T(" --silent -o \"") +proc->getTmpDir()+_T("/out#cost.xml\" > \"")+proc->getTmpDir()+_T("/out.txt\""); } //wxString path_to_input; //path_to_input = proc->getTmpDir(); //WriteMessageLog(path_to_input); /* if(rand) { content = appname+_T(" ")+path_to_input+_T("/input.xml --nogui -n ")+tr+_T(" --randomize -o ")+path_to_input+_T("/out#cost.xml"); } else { content = _T(".") + appname+_T(" ")+path_to_input+_T("/input.xml --nogui -n ")+tr+_T(" -o ")+path_to_input+_T("/out#cost.xml"); } */ WriteMessageLog(content); //cout<Write(content); batFile->Close(); delete batFile; #endif #ifdef WIN32 //wxString cmd = proc->getTmpDir() + _T("\\!run.bat"); #else wxString cmd_content = _T("sh \"")+ proc->getTmpDir() + _T("/run.sh\""); #endif //WriteMessageLog(_T("creating process")); wxProcess *process = new MyProcess(this, cmd_content, proc->getTmpDir()); //WriteMessageLog(_T("executing process")); int pid = wxExecute(cmd_content, wxEXEC_ASYNC|wxEXEC_MAKE_GROUP_LEADER, process); if ( !pid ) { delete process; WriteMessageLog(_T("Process not started: ") + cmd_content); //m_ProcessMutex->Unlock(); return -1; } else { proc->setPid(pid); proc->setRunning(true); proc->setJobID(id); proc->setStarted(wxDateTime::Now()); wxString tmp; tmp.Printf(_T("%d"), pid); WriteMessageLog(_T("Process started: pid=") + tmp + _T(", dir=") + cmd_content); //m_ProcessMutex->Unlock(); return 0; } } else { WriteMessageLog(_T("No unsused process is available, job will be rejected to server")); //m_ProcessMutex->Unlock(); return -1; } //m_ProcessMutex->Unlock(); return 0; } void FoxClient::SaveDataAsFile(wxString out, wxString filename) { wxFile outFile(filename, wxFile::write); if(outFile.IsOpened()) { outFile.Write(out); outFile.Close(); } } wxString FoxClient::getWorkingDir() { return m_working_dir; } wxString FoxClient::addToPath(wxString str1, wxString str2) { wxString res; #ifdef WIN32 res = str1 + _T("\\") + str2; #else res = str1 + _T("/") + str2; #endif return res; } bool FoxClient::LoadFile(wxString filename, wxString &in) { wxFile infile(filename, wxFile::read); in.Clear(); if(!infile.IsOpened()) return false; long len = infile.Length(); char *buffer; buffer = (char*) calloc(len+1, sizeof(char)); infile.Read(buffer, len); infile.Close(); in = wxString::FromAscii(buffer); free(buffer); return true; } void FoxClient::SaveResult(wxString fileName, wxString Cost, int ID, bool error) { WriteMessageLog(_T("Saving new result")); wxString in; if(!error) { if(!LoadFile(fileName, in)) { WriteMessageLog(_T("can't load the file")); return; } wxString out; out.Printf(_T("\n"), ID, Cost.c_str()); out += in; out += _T("\n"); GrdRslt res(ID, Cost, out); m_results.push_back(res); } else { wxString out; out.Printf(_T("\n"), ID); out += in; out += _T("\n"); GrdRslt res(ID, Cost, out); m_results.push_back(res); } //WriteMessageLog(_T("Result saved")); } void FoxClient::OnTimerEvent(wxTimerEvent& event) { DoManyThingsOnTimer(); //timer should be called only for one shot. //Imagine, that the communication with server is not done and another timer event occur... m_sendingTimer->Start(10*1000, true); } void FoxClient::DoManyThingsOnTimer() { //stop timer until this function finishes - then we have to run it again if(mpClient == NULL) { return; } if (!mpClient->IsConnected()) { //TODO: try to connect... return; } //1. send info to server (regularly) SendCurrentState(); //2. wait for answer wxString msg; if(!m_IOSocket.ReadStringFromSocket(mpClient, msg)) { return; } /* WriteMessageLog("List of jobs done:"); for(int i=0;i &FP, vector &CJ); //kill all running processes void KillProcesses(); //bool m_Connecting; bool m_exit; void WriteMessageLog(wxString msg); protected: wxString getJob(wxString inmsg, long pos); void SendCurrentState(); void SaveResult(wxString fileName, wxString Cost, int ID, bool error); bool AnalyzeMessage(wxString msg); void SaveDataAsFile(wxString out, wxString filename); bool LoadFile(wxString filename, wxString &in); wxString getMyHostname(); wxString addToPath(wxString str1, wxString str2); //reconnect client //void Reconnect(); //it runs new job, return 0 if successful //job - content of the file, id - job id, int runNewJob(wxString job, int id, int nbTrial, bool rand); //send not-accepted jobs back to the server //void rejectJobs(std::vector ids); //get file name "out-Cost-%f.xml", dir - directory with file wxString getOutputFile(wxString dir); //get cost from file name "out-Cost-%f.xml" wxString getCost(wxString filename); //reset processes (delete old and set new) void resetProcesses(int nbProcesses); //get only ONE of the unused processes FoxProcess *getUnusedProcess(); wxSocketClient * mpClient; wxString m_hostname; wxTimer * m_sendingTimer; vector m_processes; vector m_results; int m_nbOfAvailCPUs; IOSocket m_IOSocket; wxString m_working_dir; wxCriticalSection m_ProcessCriticalSection; vector m_ListOfProcessedJobs; DECLARE_EVENT_TABLE() }; class MyProcess : public wxProcess { public: MyProcess(FoxClient *parent, const wxString& cmd, wxString dir); virtual void OnTerminate(int pid, int status); protected: wxString m_cmd; FoxClient * m_parent; wxString m_dir; }; #endif objcryst-2022.1/Fox/src/FoxJob.cpp000066400000000000000000000043571430515525000166660ustar00rootroot00000000000000#include "FoxJob.h" FoxJob::FoxJob(void) { m_ID = 0; m_nbTrial = 0; m_nbRuns = 0; m_nbDone = 0; m_status = 0; m_randomize = true; } FoxJob::~FoxJob(void) { } void FoxJob::AddThread(int threadID, int nbCPUs) { for(int i=0;i::iterator it; for(int i=0;i threadIDs) { m_ThreadID.clear(); for(int i=0;i FoxJob::getThreadID() { return m_ThreadID; } int FoxJob::GetSolvingNb() { return this->getNbThread(); } void FoxJob::setName(wxString name) { this->m_name = name; } void FoxJob::setM_ID(int id){ this->m_ID = id; } void FoxJob::setNbTrial(long nbTrial){ this->m_nbTrial = nbTrial; } void FoxJob::setNbRuns(int nbRuns){ this->m_nbRuns = nbRuns; } void FoxJob::setNbDone(int nbDone){ this->m_nbDone = nbDone; } void FoxJob::setStatus(short status){ this->m_status = status; } void FoxJob::setFileName(wxString name){ this->m_fileName = name; } int FoxJob::getAvailableRuns() { return (getNbRuns()-getNbDone()-GetSolvingNb()); } int FoxJob::getM_ID(){ return m_ID; } wxString FoxJob::getName(){ return m_name; } long FoxJob::getNbTrial(){ return m_nbTrial; } int FoxJob::getNbRuns(){ return m_nbRuns; } int FoxJob::getNbDone(){ return m_nbDone; } short FoxJob::getStatus(){ return m_status; } int FoxJob::getNbThread(){ return m_ThreadID.size(); } wxString FoxJob::getFileName(){ return m_fileName; } bool FoxJob::randomize() { return m_randomize; } void FoxJob::setRand(bool rand) { m_randomize = rand; } objcryst-2022.1/Fox/src/FoxJob.h000066400000000000000000000036321430515525000163260ustar00rootroot00000000000000//#include //#include #ifdef __WX__CRYST__ // For compilers that support precompilation, includes "wx/wx.h". #ifndef __DARWIN__ // work around MacOSX type_info bug (??) #include "wx/wxprec.h" #endif #ifdef __BORLANDC__ #pragma hdrstop #endif // for all others, include the necessary headers (this file is usually all you // need because it includes almost all "standard" wxWindows headers) #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "wx/tooltip.h" #include "wx/notebook.h" #include "wx/wfstream.h" #include "wx/zstream.h" #include "wx/fileconf.h" #endif #include class FoxJob { public: FoxJob(void); ~FoxJob(void); void AddThread(int threadID, int nbCPUs); //remove thread's id from thread list (default: remove only one) //nbThreads=-1 remove all thread's ids in the list (called when lost_socket occurs) void RemoveThread(int threadID, int nbThreads = 1); int getAvailableRuns(); wxString getListOfThreads(); void setName(wxString name); void setM_ID(int id); void setNbTrial(long nbTrial); void setNbRuns(int nbRuns); void setNbDone(int nbDone); void setStatus(short status); // void setNbThread(int nbThread); void replaceThreadID(std::vector threadID); void setFileName(wxString name); bool randomize(); void setRand(bool rand); int getM_ID(); wxString getName(); long getNbTrial(); int getNbRuns(); int getNbDone(); short getStatus(); int getNbThread(); int GetSolvingNb(); std::vector getThreadID(); wxString getFileName(); private: wxString m_name; wxString m_fileName; int m_ID; long m_nbTrial; int m_nbRuns; int m_nbDone; short m_status; bool m_randomize; std::vector m_ThreadID; }; objcryst-2022.1/Fox/src/FoxServer.cpp000066400000000000000000000551541430515525000174230ustar00rootroot00000000000000#include "FoxServer.h" #include #ifdef __WX__CRYST__ #include "ObjCryst/wxCryst/wxCrystal.h" #endif using namespace ObjCryst; using namespace std; // Fox client/server grid //#include "wx/socket.h" //#include //#include static const long GRID_SERVER_ID= WXCRYST_ID(); static const long GRID_SERVER_SOCKET_ID= WXCRYST_ID(); //static const long SERVER_THREAD_EVENT= WXCRYST_ID(); #define EVT_WORKER(func) DECLARE_EVENT_TABLE_ENTRY( wxEVT_WORKER, -1, -1, (wxObjectEventFunction) (wxEventFunction) (WorkerEventFunction) & func, (wxObject *) NULL ), typedef void (wxEvtHandler::*WorkerEventFunction)(WorkerEvent&); //DEFINE_EVENT_TYPE(SERVER_THREAD_EVENT) BEGIN_EVENT_TABLE(FoxServer, wxFrame) EVT_SOCKET(GRID_SERVER_ID, FoxServer::OnServerEvent) //EVT_COMMAND(wxID_ANY, SERVER_THREAD_EVENT, FoxServer::OnThreadEvent) EVT_WORKER(FoxServer::OnWorkerEvent) //EVT_SOCKET(GRID_SERVER_SOCKET_ID, FoxServer::OnSocketEvent) END_EVENT_TABLE() //WX_DEFINE_LIST(TList); ThreadWorker::ThreadWorker(wxSocketBase *pSocket, wxString workingDir, wxFrame *parent, vector *results, vector *jobs, wxMutex *mutexProtecting_Jobs_Results) { m_socket = pSocket; //Notify() cannot be called in thread context. We have to detach from main loop //before switching thread contexts. m_socket->Notify(false); m_socket->SetFlags(wxSOCKET_WAITALL|wxSOCKET_BLOCK); pSocket->GetPeer(m_peer); m_working_directory = workingDir; m_parent = parent; m_global_results = results; m_global_jobs = jobs; m_mutexProtecting_Jobs_Results = mutexProtecting_Jobs_Results; } bool ThreadWorker::LoadFile(wxString filename, wxString &in) { wxFile infile(filename, wxFile::read); in.Clear(); if(!infile.IsOpened()) return false; long len = infile.Length(); char *buffer; buffer = (char*) calloc(len+1, sizeof(char)); infile.Read(buffer, len); infile.Close(); in = wxString::FromAscii(buffer); free(buffer); return true; } int ThreadWorker::GetId() { int i= (int) wxThread::GetId(); return i; } void ThreadWorker::WriteLogMessage(wxString msg) { #if __SERVER_LOGS wxString filename; filename.Printf(_T("thread_log_%d.txt"), GetId()); #ifdef WIN32 filename = m_working_directory + _T("\\") + filename; #else filename = m_working_directory + _T("/") + filename; #endif wxFile logfile(filename, wxFile::write_append); if(logfile.IsOpened()) { wxDateTime datetime = wxDateTime::Now(); logfile.Write(datetime.Format(_T("%X ")) + msg + _T("\n")); logfile.Close(); } #endif } void ThreadWorker::cannot_calculate_this_job(FoxJob fj) { if(m_mutexProtecting_Jobs_Results->Lock()!=wxMUTEX_NO_ERROR) return; for(int i=0;i<(*m_global_jobs).size();i++) { if((*m_global_jobs)[i].getM_ID() == fj.getM_ID()) { (*m_global_jobs)[i].RemoveThread(GetId(), fj.getNbRuns()); break; } } m_mutexProtecting_Jobs_Results->Unlock(); } void ThreadWorker::RemoveThreadFromJobList() {//run this before closing this thread if(m_mutexProtecting_Jobs_Results->Lock()!=wxMUTEX_NO_ERROR) return; for(int j=0;j<(*m_global_jobs).size();j++) { (*m_global_jobs)[j].RemoveThread(GetId(), -1); } m_mutexProtecting_Jobs_Results->Unlock(); } void ThreadWorker::RemoveActiveFromJobList(int id) { if(m_mutexProtecting_Jobs_Results->Lock()!=wxMUTEX_NO_ERROR) return; for(int j=0;j<(*m_global_jobs).size();j++) { if((*m_global_jobs)[j].getM_ID() == id) { (*m_global_jobs)[j].RemoveThread(GetId()); } } m_mutexProtecting_Jobs_Results->Unlock(); } void ThreadWorker::AddResultToJobList(int id) { if(m_mutexProtecting_Jobs_Results->Lock()!=wxMUTEX_NO_ERROR) return; for(int j=0;j<(*m_global_jobs).size();j++) { if((*m_global_jobs)[j].getM_ID() == id) { (*m_global_jobs)[j].RemoveThread(GetId()); (*m_global_jobs)[j].setNbDone((*m_global_jobs)[j].getNbDone()+1); } } m_mutexProtecting_Jobs_Results->Unlock(); } vector ThreadWorker::getJobsToCalculate(int n) {//returns copies of found available jobs. //Use their changed getNbRuns() to see how many times you have to run it vector res; //m_global_jobs is shared variable! if(m_mutexProtecting_Jobs_Results->Lock()!=wxMUTEX_NO_ERROR) return res; int all=0; //get available jobs and save it to the res for(int i=0;i<(*m_global_jobs).size();i++) { int nb = (*m_global_jobs)[i].getAvailableRuns(); if(nb<=0) continue; //do not save more than 'n' if(nb>(n-all)) nb = n-all; all += nb; FoxJob tmp = (*m_global_jobs)[i]; //just change the numbers of done and runs in the copy... tmp.setNbDone(0); tmp.setNbRuns(nb); res.push_back(tmp); //we have to say, that this job is already reserved //if sending is not successfull, we have to return it back! (*m_global_jobs)[i].AddThread(GetId(), nb); if(all>=n) break; } m_mutexProtecting_Jobs_Results->Unlock(); return res; } bool ThreadWorker::analyze_message_and_get_answer(wxString msg, wxString &answer) { /* out = _T("\n \n\n"); */ stringstream in_string; wxString ID, Cost, name; int availableCPUs=-1, freeCPUs=-1; vector ids; vector costs; vector results; bool newResult = false; //vector rejectedJobs; in_string<>tag; if(true==in_string.eof()) break; if( ("result"==tag.GetName()) && (!tag.IsEndTag()) ) { newResult = true; long id; double cost; for(int i=tag.GetNbAttribute()-1;i>=0;i--){ if(tag.GetAttributeName(i)=="ID"){ id = atol(tag.GetAttributeValue(i).c_str()); } if(tag.GetAttributeName(i)=="Cost"){ cost = atof(tag.GetAttributeValue(i).c_str()); } } long pos = in_string.tellg(); if(cost<0) { //error occured during the calculation and empty result was obtained ids.push_back(id); costs.push_back(cost); results.push_back(""); } else { wxString res = getResult(msg, pos); if(res.Cmp(_T(""))!=0) { ids.push_back(id); costs.push_back(cost); results.push_back(res); } else { ids.push_back(id); costs.push_back(-1.0); results.push_back(res); } } } if("currentstate"==tag.GetName()){ for(int i=tag.GetNbAttribute()-1;i>=0;i--){ if(tag.GetAttributeName(i)=="availableCPUs") { availableCPUs = atoi(tag.GetAttributeValue(i).c_str()); } if(tag.GetAttributeName(i)=="name") { name = wxString(tag.GetAttributeValue(i)); } if(tag.GetAttributeName(i)=="freeCPUs") { freeCPUs = atoi(tag.GetAttributeValue(i).c_str()); } } } } if(availableCPUs!=-1) { m_availableCPUs = availableCPUs; } if(name.Length()!=0) { m_name = name; } if(freeCPUs!=-1) { m_freeCPUs = freeCPUs; } if(newResult) { for(int i=0;i0) { WriteLogMessage("Looking for a new job to send ... "); //send some job ... //getting copies of global jobs - > we will not need mutex for them. vector jobs = getJobsToCalculate(m_freeCPUs); if(jobs.size()==0) { WriteLogMessage("Nothing found!"); return true; } answer += _T("\n"); for(int i=0;i\n"), jobs[i].getM_ID(), jobs[i].getNbTrial(), jobs[i].getNbRuns(), (int) jobs[i].randomize()); answer += header; answer += msg; answer += _T("\n\n"); WriteLogMessage("Job found: " + header); } answer += _T("\n"); } return true; } void ThreadWorker::SaveResult(wxString result, int JobID, float ResultCost) { int t = time(0); wxString name; int r = (int) ResultCost; #ifdef WIN32 name.Printf(_T("GridRslt\\ID-%d_Cost-%d_Thread-%d_Time-%d.xml"), JobID, r, this->GetId(), t); name = m_working_directory + _T("\\") + name; #else name.Printf(_T("GridRslt/ID-%d_Cost-%d_Thread-%d_Time-%d.xml"), JobID, r, this->GetId(), t); name = m_working_directory + _T("/") + name; #endif WriteLogMessage(_T("Saving result as file")); VFN_DEBUG_MESSAGE(__FUNCTION__<Lock()!=wxMUTEX_NO_ERROR) return; WriteLogMessage(_T("Saving result in glodal data")); GridResult newres; newres.ClientName = _T("--"); newres.filename = name; newres.JobID = JobID; newres.threadID = this->GetId(); newres.Cost = ResultCost; newres.order = m_global_results->size(); m_global_results->push_back(newres); WriteLogMessage(_T("Result saved in global data")); m_mutexProtecting_Jobs_Results->Unlock(); } wxString ThreadWorker::getResult(wxString message, long pos) { wxString result; //copy of inmsg wxString in = message; in.Remove(0,pos); //find end of the job int p = in.First(_T("")); if(p==-1) return _T(""); //save it result = in.Left(p); VFN_DEBUG_MESSAGE(__FUNCTION__<<":"<IsConnected()) { //LogWorker("ThreadWorker: not connected",wxLOG_Error); return 0; } //int to_process = -1; while (m_socket->IsConnected()) { WriteLogMessage("Waiting for reading 5s"); if(m_socket->WaitForRead(5, 0)) { if(!m_socket->IsConnected()) { WriteLogMessage("Connection lost"); break; } wxCharBuffer ch_buf; wxString msg; WriteLogMessage("Reading message from the socket"); if(!m_IO.ReadStringFromSocket(m_socket, msg)) { WriteLogMessage("ERROR: reading from the socket"); continue; } wxString tmp_path; #ifdef WIN32 tmp_path = m_working_directory + _T("\\server_msg_in.txt"); #else tmp_path = m_working_directory + _T("/server_msg_in.txt"); #endif SaveDataAsFile(msg, tmp_path); wxString answ; if(!analyze_message_and_get_answer(msg, answ)) { WriteLogMessage("ERROR: something wrong during analyzing the message..."); } if(answ.length()==0) { //send just dummy answer, because something has to be send (client is waiting for it...) answ = "Nothing to do..."; } WriteLogMessage("Sending answer ..."); if(!m_IO.WriteStringToSocket(m_socket, answ)) { WriteLogMessage("ERROR: sending answer returned false"); //Remove thread from joblist? continue; } //inform parent thread about news. Sending event is a save way how to do it. WorkerEvent e(this); e.m_exit = false; e.m_thread_info.m_name = m_name; e.m_thread_info.m_freeCPUs = m_freeCPUs; e.m_thread_info.m_availableCPUs = m_availableCPUs; e.m_thread_info.m_id = GetId(); m_parent->GetEventHandler()->AddPendingEvent( e ); } } WriteLogMessage("Connection lost ..."); //Remove this thread ID from all jobs before leaving RemoveThreadFromJobList(); //inform parent thread about leaving WorkerEvent e(this); e.m_exit = true; e.m_thread_info.m_name = m_name; e.m_thread_info.m_freeCPUs = m_freeCPUs; e.m_thread_info.m_availableCPUs = m_availableCPUs; e.m_thread_info.m_id = GetId(); m_parent->GetEventHandler()->AddPendingEvent( e ); m_socket->Destroy(); return 0; } FoxServer::FoxServer(): mpServer(0) { m_mutexProtecting_Jobs_Results = new wxMutex(); //m_needUpdate = false; m_isRunning = false; srand( (unsigned)time( NULL ) ); m_working_dir = _T(""); } FoxServer::~FoxServer() { //todo: clear m_results delete m_mutexProtecting_Jobs_Results; } void FoxServer::WriteLogMessage(wxString msg) { #if __SERVER_LOGS wxString filename; #ifdef WIN32 filename = GetWorkingDir() + _T("\\server.log"); #else filename = GetWorkingDir() + _T("/server.log"); #endif wxFile logfile(filename, wxFile::write_append); if(logfile.IsOpened()) { wxDateTime datetime = wxDateTime::Now(); logfile.Write(datetime.Format(_T("%X ")) + msg + _T("\n")); logfile.Close(); } #endif (*fpObjCrystInformUser)(msg.ToStdString()); } void FoxServer::OnWorkerEvent(WorkerEvent& pEvent) { if(pEvent.m_exit == true) { WriteLogMessage(_T("Thread closed [") + wxString::Format("%d", pEvent.m_thread_info.m_id) + _T(", ") + pEvent.m_thread_info.m_name + _T("]")); std::vector::iterator it; for(int i=0;iSetEventHandler(*this, GRID_SERVER_ID); mpServer->SetNotify(wxSOCKET_CONNECTION_FLAG); mpServer->Notify(true); if (! mpServer->Ok()) { WriteLogMessage(_T("Server starting failure")); m_isRunning = false; } else { WriteLogMessage(_T("Server started")); m_isRunning = true; } } /* void FoxServer::WriteProtocol() { if(s_mutexProtectingTheGlobalData->Lock()!=wxMUTEX_NO_ERROR) return; wxFile *logfile = new wxFile(_T("srvr_prtcl.txt"), wxFile::write); if(logfile != 0){ logfile->Write(_T("List of threads - clients\n")); if(m_threadMutex->Lock()!=wxMUTEX_NO_ERROR) { logfile->Close(); delete logfile; s_mutexProtectingTheGlobalData->Unlock(); return; } for(int i=0;iGetId()); logfile->Write(tmp); } m_threadMutex->Unlock(); logfile->Write(_T("End List of Clients\n\n")); logfile->Write(_T("List of Results\n")); for(int i=0;iWrite(tmp); } logfile->Write(_T("End List of Results\n")); logfile->Close(); } delete logfile; s_mutexProtectingTheGlobalData->Unlock(); } */ void FoxServer::GetData( std::vector &clients, std::vector &results, std::vector &Joblist) { VFN_DEBUG_MESSAGE(__FUNCTION__,10) //Clients info for(int i=0;igetStatus()) { case FG_CONNECTED: client.status = _T("connected"); break; case FG_EXPECTING_ANSWER: client.status = _T("asking"); break; case FG_EXPECTING_RESULT: client.status = _T("computing"); break; default: client.status = _T("n/a"); break; } */ clients.push_back(client); } if(m_mutexProtecting_Jobs_Results->Lock()!=wxMUTEX_NO_ERROR) return; //Results. It adds only new results. for(int i=results.size();iUnlock(); } void FoxServer::UpdateJob(int index, FoxJob *cjob) { VFN_DEBUG_MESSAGE(__FUNCTION__,10) //change only nbRuns and nbTrial //You can't change jobID if(m_mutexProtecting_Jobs_Results->Lock()!=wxMUTEX_NO_ERROR) return; if(index >= m_jobs.size()) { m_mutexProtecting_Jobs_Results->Unlock(); return; } //nbsolve + nbDone <= nbRuns if(cjob->getNbRuns() >= (m_jobs[index].getNbDone() + m_jobs[index].getNbThread())) m_jobs[index].setNbRuns(cjob->getNbRuns()); else m_jobs[index].setNbRuns(m_jobs[index].getNbDone() + m_jobs[index].getNbThread()); m_jobs[index].setNbTrial(cjob->getNbTrial()); m_jobs[index].setName(cjob->getName()); m_jobs[index].setRand(cjob->randomize()); m_mutexProtecting_Jobs_Results->Unlock(); } int FoxServer::DeleteJob(int index) { VFN_DEBUG_MESSAGE(__FUNCTION__,10) //you should call GetData(...) after this function... /* return: -1 = can't delete - not found, * 0 = can't delete - found, but number of runs changed. * 1 = Job deleted */ if(m_mutexProtecting_Jobs_Results->Lock()!=wxMUTEX_NO_ERROR) return -1; if(index >= m_jobs.size()) { m_mutexProtecting_Jobs_Results->Unlock(); return -1; } //if job was sent to client, we can't erase it. We can only change the numer of runs... if((m_jobs[index].getNbDone() + m_jobs[index].getNbThread())>0) { m_jobs[index].setNbRuns(m_jobs[index].getNbDone() + m_jobs[index].getNbThread()); m_mutexProtecting_Jobs_Results->Unlock(); return 0; } //remove it std::vector::iterator it = m_jobs.begin()+index; m_jobs.erase(it); m_mutexProtecting_Jobs_Results->Unlock(); return 1; } void FoxServer::AddJobToList(FoxJob newjob) { VFN_DEBUG_MESSAGE(__FUNCTION__,10) if(m_mutexProtecting_Jobs_Results->Lock()!=wxMUTEX_NO_ERROR) return; m_jobs.push_back(newjob); m_mutexProtecting_Jobs_Results->Unlock(); } bool FoxServer::IsServerRunning() { return m_isRunning; } void FoxServer::OnServerEvent(wxSocketEvent &event) { WriteLogMessage(_T("On Server Event")); VFN_DEBUG_MESSAGE(__FUNCTION__,10) switch(event.GetSocketEvent()) { case wxSOCKET_CONNECTION : { wxSocketBase* sock = mpServer->Accept(); wxIPV4address addr; if (!sock->GetPeer(addr)) { WriteLogMessage("Server: cannot get peer info"); } else { WriteLogMessage(wxString::Format("Got connection from %s:%d", addr.IPAddress().c_str(), addr.Service())); } bool createThread = true; if (createThread) { WriteLogMessage("Server: Creating Thread"); ThreadWorker* c = new ThreadWorker(sock, m_working_dir, this, &m_results, &m_jobs, m_mutexProtecting_Jobs_Results); if (c->Create() == wxTHREAD_NO_ERROR) { MY_STHREAD tmp; tmp.m_availableCPUs = 0; tmp.m_freeCPUs = 0; tmp.m_id = c->GetId(); //saving basic info, that will be used for communication with GUI (without any need of mutex) m_threads_info.push_back(tmp); //here we save pointers to threads m_threads.push_back(c); //m_threadWorkers.Append(c); /* if (m_threadWorkers.GetCount() > m_maxThreadWorkers) m_maxThreadWorkers++; m_threadWorkersCreated++; */ WriteLogMessage("Server: Running Thread"); c->Run(); } else { WriteLogMessage("Server: cannot create next thread "); }; } } default: break; } } objcryst-2022.1/Fox/src/FoxServer.h000066400000000000000000000114551430515525000170640ustar00rootroot00000000000000#ifdef __WX__CRYST__ // For compilers that support precompilation, includes "wx/wx.h". #ifndef __DARWIN__ // work around MacOSX type_info bug (??) #include "wx/wxprec.h" #endif #ifdef __BORLANDC__ #pragma hdrstop #endif // for all others, include the necessary headers (this file is usually all you // need because it includes almost all "standard" wxWindows headers) #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "wx/tooltip.h" #include "wx/notebook.h" #include "wx/wfstream.h" #include "wx/zstream.h" #include "wx/fileconf.h" #include "ObjCryst/RefinableObj/GlobalOptimObj.h" #include "wx/socket.h" #include "wx/dynarray.h" #include "wx/arrstr.h" #include "wx/list.h" #endif //#include //#include //#include //#include #include #define __FOX_SERVER__ #include "FoxJob.h" #include "GridResult.h" #include "IOSocket.h" //#include "FoxServerThread.h" //#include "wxCryst/wxCryst.h" //DECLARE_EVENT_TYPE(SERVER_THREAD_EVENT, -1) const wxEventType wxEVT_WORKER = wxNewEventType(); struct MY_STHREAD { int m_availableCPUs; int m_freeCPUs; wxString m_name; int m_id; }; class WorkerEvent : public wxEvent { public: WorkerEvent(void* pSender) { SetId(-1); SetEventType(wxEVT_WORKER); m_sender = pSender; m_exit = false; m_workerFailed = false; } virtual wxEvent* Clone() const { return new WorkerEvent(*this); } void* m_sender; bool m_exit; bool m_workerFailed; wxString m_msg; MY_STHREAD m_thread_info; }; //#include class ThreadWorker : public wxThread { public: ThreadWorker(wxSocketBase *pSocket, wxString workingDir, wxFrame *parent, vector *results, vector *jobs, wxMutex *mutexProtecting_Jobs_Results); virtual ExitCode Entry(); int GetId(); private: bool analyze_message_and_get_answer(wxString msg, wxString &answer); //bool read_socket(wxSocketBase* m_socket, wxCharBuffer &message); //bool write_socket(wxSocketBase* m_socket, wxCharBuffer message); void WriteLogMessage(wxString msg); bool LoadFile(wxString filename, wxString &in); void SaveDataAsFile(wxString out, wxString filename); wxString getResult(wxString message, long pos); void SaveResult(wxString result, int JobID, float ResultCost); //this will return N of available jobs (or lower no.) vector getJobsToCalculate(int n); void AddResultToJobList(int id); void RemoveActiveFromJobList(int id); void RemoveThreadFromJobList(); void cannot_calculate_this_job(FoxJob fj); wxString m_working_directory; wxSocketBase *m_socket; wxIPV4address m_peer; wxFrame *m_parent; vector *m_global_results; vector *m_global_jobs; IOSocket m_IO; wxMutex *m_mutexProtecting_Jobs_Results; wxString m_name; int m_availableCPUs; int m_freeCPUs; }; //WX_DECLARE_LIST(ThreadWorker, TList); class FoxServer: public wxFrame { public: FoxServer(); ~FoxServer(); void StartGridServer(); void SetWorkingDir(wxString path); wxString GetWorkingDir(); void OnServerEvent(wxSocketEvent &event); //void OnThreadEvent(wxCommandEvent &event); //void OnSocketEvent(wxSocketEvent &event); //void WriteProtocol(); void GetData(std::vector &Clients, std::vector &results, std::vector &Joblist); bool IsServerRunning(); //void RunAllClients(); void AddJobToList(FoxJob newjob); void UpdateJob(int index, FoxJob *cjob); int DeleteJob(int index); void OnWorkerEvent(WorkerEvent& pEvent); protected: void WriteLogMessage(wxString msg); //TList m_threadWorkers; //protecting jobs and results wxMutex * m_mutexProtecting_Jobs_Results; //wxMutex * mutexMessageLog; //wxMutex * m_threadMutex; wxSocketServer * mpServer; //here we save pointers to threads std::vector m_threads; //all results protected by mutex std::vector m_results; //all jobs proctected by mutex std::vector m_jobs; //basic info for GUI, can access without mutex vector m_threads_info; bool m_isRunning; //bool m_needUpdate; wxString m_working_dir; DECLARE_EVENT_TABLE() }; objcryst-2022.1/Fox/src/GridResult.cpp000066400000000000000000000006051430515525000175530ustar00rootroot00000000000000 #include "GridResult.h" #ifdef __WX__CRYST__ #include "ObjCryst/wxCryst/wxCrystal.h" #endif GridResult::GridResult(void) { filename = _T(""); ClientName = _T(""); threadID = -1; JobID = -1; Cost = -1; Show = false; } GridResult::~GridResult(void) { } GridClient::GridClient(void) { id = -1; allCPUs = -1; availCPUs = -1; } GridClient::~GridClient(void){ } objcryst-2022.1/Fox/src/GridResult.h000066400000000000000000000021551430515525000172220ustar00rootroot00000000000000//#include #ifdef __WX__CRYST__ // For compilers that support precompilation, includes "wx/wx.h". #ifndef __DARWIN__ // work around MacOSX type_info bug (??) #include "wx/wxprec.h" #endif #ifdef __BORLANDC__ #pragma hdrstop #endif // for all others, include the necessary headers (this file is usually all you // need because it includes almost all "standard" wxWindows headers) #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "wx/tooltip.h" #include "wx/notebook.h" #include "wx/wfstream.h" #include "wx/zstream.h" #include "wx/fileconf.h" #endif class GridResult { public: GridResult(void); ~GridResult(void); wxString filename; wxString ClientName; int threadID; int JobID; float Cost; bool Show; int order; bool operator<(const GridResult &m) const { return (Cost < m.Cost); } }; class GridClient { public: GridClient(void); ~GridClient(void); wxString name; long id; long allCPUs; long availCPUs; wxString status; }; objcryst-2022.1/Fox/src/IOSocket.cpp000066400000000000000000000063231430515525000171520ustar00rootroot00000000000000#ifdef __WX__CRYST__ #include "ObjCryst/wxCryst/wxCrystal.h" #endif using namespace ObjCryst; using namespace std; #include "IOSocket.h" #include IOSocket::IOSocket(void) { } IOSocket::~IOSocket(void) { } bool IOSocket::ReadStringFromSocket(wxSocketBase *pSocket, wxString &message) { //m_log = ""; //m_log = "ThreadWorker: Reading the socket ..."; pSocket->SetFlags(wxSOCKET_WAITALL); unsigned int len; pSocket->Read(&len, sizeof(int)); if (pSocket->Error()) { m_error = "ThreadWorker: Read error"; m_log += m_error; return false; } int processed = pSocket->LastCount(); //m_log += wxString::Format("ThreadWorker: %d bytes read in the header (len = %d)", processed, len); if (len == 0) { //m_log += "ThreadWorker: 0 bytes in socket, nothing to read..."; return true; } wxCharBuffer buf(len); //m_log += wxString::Format("Message header was: size = %d (bytes)",len); //WriteLogMessage("ThreadWorker: Reading message ..."); pSocket->Read(buf.data(), len); if (pSocket->Error()) { //WriteLogMessage("ThreadWorker: Read error"); //wxGetApp().AddPendingEvent(e); return false; } processed = pSocket->LastCount(); //m_log += wxString::Format("ThreadWorker: %d bytes readed", processed); wxString tmp(buf); message = tmp; return true; } bool IOSocket::WriteStringToSocket(wxSocketBase *pSocket, wxString msg) { pSocket->SetFlags(wxSOCKET_WAITALL); wxCharBuffer buffer=msg.ToAscii(); // Note that len is in bytes here! unsigned int len = strlen(buffer.data()) * sizeof(char); //WriteLogMessage(wxString::Format("ThreadWorker: Sending header of the message of %d kilobytes", len)); pSocket->Write(&len, sizeof(int)); if (pSocket->Error()) { //WriteLogMessage("ThreadWorker: Write error"); return false; } //WriteLogMessage("ThreadWorker: Sending the message ..."); pSocket->Write(buffer.data(), len); if (pSocket->Error()) { //WriteLogMessage("ThreadWorker: Write error"); return false; } //WriteLogMessage(m_socket->Error() ? _("ThreadWorker: failed !\n") : _("ThreadWorker: done\n")); return true; } unsigned int IOSocket::getMessageLen(wxSocketBase *pSocket) { wxUint32 len, sig; struct { unsigned char sig[4]; unsigned char len[4]; } msg; //peek socket pSocket->Peek(&msg, sizeof(msg)); if (pSocket->Error()) { m_error << _T("getMessageLen error: ") << (int) pSocket->LastError() << _T(", ") << pSocket->GetLastIOSize() <<_T(", ") << pSocket->LastCount(); m_error << _T(" (Peeking)\n"); return -1; } sig = (wxUint32)msg.sig[0]; sig |= (wxUint32)(msg.sig[1] << 8); sig |= (wxUint32)(msg.sig[2] << 16); sig |= (wxUint32)(msg.sig[3] << 24); if (sig != 0xfeeddead) { m_error << _T("Invalid signature\n"); return -1; } len = (wxUint32)msg.len[0]; len |= (wxUint32)(msg.len[1] << 8); len |= (wxUint32)(msg.len[2] << 16); len |= (wxUint32)(msg.len[3] << 24); return len; } wxString IOSocket::getError() { return this->m_error; } objcryst-2022.1/Fox/src/IOSocket.h000066400000000000000000000034131430515525000166140ustar00rootroot00000000000000#ifdef __WX__CRYST__ // For compilers that support precompilation, includes "wx/wx.h". #ifndef __DARWIN__ // work around MacOSX type_info bug (??) #include "wx/wxprec.h" #endif #ifdef __BORLANDC__ #pragma hdrstop #endif // for all others, include the necessary headers (this file is usually all you // need because it includes almost all "standard" wxWindows headers) #ifndef WX_PRECOMP #include "wx/wx.h" #endif //#include "wx/tooltip.h" //#include "wx/notebook.h" #include "wx/wfstream.h" #include "wx/zstream.h" #include "wx/fileconf.h" #include "wx/socket.h" #include "wx/process.h" #include "wx/sckstrm.h" #include "wx/sstream.h" #include "wx/zstream.h" #include "wx/wfstream.h" #include "wx/thread.h" #include "wx/stream.h" #include "wx/dir.h" //#include "wx/dynarray.h" #endif #ifndef __IO_SOCKET__ #define __IO_SOCKET__ class IOSocket { public: IOSocket(void); ~IOSocket(void); //reads message from the socket //returns true if successful, otherwise returns false //use getError() message to get error details; //receipt - send receipt? bool ReadStringFromSocket(wxSocketBase *pSocket, wxString &message); //writes message to the socket //returns true if successful, otherwise returns false //use getError() message to get error details; //receipt - send receipt? bool WriteStringToSocket(wxSocketBase *pSocket, wxString msg); //returns error message //Please note that this function merely returns the last error message, //but it should not be used to determine if an error has occurred wxString getError(); private: unsigned int getMessageLen(wxSocketBase *pSocket); wxString m_log; wxString m_error; }; #endif objcryst-2022.1/Fox/src/WXFoxClient.cpp000066400000000000000000000307531430515525000176500ustar00rootroot00000000000000#ifdef __WX__CRYST__ #include "ObjCryst/wxCryst/wxCrystal.h" #endif // Fox client/server grid /* #include "wx/socket.h" #include #include */ using namespace ObjCryst; using namespace std; #include "WXFoxClient.h" static long CONNECT_CLIENT_BUTTON= WXCRYST_ID(); static long CONNECT_TIMER= WXCRYST_ID(); static long UPDATE_TIMER= WXCRYST_ID(); BEGIN_EVENT_TABLE(WXFoxClient, wxWindow) EVT_BUTTON(CONNECT_CLIENT_BUTTON, WXFoxClient::OnConnectClient) EVT_TIMER(CONNECT_TIMER, WXFoxClient::OnConnectTimer) EVT_TIMER(UPDATE_TIMER, WXFoxClient::OnUpdateProcessTimer) END_EVENT_TABLE() WXFoxClient::WXFoxClient(wxWindow* parent, wxString working_dir): wxWindow(parent,-1) { m_parent = parent; m_working_dir = working_dir; m_FoxClient = new FoxClient(m_working_dir); InitClient(); m_ConnectTimer = new wxTimer(this, CONNECT_TIMER); m_UpdateProcessTimer = new wxTimer(this, UPDATE_TIMER); m_UpdateProcessTimer->Start(10000, false); m_connecting = false; } WXFoxClient::~WXFoxClient(void) { Clear(); } void WXFoxClient::Clear() { if(m_connecting) { m_connecting=false; if(m_ConnectTimer->IsRunning()) m_ConnectTimer->Stop(); } if (m_FoxClient != 0) { delete m_FoxClient; m_FoxClient = 0; } } void WXFoxClient::InitClient() { unsigned int xsize=600; wxBoxSizer *topSizer = new wxStaticBoxSizer( wxVERTICAL, this, ""); wxBoxSizer *IPSizer = new wxBoxSizer( wxHORIZONTAL); wxGridSizer *connect_sizer = new wxGridSizer(2, 2, 10, 10); //Editbox for IP wxStaticText *labelIP = new wxStaticText(this, NULL, _T("Server IP:"), wxDefaultPosition, wxDefaultSize, 0 , _T("label")); //IPSizer->Add(labelIP, 0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); connect_sizer->Add(labelIP, 0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); m_IPWindow = new wxComboBox(this, NULL, _T("localhost"), wxDefaultPosition, wxDefaultSize, 0,0, wxCB_DROPDOWN, wxDefaultValidator, _T("TextBox")); //IPSizer->Add(m_IPWindow, 0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); connect_sizer->Add(m_IPWindow, 0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); //nbCPUs window wxString nbCPUs; nbCPUs << wxThread::GetCPUCount(); wxStaticText *label2 = new wxStaticText(this, NULL, wxString::Format(_T("CPU cores allowed for computing (max=%d): "), wxThread::GetCPUCount()), wxDefaultPosition, wxDefaultSize, 0 , _T("label")); //IPSizer->Add(label2, 0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); connect_sizer->Add(label2, 0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); m_nbCPUs = new wxTextCtrl(this, NULL, nbCPUs, wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("TextBox")); //IPSizer->Add(m_nbCPUs, 0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); connect_sizer->Add(m_nbCPUs, 0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); //Connect Button wxBoxSizer *IPButtonSizer = new wxBoxSizer( wxVERTICAL); m_ConnectButton = new wxButton(this, CONNECT_CLIENT_BUTTON, _T("Connect"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("Button1")); m_ConnectButton->Show(); IPButtonSizer->Add(m_ConnectButton,0, wxALL|wxALIGN_RIGHT|wxALIGN_TOP ,3); wxStaticBoxSizer *ConnectSizer = new wxStaticBoxSizer( wxVERTICAL, this, "Connection"); //ConnectSizer->Add(IPSizer, 0, wxALL|wxALIGN_TOP); ConnectSizer->Add(connect_sizer, 0, wxALL|wxALIGN_TOP); ConnectSizer->Add(IPButtonSizer, 0, wxALL|wxALIGN_RIGHT); /* wxBoxSizer *eventSizer = new wxBoxSizer( wxVERTICAL ); //events window wxStaticText *label1 = new wxStaticText(this, NULL, _T("Client events: "), wxDefaultPosition, wxDefaultSize, 0 , _T("label")); eventSizer->Add(label1,0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); m_EventsWindow = new wxTextCtrl(this, NULL, wxEmptyString, wxDefaultPosition, wxSize(xsize,50), wxTE_MULTILINE|wxTE_READONLY, wxDefaultValidator, _T("TextBox")); eventSizer->Add(m_EventsWindow,0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); topSizer->Add(eventSizer, 0, wxALL|wxALIGN_TOP); */ topSizer->Add(ConnectSizer, 0, wxALL|wxALIGN_TOP); topSizer->Add(new wxStaticText(this, NULL, "List of Processes", wxDefaultPosition, wxDefaultSize, 0 , _T("label")), 0, wxALL|wxALIGN_TOP, 3); m_process_table = new wxGrid(this, NULL, wxDefaultPosition, wxSize(xsize,200), wxWANTS_CHARS, _T("List of Processes")); m_process_table->CreateGrid(1,5,wxGrid::wxGridSelectRows); m_process_table->SetColLabelValue(0, _T("No.")); m_process_table->SetColLabelValue(1, _T("Job ID")); m_process_table->SetColLabelValue(2, _T("Started")); m_process_table->SetColLabelValue(3, _T("Estimated progress")); m_process_table->SetColLabelValue(4, _T("Status")); m_process_table->SetColLabelSize(20); m_process_table->SetRowLabelSize(0); m_process_table->SetColSize(0, 1.0 * xsize/13.0); m_process_table->SetColSize(1, 3.0 * xsize/13.0); m_process_table->SetColSize(2, 3.0 * xsize/13.0); m_process_table->SetColSize(3, 3.0 * xsize/13.0); m_process_table->SetColSize(4, 3.0 * xsize/13.0); m_process_table->DeleteRows(0, 1, false); topSizer->Add(m_process_table, 0, wxALL); topSizer->Add(new wxStaticText(this, NULL, "List of processed jobs", wxDefaultPosition, wxDefaultSize, 0 , _T("label")), 0, wxALL|wxALIGN_TOP, 3); m_job_table = new wxGrid(this, NULL, wxDefaultPosition, wxSize(xsize,100), wxWANTS_CHARS, _T("List of Processed Jobs")); m_job_table->CreateGrid(1,4,wxGrid::wxGridSelectRows); m_job_table->SetColLabelValue(0, _T("No.")); m_job_table->SetColLabelValue(1, _T("Job ID")); m_job_table->SetColLabelValue(2, _T("Times processed")); m_job_table->SetColLabelValue(3, _T("Average calc. time")); m_job_table->SetColLabelSize(20); m_job_table->SetRowLabelSize(0); m_job_table->SetColSize(0, 1.0 * xsize/10.0); m_job_table->SetColSize(1, 3.0 * xsize/10.0); m_job_table->SetColSize(2, 3.0 * xsize/10.0); m_job_table->SetColSize(3, 3.0 * xsize/10.0); m_job_table->DeleteRows(0, 1, false); topSizer->Add(m_job_table, 0, wxALL); SetSizer(topSizer); //this->LoadUsedIPs(); wxTheApp->GetTopWindow()->Layout(); wxTheApp->GetTopWindow()->SendSizeEvent(); } void WXFoxClient::OnConnectClient(wxCommandEvent& event) { if(m_connecting) { m_connecting=false; if(m_ConnectTimer->IsRunning()) m_ConnectTimer->Stop(); m_ConnectButton->SetLabel(_T("Connect")); //m_EventsWindow->AppendText(_T("connecting canceled.")); }else if(m_FoxClient->IsClientConnected()) { wxMessageDialog d(this,_T("Are you sure you want to disconnect?\n It aborts conmuting of this client."), _T(""), wxYES | wxNO); if(wxID_YES!=d.ShowModal()) return; m_FoxClient->Disconnect(); m_FoxClient->KillProcesses(); m_ConnectButton->SetLabel(_T("Connect")); //m_EventsWindow->SetInsertionPointEnd(); //m_EventsWindow->AppendText(_T("Client was disconnected.\n")); } else { long nbCPUs; m_nbCPUs->GetValue().ToLong((long *) &nbCPUs); this->setNbCPU((int) nbCPUs); m_connecting = true; m_ConnectTimer->Start(2000, false); } } void WXFoxClient::setNbCPU(int nb) { m_FoxClient->setNbOfAvailCPUs(nb); wxString tmp; tmp << nb; m_nbCPUs->SetValue(tmp); } void WXFoxClient::CloseClient() { //kill processes before exit m_FoxClient->KillProcesses(); if(m_connecting) { m_connecting=false; if(m_ConnectTimer->IsRunning()) m_ConnectTimer->Stop(); } else if(m_FoxClient->IsClientConnected()) { m_FoxClient->Disconnect(); } } void WXFoxClient::OnUpdateProcessTimer(wxTimerEvent& event) { if(m_FoxClient==0) return; vector p; vector cj; m_FoxClient->get_copy_of_processes(p, cj); int nbRow = m_process_table->GetNumberRows(); //delete it just in the case of different nb of processes then before if(nbRow != p.size()) { if(nbRow>0) { m_process_table->DeleteRows(0, nbRow, true); } for(int i=0;iInsertRows(i, 1, false); } } m_process_table->ClearGrid(); for(int i=0;iSetCellValue(i,0,wxString::Format("%d",i)); m_process_table->SetReadOnly(i,0); m_process_table->SetCellBackgroundColour(i, 0, wxColour(255, 200, 200)); m_process_table->SetCellValue(i,1,wxString::Format("%d",p[i].getJobID())); m_process_table->SetReadOnly(i,1); m_process_table->SetCellBackgroundColour(i, 1, wxColour(255, 200, 200)); m_process_table->SetCellValue(i,2,wxString::Format("%s",p[i].getStartingTime().FormatTime())); m_process_table->SetReadOnly(i,2); m_process_table->SetCellBackgroundColour(i, 2, wxColour(255, 200, 200)); int cprogress = -1; for(int j=0;jSetCellValue(i,3,"not available yet"); } else { m_process_table->SetCellValue(i,3,wxString::Format("%d %%", cprogress)); } m_process_table->SetReadOnly(i,3); m_process_table->SetCellBackgroundColour(i, 3, wxColour(255, 200, 200)); m_process_table->SetCellValue(i,4,"running"); m_process_table->SetReadOnly(i,4); m_process_table->SetCellBackgroundColour(i, 4, wxColour(255, 200, 200)); } else { m_process_table->SetCellValue(i,0,wxString::Format("%d",i)); m_process_table->SetReadOnly(i,0); m_process_table->SetCellBackgroundColour(i, 0, wxColour(200, 255, 200)); m_process_table->SetCellValue(i,1,""); m_process_table->SetReadOnly(i,1); m_process_table->SetCellBackgroundColour(i, 1, wxColour(200, 255, 200)); m_process_table->SetCellValue(i,2,""); m_process_table->SetReadOnly(i,2); m_process_table->SetCellBackgroundColour(i, 2, wxColour(200, 255, 200)); m_process_table->SetCellValue(i,3,""); m_process_table->SetReadOnly(i,3); m_process_table->SetCellBackgroundColour(i, 3, wxColour(200, 255, 200)); m_process_table->SetCellValue(i,4,"waiting for job"); m_process_table->SetReadOnly(i,4); m_process_table->SetCellBackgroundColour(i, 4, wxColour(200, 255, 200)); } } //m_job_table nbRow = m_job_table->GetNumberRows(); //delete it just in the case of different nb of processes then before if(nbRow != cj.size()) { if(nbRow>0) { m_job_table->DeleteRows(0, nbRow, true); } for(int i=0;iInsertRows(i, 1, false); } } m_job_table->ClearGrid(); for(int i=0;iSetCellValue(i,0,wxString::Format("%d",i)); m_job_table->SetReadOnly(i,0); m_job_table->SetCellValue(i,1,wxString::Format("%d",cj[i].ID)); m_job_table->SetReadOnly(i,1); m_job_table->SetCellValue(i,2,wxString::Format("%d", cj[i].nb_done)); m_job_table->SetReadOnly(i,2); m_job_table->SetCellValue(i,3,cj[i].average_calc_time.Format()); m_job_table->SetReadOnly(i,3); } } void WXFoxClient::OnConnectTimer(wxTimerEvent& event) { if(!m_connecting) return; wxString host = m_IPWindow->GetValue(); ConnectClient(host); } void WXFoxClient::ConnectClient(wxString IP) { //m_EventsWindow->Clear(); //m_EventsWindow->SetValue(_T("Connecting to: \"") + IP + _T("\"... ")); m_ConnectButton->SetLabel(_T("Stop")); m_FoxClient->ConnectClient(1, IP); if(m_FoxClient->IsClientConnected()){ m_ConnectButton->SetLabel(_T("Disconnect")); //m_EventsWindow->Clear(); //m_EventsWindow->SetValue(_T(".:Client is connected to the server: \"") + IP + _T("\":.\n")); wxString CPUs; CPUs.Printf(_T("Number of available CPUs is: %d\n"), m_FoxClient->getNbOfAvailCPUs()); //m_EventsWindow->AppendText(CPUs); m_connecting=false; }else{ m_ConnectTimer->Start(10000, true); } } objcryst-2022.1/Fox/src/WXFoxClient.h000066400000000000000000000037101430515525000173060ustar00rootroot00000000000000#ifdef __WX__CRYST__ // For compilers that support precompilation, includes "wx/wx.h". #ifndef __DARWIN__ // work around MacOSX type_info bug (??) #include "wx/wxprec.h" #endif #ifdef __BORLANDC__ #pragma hdrstop #endif // for all others, include the necessary headers (this file is usually all you // need because it includes almost all "standard" wxWindows headers) #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "wx/tooltip.h" #include "wx/notebook.h" #include "wx/wfstream.h" #include "wx/zstream.h" #include "wx/fileconf.h" #include "wx/socket.h" #include "wx/grid.h" #include "wx/dynarray.h" #include "wx/timer.h" #endif /* #include #include #include #include */ #include #include "ObjCryst/ObjCryst/IO.h" #include "ObjCryst/ObjCryst/Crystal.h" #include "ObjCryst/ObjCryst/PowderPattern.h" #include "ObjCryst/ObjCryst/DiffractionDataSingleCrystal.h" #include "ObjCryst/RefinableObj/GlobalOptimObj.h" #include "FoxClient.h" class WXFoxClient : public wxWindow { public: WXFoxClient(wxWindow* parent, wxString working_dir); ~WXFoxClient(void); void Clear(); void ConnectClient(wxString IP); void OnConnectClient(wxCommandEvent& event); void setNbCPU(int nb); void CloseClient(); wxComboBox * m_IPWindow; private: void OnConnectTimer(wxTimerEvent& event); void OnUpdateProcessTimer(wxTimerEvent& event); void UpdateListOfProcesses(vector p); void InitClient(); FoxClient * m_FoxClient; wxWindow * m_parent; //wxTextCtrl * m_EventsWindow; wxTextCtrl * m_nbCPUs; //wxTextCtrl * m_TryConnectWindow; wxButton * m_ConnectButton; wxTimer * m_ConnectTimer; wxTimer * m_UpdateProcessTimer; bool m_connecting; wxString m_working_dir; wxGrid * m_process_table; wxGrid * m_job_table; DECLARE_EVENT_TABLE() }; objcryst-2022.1/Fox/src/WXFoxServer.cpp000066400000000000000000001073501430515525000176760ustar00rootroot00000000000000 #include #include "wx/filename.h" #include "wx/sstream.h" #ifdef __WX__CRYST__ #include "ObjCryst/wxCryst/wxCrystal.h" #endif // Fox client/server grid using namespace ObjCryst; using namespace std; #include "WXFoxServer.h" #include static long STOP_TO_CLIENT= WXCRYST_ID(); static long RUN_LOCAL_CLIENT= WXCRYST_ID(); static long RUN_TO_CLIENT= WXCRYST_ID(); static long NEW_JOB= WXCRYST_ID(); static long LOAD_JOB= WXCRYST_ID(); static long EDIT_JOB= WXCRYST_ID(); static long DELETE_JOB= WXCRYST_ID(); static long ID_UPDATE_TIMER= WXCRYST_ID(); static long GRID_RESULT_LIST= WXCRYST_ID(); static long GRID_JOB_LIST= WXCRYST_ID(); static long SHOW_RESULTS= WXCRYST_ID(); static long SHOW_RESULTS_SERVER= WXCRYST_ID(); BEGIN_EVENT_TABLE(WXFoxServer, wxWindow) //EVT_BUTTON(STOP_TO_CLIENT, WXFoxServer::StopAllClients) EVT_BUTTON(RUN_LOCAL_CLIENT, WXFoxServer::RunLocalClient) //EVT_BUTTON(RUN_TO_CLIENT, WXFoxServer::RunALLClient) EVT_BUTTON(NEW_JOB, WXFoxServer::OnNewJob) EVT_BUTTON(EDIT_JOB, WXFoxServer::OnEditJob) EVT_BUTTON(DELETE_JOB, WXFoxServer::OnDeleteJob) EVT_BUTTON(LOAD_JOB, WXFoxServer::OnLoadJob) EVT_TIMER(ID_UPDATE_TIMER, WXFoxServer::UpdateLists) EVT_GRID_CMD_CELL_LEFT_CLICK(GRID_RESULT_LIST, WXFoxServer::OnGridResultClick) EVT_GRID_CMD_CELL_LEFT_CLICK(GRID_JOB_LIST, WXFoxServer::OnGridJobClick) EVT_BUTTON(SHOW_RESULTS, WXFoxServer::OnShowResults) EVT_BUTTON(SHOW_RESULTS_SERVER, WXFoxServer::OnShowResultsServer) END_EVENT_TABLE() WXFoxServer::WXFoxServer(wxWindow* parent, wxString workingDir): wxWindow(parent,-1),m_parent(parent) { m_dataLoaded = false; //m_WXFoxServerDataMutex = new wxMutex(); m_working_dir = workingDir; InitServer(); } WXFoxServer::~WXFoxServer(void) { } void WXFoxServer::Clear() { m_UpdateTimer->Stop(); delete m_UpdateTimer; //todo: clear m_jobs, m_results //delete m_WXFoxServerDataMutex; delete m_FoxServer; } void WXFoxServer::InitServer() { //starting server m_FoxServer = new FoxServer(); m_FoxServer->SetWorkingDir(m_working_dir); m_FoxServer->StartGridServer(); //Start update timer m_UpdateTimer = new wxTimer(this, ID_UPDATE_TIMER); m_UpdateTimer->Start(10*1000, false); //display all necessary controls wxBoxSizer *topSizer = new wxBoxSizer( wxVERTICAL ); unsigned int xsize=650; //Job List table wxBoxSizer *JobSizer = new wxBoxSizer( wxVERTICAL ); wxStaticText *JobLabel = new wxStaticText(m_parent, NULL, _T("Job List: "), wxDefaultPosition, wxDefaultSize, 0 , _T("label")); JobSizer->Add(JobLabel,0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); m_JobListTable = new wxGrid(this,GRID_JOB_LIST, wxDefaultPosition, wxSize(xsize,150), wxWANTS_CHARS, _T("m_JobListTable")); m_JobListTable->CreateGrid(1,5,wxGrid::wxGridSelectRows); m_JobListTable->SetColLabelValue(0, _T("Job ID")); m_JobListTable->SetColLabelValue(1, _T("Job name")); m_JobListTable->SetColLabelValue(2, _T("Nb trials")); m_JobListTable->SetColLabelValue(3, _T("Randomize ?")); m_JobListTable->SetColLabelValue(4, _T("runs/done/active")); m_JobListTable->SetColLabelSize(20); m_JobListTable->SetRowLabelSize(0); m_JobListTable->SetColSize(0, (xsize-10)/5); m_JobListTable->SetColSize(1, (xsize-10)/5+20); m_JobListTable->SetColSize(2, (xsize-10)/5-20); m_JobListTable->SetColSize(3, (xsize-10)/5-10); m_JobListTable->SetColSize(4, (xsize-10)/5+10); m_JobListTable->DeleteRows(0, 1, false); JobSizer->Add(m_JobListTable,0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); wxBoxSizer *JobButtonSizer = new wxBoxSizer( wxHORIZONTAL ); wxButton *LoadJobButton = new wxButton(this, LOAD_JOB, _T("Create Job (from xml)"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("")); JobButtonSizer->Add(LoadJobButton,0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); LoadJobButton->SetToolTip(_T("Create a job from an existing xml file")); wxButton *AddJobButton = new wxButton(this, NEW_JOB, _T("Create Job (from mem)"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("")); JobButtonSizer->Add(AddJobButton,0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); AddJobButton->SetToolTip(_T("Create job from objects currently in memory\n\n") _T("This requires that you have one global \n") _T("optimization obect in memory.")); wxButton *EditJobButton = new wxButton(this, EDIT_JOB, _T("Edit Job"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("")); JobButtonSizer->Add(EditJobButton,0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); wxButton *DeleteJobButton = new wxButton(this, DELETE_JOB, _T("Delete Job"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("")); JobButtonSizer->Add(DeleteJobButton,0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); JobSizer->Add(JobButtonSizer,0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); //run button //wxButton *RunButton = new wxButton(this, RUN_TO_CLIENT, _T("Ping clients"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("Button2")); //JobButtonSizer->Add(RunButton,0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); //RunButton->SetToolTip(_T("It asks connected clients whether they compute.\n If not, it sends them job\n\n") // _T("This is useful when some client does not compute.\n Use it carefully, it increases traffic on the server.")); //stop button /* wxButton *StopButton = new wxButton(this, STOP_TO_CLIENT, _T("Stop"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("Button1")); JobButtonSizer->Add(StopButton,0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); */ //client list label wxBoxSizer *listClientSizer = new wxBoxSizer( wxVERTICAL ); wxStaticText *label2 = new wxStaticText(this, NULL, _T("Client list: "), wxDefaultPosition, wxDefaultSize, 0 , _T("label")); listClientSizer->Add(label2,0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); xsize = xsize/2-5; //client list table m_ClientTable = new wxGrid(this, NULL, wxDefaultPosition, wxSize(xsize,150), wxWANTS_CHARS, _T("m_ClientTable")); m_ClientTable->CreateGrid(1,3,wxGrid::wxGridSelectRows); m_ClientTable->SetColLabelValue(0, _T("Name")); m_ClientTable->SetColLabelValue(1, _T("ID")); m_ClientTable->SetColLabelValue(2, _T("CPUs/using")); //m_ClientTable->SetColLabelValue(3, _T("Status")); m_ClientTable->SetColLabelSize(20); m_ClientTable->SetRowLabelSize(0); m_ClientTable->SetColSize(0, xsize/3); m_ClientTable->SetColSize(1, xsize/3); m_ClientTable->SetColSize(2, xsize/3); //m_ClientTable->SetColSize(3, xsize/8); m_ClientTable->DeleteRows(0, 1, false); listClientSizer->Add(m_ClientTable,0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); //run Run local client button wxButton *RunClientButton = new wxButton(this, RUN_LOCAL_CLIENT, _T("Run local client"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("Button2")); listClientSizer->Add(RunClientButton,0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); RunClientButton->SetToolTip(_T("Gives you the option to run the job \n") _T("locally, using multiple processors or cores")); //result list label wxBoxSizer *listResultSizer = new wxBoxSizer( wxVERTICAL ); wxStaticText *label3 = new wxStaticText(this, NULL, _T("Result list: "), wxDefaultPosition, wxDefaultSize, 0 , _T("label")); listResultSizer->Add(label3,0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); //result list table m_ResultTable = new wxGrid(this, GRID_RESULT_LIST, wxDefaultPosition, wxSize(xsize,150), wxWANTS_CHARS, _T("m_ResultTable")); m_ResultTable->CreateGrid(1,3,wxGrid::wxGridSelectCells); m_ResultTable->SetColLabelValue(0, _T("Nb")); m_ResultTable->SetColLabelValue(1, _T("Job ID")); m_ResultTable->SetColLabelValue(2, _T("Cost")); //m_ResultTable->SetColLabelValue(3, _T("Show")); m_ResultTable->SetColLabelSize(20); m_ResultTable->SetRowLabelSize(0); m_ResultTable->SetColSize(0, 50); m_ResultTable->SetColSize(1, (xsize-50)/2); m_ResultTable->SetColSize(2, (xsize-50)/2); //m_ResultTable->SetColSize(3, 50); m_ResultTable->DeleteRows(0, 1, false); listResultSizer->Add(m_ResultTable,0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); wxBoxSizer *ResultListButtonsSizer = new wxBoxSizer( wxHORIZONTAL ); wxButton *ShowButtom = new wxButton(this, SHOW_RESULTS, _T("Open by new FOX"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("Button3")); ResultListButtonsSizer->Add(ShowButtom,0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); wxButton *ShowButton = new wxButton(this, SHOW_RESULTS_SERVER, _T("Open by server"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("Button3")); ResultListButtonsSizer->Add(ShowButton,0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); listResultSizer->Add(ResultListButtonsSizer, 0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); wxBoxSizer *listsSizer = new wxBoxSizer( wxHORIZONTAL ); listsSizer->Add(listClientSizer, 0, wxALL|wxALIGN_TOP); listsSizer->Add(listResultSizer, 0, wxALL|wxALIGN_TOP); //topSizer->Add(eventSizer, 0, wxALL|wxALIGN_TOP); topSizer->Add(JobSizer, 0, wxALL|wxALIGN_TOP); topSizer->Add(listsSizer, 0, wxALL|wxALIGN_TOP); //topSizer->Add(ButtonSizer, 0, wxALL|wxALIGN_TOP); this->SetSizer( topSizer ); wxTheApp->GetTopWindow()->Layout(); wxTheApp->GetTopWindow()->SendSizeEvent(); } int WXFoxServer::GenerateJobID() { wxString filename; int ID; bool again; do{ again=false; long long date = (long long) time(0); while(date>1000000000){date-=1000000000;}//int is only to 2,147,483,647... ID = (int) date; for(int i=0;iLoadFile(filename, file)) { int r = (int) rand; data.Printf(_T("\n"), name.c_str(), ID, nbOfTrial, nbRun, r); data +=file; SaveDataAsFile(data, filename); } } void WXFoxServer::ChangeJobHeader(wxString filename, int ID, wxString name, long nbOfTrial, int nbRun, bool rand) { wxString file; wxString data; if(LoadFile(filename, file)) { int r = (int) rand; int pos = file.First(_T("")); if(pos!=-1) { pos +=9; file = file.Mid(pos); } data.Printf(_T("\n"), name.c_str(), ID, nbOfTrial, nbRun, r); data +=file; SaveDataAsFile(data, filename); } } bool WXFoxServer::LoadFile(wxString filename, wxString &in) { wxFile infile(filename, wxFile::read); in.Clear(); if(!infile.IsOpened()) return false; long len = infile.Length(); char *buffer; buffer = (char*) calloc(len+1, sizeof(char)); infile.Read(buffer, len); infile.Close(); in = wxString::FromAscii(buffer); free(buffer); return true; } void WXFoxServer::SaveDataAsFile(wxString out, wxString filename) { wxFile outFile(filename, wxFile::write); if(outFile.IsOpened()) { outFile.Write(out); outFile.Close(); } } void WXFoxServer::OnNewJob(wxCommandEvent& event) { //if(!m_dataLoaded) if(gOptimizationObjRegistry.GetNb()==0) { wxMessageBox(_T("You need at least one optimization object !"), _T("No data to optimize"), wxOK | wxICON_INFORMATION, this); return; } WXCrystValidateAllUserInput(); int newID = GenerateJobID(); wxString Name = _T("jobname"); long nbOfTrial = 1000000; long nbRun = 10; bool randomize = true; do{//show setup window if(!ShowSetJobWindow(newID, Name, nbOfTrial, nbRun, randomize)) return; cout<>tag; } while("FoxJob"!=tag.GetName()); for(int i=tag.GetNbAttribute()-1;i>=0;i--) { if(tag.GetAttributeName(i)=="Name"){ name = wxString::FromAscii(tag.GetAttributeValue(i).c_str()); } if(tag.GetAttributeName(i)=="ID"){ ID = wxString::FromAscii(tag.GetAttributeValue(i).c_str()); ID.ToLong((long*) &id); } if(tag.GetAttributeName(i)=="nbOfTrial"){ Tr = wxString::FromAscii(tag.GetAttributeValue(i).c_str()); Tr.ToLong((long*) &nbOfTrial); } if(tag.GetAttributeName(i)=="nbRun"){ Run = wxString::FromAscii(tag.GetAttributeValue(i).c_str()); Run.ToLong((long*) &nbRun); } if(tag.GetAttributeName(i)=="rand"){ long r; Rand = wxString::FromAscii(tag.GetAttributeValue(i).c_str()); Rand.ToLong((long*) &r); rand = (bool) r; } } is.close(); return true; } bool WXFoxServer::isJobLoaded(long ID) { //if(m_WXFoxServerDataMutex->Lock()!=wxMUTEX_NO_ERROR) return true; for(int i=0;iUnlock(); return false; } void WXFoxServer::AddServerJob(wxString filename, wxString name, int id, long nbOfTrial, long nbRun, bool rand) { //save it in joblist FoxJob newJob; newJob.setFileName(filename); newJob.setM_ID(id); newJob.setNbDone(0); newJob.setNbRuns((int)nbRun); newJob.setNbTrial(nbOfTrial); newJob.setStatus(0); newJob.setName(name); newJob.setRand(rand); //if(m_WXFoxServerDataMutex->Lock()!=wxMUTEX_NO_ERROR) return; //save it and save it in FoxServer //m_jobs.push_back(newJob); m_FoxServer->AddJobToList(newJob); //m_WXFoxServerDataMutex->Unlock(); //m_UpdateTimer->Stop(); //Update GUI wxTimerEvent evt; evt.SetId(ID_UPDATE_TIMER); this->UpdateLists(evt); //int interval = m_UpdateTimer->GetInterval(); //m_UpdateTimer->Start(interval); } void WXFoxServer::OnLoadJob(wxCommandEvent& event) { wxFileDialog *dlg; dlg = new wxFileDialog(this,_T("Choose File :"), _T(""),_T(""),_T("FOX files (*.xml,*.xmlgz)|*.xml;*.xmlgz;*.gz"),wxFD_OPEN | wxFD_FILE_MUST_EXIST); if(dlg->ShowModal() != wxID_OK) return; wxString path=dlg->GetPath(); int newID; wxString Name=wxFileName::FileName(path).GetName(); long nbOfTrial; long nbRun; wxString filename; bool randomize=true; if(path.Mid(path.size()-4)==wxString(_T(".xml")) && isFileFoxJob(path, Name, newID, nbOfTrial, nbRun, randomize)) { if(!isJobLoaded(newID)) { do{//show setup window if(!ShowSetJobWindow(newID, Name, nbOfTrial, nbRun, randomize)) return; cout<7) if(path.Mid(path.size()-6)==wxString(_T(".xml.gz"))) gz=true; if(path.size()>6) if(path.Mid(path.size()-6)==wxString(_T(".xmlgz"))) gz=true; if(gz) { wxFileInputStream is(path); wxZlibInputStream zstream(is); wxStringOutputStream wxos; zstream.Read(wxos); newID = GenerateJobID(); nbOfTrial = 1000000; nbRun = 10; do{//show setup window if(!ShowSetJobWindow(newID, Name, nbOfTrial, nbRun, randomize)) return; cout<Destroy(); } bool WXFoxServer::ShowSetJobWindow(int ID, wxString &name, long &trials, long &runs, bool &rand) { wxString tmp; tmp.Printf(_T("%d"), ID); wxDialog *InfoWindow = new wxDialog(NULL, -1,_T("Set job parameters"),wxDefaultPosition, wxDefaultSize, wxCAPTION); wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL ); wxStaticText *label1 = new wxStaticText(InfoWindow, NULL, _T("Job ID:")); sizer->Add(label1, 0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); wxTextCtrl *IDText = new wxTextCtrl(InfoWindow, NULL, tmp, wxDefaultPosition, wxDefaultSize, wxTE_READONLY); sizer->Add(IDText, 0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); wxStaticText *label1a = new wxStaticText(InfoWindow, NULL, _T("Job Name")); sizer->Add(label1a, 0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); wxTextCtrl *NameText = new wxTextCtrl(InfoWindow, NULL, name, wxDefaultPosition, wxDefaultSize); sizer->Add(NameText, 0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); wxStaticText *label2 = new wxStaticText(InfoWindow, NULL, _T("Number of trials:")); sizer->Add(label2, 0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); tmp.Printf(_T("%ld"), trials); wxTextCtrl *TrialText = new wxTextCtrl(InfoWindow, NULL, tmp, wxDefaultPosition, wxDefaultSize); sizer->Add(TrialText, 0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); wxStaticText *label3 = new wxStaticText(InfoWindow, NULL, _T("Number of runs:")); sizer->Add(label3, 0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); tmp.Printf(_T("%ld"), runs); wxTextCtrl *RunText = new wxTextCtrl(InfoWindow, NULL, tmp, wxDefaultPosition, wxDefaultSize); sizer->Add(RunText, 0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); wxCheckBox *xrand = new wxCheckBox(InfoWindow, NULL, _T( "randomize"), wxDefaultPosition, wxDefaultSize); xrand->SetValue(rand); sizer->Add(xrand, 0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); wxButton *OKButton = new wxButton(InfoWindow, wxID_OK, _T("Save")); wxButton *NOButton = new wxButton(InfoWindow, wxID_CANCEL, _T("Cancel")); sizer->Add(OKButton, 0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); sizer->Add(NOButton, 0, wxALL|wxALIGN_LEFT|wxALIGN_TOP ,3); InfoWindow->SetAutoLayout( TRUE ); InfoWindow->SetSizer( sizer ); sizer->SetSizeHints( InfoWindow ); sizer->Fit( InfoWindow ); if(InfoWindow->ShowModal() == wxID_OK) { wxString Trials = TrialText->GetValue(); wxString Runs = RunText->GetValue(); name = NameText->GetValue(); rand = xrand->GetValue(); Trials.ToLong((long *) &trials); Runs.ToLong((long *) &runs); InfoWindow->Destroy(); return true; } InfoWindow->Destroy(); return false; } void WXFoxServer::EditJob() { int nb = m_JobListTable->GetSelectedRows().Count(); if(nb!=1) return; int r = m_JobListTable->GetSelectedRows().Item(0); if(r>= m_jobs.size()) { return; } int ID = m_jobs[r].getM_ID(); long trials = m_jobs[r].getNbTrial(); long runs = m_jobs[r].getNbRuns(); wxString name = m_jobs[r].getName(); wxString filename = m_jobs[r].getFileName(); bool randomize = m_jobs[r].randomize(); do{//show setup window if(!ShowSetJobWindow(ID, name, trials, runs, randomize)) { return; } }while((runs<=0)||(trials<=0)||(name==_T(""))); ChangeJobHeader(filename, ID, name, trials, runs, randomize); FoxJob newjob; newjob.setNbTrial(trials); newjob.setNbRuns(runs); newjob.setName(name); newjob.setRand(randomize); m_FoxServer->UpdateJob(r,&newjob); } void WXFoxServer::OnEditJob(wxCommandEvent& event) { m_UpdateTimer->Stop(); this->EditJob(); //Update GUI List wxTimerEvent evt; evt.SetId(ID_UPDATE_TIMER); this->UpdateLists(evt); //start timer for updating gui... int interval = m_UpdateTimer->GetInterval(); m_UpdateTimer->Start(interval); } void WXFoxServer::OnDeleteJob(wxCommandEvent& event) { int nb = m_JobListTable->GetSelectedRows().Count(); if(nb!=1) return; //not sure what happens woth the timer events if the modal window is open for some time... //better to stop the timer m_UpdateTimer->Stop(); wxMessageDialog d(this,_T("Do you really want to delete selected job?"), _T("Alert"), wxYES | wxNO); if(wxID_YES!=d.ShowModal()) { int interval = m_UpdateTimer->GetInterval(); m_UpdateTimer->Start(interval); return; } int r = m_JobListTable->GetSelectedRows().Item(0); int er = m_FoxServer->DeleteJob(r); if(er==1) wxMessageBox(_T("Job was deleted"), _T("Notice"), wxOK, this); if(er==0) wxMessageBox(_T("Can't delete this job.\n Job was sent to clients or job finished. Only 'nbRuns' was changed."), _T("Notice"), wxOK, this); if(er==-1) wxMessageBox(_T("Can't delete this job! Job not found or server is busy."), _T("Notice"), wxOK, this); //Update Lists wxTimerEvent evt; // TODO: wxTimerEvent use is deprecated evt.SetId(ID_UPDATE_TIMER); this->UpdateLists(evt); int interval = m_UpdateTimer->GetInterval(); m_UpdateTimer->Start(interval); } void WXFoxServer::RunLocalClient(wxCommandEvent& event) { m_UpdateTimer->Stop(); int nCPU = wxThread::GetCPUCount(); wxString nbCPUs; nbCPUs.Printf(_T("%d"), nCPU); wxString message; wxStandardPaths sp=wxStandardPaths::Get(); message.Printf(_T("Would you also like to run client on this computer?\nSet the number of CPUs available for client or cancel this operation.\n%d CPUs have been detected.") , nCPU); wxTextEntryDialog dlg(m_parent, message, _T("Set a number of available CPUs"), nbCPUs, wxCANCEL | wxOK ); dlg.SetTextValidator(wxTextValidator(wxFILTER_DIGITS)); if(wxID_OK==dlg.ShowModal()){ nbCPUs = dlg.GetValue(); //wxString appname = wxApp::GetInstance()->argv[0]; wxString appname = sp.GetExecutablePath(); #ifdef WIN32 wxString ClientDir = m_working_dir + _T("\\client"); if(!wxDirExists(ClientDir)) wxMkdir(ClientDir); wxString cmd = appname + _T(" --runclient localhost --CPUs ") + nbCPUs + _T(" --working_dir ") + _T("\"") + ClientDir + _T("\""); wxExecute(cmd); #else //if(appname(0,1)!=_T("/")) appname=wxGetCwd()+_T("/")+appname; //wxExecute(appname+_T(" --runclient localhost --CPUs ") + nbCPUs); wxString ClientDir = m_working_dir + _T("/client"); if(!wxDirExists(ClientDir)) wxMkdir(ClientDir); long result= wxExecute(appname+_T(" --runclient localhost --CPUs ") + nbCPUs + _T(" --working_dir \"") + ClientDir+ _T("\"")); //if(result==0) result=wxExecute(wxGetCwd()+_T("/")+appname+_T(" --runclient localhost --CPUs ") + nbCPUs); //if(result==0) result=wxExecute(_T("/usr/bin/")+appname+_T(" --runclient localhost --CPUs ") + nbCPUs); //if(result==0) result=wxExecute(_T("/usr/local/bin/")+appname+_T(" --runclient localhost --CPUs ") + nbCPUs); //if(appname(0,1)!=_T("/")) appname=wxGetCwd()+_T("/")+appname; //wxExecute(appname+_T(" --runclient localhost --CPUs ") + nbCPUs); #endif } int interval = m_UpdateTimer->GetInterval(); m_UpdateTimer->Start(interval); } void WXFoxServer::UpdateJobList() { int nbRow = m_JobListTable->GetNumberRows(); if(nbRow>0) m_JobListTable->DeleteRows(0, nbRow, true); wxString tmp; for(int i=0;iInsertRows(i,1,false); tmp.Printf(_T("%d"),m_jobs[i].getM_ID()); m_JobListTable->SetCellValue(i,0,tmp);//ID m_JobListTable->SetReadOnly(i,0); m_JobListTable->SetCellValue(i,1,m_jobs[i].getName());//name m_JobListTable->SetReadOnly(i,1); tmp.Printf(_T("%ld"), m_jobs[i].getNbTrial()); m_JobListTable->SetCellValue(i,2,tmp);//nbtrial m_JobListTable->SetReadOnly(i,1); //rand if(m_jobs[i].randomize()) { tmp.Printf(_T("YES"), m_jobs[i].getNbTrial());//???? :TODO: } else { tmp.Printf(_T("NO"), m_jobs[i].getNbTrial());//???? :TODO: } m_JobListTable->SetCellValue(i,3,tmp);//nbtrial m_JobListTable->SetReadOnly(i,1); tmp.Printf(_T("%d/%d/%d"), m_jobs[i].getNbRuns(), m_jobs[i].getNbDone(), m_jobs[i].GetSolvingNb()); m_JobListTable->SetCellValue(i,4,tmp);//runs m_JobListTable->SetReadOnly(i,2); wxColor ccolor(255, 255, 255); if(m_jobs[i].getNbDone() >= m_jobs[i].getNbRuns()) { ccolor.Set(200, 255, 200); } else if(m_jobs[i].GetSolvingNb()>0) { ccolor.Set(255, 200, 200); } else if(m_jobs[i].getNbDone()>0) { ccolor.Set(255, 255, 200); } m_JobListTable->SetCellBackgroundColour(i, 0, ccolor); m_JobListTable->SetCellBackgroundColour(i, 1, ccolor); m_JobListTable->SetCellBackgroundColour(i, 2, ccolor); m_JobListTable->SetCellBackgroundColour(i, 3, ccolor); m_JobListTable->SetCellBackgroundColour(i, 4, ccolor); } } void WXFoxServer::UpdateResultList() { int nb = m_ResultTable->GetNumberRows(); std::sort(m_results.begin(), m_results.end()); wxString tmp; //rewrite already present rows (because we sorted/changed results before) and insert new ones. for(int i=0;i=nb) { m_ResultTable->InsertRows(i, 1, false); } tmp.Printf(_T("%d"), m_results[i].order); m_ResultTable->SetCellValue(i, 0, tmp);//Nb tmp.Printf(_T("%d"), m_results[i].JobID); m_ResultTable->SetCellValue(i, 1, tmp);//Job ID tmp.Printf(_T("%0.2f"), m_results[i].Cost); m_ResultTable->SetCellValue(i, 2, tmp);//Cost //if(m_results[i].Show) m_ResultTable->SetCellValue(i, 3, _T("TRUE"));//Show //else m_ResultTable->SetCellValue(i, 3, _T("FALSE"));//Show } } void WXFoxServer::UpdateClientList() { //update client list int nbRow = m_ClientTable->GetNumberRows(); if(nbRow>0) m_ClientTable->DeleteRows(0, nbRow, true); for(int i=0;iInsertRows(i,1,false); wxString tmp; //Name m_ClientTable->SetCellValue(i,0,m_clients[i].name); m_ClientTable->SetReadOnly(i,0); //ID tmp.Printf(_T("%d"), (int) m_clients[i].id); m_ClientTable->SetCellValue(i,1,tmp); m_ClientTable->SetReadOnly(i,1); //CPUs tmp.Printf(_T("%d/%d"), (int) m_clients[i].allCPUs, (int) (m_clients[i].allCPUs-m_clients[i].availCPUs)); m_ClientTable->SetCellValue(i,2,tmp); m_ClientTable->SetReadOnly(i,2); //status //m_ClientTable->SetCellValue(i,3,clients[i].status); //m_ClientTable->SetReadOnly(i,3); //set colors if(m_clients[i].availCPUs < m_clients[i].allCPUs) { m_ClientTable->SetCellBackgroundColour(i, 0, wxColour(255, 200, 200)); m_ClientTable->SetCellBackgroundColour(i, 1, wxColour(255, 200, 200)); m_ClientTable->SetCellBackgroundColour(i, 2, wxColour(255, 200, 200)); } else { m_ClientTable->SetCellBackgroundColour(i, 0, wxColour(200, 255, 200)); m_ClientTable->SetCellBackgroundColour(i, 1, wxColour(200, 255, 200)); m_ClientTable->SetCellBackgroundColour(i, 2, wxColour(200, 255, 200)); } } } void WXFoxServer::UpdateLists(wxTimerEvent& event) { std::vector newclients; std::vector newjobs; if(m_FoxServer->IsServerRunning()){ m_FoxServer->GetData(newclients, m_results, newjobs); } //check if there is something new in client list bool update = false; if(m_clients.size() == newclients.size()) { for(int i=0;iGetSelectedRows().Count()==1){ m_JobListTable->DeselectRow(m_JobListTable->GetSelectedRows().Item(0)); } m_JobListTable->SelectRow(r, true); } void WXFoxServer::OnGridResultClick(wxGridEvent &event) { int r = event.GetRow(); int c = event.GetCol(); //if(m_WXFoxServerDataMutex->Lock()!=wxMUTEX_NO_ERROR) return; if(m_ResultTable->GetSelectedRows().Count()==1){ m_ResultTable->DeselectRow(m_ResultTable->GetSelectedRows().Item(0)); } m_ResultTable->SelectRow(r, true); //m_WXFoxServerDataMutex->Unlock(); } void WXFoxServer::OnShowResultsServer(wxCommandEvent& event) { int nb = m_ResultTable->GetSelectedRows().Count(); #ifdef __DEBUG__ (*fpObjCrystInformUser)(wxString::Format("Show Results: %d rows selected",nb).ToStdString()); #endif if(nb!=1) { wxMessageBox(_T("Select one result!"), _T("Error"), wxOK, this); return; } int r = m_ResultTable->GetSelectedRows().Item(0); #ifdef __DEBUG__ (*fpObjCrystInformUser)(wxString::Format("Show Results: result %d/%zd selected",r,m_results.size()).ToStdString()); #endif if(r>=m_results.size()) return; wxString file = m_results[r].filename; (*fpObjCrystInformUser)(wxString::Format("Show Results: opening file: "+file).ToStdString()); /* if(safe) { bool saved=true; for(int i=0;imClockLastSave) { saved=false; break; } if(!saved) { wxString msg; msg.Printf( _T("Some objects have not been saved\n") _T("Do you really want to close all ?")); wxMessageDialog d(this,msg, _T("Really Close ?"), wxYES | wxNO); if(wxID_YES!=d.ShowModal()) return; } } */ if(m_dataLoaded) { gOptimizationObjRegistry.DeleteAll(); gDiffractionDataSingleCrystalRegistry.DeleteAll(); gPowderPatternRegistry.DeleteAll(); gCrystalRegistry.DeleteAll(); (*fpObjCrystInformUser)(""); (*fpObjCrystInformUser)("Closed all objects"); (*fpObjCrystInformUser)(""); m_dataLoaded = false; } if(file.size()>4 && file.Mid(file.size()-4)==wxString(_T(".xml"))) { wxFileInputStream is(file); stringstream in; if(is.GetSize()>0) { char * tmpbuf=new char[is.GetSize()]; is.Read(tmpbuf,is.GetSize()); in.write(tmpbuf,is.GetSize()); delete[] tmpbuf; } else while (!is.Eof()) in<<(char)is.GetC(); try{XMLCrystFileLoadAllObject(in);} catch(const ObjCrystException &except) { wxMessageDialog d(this,_T("Failed loading file1:\n")+file,_T("Error loading file"),wxOK|wxICON_ERROR); d.ShowModal(); return; }; m_dataLoaded = true; } } void WXFoxServer::OnShowResults(wxCommandEvent& event) { //if(m_WXFoxServerDataMutex->Lock()!=wxMUTEX_NO_ERROR) return; int nb = m_ResultTable->GetSelectedRows().Count(); #ifdef __DEBUG__ (*fpObjCrystInformUser)(wxString::Format("Show Results: %d rows selected",nb).ToStdString()); #endif if(nb!=1) { wxMessageBox(_T("Select one result!"), _T("Error"), wxOK, this); return; } int r = m_ResultTable->GetSelectedRows().Item(0); #ifdef __DEBUG__ (*fpObjCrystInformUser)(wxString::Format("Show Results: result %d/%zd selected",r,m_results.size()).ToStdString()); #endif if(r>=m_results.size()) return; wxString file = m_results[r].filename; (*fpObjCrystInformUser)(wxString::Format("Show Results: opening file: "+file).ToStdString()); //m_WXFoxServerDataMutex->Unlock(); wxString cmd; #ifdef WIN32 cmd = wxApp::GetInstance()->argv[0]; cmd +=_T(" "); cmd += file; wxExecute(cmd); #else wxString appname = wxStandardPaths::Get().GetExecutablePath(); wxString com=appname+_T(" ")+file; long result= wxExecute(com); (*fpObjCrystInformUser)(com.ToStdString()); //if(result==0) result=wxExecute(wxGetCwd()+_T("/")+appname+_T(" ")+file); //if(result==0) result=wxExecute(_T("/usr/bin/")+appname+_T(" ")+file); //if(result==0) result=wxExecute(_T("/usr/local/bin/")+appname+_T(" ")+file); #endif } objcryst-2022.1/Fox/src/WXFoxServer.h000066400000000000000000000057551430515525000173510ustar00rootroot00000000000000#ifdef __WX__CRYST__ // For compilers that support precompilation, includes "wx/wx.h". #ifndef __DARWIN__ // work around MacOSX type_info bug (??) #include "wx/wxprec.h" #endif #ifdef __BORLANDC__ #pragma hdrstop #endif // for all others, include the necessary headers (this file is usually all you // need because it includes almost all "standard" wxWindows headers) #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "wx/tooltip.h" #include "wx/notebook.h" #include "wx/wfstream.h" #include "wx/zstream.h" #include "wx/fileconf.h" #include "wx/socket.h" #include "wx/grid.h" #include "wx/dynarray.h" #include "wx/stdpaths.h" #endif #include "ObjCryst/ObjCryst/IO.h" #include "ObjCryst/ObjCryst/Crystal.h" #include "ObjCryst/ObjCryst/PowderPattern.h" #include "ObjCryst/ObjCryst/DiffractionDataSingleCrystal.h" #include "ObjCryst/RefinableObj/GlobalOptimObj.h" #include "FoxServer.h" #define __FOX_SERVER__ class WXFoxServer : public wxWindow { public: WXFoxServer(wxWindow* parent, wxString workingDir); ~WXFoxServer(void); void Clear(); bool m_dataLoaded; private: void InitServer(); void OnGridResultClick(wxGridEvent &event); void OnGridJobClick(wxGridEvent &event); void OnShowResults(wxCommandEvent& event); void OnShowResultsServer(wxCommandEvent& event); void RunLocalClient(wxCommandEvent& event); //void RunALLClient(wxCommandEvent& event); void UpdateLists(wxTimerEvent& event); void OnNewJob(wxCommandEvent& event); void OnEditJob(wxCommandEvent& event); void EditJob(); void OnDeleteJob(wxCommandEvent& event); void OnLoadJob(wxCommandEvent& event); int GenerateJobID(); void UpdateJobList(); void UpdateResultList(); void UpdateClientList(); bool ShowSetJobWindow(int ID, wxString &name, long &trials, long &runs, bool &rand); bool isFileFoxJob(wxString path, wxString &name, int &id, long &nbOfTrial, long &nbRun, bool &rand); void saveJobHeader(wxString filename, int ID, wxString name, long nbOfTrial, int nbRun, bool rand); void ChangeJobHeader(wxString filename, int ID, wxString name, long nbOfTrial, int nbRun, bool rand); void AddServerJob(wxString filename, wxString name, int id, long nbOfTrial, long nbRun, bool rand); void SaveDataAsFile(wxString out, wxString filename); bool LoadFile(wxString filename, wxString &in); bool isJobLoaded(long ID); wxWindow * m_parent; wxGrid * m_ResultTable; wxGrid * m_ClientTable; wxGrid * m_JobListTable; //wxTextCtrl * m_EventsWindow; //wxTextCtrl * m_ClientWindow; //wxTextCtrl * m_JobListWindow; wxTimer * m_UpdateTimer; FoxServer * m_FoxServer; std::vector m_jobs; std::vector m_results; std::vector m_clients; //wxMutex * m_WXFoxServerDataMutex; wxString m_working_dir; DECLARE_EVENT_TABLE() }; objcryst-2022.1/Fox/src/WXGridWindow.cpp000066400000000000000000000051701430515525000200250ustar00rootroot00000000000000 #ifdef __WX__CRYST__ #include "ObjCryst/wxCryst/wxCrystal.h" //#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__) // #include "Fox.xpm" //#endif #endif using namespace ObjCryst; using namespace std; #include "WXGridWindow.h" WXGrigWindow::WXGrigWindow(wxWindow *parent): wxWindow(parent,-1) { dataLoaded = false; m_WXFoxServer = NULL; m_WXFoxClient = NULL; } WXGrigWindow::~WXGrigWindow(void) { if (m_WXFoxServer != NULL) { m_WXFoxServer->Clear(); delete m_WXFoxServer; } if (m_WXFoxClient != NULL) { m_WXFoxClient->Clear(); delete m_WXFoxClient; } } WXFoxServer *WXGrigWindow::StartServer() { //if client or server exist return NULL if(m_WXFoxClient!=NULL) return NULL; if(m_WXFoxServer!=NULL) return NULL; m_WXFoxServer = new WXFoxServer(this, m_working_dir); m_WXFoxServer->m_dataLoaded = dataLoaded; if(this->GetSizer()==NULL) this->SetSizer(new wxBoxSizer(wxVERTICAL)); this->GetSizer()->Add(m_WXFoxServer); this->Layout(); wxTopLevelWindow *ptopwin = dynamic_cast( wxTheApp->GetTopWindow()); if(ptopwin!=NULL) { wxString title=ptopwin->GetTitle(); if(wxNOT_FOUND==title.Find("GRID")) { title +=" [GRID SERVER]"; ptopwin->SetTitle(title); } } wxTheApp->GetTopWindow()->Layout(); wxTheApp->GetTopWindow()->SendSizeEvent(); return m_WXFoxServer; } WXFoxClient *WXGrigWindow::StartClientWindow() { //if client or server exist return NULL if(m_WXFoxClient!=NULL) return NULL; if(m_WXFoxServer!=NULL) return NULL; m_WXFoxClient = new WXFoxClient(this, m_working_dir); if(this->GetSizer()==NULL) this->SetSizer(new wxBoxSizer(wxVERTICAL)); this->GetSizer()->Add(m_WXFoxClient); this->Layout(); wxTopLevelWindow *ptopwin = dynamic_cast( wxTheApp->GetTopWindow()); if(ptopwin!=NULL) { wxString title=ptopwin->GetTitle(); if(wxNOT_FOUND==title.Find("GRID")) { title +=" [GRID CLIENT]"; ptopwin->SetTitle(title); } } wxTheApp->GetTopWindow()->Layout(); wxTheApp->GetTopWindow()->SendSizeEvent(); return m_WXFoxClient; } void WXGrigWindow::DataLoaded() { dataLoaded = true; if(m_WXFoxServer!=NULL) { m_WXFoxServer->m_dataLoaded = true; } } void WXGrigWindow::Clear() { if(m_WXFoxServer!=NULL) { m_WXFoxServer->Clear(); delete m_WXFoxServer; m_WXFoxServer=NULL; } if(m_WXFoxClient!=NULL) { m_WXFoxClient->Clear(); delete m_WXFoxClient; m_WXFoxClient=NULL; } } objcryst-2022.1/Fox/src/WXGridWindow.h000066400000000000000000000017061430515525000174730ustar00rootroot00000000000000#define __WXGRIDWINDOW__ #ifdef __WX__CRYST__ // For compilers that support precompilation, includes "wx/wx.h". #ifndef __DARWIN__ // work around MacOSX type_info bug (??) #include "wx/wxprec.h" #endif #ifdef __BORLANDC__ #pragma hdrstop #endif // for all others, include the necessary headers (this file is usually all you // need because it includes almost all "standard" wxWindows headers) #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "wx/frame.h" #endif #include "WXFoxServer.h" #include "WXFoxClient.h" class WXGrigWindow: public wxWindow { public: WXGrigWindow(wxWindow *parent); ~WXGrigWindow(void); WXFoxServer *StartServer(); WXFoxClient *StartClientWindow(); //WXFoxClient *StartClientWindow(wxString IP, int nbCPU=-1); void DataLoaded(); void Clear(); WXFoxServer *m_WXFoxServer; WXFoxClient *m_WXFoxClient; bool dataLoaded; wxString m_working_dir; }; objcryst-2022.1/Fox/src/bc32.mak000066400000000000000000000006031430515525000162040ustar00rootroot00000000000000!include ..\ObjCryst\rules.mak TARGET= Fox OBJECTS = $(TARGET).obj #build a wx application $(TARGET).exe: $(OBJECTS) $(TARGET).res libsglite libatominfo libnewmat libCrystVector libQuirks libRefinableObj libcryst libwxCryst cd ${DIR_CRYST}\..\src ilink32 $(LINKFLAGS) -LC:${DIR_CRYST}\..\Fox\src @&&! c0w32.obj $(OBJECTS) $(TARGET) $(LINKLIBS) $(TARGET).res ! all: $(TARGET).exe objcryst-2022.1/Fox/src/gnu.mak000066400000000000000000000026001430515525000162430ustar00rootroot00000000000000BUILD_DIR = $(CURDIR)/../.. include $(BUILD_DIR)/ObjCryst/rules.mak OBJ = Fox.o FoxJob.o GridResult.o IOSocket.o FoxServer.o FoxClient.o WXFoxClient.o WXFoxServer.o WXGridWindow.o ifeq ($(profile),2) %.o : %.c @rm -f $(*F).gcda $(*F).gcno @$(MAKEDEPEND) ${CC} ${CPPFLAGS} ${CXXFLAGS} -c $< -o $@ else %.o : %.c @$(MAKEDEPEND) ${CC} ${CPPFLAGS} ${CXXFLAGS} -c $< -o $@ endif ifeq ($(profile),2) %.o : %.cpp $(libwx) $(libnewmat) libcctbx @rm -f $(*F).gcda $(*F).gcno @$(MAKEDEPEND) ${CXX} ${CPPFLAGS} ${CXXFLAGS} -c $< -o $@ else %.o : %.cpp @$(MAKEDEPEND) ${CXX} ${CPPFLAGS} ${CXXFLAGS} -c $< -o $@ endif %.o : %.rc windres -i $< -o $@ --include-dir ${DIR_WXWINDOWS}/include -include $(OBJ:.o=.dep) libFox: $(OBJ) #Main Application Fox: $(libwx) $(libnewmat) $(libfftw) $(COD_LIB) libCrystVector libQuirks libRefinableObj libcctbx libCryst libwxCryst $(MAKE) -f gnu.mak libFox ${LINKER} ${CRYST_LDFLAGS} -o $@ ${filter-out %.h %.a %.so lib%, $^} $(OBJ) ${LOADLIBES} Fox-nogui: $(libnewmat) libcctbx libCrystVector libQuirks libRefinableObj libCryst Fox.o ${LINKER} ${CRYST_LDFLAGS} -o $@ ${filter-out %.h %.a %.so lib%, $^} ${LOADLIBES} fox: Fox # target for making everything .PHONY : all all: Fox # target for removing all object files .PHONY : tidy tidy:: @${RM} core *.o *.dep # target for removing all object files and libraries .PHONY : clean clean:: tidy @${RM} *.a Fox objcryst-2022.1/Fox/src/vc.mak000066400000000000000000000007661430515525000160750ustar00rootroot00000000000000!include ..\ObjCryst\rules.mak TARGET= Fox OBJECTS = $(TARGET).obj $(TARGET).exe: $(OBJECTS) libcctbx libnewmat libCrystVector libQuirks libRefinableObj libcryst libwxCryst cd $(DIR_CRYST)\..\src rc -r -i$(DIR_WXWINDOWS)\include -i$(DIR_WXWINDOWS)\contrib\include -i"C:\Program Files\Microsoft Visual C++ Toolkit 2003\include" -i"E:\Program Files\Microsoft SDK\include" -fo$(TARGET).res $(TARGET).rc link $(TARGET).obj $(TARGET).res $(LINKFLAGS) $(LINKLIBS) -out:$(TARGET).exe all:$(TARGET).exe objcryst-2022.1/Fox/wiki2pdf.py000066400000000000000000000205251430515525000162700ustar00rootroot00000000000000from urllib.request import urlopen, urlretrieve from urllib.parse import urlparse, urlunparse import re import os from time import sleep class MoinSpider: def __init__(self, site='fox.vincefn.net', exclude=["RecentChanges", "action=", "FindPage", "TitleIndex", "WordIndex", "Help", "template", "Template", "MoinMoin", "UserPreferences", "WikiSandBox", "ScriptAlias", "ScriptAlias"]): # self.u.addheader(('USER_AGENT', 'Mozilla/4.0')) self.base = 'href=\"/' self.suffix = "?action=print" self.site = site self.pages = [] # list of pairs [relative URL, page content] self.d = {} # dictionnary with keys=relative URL, value= short filename for the downloaded page self.exclude = exclude self.nbFail = 0 # pages which failed to load self.img = set() def Weave(self, lnk='/Fox/FoxWiki', nbtry=3): """ Download recursively all pages, starting from one relative URL. """ if self.d.has_key(lnk): # we already got that page ! return self.d[lnk] = "wiki_%i.html" % (1000 + len(self.d)) url = "http://" + self.site + lnk + self.suffix #:TODO: use urlparse ! print() print("Getting page: %s" % url) print(" -> %s" % (self.d[lnk])) nb = nbtry cont = True while (nb > 0): try: p = urlopen(url) page = p.read().decode('utf-8') nb = -1 except IOError: nb -= 1 print("IOError..... retry #%i" % (nbtry - nb)) sleep(1) if nb == 0: print("Failed to load page, after %i trials:" % nbtry, lnk) self.nbFail += 1 return if re.search("This page does not exist yet", page) is not None: print(" -> Page has not been written yet !") self.d[lnk] = "http://" + self.site + lnk # Link directly to site return self.pages.append([lnk, page]) for m in re.finditer(r"href\=\"(.*?)\"", page): newlink = m.group() if len(newlink) >= len(self.base): if newlink[:len(self.base)] == self.base: keep = True for x in self.exclude: if re.search(x, newlink) != None: keep = False break if keep: # print(" ->%s"%newlink) newlink = newlink[6:-1] # [6:-1] -> exlude ' href=" ' and the end ' " ' newlink = re.split('#', newlink)[0] # exclude anchors self.Weave(newlink) # else: # print(" ->%s ? NO"%newlink) def WeaveStatic(self, pagelist, nbtry=3): """ Alternative to weave: download a pre-selected list of pages """ for lnk in pagelist: self.d[lnk] = "wiki_%i.html" % (1000 + len(self.d)) url = "http://" + self.site + lnk + self.suffix #:TODO: use urlparse ! print("Getting page: %s -> %s" % (url, self.d[lnk])) nb = nbtry cont = True while (nb > 0): try: print(url) p = urlopen(url) page = p.read().decode('utf-8') nb = -1 except IOError: nb -= 1 print("IOError..... retry #%i" % (nbtry - nb)) sleep(1) if nb == 0: print("Failed to load page, after %i trials:" % nbtry, lnk) if re.search("This page does not exist yet", page) is not None: print(" -> Page has not been written yet !") self.d[lnk] = "http://" + self.site + lnk # Link directly to site nb = 0 else: self.pages.append([lnk, page]) def Pages2Html(self, d="wikihtml"): # TODO : remove links to non-written pages if not os.path.exists(d): os.mkdir(d) # this is necessary so that urls that contain other (smaller) urls # are replaced first ks = list(self.d.keys()) ks.sort(reverse=True) for p in self.pages: for m in re.finditer(r"img .*? src\=\"(.*?)\"", p[1]): print(re.findall(r"src\=\"(.*?)\"", m.group())) url = re.findall(r"src\=\"(.*?)\"", m.group())[0] up = urlparse(url) print(url) up0, up1, up2, up3, up4, up5 = up[0], up[1], up[2], up[3], up[4], up[5] if up4 != '': name = re.split('=', up4).pop() else: name = re.split('/', up2).pop() if name not in self.img: # download image once self.img.add(name) if up0 == '': up0 = 'http' if up1 == '': up1 = self.site urlimg = urlunparse((up0, up1, up2, up3, up4, up5)).replace('&', '&') print(" %s -> %s" % (urlimg, name)) nbTry = 3 nb = nbTry while nb > 0: try: urlretrieve(urlimg, d + "/" + name) nb = -1 except IOError: nb -= 1 print("IOError..... retry #%i to get %s" % (nbTry - nb, name)) sleep(1) if nb == 0: print("Failed to load image, after %i trials: %s" % (nbtry, name)) else: # KLUDGE png->png cause htmldoc chokes on these... if name[-4:] == ".png": print("convert %s %s" % (d + "/" + name, d + "/" + name[:-3] + "jpg")) os.system("convert %s %s" % (d + "/" + name, d + "/" + name[:-3] + "jpg")) os.system("rm -f %s" % (d + "/" + name)) p[1] = p[1].replace(url, name) for k in ks: # change to local url if k != self.d[k]: p[1] = p[1].replace(k, self.d[k]) # Change src field of img from "wiki_1002.html?action=AttachFile&do=get&target=toto.jpg" # to "toto.jpg" p[1] = p[1].replace("%s?action=AttachFile&do=get&target=" % k, "") p[1] = p[1].replace(".png", ".jpg") f = open(d + "/" + self.d[p[0]], 'w') f.write(p[1]) def Html2pdf(self, d="wikihtml"): os.system("mogrify -resize '600x>' wikihtml/*.jpg") # os.system("htmldoc --jpeg=85 --webpage %s/*.html --linkcolor blue -f wiki.pdf"%d) os.system("htmldoc --jpeg=85 --webpage %s/*.html --linkcolor blue --size a4 --format pdf14 " "--links --book --toclevels 3 --left 1.5cm --right 1.5cm --top 1.5cm --bottom 1.5cm " "--footer Dc1 -f FoxManual.pdf" % d) # os.system("rm -f wikihtml/*") # m=MoinSpider(site="objcryst.sourceforge.net") m = MoinSpider(site="fox.vincefn.net") m.WeaveStatic(["/FoxWiki", "/BiblioReferences", "/Screenshots", "/Download", "/Install", "/Install/Linux", "/Install/MacOSX", "/Install/Windows", "/Tutorials", "/Tutorials/Cimetidine", "/Tutorials/PbSO4", "/Tutorials/YLID", "/Manual", "/Manual/Crystal", "/Manual/Powder", "/Manual/Indexing", "/Manual/ProfileFitting", "/Manual/SingleCrystalDiffraction", "/Manual/Algorithm", "/Manual/CIF", "/Manual/Fox.Grid", "/Manual/Tips", "/MailingList", "/Changelog", "/FoxCompile", "/Compile/Linux", "/Compile/MacOSX", # "/Compile/Windows" # "/BiblioStructures", # "/VincentFavreNicolin" ]) m.Pages2Html() m.Html2pdf() objcryst-2022.1/LICENSE.txt000066400000000000000000000357241430515525000152750ustar00rootroot00000000000000NOTE: This is the main FOX/ObjCryst++ license. Please also refer to the license of the (also open-source) libraries used by Fox: cctbx, newmat,, wxwidgets, fftw3, mysql, freeglut. ####### GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS objcryst-2022.1/ObjCryst/000077500000000000000000000000001430515525000151765ustar00rootroot00000000000000objcryst-2022.1/ObjCryst/.cvsignore000066400000000000000000000002071430515525000171750ustar00rootroot00000000000000*.o *.exe *.out *.old *.dep *.a .directory .systemG.Desktop tags html latex *.oxy *.xml profile.0.0.0 *.pov Makefile rules.mak .xvpics objcryst-2022.1/ObjCryst/CrystVector/000077500000000000000000000000001430515525000174655ustar00rootroot00000000000000objcryst-2022.1/ObjCryst/CrystVector/.cvsignore000066400000000000000000000001771430515525000214720ustar00rootroot00000000000000*.o *.exe *.out *.old *.dep *.a .directory .systemG.Desktop tags html latex *.oxy *.xml profile.0.0.0 *.pov Makefile rules.mak objcryst-2022.1/ObjCryst/CrystVector/CrystVector.cpp000066400000000000000000001271321430515525000224660ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ObjCryst/CrystVector/CrystVector.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" #include "ObjCryst/ObjCryst/General.h" #ifdef __LIBCRYST_VECTOR_USE_BLITZ__ #define CrystVector Array #define CrystMatrix Array template T MaxDifference(const Array &a,const Array &b) { return max(fabs(a-b)); } template T MaxDifference(const Array &a,const Array &b) { return max(fabs(a-b)); } #else // __LIBCRYST_VECTOR_USE_BLITZ__ //Still using pointers instead of blitz for geometrical structure factor, //due to huge memory requirements with gcc when using blitz. #define __VFN_GEOM_STRUCT_FACTOR_USE_POINTERS #include "ObjCryst/Quirks/VFNDebug.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" //###################################################################### // CrystVector //###################################################################### template CrystVector::CrystVector():mpData(0),mNumElements(0),mIsAreference(false) {} template CrystVector::CrystVector(const long nbElements): mNumElements(nbElements),mIsAreference(false) { mpData=new T[mNumElements]; } template CrystVector::CrystVector(const CrystVector &old): mNumElements(old.numElements()),mIsAreference(false) { mpData=new T[mNumElements]; T *p1=mpData; const T *p2=old.data(); for(long i=0;i CrystVector::~CrystVector() { if(!mIsAreference) { delete[] mpData; } } template void CrystVector::operator=(const CrystVector &old) { VFN_DEBUG_MESSAGE("CrystVector::operator=()",0) this->resize(old.numElements()); mIsAreference=false; T *p1=mpData; const T *p2=old.data(); for(long i=0;i void CrystVector::reference(CrystVector &old, const long imin, const long imax) { if(!mIsAreference) { delete[] mpData ; } if(imax>imin) { mNumElements=imax-imin; mpData=old.data()+imin; } else { mNumElements=old.numElements(); mpData=old.data(); } mIsAreference=true; } template long CrystVector::numElements()const {return mNumElements;} template long CrystVector::size()const {return mNumElements;} template T CrystVector::sum()const { T tmp=0; const T *p=this->data(); for(long i=0;inumElements();i++) tmp += *p++ ; return tmp; } template T CrystVector::min()const { T tmp=0; const T *p=this->data(); tmp=*p++; for(long i=1;inumElements();i++) { if(tmp>*p) tmp=*p; p++; } return tmp; } template T CrystVector::max()const { T tmp=0; const T *p=this->data(); tmp=*p++; for(long i=1;inumElements();i++) { if(tmp<*p) tmp=*p; p++; } return tmp; } template unsigned long CrystVector::imin(const unsigned long start0,const unsigned long finish0)const { unsigned long start=start0,finish=finish0; if(start0==finish0) { start=0; finish=this->numElements(); } T tmp=0; const T *p=this->data()+start; tmp=*p++; long im=0; for(unsigned long i=start+1;i*p) {tmp=*p;im=i;} p++; } return (unsigned long)im; } template unsigned long CrystVector::imax(const unsigned long start0,const unsigned long finish0)const { unsigned long start=start0,finish=finish0; if(start0==finish0) { start=0; finish=this->numElements(); } T tmp=0; const T *p=this->data()+start; tmp=*p++; long im=start; for(unsigned long i=start+1;i T * CrystVector::data() {return mpData;} template const T * CrystVector::data() const {return mpData;} template void CrystVector::resize(const long newNbElements) { if(mNumElements==newNbElements) return; VFN_DEBUG_MESSAGE("CrystVector::resize():("<" <0) { mpData=new T[mNumElements]; } mIsAreference=false; } template void CrystVector::resizeAndPreserve(const long newNbElements) { //:TODO: check memory allocation if(newNbElements == mNumElements) return; T * RESTRICT p=mpData; T * RESTRICT p2,*p1; mpData=0; mpData=new T[newNbElements]; p2=mpData; p1=p; const long tmp= (newNbElements > mNumElements) ? mNumElements : newNbElements ; for(long i=tmp;i>0;i--) *p2++ = *p1++ ; if(mIsAreference==false) { delete[] p ; } mNumElements=newNbElements; mIsAreference=false; } template void CrystVector::operator*=(const T num) { T * RESTRICT p=mpData; for(int i=mNumElements;i>0;i--) *p++ *= num; } template void CrystVector::operator*=(const CrystVector &vect) { #ifdef __DEBUG__ if( vect.numElements() != mNumElements) { cout<<"CrystVector::operator*=(&vect)(i): Number of elements differ:"<< mNumElements \ << "!="<< vect.numElements() <0;i--) { *p *= *rhs; p++ ; rhs++;} } else { T *p=mpData; for(int i=mNumElements;i>0;i--) { *p *= *p; p++ ;} } } template void CrystVector::operator/=(const T num) { T * RESTRICT p=mpData; const REAL d=1/num; for(int i=mNumElements;i>0;i--) *p++ *= d; } template void CrystVector::operator/=(const CrystVector &vect) { #ifdef __DEBUG__ if( vect.numElements() != mNumElements) { cout<<"CrystVector::operator/=(&vect)(i): Number of elements differ:"<< mNumElements \ << "!="<< vect.numElements() <0;i--) { *p /= *rhs; p++ ; rhs++;} } else *this=1; } template void CrystVector::operator+=(const T num) { T * RESTRICT p=mpData; for(int i=mNumElements;i>0;i--) *p++ += num; } template void CrystVector::operator+=(const CrystVector &vect) { #ifdef __DEBUG__ if( vect.numElements() != mNumElements) { cout<<"CrystVector::operator+=(&vect)(i): Number of elements differ:"<< mNumElements \ << "!="<< vect.numElements() <0;i--) *p++ += *rhs++; } else { T *p=mpData; for(int i=mNumElements;i>0;i--) {*p += *p; p++;} } } template void CrystVector::operator-=(const CrystVector &vect) { #ifdef __DEBUG__ if( vect.numElements() != mNumElements) { cout<<"CrystVector::operator-=(&vect)(i): Number of elements differ:"<< mNumElements \ << "!="<< vect.numElements() <0;i--) *p++ -= *rhs++; } else (*this)=0; } template void CrystVector::operator=(const T num) { T *p=mpData; for(int i=mNumElements;i>0;i--) *p++ = num; } template T CrystVector::operator()(const long i) const { #ifdef __DEBUG__ if( (i<0) || (i>=mNumElements)) { cout<<"CrystVector::operator()(i): Tried to access an element out of bounds :"< T& CrystVector::operator()(const long i) { #ifdef __DEBUG__ if( (i<0) || (i>=mNumElements)) { cout<<"CrystVector::operator()(i): Tried to access an element out of bounds !"< ostream& operator<<(ostream &os, CrystVector &vect) { //return os << FormatHorizVector(vect); for(long i=0;i CrystVector SortSubs(const CrystVector &vect) { CrystVector subscript(vect.numElements()); { long *pLong=subscript.data(); for(long i=0;i v; v=vect; QuickSortSubs(v,subscript,v.numElements()-1,0,0); return subscript; } template long QuickSortSubs(CrystVector &vect, CrystVector &subscript, long last,long first, int depth) { //assert(depth++ <50);//for up to 2^50 elements static long count=0; long low, high; T tmpT, sepValeur ; long tmpSubs; low = first; high = last; sepValeur = vect( (first + last) / 2 ); do { while( vect(low) < sepValeur ) low++; while( vect(high) > sepValeur ) high--; if( low <= high ) { count++; tmpT = vect(low); vect(low) = vect(high); vect(high) = tmpT; tmpSubs = subscript(low); subscript(low++) = subscript(high); subscript(high--) = tmpSubs; } } while( low <= high); if( first < high ) QuickSortSubs(vect,subscript, high, first,depth); if( low < last ) QuickSortSubs(vect,subscript, last, low,depth); return count ; } template CrystVector cos(const CrystVector &vect) { CrystVector cosVect(vect.numElements()); for(long i=0;i CrystVector sin(const CrystVector &vect) { CrystVector sinVect(vect.numElements()); for(long i=0;i CrystVector tan(const CrystVector &vect) { CrystVector tanVect(vect.numElements()); for(long i=0;i CrystVector sqrt(const CrystVector &vect) { CrystVector tanVect(vect.numElements()); for(long i=0;i CrystMatrix ::CrystMatrix(): mpData(0),mNumElements(0),mXSize(0),mYSize(0),mIsAreference(false){} template CrystMatrix::CrystMatrix(const long ySize,const long xSize): mNumElements(xSize*ySize),mXSize(xSize),mYSize(ySize),mIsAreference(false) { mpData=new T[mNumElements]; } template CrystMatrix::CrystMatrix(const CrystMatrix &old): mNumElements(old.numElements()),mXSize(old.cols()),mYSize(old.rows()),mIsAreference(false) { mpData=new T[mNumElements]; T *p1=mpData; const T *p2=old.data(); for(long i=0;i CrystMatrix::~CrystMatrix() { if(!mIsAreference) { delete[] mpData; } } template void CrystMatrix::operator=(const CrystMatrix &old) { mXSize=old.cols(); mYSize=old.rows(); mIsAreference=false; if(mNumElements!=old.numElements()) { if(mIsAreference==false) { delete[] mpData ; } mNumElements=old.numElements(); mpData=new T[mNumElements]; } T *p1=mpData; const T *p2=old.data(); for(long i=0;i void CrystMatrix::reference(CrystMatrix &old) { if(mIsAreference==false) { delete[] mpData ; } mIsAreference=true; mNumElements=old.numElements(); mpData=old.data(); } template long CrystMatrix::numElements()const {return mNumElements;} template long CrystMatrix::size()const {return mNumElements;} template T CrystMatrix::sum()const { T tmp=0; const T *p=this->data(); for(long i=0;inumElements();i++) tmp += *p++ ; return tmp; } template T CrystMatrix::min()const { T tmp=0; const T *p=this->data(); tmp=*p++; for(long i=1;inumElements();i++) { if(tmp>*p) tmp=*p; p++; } return tmp; } template T CrystMatrix::max()const { T tmp=0; const T *p=this->data(); tmp=*p++; for(long i=1;inumElements();i++) { if(tmp<*p) tmp=*p; p++; } return tmp; } template long CrystMatrix::cols()const {return mXSize;} template long CrystMatrix::rows()const {return mYSize;} template T* CrystMatrix::data() {return mpData;} template const T* CrystMatrix::data() const {return mpData;} template void CrystMatrix::resize(const long ySize,const long xSize) { mXSize=xSize; mYSize=ySize; if(xSize*ySize == mNumElements) return; if(!mIsAreference) { delete[] mpData ; } mpData=0; mXSize=xSize; mYSize=ySize; mNumElements=xSize*ySize; if(mNumElements>0) { mpData=new T[mNumElements]; } } template void CrystMatrix::resizeAndPreserve(const long ySize,const long xSize) { mXSize=xSize; mYSize=ySize; if(xSize*ySize == mNumElements) return; T *p=mpData; T *p2,*p1; mpData=0; mpData=new T[xSize*ySize]; p2=mpData; p1=p; long tmp= ( (xSize*ySize) > mNumElements) ? mNumElements : xSize*ySize; for(long i=0;i void CrystMatrix::operator=(const T num) { T *p=mpData; for(int i=0;i void CrystMatrix::operator*=(const T num) { T *p=mpData; for(int i=0;i void CrystMatrix::operator*=(const CrystMatrix &vect) { #ifdef __DEBUG__ if( this->numElements() != vect.numElements()) { cout<<"CrystMatrix::operator*=(): Number of elements differ !"< void CrystMatrix::operator/=(const T num) { T *p=mpData; for(int i=0;i void CrystMatrix::operator+=(const T num) { T *p=mpData; for(int i=0;i void CrystMatrix::operator-=(const T num) { T *p=mpData; for(int i=0;i CrystMatrix CrystMatrix::Mult(const CrystMatrix &rhs) { if((this->cols()!=rhs.rows())||(this->rows()!=rhs.cols())) { //throw ObjCrystException("CrystMatrix::Mult(...): matrix sizes do not match !!"); } CrystMatrix mult(this->rows(),rhs.cols()); for(unsigned int r=0;rrows();r++) for(unsigned int c=0;rcols();i++) tmp+=(*this)(r,i)*rhs(i,c); mult(r,c)=tmp; } return mult; } template T CrystMatrix::operator()(const long i) const { #ifdef __DEBUG__ if( (i<0) || (i>=mNumElements)) { cout<<"CrystMatrix::operator()(i): element out of bounds !"< T CrystMatrix::operator()(const long i,const long j) const { #ifdef __DEBUG__ if( (i<0) || (j<0) || (i>=mYSize) || (j>=mXSize) ) { cout<<"CrystMatrix::operator()(i,j): element out of bounds:"< T& CrystMatrix::operator()(const long i) { #ifdef __DEBUG__ if( (i<0) || (i>=mNumElements)) { cout<<"CrystMatrix::operator()(i): element out of bounds !"< T& CrystMatrix::operator()(const long i,const long j) { #ifdef __DEBUG__ if( (i<0) || (j<0) || (i>=mYSize) || (j>=mXSize) ) { cout<<"CrystMatrix::operator()(i,j): element out of bounds:"< CrystMatrix CrystMatrix::transpose()const { CrystMatrix newM(this->cols(),this->rows()); for(long i=0;icols();i++) for(long j=0;jrows();j++) newM(i,j)=(*this)(j,i); return newM; } //###################################################################### // CrystArray3D //###################################################################### template CrystArray3D ::CrystArray3D(): mpData(0),mNumElements(0),mXSize(0),mYSize(0),mZSize(0),mIsAreference(false){} template CrystArray3D::CrystArray3D(const long zSize, const long ySize, const long xSize): mNumElements(xSize*ySize*zSize),mXSize(xSize),mYSize(ySize),mZSize(zSize), mIsAreference(false) { mpData=new T[mNumElements]; } template CrystArray3D::CrystArray3D(const CrystArray3D &old): mNumElements(old.numElements()), mXSize(old.cols()),mYSize(old.rows()),mZSize(old.depth()), mIsAreference(false) { mpData=new T[mNumElements]; T *p1=mpData; const T *p2=old.data(); for(long i=0;i CrystArray3D::~CrystArray3D() { if(!mIsAreference)delete[] mpData;} template void CrystArray3D::operator=(const CrystArray3D &old) { mXSize=old.cols(); mYSize=old.rows(); mZSize=old.depth(); mIsAreference=false; if(mNumElements!=old.numElements()) { mNumElements=old.numElements(); if(mIsAreference==false)delete[] mpData ; mpData=new T[mNumElements]; } T *p1=mpData; const T *p2=old.data(); for(long i=0;i void CrystArray3D::reference(CrystArray3D &old) { if(mIsAreference==false) delete[] mpData ; mIsAreference=true; mNumElements=old.numElements(); mpData=old.data(); } template long CrystArray3D::numElements()const{return mNumElements;} template long CrystArray3D::size()const{return mNumElements;} template T CrystArray3D::sum()const { T tmp=0; const T *p=this->data(); for(long i=0;inumElements();i++) tmp += *p++ ; return tmp; } template T CrystArray3D::min()const { T tmp=0; const T *p=this->data(); tmp=*p++; for(long i=1;inumElements();i++) { if(tmp>*p) tmp=*p; p++; } return tmp; } template T CrystArray3D::max()const { T tmp=0; const T *p=this->data(); tmp=*p++; for(long i=1;inumElements();i++) { if(tmp<*p) tmp=*p; p++; } return tmp; } template long CrystArray3D::cols()const {return mXSize;} template long CrystArray3D::rows()const {return mYSize;} template long CrystArray3D::depth()const {return mZSize;} template T* CrystArray3D::data() {return mpData;} template const T* CrystArray3D::data() const {return mpData;} template void CrystArray3D::resize(const long zSize, const long ySize, const long xSize) { mXSize=xSize; mYSize=ySize; mZSize=zSize; if(xSize*ySize*zSize == mNumElements) return; if(!mIsAreference)delete[] mpData ; mpData=0; mNumElements=xSize*ySize*zSize; if(mNumElements>0) mpData=new T[mNumElements]; } template void CrystArray3D::resizeAndPreserve(const long zSize, const long ySize, const long xSize) { mXSize=xSize; mYSize=ySize; mZSize=zSize; if(xSize*ySize*zSize == mNumElements) return; T *p=mpData; T *p2,*p1; mpData=new T[xSize*ySize*zSize]; p2=mpData; p1=p; long tmp= ( (xSize*ySize*zSize) > mNumElements) ? mNumElements : xSize*ySize*zSize; for(long i=0;i void CrystArray3D::operator=(const T num) { VFN_DEBUG_MESSAGE("CrystArray3D::operator=():"< void CrystArray3D::operator*=(const T num) { T *p=mpData; for(int i=0;i void CrystArray3D::operator*=(const CrystArray3D &vect) { #ifdef __DEBUG__ if( this->numElements() != vect.numElements()) { cout<<"CrystArray3D::operator*=(): Number of elements differ !"< void CrystArray3D::operator/=(const T num) { T *p=mpData; for(int i=0;i void CrystArray3D::operator+=(const T num) { T *p=mpData; for(int i=0;i void CrystArray3D::operator-=(const T num) { T *p=mpData; for(int i=0;i T CrystArray3D::operator()(const long i) const { #ifdef __DEBUG__ if( (i<0) || (i>=mNumElements)) { cout<<"CrystArray3D::operator()(i): element out of bounds !"< T CrystArray3D::operator()(const long i,const long j,const long k) const { #ifdef __DEBUG__ if( (i<0) || (j<0) || (k<0) || (i>=mZSize) || (j>=mYSize) || (k>=mXSize)) { cout<<"CrystArray3D::operator()(i,j,k): element out of bounds:"< T& CrystArray3D::operator()(const long i) { #ifdef __DEBUG__ if( (i<0) || (i>=mNumElements)) { cout<<"CrystArray3D::operator()(i): element out of bounds !"< T& CrystArray3D::operator()(const long i,const long j,const long k) { #ifdef __DEBUG__ if( (i<0) || (j<0) || (k<0) || (i>=mZSize) || (j>=mYSize) || (k>=mXSize)) { cout<<"CrystArray3D::operator()(i,j,k): element out of bounds:"< ostream& operator<<(ostream &os, const CrystMatrix &vect) { //return os << FormatHorizVector(vect); for(long i=0;i ostream& operator<<(ostream &os, const CrystArray3D &vect) { for(long i=0;i T MaxDifference(const CrystVector &a,const CrystVector &b) { const T *p1=a.data(); const T *p2=b.data(); REAL max=0; REAL tmp=0; for(long i=0;imax) max=tmp; } return (T)max; } template T MaxDifference(const CrystMatrix &a,const CrystMatrix &b) { const T *p1=a.data(); const T *p2=b.data(); T max=0; T tmp=0; for(long i=0;imax) max=tmp; } return max; } template CrystMatrix product(const CrystMatrix &a,const CrystMatrix &b) { VFN_DEBUG_ENTRY("CrystMatrix product()",2) //:TODO: check a.cols()==b.rows() CrystMatrix ab(a.rows(),b.cols()); for(long i=0;i product()",2) return ab; } //###################################################################### // explicit instantiation //###################################################################### template class CrystVector; template REAL MaxDifference(const CrystVector&,const CrystVector&); template ostream& operator<<(ostream &os, CrystVector &vect); template CrystVector SortSubs(const CrystVector &vect); template long QuickSortSubs(CrystVector &vect,CrystVector &subscript, long last,long first, int depth); template class CrystMatrix; template REAL MaxDifference(const CrystMatrix&,const CrystMatrix&); template CrystMatrix product(const CrystMatrix&,const CrystMatrix&); template ostream& operator<<(ostream &os, const CrystMatrix &vect); template CrystVector cos(const CrystVector&); template CrystVector sin(const CrystVector&); template CrystVector tan(const CrystVector&); template CrystVector sqrt(const CrystVector&); template class CrystArray3D; template ostream& operator<<(ostream &os, const CrystArray3D &vect); template class CrystVector; template long MaxDifference(const CrystVector&,const CrystVector&); template ostream& operator<<(ostream &os, CrystVector &vect); template CrystVector SortSubs(const CrystVector &vect); template long QuickSortSubs(CrystVector &vect,CrystVector &subscript, long last,long first, int depth); template class CrystMatrix; template long MaxDifference(const CrystMatrix&,const CrystMatrix&); template CrystMatrix product(const CrystMatrix&,const CrystMatrix&); template ostream& operator<<(ostream &os, const CrystMatrix &vect); template class CrystVector; template int MaxDifference(const CrystVector&,const CrystVector&); template ostream& operator<<(ostream &os, CrystVector &vect); template CrystVector SortSubs(const CrystVector &vect); template long QuickSortSubs(CrystVector &vect,CrystVector &subscript, long last,long first, int depth); template class CrystMatrix; template int MaxDifference(const CrystMatrix&,const CrystMatrix&); template CrystMatrix product(const CrystMatrix&,const CrystMatrix&); template ostream& operator<<(ostream &os, const CrystMatrix &vect); template class CrystVector; template unsigned int MaxDifference(const CrystVector&,const CrystVector&); template ostream& operator<<(ostream &os, CrystVector &vect); template CrystVector SortSubs(const CrystVector &vect); template long QuickSortSubs(CrystVector &vect,CrystVector &subscript, long last,long first, int depth); template class CrystMatrix; template unsigned int MaxDifference(const CrystMatrix&,const CrystMatrix&); template CrystMatrix product(const CrystMatrix&,const CrystMatrix&); template ostream& operator<<(ostream &os, const CrystMatrix &vect); template class CrystVector; template ostream& operator<<(ostream &os, CrystVector &vect); template class CrystMatrix; template bool MaxDifference(const CrystMatrix&,const CrystMatrix&); template ostream& operator<<(ostream &os, const CrystMatrix &vect); #endif // __LIBCRYST_VECTOR_USE_BLITZ__ //###################################################################### // Functions //###################################################################### CrystMatrix_REAL InvertMatrix(const CrystMatrix_REAL &m) {//:TODO: Check Pivoting... VFN_DEBUG_ENTRY("InvertMatrix()",2) VFN_DEBUG_MESSAGE("->Matrix to invert :"< max) { max=fabs(m(j,i)); rowMax=j; } //Check if pivot is non-singular :TODO: /* if(max < eps) { throw i; } */ } //pivot if(rowMax != i) { //cout << "Exchanging rows: "<< i << " and " << rowMax <=0;j--) { a=cm(j,i)/cm(i,i); for(long k=0;kInverted Matrix :"< void MatrixExchangeRows(CrystMatrix_T &m, const long row1, const long row2) { //cout << "Exchanging rows:begin" < T MaxAbs(const CrystVector_T &vector) { const T* pData=vector.data(); T max =(T) fabs((REAL) *pData++); for(long i=1;i max) max=(T) fabs((REAL) *pData); pData++; } return max; } //Explicit instatiation template REAL MaxAbs(const CrystVector_REAL &vector); template int MaxAbs(const CrystVector_int &vector); template unsigned int MaxAbs(const CrystVector_uint &vector); template long MaxAbs(const CrystVector_long &vector); template T MinAbs(const CrystVector_T &vector) { const T* pData=vector.data(); T min =(T) fabs((REAL) *pData++); for(long i=1;iInit(x,y,yp0,ypn); } CubicSpline::CubicSpline(const REAL *px, const REAL *py, const unsigned long nbPoints, const REAL yp0, const REAL ypn) { this->Init(px,py,nbPoints,yp0,ypn); } CubicSpline::CubicSpline(const CrystVector_REAL &x, const CrystVector_REAL &y) { this->Init(x,y); } CubicSpline::CubicSpline(const REAL *px, const REAL *py, const unsigned long nbPoints) { this->Init(px,py,nbPoints); } void CubicSpline::Init(const CrystVector_REAL &x, const CrystVector_REAL &y, const REAL yp0, const REAL ypn) { VFN_DEBUG_ENTRY("CubicSpline::Init(x,y,yp0,ypn)",5) mX=x; mY=y; mYsecond.resize(x.numElements()); this->InitSpline(yp0,ypn); VFN_DEBUG_EXIT("CubicSpline::Init(x,y,yp0,ypn)",5) } void CubicSpline::Init(const REAL *px, const REAL *py, const unsigned long nbPoints, const REAL yp0, const REAL ypn) { VFN_DEBUG_ENTRY("CubicSpline::Init(px,py,yp0,ypn)",5) mX.resize(nbPoints); mY.resize(nbPoints); mYsecond.resize(nbPoints); for(unsigned long i=0;iInitSpline(yp0,ypn); VFN_DEBUG_EXIT("CubicSpline::Init(x,y,yp0,ypn)",5) } void CubicSpline::Init(const CrystVector_REAL &x, const CrystVector_REAL &y) { VFN_DEBUG_ENTRY("CubicSpline::Init(x,y)",5) mX=x; mY=y; mYsecond.resize(x.numElements()); this->InitNaturalSpline(); VFN_DEBUG_EXIT("CubicSpline::Init(x,y)",5) } void CubicSpline::Init(const REAL *px, const REAL *py, const unsigned long nbPoints) { VFN_DEBUG_ENTRY("CubicSpline::Init(px,py,n)",5) mX.resize(nbPoints); mY.resize(nbPoints); mYsecond.resize(nbPoints); for(unsigned long i=0;iInitNaturalSpline(); VFN_DEBUG_EXIT("CubicSpline::Init(x,y,n)",5) } CubicSpline::~CubicSpline() { } REAL CubicSpline::operator()(const REAL x) const { //:TODO: faster! //:TODO: take into account beginning and end derivatives for out-of-bounds points long i; if(x=0;i--) mYsecond(i)=mYsecond(i)*mYsecond(i+1)+u(i); } void CubicSpline::InitNaturalSpline() { const long n=mX.numElements(); CrystVector_REAL u(mX.numElements()); mYsecond(0)=0; u(0)=0; REAL a,b; for(long i=1;i<=(n-2);i++) { a=(mX(i)-mX(i-1))/(mX(i+1)-mX(i-1)); b=a*mYsecond(i-1)+2; mYsecond(i)=(a-1)/b; u(i)=(6*((mY(i+1)-mY(i))/(mX(i+1)-mX(i))-(mY(i)-mY(i-1))/(mX(i)-mX(i-1))) /(mX(i+1)-mX(i-1))-a*u(i-1))/b; } mYsecond(n-1)=0; for(long i=(n-2);i>=0;i--) mYsecond(i)=mYsecond(i)*mYsecond(i+1)+u(i); } //###################################################################### // Savitzky-Golay interpolation //###################################################################### // Coefficients for smoothing (deriv=0) - is there a general formula for these ? REAL sgcoeffs_0_5[]={-0.08571429, 0.34285714, 0.48571429, 0.34285714, -0.08571429}; REAL sgcoeffs_0_7[]={-0.0952381 , 0.14285714, 0.28571429, 0.33333333, 0.28571429, 0.14285714, -0.0952381}; REAL sgcoeffs_0_9[]={-0.09090909, 0.06060606, 0.16883117, 0.23376623, 0.25541126, 0.23376623, 0.16883117, 0.06060606, -0.09090909}; REAL sgcoeffs_0_11[]={-0.08391608, 0.02097902, 0.1025641 , 0.16083916, 0.1958042 , 0.20745921, 0.1958042 , 0.16083916, 0.1025641 , 0.02097902, -0.08391608}; REAL sgcoeffs_0_13[]={-7.69230769e-02, 1.73472348e-18, 6.29370629e-02, 1.11888112e-01, 1.46853147e-01, 1.67832168e-01, 1.74825175e-01, 1.67832168e-01, 1.46853147e-01, 1.11888112e-01, 6.29370629e-02, 1.73472348e-18, -7.69230769e-02}; REAL sgcoeffs_0_15[]={-0.07058824, -0.01176471, 0.03800905, 0.07873303, 0.11040724, 0.13303167, 0.14660633, 0.15113122, 0.14660633, 0.13303167, 0.11040724, 0.07873303, 0.03800905, -0.01176471, -0.07058824}; REAL sgcoeffs_0_17[]={-0.06501548, -0.01857585, 0.02167183, 0.05572755, 0.08359133, 0.10526316, 0.12074303, 0.13003096, 0.13312693, 0.13003096, 0.12074303, 0.10526316, 0.08359133, 0.05572755, 0.02167183, -0.01857585, -0.06501548}; REAL sgcoeffs_0_19[]={-0.06015038, -0.02255639, 0.01061477, 0.03936311, 0.06368863, 0.08359133, 0.09907121, 0.11012826, 0.11676249, 0.11897391, 0.11676249, 0.11012826, 0.09907121, 0.08359133, 0.06368863, 0.03936311, 0.01061477, -0.02255639, -0.06015038}; REAL sgcoeffs_0_21[]={-0.05590062, -0.02484472, 0.00294214, 0.02745995, 0.04870873, 0.06668846, 0.08139915, 0.0928408 , 0.1010134 , 0.10591697, 0.10755149, 0.10591697, 0.1010134 , 0.0928408 , 0.08139915, 0.06668846, 0.04870873, 0.02745995, 0.00294214, -0.02484472, -0.05590062}; REAL sgcoeffs_0_23[]={-0.05217391, -0.02608696, -0.00248447, 0.01863354, 0.03726708, 0.05341615, 0.06708075, 0.07826087, 0.08695652, 0.0931677 , 0.09689441, 0.09813665, 0.09689441, 0.0931677 , 0.08695652, 0.07826087, 0.06708075, 0.05341615, 0.03726708, 0.01863354, -0.00248447, -0.02608696, -0.05217391}; CrystVector_REAL SavitzkyGolay(const CrystVector_REAL &v, const unsigned int um, const unsigned int deriv) { const int m=(int)um; REAL *sgcoeffs=0; if(deriv==0) { if(m==2)sgcoeffs=sgcoeffs_0_5; if(m==3)sgcoeffs=sgcoeffs_0_7; if(m==4)sgcoeffs=sgcoeffs_0_9; if(m==5)sgcoeffs=sgcoeffs_0_11; if(m==6)sgcoeffs=sgcoeffs_0_13; if(m==7)sgcoeffs=sgcoeffs_0_15; if(m==8)sgcoeffs=sgcoeffs_0_17; if(m==9)sgcoeffs=sgcoeffs_0_19; if(m==10)sgcoeffs=sgcoeffs_0_21; if(m==11)sgcoeffs=sgcoeffs_0_23; } if(deriv==1) { sgcoeffs=new REAL[2*m+1]; REAL *p=sgcoeffs; const REAL f=3/(REAL) (m*(m+1)*(2*m+1)); for(int j=-m;j<=m;++j) *p++ = f*j; } if(deriv==2) { sgcoeffs=new REAL[2*m+1]; REAL *p=sgcoeffs; const REAL f1=45/(REAL) (m*(m+1)*(2*m+1)*(4*m*(m+1)-3)); const REAL f2=-15/(REAL) ((2*m+1)*(4*m*(m+1)-3)); for(int j=-m;j<=m;++j) *p++ = f1*j*j + f2; } //cout<<__FILE__<<":"<<__LINE__<<"Savitzky-Golay coeeficients(m="< using namespace blitz; //Still use pointers for the Geometrical Structure computation ? //(due to the complexity of the formulas, a blitz coding requires //to much memory when compiling) #define __VFN_GEOM_STRUCT_FACTOR_USE_POINTERS #define CrystVector_REAL Array #define CrystVector_float Array #define CrystVector_long Array #define CrystVector_int Array #define CrystVector_uint Array #define CrystVector_bool Array #define CrystMatrix_REAL Array #define CrystMatrix_float Array #define CrystMatrix_long Array #define CrystMatrix_int Array #define CrystMatrix_uint Array #define CrystMatrix_bool Array #define CrystVector_T Array #define CrystMatrix_T Array #define CrystArray3D_T Array template T MaxDifference(const Array &a,const Array &b); template T MaxDifference(const Array &a,const Array &b); #else // __VFN_VECTOR_USE_BLITZ__ #define CrystVector_REAL CrystVector #define CrystVector_double CrystVector #define CrystVector_float CrystVector #define CrystVector_long CrystVector #define CrystVector_int CrystVector #define CrystVector_uint CrystVector #define CrystVector_bool CrystVector #define CrystMatrix_REAL CrystMatrix #define CrystMatrix_double CrystMatrix #define CrystMatrix_float CrystMatrix #define CrystMatrix_long CrystMatrix #define CrystMatrix_int CrystMatrix #define CrystMatrix_uint CrystMatrix #define CrystMatrix_bool CrystMatrix #define CrystArray3D_REAL CrystArray3D #define CrystVector_T CrystVector #define CrystMatrix_T CrystMatrix #define CrystArray3D_T CrystMatrix #define __VFN_GEOM_STRUCT_FACTOR_USE_POINTERS #include #include using namespace std; #ifdef _MSC_VER // MS VC++ predefined macros.... #undef min #undef max #endif //###################################################################### // CrystVector //###################################################################### /** \brief Vector library (Blitz++ mimic) for ObjCryst++ * * The CrystVector library is not a new array computation library, despite * the appearances. ObjCryst++ should used the * Blitz++ array library , which yields * excellent performance \e and simple array expressions. Unfortunately, the memory * required to \e compile the library using gcc is far too high to be reasonable * when using complex expressions and optimizing code. So until this has changed, * The CrystVector and CrystMatrix library have been created, and these emulate * (supposedly exactly) the Blitz++ interface (but not the smart handling of * mathematical expressions, so pointers must be used). For documentation about these * two libraries you should read the * Blitz++ documentation. CrystVector and CrystMatrix use the same kind of storage * in memory. * * You can use CrystVector_REAL, CrystVector_long,etc... to declare 1D vectors. Macros * ensure (well, should) ensure compatibility with Blitz++. (as of april 2001 support of * blitz++ is broken). * * \todo check again Blitz++ support in newer gcc versions. */ template class CrystVector { public: CrystVector(); CrystVector(const long nbElements); CrystVector(const CrystVector &old); ~CrystVector(); void operator=(const CrystVector &old); template void operator=(const CrystVector &old) { if(mNumElements != old.numElements()) { mNumElements = old.numElements(); delete[] mpData; mpData=new T[mNumElements]; }; mIsAreference=false; T *p1=mpData; const U *p2=old.data(); for(long i=0;i() const { CrystVector vect; vect=*this; return vect; } operator CrystVector() const { CrystVector vect; vect=*this; return vect; } operator CrystVector() const { CrystVector vect; vect=*this; return vect; } operator CrystVector() const { CrystVector vect; vect=*this; return vect; } operator CrystVector() const { CrystVector vect; vect=*this; return vect; } #else template operator CrystVector() const { CrystVector vect; vect=*this; return vect; } #endif /** Define this vector as a reference to another vector, or part of another vector * * \param old: the vector this one should point to * \param imin,imax: imax>imin, this vector will point to a part of the other * vector, from old(i) to old(imax-1) */ void reference(CrystVector &old, const long imin=0, const long imax=0); long numElements()const; long size()const; T sum()const; T min()const; T max()const; /// Find index of minimum, between start and end (if start==end, use full vector) unsigned long imin(const unsigned long start=0,const unsigned long finish=0)const; /// Find index of maximum, between start and end (if start==end, use full vector) unsigned long imax(const unsigned long start=0,const unsigned long finish=0)const; T * data(); const T * data() const; void resize(const long newNbElements); void resizeAndPreserve(const long newNbElements); void operator*=(const T num); void operator*=(const CrystVector &vect); void operator/=(const T num); void operator/=(const CrystVector &vect); void operator+=(const T num); void operator+=(const CrystVector &vect); void operator-=(const CrystVector &vect); /* Buggy ? (my version, not Blitz's!) // ListInitializer & ListInitializerSwitch are a simplified //version borrowed from the blitz++ library (see the blitz/listinit.h file) // // It allows a very convenient way of initializing arrays like this: // CrystVector arr(5); arr = 1,3,6,8,9; class ListInitializer { public: ListInitializer(T *pData):mpData(pData){}; ~ListInitializer(){cout << "toto";}; ListInitializer operator,(T x) { *mpData=x; return ListInitializer(mpData+1); } private: ListInitializer(){}; T *mpData; }; class ListInitializerSwitch { public: ListInitializerSwitch(CrystVector &vect, const T value): mVectData(vect.data()),mValue(value), mNumElements(vect.numElements()),wipeOnDestruct(true) {}; ~ListInitializerSwitch() { if(wipeOnDestruct) { //only one value given -> set all elements for(int i=0;i ostream& operator<<(ostream &os, CrystVector &vect); //Return the sorted subscripts of the array template CrystVector SortSubs(const CrystVector &vect); //Sort the array in place and also return the sorted subscripts template long QuickSortSubs(CrystVector &vect, CrystVector &subscript, long last,long first=0, int depth=0); ///Cosinus (slow routine, not memory-savy..) template CrystVector cos(const CrystVector &vect); ///Sinus (slow routine, not memory-savy...) template CrystVector sin(const CrystVector &vect); ///Tangent (slow routine, not memory-savy...) template CrystVector tan(const CrystVector &vect); ///Square root (slow routine, not memory-savy...) template CrystVector sqrt(const CrystVector &vect); //###################################################################### // CrystMatrix //###################################################################### /** \brief 2D Vector library (Blitz++ mimic) for ObjCryst++ * * The CrystVector library is not a new array computation library, despite * the appearances. ObjCryst++ should used the * Blitz++ array library , which yields * excellent performance \e and simple array expressions. Unfortunately, the memory * required to \e compile the library using gcc is far too high to be reasonable * when using complex expressions and optimizing code. So until this has changed, * The CrystVector and CrystMatrix library have been created, and these emulate * (supposedly exactly) the Blitz++ interface (but not the smart handling of * mathematical expressions, so pointers must be used). For documentation about these * two libraries you should read the * Blitz++ documentation. CrystVector and CrystMatrix use the same kind of storage * in memory. * * You can use CrystMatrix_REAL, CrystMatrix_long,etc... to declare 2D vectors. Macros * ensure (well, should) ensure compatibility with Blitz++. (as of april 2001 support of * blitz++ is broken). */ template class CrystMatrix { public: CrystMatrix(); //ySize : number of rows, xSize : number of columns CrystMatrix(const long ySize,const long xSize); CrystMatrix(const CrystMatrix &old); ~CrystMatrix(); void operator=(const CrystMatrix &old); void reference(CrystMatrix &old); long numElements()const; long size()const; T sum()const; T min()const; T max()const; long rows()const; long cols()const; T * data(); const T * data() const; void resize(const long ySize,const long xSize); void resizeAndPreserve(const long ySize,const long xSize); //void operator=(const T num); /// Element-by element multiplication (array-like) void operator*=(const T num); /// Element-by element multiplication (array-like) void operator*=(const CrystMatrix &vect); /// Element-by element division (array-like) void operator/=(const T num); /// Element-by element addition (array-like) void operator+=(const T num); /// Element-by element substraction (array-like) void operator-=(const T num); /// matrix multiplication (linear algebra) CrystMatrix Mult(const CrystMatrix &rhs); //:TODO: Check the following... // ListInitializer & ListInitializerSwitch are a simplified //version borrowed from the blitz++ library (see the blitz/listinit.h file) // // It allows a very convenient way of initializing arrays like this: // CrystVector arr(5); arr = 1,3,6,8,9; class ListInitializer { public: ListInitializer(T *pData):mpData(pData){}; ~ListInitializer(){}; ListInitializer operator,(T x) { *mpData=x; return ListInitializer(mpData+1); } private: ListInitializer(){}; T *mpData; }; class ListInitializerSwitch { public: ListInitializerSwitch(CrystMatrix &vect, const T value): mVectData(vect.data()),mValue(value), mNumElements(vect.numElements()),wipeOnDestruct(true) {}; ~ListInitializerSwitch() { if(wipeOnDestruct) { //only one value given -> set all elements for(int i=0;i ostream& operator<<(ostream &os, const CrystMatrix &vect); template T MaxDifference(const CrystVector &a,const CrystVector &b); template T MaxDifference(const CrystMatrix &a,const CrystMatrix &b); template CrystMatrix product(const CrystMatrix &a,const CrystMatrix &b); //###################################################################### // CrystArray3D //###################################################################### /** \brief 3D Vector (Blitz++ mimic) for ObjCryst++ * * The CrystVector library is not a new array computation library, despite * the appearances. ObjCryst++ should used the * Blitz++ array library , which yields * excellent performance \e and simple array expressions. Unfortunately, the memory * required to \e compile the library using gcc is far too high to be reasonable * when using complex expressions and optimizing code. So until this has changed, * The CrystVector and CrystMatrix library have been created, and these emulate * (supposedly exactly) the Blitz++ interface (but not the smart handling of * mathematical expressions, so pointers must be used). For documentation about these * two libraries you should read the * Blitz++ documentation. CrystVector and CrystMatrix use the same kind of storage * in memory. * * You can use CrystArray3D_REAL, CrystArray3D_long,etc... to declare 3D vectors. Macros * ensure (well, should) ensure compatibility with Blitz++. (as of april 2001 support of * blitz++ is broken). */ template class CrystArray3D { public: CrystArray3D(); //ySize : number of rows, xSize : number of columns CrystArray3D(const long zSize,const long ySize,const long xSize); CrystArray3D(const CrystArray3D &old); ~CrystArray3D(); void operator=(const CrystArray3D &old); void reference(CrystArray3D &old); long numElements()const; long size()const; T sum()const; T min()const; T max()const; long rows()const; long cols()const; long depth()const; T * data(); const T * data() const; void resize(const long zSize,const long ySize,const long xSize); void resizeAndPreserve(const long zSize,const long ySize,const long xSize); void operator=(const T num); void operator*=(const T num); void operator*=(const CrystArray3D &vect); void operator/=(const T num); void operator+=(const T num); void operator-=(const T num); //void operator=(const T num); T operator()(const long i) const; T operator()(const long depth,const long row,const long col) const; T& operator()(const long i); T& operator()(const long depth,const long row,const long col); protected: private: T *mpData; long mNumElements; long mXSize,mYSize,mZSize; bool mIsAreference;//is a reference to another vector ? }; template ostream& operator<<(ostream &os, const CrystArray3D &vect); #endif // __LIBCRYST_VECTOR_USE_BLITZ__ //Basic Gauss-Jordan elimination with partial pivot (rows only, using max pivot) //Definitly *not* optimized ! CrystMatrix_REAL InvertMatrix(const CrystMatrix_REAL &m); template void MatrixExchangeRows(CrystMatrix_T &m, const long row1, const long row2); ///Maximum absolute value of vector template T MaxAbs(const CrystVector_T &vector); ///Minimum absolute value of vector template T MinAbs(const CrystVector_T &vector); //###################################################################### // CubicSpline //###################################################################### /// Cubic spline interpolation. class CubicSpline { public: /// Default constructor - CubicSpline::Init() should be called afterwards CubicSpline(); /// Spline with given extremum derivatives CubicSpline(const CrystVector_REAL &x, const CrystVector_REAL &y, const REAL yp1, const REAL ypn); /// Spline with given extremum derivatives CubicSpline(const REAL *px, const REAL *py, const unsigned long nbPoints, const REAL yp1, const REAL ypn); /// Natural cubic spline CubicSpline(const CrystVector_REAL &x, const CrystVector_REAL &y); /// Natural cubic spline CubicSpline(const REAL *px, const REAL *py, const unsigned long nbPoints); ~CubicSpline(); /// Spline with given extremum derivatives void Init(const CrystVector_REAL &x, const CrystVector_REAL &y, const REAL yp1, const REAL ypn); /// Spline with given extremum derivatives void Init(const REAL *px, const REAL *py, const unsigned long nbPoints, const REAL yp1, const REAL ypn); /// Natural cubic spline void Init(const CrystVector_REAL &x, const CrystVector_REAL &y); /// Natural cubic spline void Init(const REAL *px, const REAL *py, const unsigned long nbPoints); /// Get spline value at a series of point - x is assumed to be sorted by increasing values CrystVector_REAL operator()(const CrystVector_REAL &x) const; /// Get spline value on a range of values with a fixed step CrystVector_REAL operator()(const REAL min,const REAL step, const long nbpoint) const; /// Get spline value at one point REAL operator()(const REAL x) const; private: void InitSpline(const REAL yp1, const REAL ypn); void InitNaturalSpline(); CrystVector_REAL mX; CrystVector_REAL mY; CrystVector_REAL mYsecond; }; //###################################################################### // Savitzky-Golay interpolation //###################################################################### /** Savitzky-Golay computing of smoothed data, using 2nd order polynomial coefficients * */ CrystVector_REAL SavitzkyGolay(const CrystVector_REAL &v, const unsigned int m, const unsigned int deriv); #endif // __LIBCRYST_VECTOR_H objcryst-2022.1/ObjCryst/CrystVector/bc32.mak000066400000000000000000000002261430515525000207100ustar00rootroot00000000000000!include ..\rules.mak libCrystVector.lib : CrystVector.obj tlib "libCrystVector.lib" -+CrystVector lib: libCrystVector.lib default: lib all: lib objcryst-2022.1/ObjCryst/CrystVector/gnu.mak000066400000000000000000000017461430515525000207600ustar00rootroot00000000000000BUILD_DIR=$(CURDIR)/../.. include $(BUILD_DIR)/ObjCryst/rules.mak ##Using blitz library ?? ##Make it (in blitz dir) using : ./configure --with-cxx=gcc --enable-optimize ##and then : make lib #ifeq (${VFNVECTOR_USE_BLITZ},1) # C_BLITZFLAG := -D__VFN_VECTOR_USE_BLITZ__ # AR_BLITZ := ${DIR_BLITZ}/lib/libblitz.a #else C_BLITZFLAG := AR_BLITZ := #endif OBJ=CrystVector.o ifeq ($(profile),2) %.o : %.cpp @rm -f $(*F).gcda $(*F).gcno @$(MAKEDEPEND) ${CXX} ${CPPFLAGS} ${CXXFLAGS} -c $< -o $@ else %.o : %.cpp @$(MAKEDEPEND) ${CXX} ${CPPFLAGS} ${CXXFLAGS} -c $< -o $@ endif -include $(OBJ:.o=.dep) libCrystVector.a : ${OBJ} ${AR} crs $@ ${AR_BLITZ} ${filter-out %.a %.so, $^} lib: libCrystVector.a dep: makedepend *.cpp -Y -I. -I../ default: lib # target for removing all object files .PHONY : tidy tidy:: @${RM} core *.o *.dep # target for removing all object files and libraries .PHONY : clean clean:: tidy @${RM} *.a *.exe cvsignore: cp -f ${DIR_CRYST}/.cvsignore ./ objcryst-2022.1/ObjCryst/CrystVector/vc.mak000066400000000000000000000002321430515525000205640ustar00rootroot00000000000000!include ..\rules.mak libCrystVector.lib : CrystVector.obj lib -OUT:libCrystVector.lib CrystVector.obj lib: libCrystVector.lib default: lib all: lib objcryst-2022.1/ObjCryst/ObjCryst/000077500000000000000000000000001430515525000167355ustar00rootroot00000000000000objcryst-2022.1/ObjCryst/ObjCryst/.cvsignore000066400000000000000000000001771430515525000207420ustar00rootroot00000000000000*.o *.exe *.out *.old *.dep *.a .directory .systemG.Desktop tags html latex *.oxy *.xml profile.0.0.0 *.pov Makefile rules.mak objcryst-2022.1/ObjCryst/ObjCryst/Atom.cpp000066400000000000000000000455151430515525000203530ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Atom.cpp * source file for the Atom scatterer * */ #include #include #include //for sprintf() #include "ObjCryst/ObjCryst/Atom.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" //simple formatting of integers, REALs.. #include "ObjCryst/Quirks/VFNDebug.h" #ifdef OBJCRYST_GL #ifdef __DARWIN__ #include #else #include #endif #endif #ifdef __WX__CRYST__ #include "ObjCryst/wxCryst/wxAtom.h" #endif #include #include namespace ObjCryst { //////////////////////////////////////////////////////////////////////// // // ATOM : the basic atom, within the crystal // //includes thermic factor (betas) and x,y,z,population // //////////////////////////////////////////////////////////////////////// Atom::Atom() :mScattCompList(1),mpScattPowAtom(0) { VFN_DEBUG_MESSAGE("Atom::Atom()",5) this->InitRefParList(); mScattCompList(0).mpScattPow=mpScattPowAtom; } Atom::Atom( const REAL x, const REAL y, const REAL z, const string &name,const ScatteringPower *pow) :mScattCompList(1),mpScattPowAtom(pow) { VFN_DEBUG_MESSAGE("Atom::Atom(x,y,z,name,ScatteringPower):"<Init(x,y,z,name,pow,1); } Atom::Atom( const REAL x, const REAL y, const REAL z, const string &name, const ScatteringPower *pow,const REAL popu) :mScattCompList(1),mpScattPowAtom(pow) { VFN_DEBUG_MESSAGE("Atom::Atom(x,y,z,P,B,name,ScatteringPower):"<Init(x,y,z,name,mpScattPowAtom,popu); } Atom::Atom(const Atom &old) :Scatterer(old),mScattCompList(1),mpScattPowAtom(old.mpScattPowAtom) { VFN_DEBUG_MESSAGE("Atom::Atom(&old):/Name="<Init(old.mXYZ(0),old.mXYZ(1),old.mXYZ(2), old.mName,mpScattPowAtom, old.mOccupancy); this->GetPar(mXYZ.data()). CopyAttributes(old.GetPar(old.mXYZ.data())); this->GetPar(mXYZ.data()+1).CopyAttributes(old.GetPar(old.mXYZ.data()+1)); this->GetPar(mXYZ.data()+2).CopyAttributes(old.GetPar(old.mXYZ.data()+2)); this->GetPar(&mOccupancy). CopyAttributes(old.GetPar(&(old.mOccupancy))); } Atom* Atom::CreateCopy() const { VFN_DEBUG_MESSAGE("Atom::CreateCopy():/Name="<DeRegisterClient(*this); } const string& Atom::GetClassName()const { const static string className="Atom"; return className; } void Atom::operator=(const Atom &rhs) { VFN_DEBUG_MESSAGE("Atom::operator=():/Name="<Init(rhs.mXYZ(0),rhs.mXYZ(1),rhs.mXYZ(2), rhs.mName,rhs.mpScattPowAtom, rhs.mOccupancy); this->GetPar(mXYZ.data()). CopyAttributes(rhs.GetPar(rhs.mXYZ.data())); this->GetPar(mXYZ.data()+1).CopyAttributes(rhs.GetPar(rhs.mXYZ.data()+1)); this->GetPar(mXYZ.data()+2).CopyAttributes(rhs.GetPar(rhs.mXYZ.data()+2)); this->GetPar(&mOccupancy). CopyAttributes(rhs.GetPar(&(rhs.mOccupancy))); } void Atom::Init(const REAL x, const REAL y, const REAL z, const string &name, const ScatteringPower *pow, const REAL popu) { VFN_DEBUG_MESSAGE("Atom::Init():"<GetName();} void Atom::Print() const { VFN_DEBUG_MESSAGE("Atom::Print()",1) if(this->IsDummy()) { cout << "Atom (DUMMY) :" << FormatString(this->GetName(),16) << " at : " << FormatFloat(this->GetX()) << FormatFloat(this->GetY()) << FormatFloat(this->GetZ()); } else { cout << "Atom (" << FormatString(mpScattPowAtom->GetSymbol(),4) << ") :" << FormatString(this->GetName(),16) << " at : " << FormatFloat(this->GetX()) << FormatFloat(this->GetY()) << FormatFloat(this->GetZ()) << ", Biso=" << FormatFloat(mpScattPowAtom->GetBiso()) << ", Popu=" << FormatFloat(this->GetOccupancy()); } cout << endl; } REAL Atom::GetMass() const { if(true==this->IsDummy()) return 0; return mpScattPowAtom->GetBiso(); } REAL Atom::GetRadius() const { if(this->IsDummy()) return 0.5; return mpScattPowAtom->GetRadius(); } ostream& Atom::POVRayDescription(ostream &os, const CrystalPOVRayOptions &options)const { if(this->IsDummy()) return os; if(options.mShowHydrogens==false && (mpScattPowAtom->GetForwardScatteringFactor(RAD_XRAY)<1.5)) return os; const REAL xMin=options.mXmin; const REAL xMax=options.mXmax; const REAL yMin=options.mYmin; const REAL yMax=options.mYmax; const REAL zMin=options.mZmin; const REAL zMax=options.mZmax; REAL x0,y0,z0; x0=mXYZ(0); y0=mXYZ(1); z0=mXYZ(2); const REAL aa=this->GetCrystal().GetLatticePar(0); const REAL bb=this->GetCrystal().GetLatticePar(1); const REAL cc=this->GetCrystal().GetLatticePar(2); CrystMatrix_REAL xyzCoords ; xyzCoords=this->GetCrystal().GetSpaceGroup().GetAllSymmetrics(x0,y0,z0,false,false,true); int nbSymmetrics=xyzCoords.rows(); os << "// Description of Atom :" << this->GetName()<< endl; for(int i=0;i=xMin) && (x<=xMax)) && ((y>=yMin) && (y<=yMax)) && ((z>=zMin) && (z<=zMax)); REAL borderdist; if(isinside) borderdist=0; else { borderdist=0; if(xMin>x) borderdist+=(xMin-x)*aa*(xMin-x)*aa; if(yMin>y) borderdist+=(yMin-y)*bb*(yMin-y)*bb; if(zMin>z) borderdist+=(zMin-z)*cc*(zMin-z)*cc; if(xMaxGetCrystal().GetDynPopCorr(this,0); if(fout>0.001) { this->GetCrystal().FractionalToOrthonormalCoords(x,y,z); os << " ObjCrystAtom(" <GetScatteringPower().GetRadius()/3.0<<"," <<"colour_"+this->GetScatteringPower().GetName()<<"," <GetOccupancy()<<","<GetName(),5) if(this->IsDummy()) return ; REAL en=1; if(displayEnantiomer==true) en=-1; const float r=mpScattPowAtom->GetColourRGB()[0]; const float g=mpScattPowAtom->GetColourRGB()[1]; const float b=mpScattPowAtom->GetColourRGB()[2]; const float f=mOccupancy; const GLfloat colour0[] = {.0, .0, .0, 0.0}; GLfloat colourChar [] = {1.0, 1.0, 1.0, 1.0}; if((r>0.8)&&(g>0.8)&&(b>0.8)) { colourChar[0] = 0.5; colourChar[1] = 0.5; colourChar[2] = 0.5; } const REAL aa=this->GetCrystal().GetLatticePar(0); const REAL bb=this->GetCrystal().GetLatticePar(1); const REAL cc=this->GetCrystal().GetLatticePar(2); if(hideHydrogens && (mpScattPowAtom->GetForwardScatteringFactor(RAD_XRAY)<1.5)) return; GLUquadricObj* pQuadric = gluNewQuadric(); if(true==onlyIndependentAtoms) { const GLfloat colourAtom [] = {r, g, b, f}; REAL x,y,z; x=mXYZ(0); y=mXYZ(1); z=mXYZ(2); x = fmod((REAL)x,(int)1); if(x<0) x+=1.; y = fmod((REAL)y,(int)1); if(y<0) y+=1.; z = fmod((REAL)z,(int)1); if(z<0) z+=1.; this->GetCrystal().FractionalToOrthonormalCoords(x,y,z); glPushMatrix(); glTranslatef(x*en, y, z); if(displayNames) { glMaterialfv(GL_FRONT, GL_AMBIENT, colour0); glMaterialfv(GL_FRONT, GL_DIFFUSE, colour0); glMaterialfv(GL_FRONT, GL_SPECULAR, colour0); glMaterialfv(GL_FRONT, GL_EMISSION, colourChar); glMaterialfv(GL_FRONT, GL_SHININESS, colour0); glRasterPos3f(0,0,0); crystGLPrint(this->GetName()); } else { glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, colourAtom); glMaterialfv(GL_FRONT, GL_SPECULAR, colour0); glMaterialfv(GL_FRONT, GL_EMISSION, colour0); glMaterialfv(GL_FRONT, GL_SHININESS, colour0); glPolygonMode(GL_FRONT, GL_FILL); gluSphere(pQuadric,this->GetRadius()/3.,20,20); } glPopMatrix(); } else { REAL x0,y0,z0; x0=mXYZ(0); y0=mXYZ(1); z0=mXYZ(2); CrystMatrix_REAL xyzCoords ; xyzCoords=this->GetCrystal().GetSpaceGroup().GetAllSymmetrics(x0,y0,z0,false,false,true); int nbSymmetrics=xyzCoords.rows(); for(int i=0;i=xMin) && (x<=xMax)) && ((y>=yMin) && (y<=yMax)) && ((z>=zMin) && (z<=zMax)); REAL borderdist; if(isinside) borderdist=0; else { borderdist=0; if(xMin>x) borderdist+=(xMin-x)*aa*(xMin-x)*aa; if(yMin>y) borderdist+=(yMin-y)*bb*(yMin-y)*bb; if(zMin>z) borderdist+=(zMin-z)*cc*(zMin-z)*cc; if(xMaxfadeDistance) fout = 0; else fout*=(fadeDistance-borderdist)/fadeDistance*this->GetCrystal().GetDynPopCorr(this,0); } if(fout>0.01) { const GLfloat colourAtom [] = {r, g, b, f*fout}; this->GetCrystal().FractionalToOrthonormalCoords(x,y,z); glPushMatrix(); glTranslatef(x*en, y, z); if(displayNames) { if(fout>0.99) { glMaterialfv(GL_FRONT, GL_AMBIENT, colour0); glMaterialfv(GL_FRONT, GL_DIFFUSE, colour0); glMaterialfv(GL_FRONT, GL_SPECULAR, colour0); glMaterialfv(GL_FRONT, GL_EMISSION, colourChar); glMaterialfv(GL_FRONT, GL_SHININESS, colour0); glRasterPos3f(0,0,0); crystGLPrint(this->GetName()); } } else { glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, colourAtom); glMaterialfv(GL_FRONT, GL_SPECULAR, colour0); glMaterialfv(GL_FRONT, GL_EMISSION, colour0); glMaterialfv(GL_FRONT, GL_SHININESS, colour0); glPolygonMode(GL_FRONT, GL_FILL); gluSphere(pQuadric,this->GetRadius()/3.,20,20); } glPopMatrix(); } } } } gluDeleteQuadric(pQuadric); VFN_DEBUG_MESSAGE("Atom::GLInitDisplayList():End",5) } #endif // OBJCRYST_GL bool Atom::IsDummy()const { if(0==mScattCompList(0).mpScattPow) return true; return false;} const ScatteringPower& Atom::GetScatteringPower()const { return *mpScattPowAtom;} void Atom::SetScatteringPower(const ScatteringPower &p) { if(mpScattPowAtom!=&p) { if(mpScattPowAtom!=0) mpScattPowAtom->DeRegisterClient(*this); mpScattPowAtom = &p; mScattCompList(0).mpScattPow=mpScattPowAtom; mClockScatterer.Click(); if(mpScattPowAtom!=0) mpScattPowAtom->RegisterClient(*this); } } void Atom::GetGeneGroup(const RefinableObj &obj, CrystVector_uint & groupIndex, unsigned int &first) const { //One group for all translation parameters unsigned int posIndex=0; VFN_DEBUG_MESSAGE("Atom::GetGeneGroup()",4) for(long i=0;iGetNbPar();j++) if(&(obj.GetPar(i)) == &(this->GetPar(j))) { if(this->GetPar(j).GetType()->IsDescendantFromOrSameAs(gpRefParTypeScattTransl)) { if(posIndex==0) posIndex=first++; groupIndex(i)=posIndex; } else groupIndex(i)= first++; } } void Atom::InitRefParList() { mClockScatterer.Click(); VFN_DEBUG_MESSAGE("Atom::InitRefParList()",5) this->ResetParList(); //:TODO: Add thermic factors { RefinablePar tmp("x",&mXYZ(0),0,1.,gpRefParTypeScattTranslX, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,true,1.,1.); tmp.AssignClock(mClockScatterer); this->AddPar(tmp); } { RefinablePar tmp("y",&mXYZ(1),0,1.,gpRefParTypeScattTranslY, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,true,1.,1.); tmp.AssignClock(mClockScatterer); this->AddPar(tmp); } { RefinablePar tmp("z",&mXYZ(2),0,1.,gpRefParTypeScattTranslZ, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,true,1.,1.); tmp.AssignClock(mClockScatterer); this->AddPar(tmp); } if(false==this->IsDummy()) { { RefinablePar tmp(this->GetName()+(string)"occup",&mOccupancy,0.01,1., gpRefParTypeScattOccup,REFPAR_DERIV_STEP_ABSOLUTE,true,true); tmp.AssignClock(mClockScatterer); tmp.SetGlobalOptimStep(.2); this->AddPar(tmp); } } } #ifdef __WX__CRYST__ WXCrystObjBasic* Atom::WXCreate(wxWindow* parent) { //:TODO: Check mpWXCrystObj==0 mpWXCrystObj=new WXAtom(parent,this); return mpWXCrystObj; } #endif }//namespace objcryst-2022.1/ObjCryst/ObjCryst/Atom.h000066400000000000000000000157261430515525000200210ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Atom.h * header file for the Atom scatterer * */ #ifndef _OBJCRYST_ATOM_H_ #define _OBJCRYST_ATOM_H_ #include "ObjCryst/CrystVector/CrystVector.h" #include "ObjCryst/ObjCryst/General.h" #include "ObjCryst/ObjCryst/ScatteringPower.h" #include "ObjCryst/ObjCryst/Scatterer.h" //#include #include //#include //#include //#include //#include //#include //using namespace std; namespace ObjCryst { //###################################################################### // /// The basic atom scatterer, in a crystal. /// /// This class records the position of the atom, and has a pointer to its /// ScatteringPowerAtom. /// /// \note there can be 'Dummy' atoms, for which the used symbol is "X", /// and which have no scattering power (use with caution: dummy atoms /// are only supposed to be used within ZScatterer) //###################################################################### class Atom: public Scatterer { public: /// Default constructor. The Atom \e must be initialized thereafter /// using Atom::Init() Atom(); /** \brief Atom constructor * \param x,y,z : \e fractional coordinates of the atom * \param pow : the ScatteringPower associated to this atom. Must be allocated separately. * \param name : name of the atom ('Ta1','Sm2', 'Tungsten_1'...). * The name can have \e any format but spaces should be avoided. */ Atom( const REAL x, const REAL y, const REAL z, const string &name, const ScatteringPower *pow); /** \brief Atom constructor * \param x,y,z : \e fractional coordinates of the atom * \param popu : the population of the atom (0.0->1.0) * This should take into account the multiplicity of the atom. For * an atom in group P2 and on the 2 axis, this should be set to 0.5, * \b unless you are using the dynamical occupancy correction (recommended * for global optimizations). See Crystal::CalcDynPopCorr() and * Crystal::mUseDynPopCorr * * \param pow : the ScatteringPower associated to this atom. Must be allocated separatly. * \param name : name of the atom ('Ta1','Sm2', 'Tungsten_1'...). * The name can have \e any format but spaces should be avoided (just a precaution) */ Atom( const REAL x, const REAL y, const REAL z,const string &name, const ScatteringPower *pow, const REAL popu); /// Copy constructor Atom(const Atom &old); virtual Atom* CreateCopy() const; /// Destructor... ~Atom(); virtual const string& GetClassName() const; /// virtual void operator=(const Atom & rhs); /** initialize the atom (used for arrays of atoms). * \param x,y,z : \e fractional coordinates of the atom * \param pow : the ScatteringPower associated to this atom. Must be allocated separately. * \param name : name of the atom ('Ta1','Sm2', 'Tungsten_1'...). */ void Init(const REAL x, const REAL y, const REAL z, const string &name, const ScatteringPower *pow, const REAL popu=1); virtual int GetNbComponent() const; virtual const ScatteringComponentList& GetScatteringComponentList() const; virtual string GetComponentName(const int i) const; virtual void Print() const; /** \brief Returns the molar mass of the atom. * * Values are extracted from the 'atominfo' package, * which uses data from the CRC Handbook of Chemistry & Physics, 63rd & 70th editions * The Mass is actually extracted from the ScatteringPowerAtom. */ REAL GetMass() const; /** \brief Returns the radius (in Angstroems) of the atom. * * Values are extracted from the 'atominfo' package, * which uses data from the ICSD/CRYSTIN Manual * The Radius is extracted from the ScatteringPowerAtom. */ REAL GetRadius() const; /** \brief XMLOutput a description of the scatterer for POVRay * */ virtual ostream& POVRayDescription(ostream &os, const CrystalPOVRayOptions &options)const; #ifdef OBJCRYST_GL virtual void GLInitDisplayList(const bool noSymmetrics=false, const REAL xMin=-.1,const REAL xMax=1.1, const REAL yMin=-.1,const REAL yMax=1.1, const REAL zMin=-.1,const REAL zMax=1.1, const bool displayEnantiomer=false, const bool displayNames=false, const bool hideHydrogens=false, const REAL fadeDistance=0, const bool fullMoleculeInLimits=false)const; #endif // OBJCRYST_GL /// Is this a dummy atom ? (ie no ScatteringPower) /// Dummy atoms should not exist ! bool IsDummy()const; virtual void XMLOutput(ostream &os,int indent=0)const; virtual void XMLInput(istream &is,const XMLCrystTag &tag); //virtual void XMLInputOld(istream &is,const IOCrystTag &tag); /// Get the ScatteringPowerAtom corresponding to this atom. const ScatteringPower& GetScatteringPower()const; /// Change the ScatteringPower for this atom void SetScatteringPower(const ScatteringPower &pow); virtual void GetGeneGroup(const RefinableObj &obj, CrystVector_uint & groupIndex, unsigned int &firstGroup) const; protected: private: /// Prepare refinable parameters for the scatterer object virtual void InitRefParList(); /// The list of scattering components. mutable ScatteringComponentList mScattCompList; /// The ScatteringPowerAtom associated to that atom const ScatteringPower *mpScattPowAtom; #ifdef __WX__CRYST__ public: virtual WXCrystObjBasic* WXCreate(wxWindow*); friend class WXAtom; #endif }; }//namespace Objcryst // do we need this ? #include "ObjCryst/ObjCryst/Crystal.h" #endif //_OBJCRYST_ATOM_H_ objcryst-2022.1/ObjCryst/ObjCryst/CIF.cpp000066400000000000000000001511571430515525000200540ustar00rootroot00000000000000#include #include #include #include "cctbx/sgtbx/space_group.h" #include "cctbx/sgtbx/space_group_type.h" #include "cctbx/miller/sym_equiv.h" #include "cctbx/sgtbx/brick.h" #include "ObjCryst/ObjCryst/CIF.h" #include "ObjCryst/ObjCryst/Crystal.h" #include "ObjCryst/ObjCryst/Atom.h" #include "ObjCryst/ObjCryst/PowderPattern.h" #include "ObjCryst/Quirks/Chronometer.h" #define POSSIBLY_UNUSED(expr) (void)(expr) using namespace std; namespace ObjCryst { CIFData::CIFAtom::CIFAtom(): mLabel(""),mSymbol(""),mOccupancy(1.0),mBiso(0.0) {} CIFData::CIFData() {} void CIFData::ExtractAll(const bool verbose) { (*fpObjCrystInformUser)("CIF: Extract Data..."); // :TODO: convert cartesian to fractional coordinates and vice-versa, if unit cell is known // :TODO: Take care of values listed as "." and "?" instead of a real value. this->ExtractName(verbose); this->ExtractUnitCell(verbose); this->ExtractSpacegroup(verbose); this->ExtractAtomicPositions(verbose); this->ExtractAnisotropicADPs(verbose); this->ExtractPowderPattern(verbose); this->ExtractSingleCrystalData(verbose); (*fpObjCrystInformUser)("CIF: Finished Extracting Data..."); } void CIFData::ExtractUnitCell(const bool verbose) { map::const_iterator positem; positem=mvItem.find("_cell_length_a"); if(positem!=mvItem.end()) { (*fpObjCrystInformUser)("CIF: Extract Unit Cell..."); mvLatticePar.resize(6); mvLatticePar[0]=CIFNumeric2REAL(positem->second); positem=mvItem.find("_cell_length_b"); if(positem!=mvItem.end()) mvLatticePar[1]=CIFNumeric2REAL(positem->second); positem=mvItem.find("_cell_length_c"); if(positem!=mvItem.end()) mvLatticePar[2]=CIFNumeric2REAL(positem->second); positem=mvItem.find("_cell_angle_alpha"); if(positem!=mvItem.end()) mvLatticePar[3]=CIFNumeric2REAL(positem->second); positem=mvItem.find("_cell_angle_beta"); if(positem!=mvItem.end()) mvLatticePar[4]=CIFNumeric2REAL(positem->second); positem=mvItem.find("_cell_angle_gamma"); if(positem!=mvItem.end()) mvLatticePar[5]=CIFNumeric2REAL(positem->second); if(verbose) cout<<"Found Lattice parameters:" <CalcMatrices(); } } void CIFData::ExtractSpacegroup(const bool verbose) { map::const_iterator positem; positem=mvItem.find("_space_group_IT_number"); if(positem!=mvItem.end()) { mSpacegroupNumberIT=positem->second;//CIFNumeric2Int() if(verbose) cout<<"Found spacegroup IT number:"<second;//CIFNumeric2Int() if(verbose) cout<<"Found spacegroup IT number (with OBSOLETE CIF #1.0 TAG):"<second; if(verbose) cout<<"Found spacegroup Hall symbol:"<second; if(verbose) cout<<"Found spacegroup Hall symbol (with OBSOLETE CIF #1.0 TAG):"<second; if(verbose) cout<<"Found spacegroup Hermann-Mauguin symbol:"<second; if(verbose) cout<<"Found spacegroup Hall Hermann-Mauguin (with OBSOLETE CIF #1.0 TAG):"<,map > >::const_iterator loop=mvLoop.begin(); loop!=mvLoop.end();++loop) { if(mvSymmetry_equiv_pos_as_xyz.size()>0) break;// only extract ONE list of symmetry strings map >::const_iterator pos; pos=loop->second.find("_symmetry_equiv_pos_as_xyz"); if(pos!=loop->second.end()) { if(verbose) cout<<"Found list of _symmetry_equiv_pos_as_xyz:"<second.size();++i) { if(verbose) cout<<" "<second[i]<second[i]); } } } } void CIFData::ExtractName(const bool verbose) { map::const_iterator positem; positem=mvItem.find("_chemical_name_systematic"); if(positem!=mvItem.end()) { mName=positem->second; if(verbose) cout<<"Found chemical name:"<second; if(verbose) cout<<"Found chemical name:"<second; if(verbose) cout<<"Found chemical name:"<second; if(verbose) cout<<"Found chemical name:"<second; if(verbose) cout<<"Found chemical name:"<second; if(verbose) cout<<"Found chemical name:"<second; if(verbose) cout<<"Found chemical formula:"<second; if(verbose) cout<<"Found chemical formula:"<second; if(verbose) cout<<"Found chemical formula:"<second; if(verbose) cout<<"Found chemical formula:"<::const_iterator positem; for(map,map > >::const_iterator loop=mvLoop.begin(); loop!=mvLoop.end();++loop) { if(mvAtom.size()>0) break;// only extract ONE list of atoms, preferably fractional coordinates map >::const_iterator posx,posy,posz,poslabel,possymbol,posoccup,posadp; posx=loop->second.find("_atom_site_fract_x"); posy=loop->second.find("_atom_site_fract_y"); posz=loop->second.find("_atom_site_fract_z"); unsigned int nb = 0; if( (posx!=loop->second.end()) && (posy!=loop->second.end()) && (posz!=loop->second.end())) { nb=posx->second.size(); mvAtom.resize(nb); for(unsigned int i=0;isecond[i]); mvAtom[i].mCoordFrac[1]=CIFNumeric2REAL(posy->second[i]); mvAtom[i].mCoordFrac[2]=CIFNumeric2REAL(posz->second[i]); } this->Fractional2CartesianCoord(); } else { posx=loop->second.find("_atom_site_Cartn_x"); posy=loop->second.find("_atom_site_Cartn_y"); posz=loop->second.find("_atom_site_Cartn_z"); if( (posx!=loop->second.end()) && (posy!=loop->second.end()) && (posz!=loop->second.end())) { nb=posx->second.size(); mvAtom.resize(nb); for(unsigned int i=0;isecond[i]); mvAtom[i].mCoordCart[1]=CIFNumeric2REAL(posy->second[i]); mvAtom[i].mCoordCart[2]=CIFNumeric2REAL(posz->second[i]); } this->Cartesian2FractionalCoord(); } } if(mvAtom.size()>0) {// Got the atoms, get names, symbols and adps (*fpObjCrystInformUser)("CIF: Extract Atoms..."); possymbol=loop->second.find("_atom_site_type_symbol"); if(possymbol!=loop->second.end()) for(unsigned int i=0;isecond[i]; poslabel=loop->second.find("_atom_site_label"); if(poslabel!=loop->second.end()) for(unsigned int i=0;isecond[i]; if(possymbol==loop->second.end()) {// There was no symbol, use the labels to guess it int nbc=0; if(mvAtom[i].mLabel.size()==1) if(isalpha(mvAtom[i].mLabel[0])) nbc=1; if(mvAtom[i].mLabel.size()>=2) { if(isalpha(mvAtom[i].mLabel[0]) && isalpha(mvAtom[i].mLabel[1])) nbc=2; else if(isalpha(mvAtom[i].mLabel[0])) nbc=1; } if(nbc>0) mvAtom[i].mSymbol=mvAtom[i].mLabel.substr(0,nbc); else mvAtom[i].mSymbol="H";//Something wen wrong, no symbol ! } } // Occupancy ? posoccup=loop->second.find("_atom_site_occupancy"); if(posoccup!=loop->second.end()) for(unsigned int i=0;isecond[i]); // ADPs - Record ani, ovl or mpl as iso. REAL mult = 1.0; posadp=loop->second.find("_atom_site_B_iso_or_equiv"); if(posadp==loop->second.end()) { mult = 8 * M_PI * M_PI; posadp=loop->second.find("_atom_site_U_iso_or_equiv"); } if(posadp!=loop->second.end()) for(unsigned int i=0;isecond[i]); // Now be somewhat verbose if(verbose) { cout << "Found "<0) { cout<<" , Fractional: "; for(unsigned int j=0;j0) { cout<<" , Cartesian: "; for(unsigned int j=0;jsecond.find("_atom_site_aniso_label"); // Move to the next loop if we can't find it here. if (anisolabels == loop->second.end()) continue; if(verbose) cout << "Found labels!" << endl; // We have a list of labels. Position the iterators for each of the // adps. for (int idx = 0; idx < 6; ++idx) { EntryIter& betaiter = *betaiters[idx]; betaiter = loop->second.find(bijlabels[idx]); mult[idx] = 1.0; if(betaiter == loop->second.end()) { betaiter = loop->second.find(uijlabels[idx]); mult[idx] = utob; } if(betaiter == loop->second.end()) mult[idx] = 0.0; } // Check that we have values. If not, then we can get out of here. bool havedata = false; for (int i = 0; i < 6; ++i) { if( mult[i] != 0 ) havedata = true; } if (!havedata) return; // Now loop over the labels, find the corresponding CIFAtom, and fill in // its information. size_t nb = anisolabels->second.size(); if(verbose) cout << "Have " << nb << " labels." << endl; for (size_t i = 0; i < nb; ++i) { string label = anisolabels->second[i]; if(verbose) cout << label << endl; // See if we have a CIFAtom with this label. If so, initialize the mBeta // vector. vector::iterator atom = mvAtom.begin(); for (; atom != mvAtom.end(); ++atom) { if (atom->mLabel == label) { atom->mBeta.resize(6, 0.0); break; } } // If we didn't find the mvAtom, then we should move on to the next // label. if (atom == mvAtom.end()) continue; // Fill in what we've got, one entry at a time. for (int idx=0; idx<6; ++idx) { if (mult[idx] == 0) { if(verbose) cout << "skipping index " << idx << endl; continue; } EntryIter& betaiter = *betaiters[idx]; if (betaiter->second.size() <= i) continue; double beta = CIFNumeric2REAL(betaiter->second[i]); atom->mBeta[idx] = mult[idx] * beta; if(verbose) cout << "mBeta " << idx << " " << atom->mBeta[idx] << endl; } } } return; } /// This is the default wavelength - whenever a "_diffrn_radiation_wavelength" or /// "_pd_proc_wavelength"entry is found, /// it is used as a new value for the default wavelength. Since the powder CIFs do not /// include the wavelength, this could be useful if the crystal structure CIF (including /// the wavelength) is parsed right before the powder pattern one. static REAL defaultWavelength=1.0; void CIFData::ExtractPowderPattern(const bool verbose) { map::const_iterator positem; positem=mvItem.find("_diffrn_radiation_wavelength"); if(positem==mvItem.end()) positem=mvItem.find("_pd_proc_wavelength"); if(positem!=mvItem.end()) { mWavelength=CIFNumeric2REAL(positem->second); defaultWavelength=mWavelength; if(verbose) cout<<"Found wavelength:"<,map > >::const_iterator loop=mvLoop.begin(); loop!=mvLoop.end();++loop) { mDataType=WAVELENGTH_MONOCHROMATIC; map >::const_iterator pos_x,pos_iobs,pos_weight,pos_mon,pos_wavelength; pos_wavelength=loop->second.find("_diffrn_radiation_wavelength"); if(pos_wavelength!=loop->second.end()) { if(verbose) cout<<"Found wavelength (in loop):"<second[0]; mWavelength=CIFNumeric2REAL(pos_wavelength->second[0]); defaultWavelength=mWavelength; if(verbose) cout<<" -> "<second.find("_pd_meas_counts_total"); if(pos_iobs==loop->second.end()) pos_iobs=loop->second.find("_pd_meas_intensity_total"); if(pos_iobs==loop->second.end()) pos_iobs=loop->second.find("_pd_proc_intensity_total"); if(pos_iobs==loop->second.end()) pos_iobs=loop->second.find("_pd_proc_intensity_net"); if(pos_iobs==loop->second.end()) continue;//no observed powder data found pos_weight=loop->second.find("_pd_proc_ls_weight"); pos_x=loop->second.find("_pd_proc_2theta_corrected"); if(pos_x==loop->second.end()) pos_x=loop->second.find("_pd_meas_angle_2theta"); if(pos_x==loop->second.end()) pos_x=loop->second.find("_pd_meas_2theta_scan"); if(pos_x==loop->second.end()) { pos_x=loop->second.find("_pd_meas_time_of_flight"); if(pos_x!=loop->second.end()) mDataType=WAVELENGTH_TOF; } bool x_fixed_step=false; REAL xmin = 0, xmax = 0, xinc = 0; POSSIBLY_UNUSED(xmax); if(pos_x==loop->second.end()) { map::const_iterator pos_min,pos_max,pos_inc; pos_min=mvItem.find("_pd_proc_2theta_range_min"); if(pos_min==mvItem.end()) pos_min=mvItem.find("_pd_meas_2theta_range_min"); pos_max=mvItem.find("_pd_proc_2theta_range_max"); if(pos_max==mvItem.end()) pos_max=mvItem.find("_pd_meas_2theta_range_max"); pos_inc=mvItem.find("_pd_proc_2theta_range_inc"); if(pos_inc==mvItem.end()) pos_inc=mvItem.find("_pd_meas_2theta_range_inc"); if((pos_min!=mvItem.end()) && (pos_max!=mvItem.end()) && (pos_inc!=mvItem.end()) ) { x_fixed_step=true; xmin=CIFNumeric2REAL(pos_min->second); xmax=CIFNumeric2REAL(pos_max->second); xinc=CIFNumeric2REAL(pos_inc->second); } } pos_mon=loop->second.find("_pd_meas_intensity_monitor"); if(pos_mon==loop->second.end()) pos_mon=loop->second.find("_pd_meas_step_count_time"); if( (pos_iobs!=loop->second.end()) && ( (pos_x!=loop->second.end()) || (x_fixed_step)) ) {// Found powder data ! const long nb=pos_iobs->second.size(); if(verbose) cout<<"Found powder data, with "<second[i]); if(x_fixed_step) mPowderPatternX[i]=(xmin+i*xinc)*mult; else mPowderPatternX[i]=CIFNumeric2REAL(pos_x->second[i])*mult; // :TODO: use esd on observed intensity, if available. if(pos_weight!=loop->second.end()) { mPowderPatternSigma[i]=CIFNumeric2REAL(pos_weight->second[i]); if(mPowderPatternSigma[i]>0) mPowderPatternSigma[i]=1/sqrt(fabs(mPowderPatternSigma[i])); else mPowderPatternSigma[i]=sqrt(fabs(mPowderPatternObs[i])); // :KLUDGE: ? } else mPowderPatternSigma[i]=sqrt(fabs(mPowderPatternObs[i])); if(pos_mon!=loop->second.end()) {//VCT or monitor const REAL mon=CIFNumeric2REAL(pos_mon->second[i]); if(mon>0) { mPowderPatternObs[i]/=mon; mPowderPatternSigma[i]/=sqrt(mon); } } //if((i<10) && verbose) cout<::const_iterator positem; positem=mvItem.find("_diffrn_radiation_wavelength"); if(positem==mvItem.end()) positem=mvItem.find("_pd_proc_wavelength"); if(positem!=mvItem.end()) { mWavelength=CIFNumeric2REAL(positem->second); defaultWavelength=mWavelength; if(verbose) cout<<"Found wavelength:"<,map > >::const_iterator loop=mvLoop.begin(); loop!=mvLoop.end();++loop) { mDataType=WAVELENGTH_MONOCHROMATIC; map >::const_iterator pos_h,pos_k,pos_l,pos_iobs,pos_sigma,pos_wavelength; pos_wavelength=loop->second.find("_diffrn_radiation_wavelength"); if(pos_wavelength!=loop->second.end()) { if(verbose) cout<<"Found wavelength (in loop):"<second[0]; mWavelength=CIFNumeric2REAL(pos_wavelength->second[0]); defaultWavelength=mWavelength; if(verbose) cout<<" -> "<second.find("_refln_F_squared_meas"); if(pos_iobs==loop->second.end()) continue;//no observed powder data found pos_sigma=loop->second.find("_refln_F_squared_sigma"); pos_h=loop->second.find("_refln_index_h"); pos_k=loop->second.find("_refln_index_k"); pos_l=loop->second.find("_refln_index_l"); if( (pos_iobs!=loop->second.end()) && (pos_h!=loop->second.end()) && (pos_k!=loop->second.end()) && (pos_l!=loop->second.end())) {// Found single crystal data ! const long nb=pos_iobs->second.size(); if(verbose) cout<<"Found single crystal data, with "<second[i]); mH(i)=CIFNumeric2Int(pos_h->second[i]); mK(i)=CIFNumeric2Int(pos_k->second[i]); mL(i)=CIFNumeric2Int(pos_l->second[i]); if(pos_sigma!=loop->second.end()) mSigma(i)=CIFNumeric2REAL(pos_sigma->second[i]); else mSigma(i)=sqrt(fabs(abs(mIobs(i)))); } } } } void CIFData::CalcMatrices(const bool verbose) { if(mvLatticePar.size()==0) return;//:TODO: throw error REAL a,b,c,alpha,beta,gamma;//direct space parameters REAL aa,bb,cc,alphaa,betaa,gammaa;//reciprocal space parameters POSSIBLY_UNUSED(aa); POSSIBLY_UNUSED(bb); POSSIBLY_UNUSED(betaa); POSSIBLY_UNUSED(gammaa); REAL v;//volume of the unit cell a=mvLatticePar[0]; b=mvLatticePar[1]; c=mvLatticePar[2]; alpha=mvLatticePar[3]; beta=mvLatticePar[4]; gamma=mvLatticePar[5]; v=sqrt(fabs(1-cos(alpha)*cos(alpha)-cos(beta)*cos(beta)-cos(gamma)*cos(gamma) +2*cos(alpha)*cos(beta)*cos(gamma))); aa=sin(alpha)/a/v; bb=sin(beta )/b/v; cc=sin(gamma)/c/v; alphaa=acos( (cos(beta )*cos(gamma)-cos(alpha))/sin(beta )/sin(gamma) ); betaa =acos( (cos(alpha)*cos(gamma)-cos(beta ))/sin(alpha)/sin(gamma) ); gammaa=acos( (cos(alpha)*cos(beta )-cos(gamma))/sin(alpha)/sin(beta ) ); mOrthMatrix[0][0]=a; mOrthMatrix[0][1]=b*cos(gamma); mOrthMatrix[0][2]=c*cos(beta); mOrthMatrix[1][0]=0; mOrthMatrix[1][1]=b*sin(gamma); mOrthMatrix[1][2]=-c*sin(beta)*cos(alphaa); mOrthMatrix[2][0]=0; mOrthMatrix[2][1]=0; mOrthMatrix[2][2]=1/cc; // Invert upper triangular matrix REAL cm[3][3]; cm[0][0]=mOrthMatrix[0][0]; cm[0][1]=mOrthMatrix[0][1]; cm[0][2]=mOrthMatrix[0][2]; cm[1][0]=mOrthMatrix[1][0]; cm[1][1]=mOrthMatrix[1][1]; cm[1][2]=mOrthMatrix[1][2]; cm[2][0]=mOrthMatrix[2][0]; cm[2][1]=mOrthMatrix[2][1]; cm[2][2]=mOrthMatrix[2][2]; for(long i=0;i<3;i++) for(long j=0;j<3;j++) if(i==j) mOrthMatrixInvert[i][j]=1; else mOrthMatrixInvert[i][j]=0; for(long i=0;i<3;i++) { REAL a; for(long j=i-1;j>=0;j--) { a=cm[j][i]/cm[i][i]; for(long k=0;k<3;k++) mOrthMatrixInvert[j][k] -= mOrthMatrixInvert[i][k]*a; for(long k=0;k<3;k++) cm[j][k] -= cm[i][k]*a; } a=cm[i][i]; for(long k=0;k<3;k++) mOrthMatrixInvert[i][k] /= a; for(long k=0;k<3;k++) cm[i][k] /= a; } if(verbose) { cout <<"Fractional2Cartesian matrix:"<::iterator pos=mvAtom.begin();pos!=mvAtom.end();++pos) { pos->mCoordFrac.resize(3); pos->mCoordFrac[0]=pos->mCoordCart.at(0); pos->mCoordFrac[1]=pos->mCoordCart.at(1); pos->mCoordFrac[2]=pos->mCoordCart.at(2); c2f(pos->mCoordFrac[0],pos->mCoordFrac[1],pos->mCoordFrac[2]); } } void CIFData::Fractional2CartesianCoord() { for(vector::iterator pos=mvAtom.begin();pos!=mvAtom.end();++pos) { pos->mCoordCart.resize(3); pos->mCoordCart[0]=pos->mCoordFrac.at(0); pos->mCoordCart[1]=pos->mCoordFrac.at(1); pos->mCoordCart[2]=pos->mCoordFrac.at(2); f2c(pos->mCoordCart[0],pos->mCoordCart[1],pos->mCoordCart[2]); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// CIF::CIF(istream &is, const bool interpret,const bool verbose) { string s; (*fpObjCrystInformUser)("CIF: Opening CIF"); Chronometer chrono; chrono.start(); //Copy to an iostream so that we can put back characters if necessary stringstream in; char c; while(is.get(c))in.put(c); const float t0read=chrono.seconds(); s=(boost::format("CIF: Parsing CIF (reading dt=%5.3fs)")%t0read).str(); (*fpObjCrystInformUser)(s); this->Parse(in); const float t1parse=chrono.seconds(); s=(boost::format("CIF: Finished Parsing, Extracting...(parsing dt=%5.3fs)") % (t1parse-t0read)).str(); (*fpObjCrystInformUser)(s); // Extract structure from blocks if(interpret) for(map::iterator posd=mvData.begin();posd!=mvData.end();++posd) posd->second.ExtractAll(verbose); const float t2interpret=chrono.seconds(); s=(boost::format("CIF: Finished Import...(interpret dt=%5.3fs, total CIF import=%5.3fs)")%(t2interpret-t1parse)%t2interpret).str(); (*fpObjCrystInformUser)(s); } bool iseol(const char c) { return ((c=='\n')||(c=='\r'));} std::string trimString(const std::string &s) { const size_t i0 = s.find_first_not_of(" \t\r\n"); if (i0 == std::string::npos) return ""; const size_t i1 = s.find_last_not_of(" \t\r\n"); return s.substr(i0, i1-i0+1); } /// Read one value, whether it is numeric, string or text string CIFReadValue(stringstream &in,char &lastc) { bool vv=false;//very verbose ? string value; while(!isgraph(in.peek())) in.get(lastc); while(in.peek()=='#') {//discard these comments for now string tmp; getline(in,tmp); lastc='\r'; while(!isgraph(in.peek())) in.get(lastc); } if(in.peek()==';') {//SemiColonTextField bool warning=!iseol(lastc); if(warning) cout<<"WARNING: Trying to read a SemiColonTextField but last char is not an end-of-line char !"<>value; if(vv) cout<<"NormalValue:"<>tag; // Convert all dots to underscores to cover much of DDL2 with this DDL1 parser. for (string::size_type pos = tag.find('.'); pos != string::npos; pos = tag.find('.', ++ pos)) tag.replace(pos, 1, 1, '_'); value=CIFReadValue(in,lastc); if(value==string("?")) continue;//useless mvData[block].mvItem[ci_string(tag.c_str())]=value; if(vv)cout<<"New Tag:"<>tmp; block=tmp.substr(5); if(vv) cout<"< tit; string tmp; in>>tmp; //should be loop_ if(vv) cout<<"LOOP : "<>tmp; // Convert all dots to underscores to cover much of DDL2 with this DDL1 parser. for (string::size_type pos = tmp.find('.'); pos != string::npos; pos = tmp.find('.', ++ pos)) tmp.replace(pos, 1, 1, '_'); tit.push_back(ci_string(tmp.c_str())); if(vv) cout<<" , "< > lp; while(true) { while(!isgraph(in.peek()) && !in.eof()) in.get(lastc); if(in.eof()) break; if(vv) cout<<"LOOP VALUES...: "<<(char)in.peek()<<" "<>tmp; if(vv) cout<<"WHATNEXT? "<=5) if(ci_string(tmp.substr(0,5).c_str())=="data_") {//go back and continue if(vv) cout< stit; for(unsigned int i=0;i>v; return v; } int CIFNumeric2Int(const string &s) { if((s==".") || (s=="?")) return 0; // Use stream rather than sscanf to rely on C++ locale to read C-locale values int v=0; stringstream ss(s); ss.imbue(std::locale::classic()); ss>>v; return v; } Crystal* CreateCrystalFromCIF(CIF &cif,bool verbose,bool checkSymAsXYZ) { return CreateCrystalFromCIF(cif,verbose,checkSymAsXYZ,false,false); } Crystal* CreateCrystalFromCIF(CIF &cif,const bool verbose,const bool checkSymAsXYZ, const bool oneScatteringPowerPerElement, const bool connectAtoms, Crystal *pCryst) { (*fpObjCrystInformUser)("CIF: Opening CIF"); Chronometer chrono; chrono.start(); // If oneScatteringPowerPerElement==true, we hold this to compute the average Biso per element std::map > vElementBiso; bool import_multiple = true; if(pCryst!=NULL) import_multiple = false; bool crystal_found = false; for(map::iterator pos=cif.mvData.begin();pos!=cif.mvData.end();++pos) if(pos->second.mvLatticePar.size()==6) { // If no atoms are listed and we already have a crystal structure defined, //asssume we don't want this one - e.g. like some IuCr journals single crystal //data cif files including cell parameters if((pos->second.mvAtom.size()==0) && (gCrystalRegistry.GetNb()>0)) continue; // Use unambigous Hall symbol if present, otherwise try HM symbol or spg number string spg; if(pos->second.mSpacegroupSymbolHall!="") try { tmp_C_Numeric_locale tmploc; cctbx::sgtbx::space_group cctbxspg(pos->second.mSpacegroupSymbolHall); cctbxspg.t_den(); cctbxspg.n_smx(); cctbxspg.n_ltr(); cctbxspg.type(); cctbxspg.type().number(); cctbxspg.type().hall_symbol(); cctbxspg.type().lookup_symbol(); cctbxspg.match_tabulated_settings().extension(); cctbxspg.match_tabulated_settings().hermann_mauguin(); cctbxspg.type().universal_hermann_mauguin_symbol(); cctbx::sgtbx::brick b(cctbxspg.type()); spg=pos->second.mSpacegroupSymbolHall; } catch(exception) { VFN_DEBUG_MESSAGE("CreateCrystalFromCIF(): could not interpret Hall symbol:"<second.mSpacegroupSymbolHall, 10) } if((spg=="") && (pos->second.mSpacegroupHermannMauguin!="")) try { tmp_C_Numeric_locale tmploc; cctbx::sgtbx::space_group cctbxspg(cctbx::sgtbx::space_group_symbols(pos->second.mSpacegroupHermannMauguin)); cctbxspg.t_den(); cctbxspg.n_smx(); cctbxspg.n_ltr(); cctbxspg.type(); cctbxspg.type().number(); cctbxspg.type().hall_symbol(); cctbxspg.type().lookup_symbol(); cctbxspg.type().universal_hermann_mauguin_symbol(); cctbxspg.match_tabulated_settings().extension(); cctbxspg.match_tabulated_settings().hermann_mauguin(); cctbx::sgtbx::brick b(cctbxspg.type()); spg=pos->second.mSpacegroupHermannMauguin; } catch(exception) { VFN_DEBUG_MESSAGE("CreateCrystalFromCIF(): could not interpret Hermann-Mauguin symbol:"<second.mSpacegroupHermannMauguin, 10) } if((spg=="") && (pos->second.mSpacegroupNumberIT!="")) try { tmp_C_Numeric_locale tmploc; cctbx::sgtbx::space_group cctbxspg(cctbx::sgtbx::space_group_symbols(pos->second.mSpacegroupNumberIT)); cctbxspg.t_den(); cctbxspg.n_smx(); cctbxspg.n_ltr(); cctbxspg.type(); cctbxspg.type().number(); cctbxspg.type().hall_symbol(); cctbxspg.type().lookup_symbol(); cctbxspg.type().universal_hermann_mauguin_symbol(); cctbxspg.match_tabulated_settings().extension(); cctbxspg.match_tabulated_settings().hermann_mauguin(); cctbx::sgtbx::brick b(cctbxspg.type()); spg=pos->second.mSpacegroupNumberIT; } catch(exception) { VFN_DEBUG_MESSAGE("CreateCrystalFromCIF(): could not interpret spacegroup number (!) :"<second.mSpacegroupNumberIT, 10) } if(spg=="") spg="P1"; if(verbose) cout<<"Create crystal with spacegroup: "<second.mSpacegroupHermannMauguin <<" / "<second.mSpacegroupSymbolHall <<" / "<second.mSpacegroupNumberIT <<"-> "<second.mSpacegroupSymbolHall=="") &&(pos->second.mvSymmetry_equiv_pos_as_xyz.size()>0) &&(pos->second.mSpacegroupHermannMauguin!="") &&checkSymAsXYZ) {// Could not use a Hall symbol, but we have a list of symmetry_equiv_pos_as_xyz, // so check we have used the best possible origin tmp_C_Numeric_locale tmploc; static vector origin_list; if(origin_list.size()==0) {//ugly ? origin_list.resize(5); origin_list[0]=""; origin_list[1]=":1"; origin_list[2]=":2"; origin_list[3]=":R"; origin_list[4]=":H"; } // If we do not have an HM symbol, then use the one generated by cctbx (normally from spg number) string hmorig=pos->second.mSpacegroupHermannMauguin; if(hmorig=="") hmorig=pCryst->GetSpaceGroup().GetCCTbxSpg().match_tabulated_settings().hermann_mauguin(); if(verbose) cout<<" Symmetry checking using symmetry_equiv_pos_as_xyz:"<::const_iterator posOrig=origin_list.begin();posOrig!=origin_list.end();++posOrig) { // The origin extension may not make sense, so we need to watch for exception try { pCryst->GetSpaceGroup().ChangeSpaceGroup(hmorig+*posOrig); } catch(invalid_argument) { continue; } // If the symbol is the same as before, the origin probably was not understood - no need to test if((posOrig!=origin_list.begin())&&(pCryst->GetSpaceGroup().GetName()==bestsymbol)) continue; unsigned int nbSymSpg=pCryst->GetSpaceGroup().GetCCTbxSpg().all_ops().size(); unsigned int nbSymCommon=0; try { for(unsigned int i=0;i::const_iterator posSymCIF=pos->second.mvSymmetry_equiv_pos_as_xyz.begin(); posSymCIF!=pos->second.mvSymmetry_equiv_pos_as_xyz.end();++posSymCIF) { cctbx::sgtbx::rt_mx mx1(*posSymCIF); cctbx::sgtbx::rt_mx mx2(pCryst->GetSpaceGroup().GetCCTbxSpg().all_ops()[i]); mx1.mod_positive_in_place(); mx2.mod_positive_in_place(); if(mx1==mx2) { nbSymCommon++; break; } } } if(verbose) cout<<" Trying: "<GetSpaceGroup().GetName() <<" nbsym:"<second.mvSymmetry_equiv_pos_as_xyz.size()<<"(CIF)" <<",common:"<second.mvSymmetry_equiv_pos_as_xyz.size())*nbSymCommon)) { bestscore=(nbSymSpg==pos->second.mvSymmetry_equiv_pos_as_xyz.size())*nbSymCommon; bestsymbol=pCryst->GetSpaceGroup().GetName(); } } catch(cctbx::error) { cout<<"WOOPS: cctbx error ! Wrong symmetry_equiv_pos_as_xyz strings ?"<GetSpaceGroup().ChangeSpaceGroup(bestsymbol); } // Try to set name from CIF. If that fails, the computed formula will be used at the end if(pos->second.mName!="") pCryst->SetName(pos->second.mName); else if(pos->second.mFormula!="") pCryst->SetName(pos->second.mFormula); const float t1=chrono.seconds(); (*fpObjCrystInformUser)((boost::format("CIF: Create Crystal:%s(%s)(dt=%6.3fs)")%pCryst->GetName() % pCryst->GetSpaceGroup().GetName() % t1).str()); bool doInformUserAllAtoms=true; if(pos->second.mvAtom.size()>30) doInformUserAllAtoms = false; unsigned int ctatom=0; for(vector::const_iterator posat=pos->second.mvAtom.begin();posat!=pos->second.mvAtom.end();++posat) { if( (posat->mLabel==".") || (posat->mSymbol==".") || (posat->mLabel.find("dummy")!=std::string::npos) || (posat->mSymbol.find("dummy")!=std::string::npos) ) { if(doInformUserAllAtoms) (*fpObjCrystInformUser)("CIF: Ignoring DUMMY Atom:"+posat->mLabel+"(symbol="+posat->mSymbol+")"); continue; } ctatom++; //const float t20=chrono.seconds(); // Try to find an existing scattering power with the same properties, or create a new one ScatteringPower* sp=NULL; if(oneScatteringPowerPerElement) { for(unsigned int i=0;iGetScatteringPowerRegistry().GetNb();++i) { if(pCryst->GetScatteringPowerRegistry().GetObj(i).GetSymbol()!=posat->mSymbol) continue; vElementBiso[&(pCryst->GetScatteringPowerRegistry().GetObj(i))].first+=posat->mBiso; vElementBiso[&(pCryst->GetScatteringPowerRegistry().GetObj(i))].second+=1; sp=&(pCryst->GetScatteringPowerRegistry().GetObj(i)); break; } if(sp==NULL) { if(verbose) cout<<"Scattering power "<mSymbol<<" not found, creating it..."<mSymbol,posat->mSymbol); // Always extract isotropic DP, even with ADPs present // :TODO: if only ADP are listed, calculate isotropic DP vElementBiso[sp].first+=posat->mBiso; vElementBiso[sp].second=1; pCryst->AddScatteringPower(sp); //const float t21=chrono.seconds(); //(*fpObjCrystInformUser)((boost::format("CIF: Add scattering power: %s (dt=%6.3fsCrystal creation=%6.3fs total)")% posat->mSymbol % (t21-t20) % t21).str()); } } else { #if 0 for(unsigned int i=0;iGetScatteringPowerRegistry().GetNb();++i) { if(pCryst->GetScatteringPowerRegistry().GetObj(i).GetSymbol()!=posat->mSymbol) continue; if(posat->mBeta.size() == 6) { if( (pCryst->GetScatteringPowerRegistry().GetObj(i).GetBij(0)!=posat->mBeta[0]) ||(pCryst->GetScatteringPowerRegistry().GetObj(i).GetBij(1)!=posat->mBeta[1]) ||(pCryst->GetScatteringPowerRegistry().GetObj(i).GetBij(2)!=posat->mBeta[2]) ||(pCryst->GetScatteringPowerRegistry().GetObj(i).GetBij(3)!=posat->mBeta[3]) ||(pCryst->GetScatteringPowerRegistry().GetObj(i).GetBij(4)!=posat->mBeta[4]) ||(pCryst->GetScatteringPowerRegistry().GetObj(i).GetBij(5)!=posat->mBeta[5])) continue; } else if(posat->mBiso!=pCryst->GetScatteringPowerRegistry().GetObj(i).GetBiso()) continue; sp=&(pCryst->GetScatteringPowerRegistry().GetObj(i)); break; } if(sp==NULL) #endif { if(verbose) cout<<"Creating new scattering power for:"<mLabel<mLabel,posat->mSymbol); // Always extract isotropic DP, even with ADPs present // :TODO: if only ADP are listed, calculate isotropic DP sp->SetBiso(posat->mBiso); // ADPs ? if(posat->mBeta.size() == 6) { for (int idx=0; idx<6; ++idx) sp->SetBij(idx, posat->mBeta[idx]); } pCryst->AddScatteringPower(sp); //const float t21=chrono.seconds(); //(*fpObjCrystInformUser)((boost::format("CIF: Add scattering power: %s (dt=%6.3fsCrystal creation=%6.3fs total)") % posat->mLabel % (t21-t20) % t21).str()); } } // (*fpObjCrystInformUser)("CIF: Add Atom:"+posat->mLabel+"("+sp->GetName()+")"); pCryst->AddScatterer(new Atom(posat->mCoordFrac[0],posat->mCoordFrac[1],posat->mCoordFrac[2], posat->mLabel,sp,posat->mOccupancy)); const float t22=chrono.seconds(); if(doInformUserAllAtoms) (*fpObjCrystInformUser)((boost::format("CIF: new Atom: %s (%s) (Crystal creation=%6.3fs total)") % posat->mLabel % sp->GetName() % t22).str()); else if (ctatom%20 == 0)(*fpObjCrystInformUser)((boost::format("CIF: imported %u atoms (Crystal creation=%6.3fs total)") % ctatom % t22).str()); } if(oneScatteringPowerPerElement) { for(std::map >::iterator pos=vElementBiso.begin();pos!=vElementBiso.end();++pos) pos->first->SetBiso(pos->second.first/pos->second.second); } (*fpObjCrystInformUser)((boost::format("CIF: Finished importing %u atoms (Crystal creation=%6.3fs total)") % ctatom % chrono.seconds()).str()); if(connectAtoms) { (*fpObjCrystInformUser)("CIF: connecting atoms"); pCryst->ConnectAtoms(); unsigned int ctat=0; unsigned int ctmol=0; for(int i=0;iGetNbScatterer();i++) { if(pCryst->GetScatt(i).GetClassName()=="Atom") ctat +=1; else if(pCryst->GetScatt(i).GetClassName()=="Molecule") ctmol +=1; } (*fpObjCrystInformUser)((boost::format("CIF: finished connecting atoms (%u isolated atoms, %u molecules) (Crystal creation=%6.3fs total)") % ctat % ctmol % chrono.seconds()).str()); } if(pCryst->GetName()=="") pCryst->SetName(pCryst->GetFormula()); if(!import_multiple) return pCryst; } if(!crystal_found) throw ObjCrystException("CreateCrystalFromCIF: no structure found"); return pCryst; } PowderPattern* CreatePowderPatternFromCIF(CIF &cif) { PowderPattern* pPow=NULL; for(map::iterator pos=cif.mvData.begin();pos!=cif.mvData.end();++pos) { if(pos->second.mPowderPatternObs.size()>10) { pPow=new PowderPattern(); pPow->ImportPowderPatternCIF(cif); (*fpObjCrystInformUser)((boost::format("CIF: Imported POWDER PATTERN, with %d points") % pPow->GetNbPoint()).str()); } } return pPow; } DiffractionDataSingleCrystal* CreateSingleCrystalDataFromCIF(CIF &cif, Crystal *pcryst) { DiffractionDataSingleCrystal* pData=NULL; std::string name(""); for(map::iterator pos=cif.mvData.begin();pos!=cif.mvData.end();++pos) { if(pos->second.mH.numElements()>0) { (*fpObjCrystInformUser)((boost::format("CIF: Importing SINGLE CRYSTAL DIFFRACTION data")).str()); if(pcryst==0) { if(gCrystalRegistry.GetNb()>0) { // Use last Crystal created pcryst=&(gCrystalRegistry.GetObj(gCrystalRegistry.GetNb()-1)); (*fpObjCrystInformUser)((boost::format("CIF: Importing SINGLE CRYSTAL DIFFRACTION data: using last Crystal structure as corresponding crystal [%s]") % pcryst->GetName().c_str()).str()); name = pcryst->GetName(); } else { pcryst=new Crystal; pcryst->SetName("Crystal data for Single Crystal Diffraction data imported from CIF"); (*fpObjCrystInformUser)((boost::format("CIF: Importing SINGLE CRYSTAL DIFFRACTION data: creating new empty Crystal structure")).str()); } } pData=new DiffractionDataSingleCrystal(*pcryst); pData->SetHklIobs(pos->second.mH,pos->second.mK,pos->second.mL,pos->second.mIobs,pos->second.mSigma); if(pData->GetName()=="") pData->SetName(name); (*fpObjCrystInformUser)((boost::format("CIF: Imported SINGLE CRYSTAL DIFFRACTION data, with %d reflections") % pData->GetNbRefl()).str()); } } return pData; } }//namespace objcryst-2022.1/ObjCryst/ObjCryst/CIF.h000066400000000000000000000261561430515525000175210ustar00rootroot00000000000000#ifndef _OBJCRYST_CIF_H #define _OBJCRYST_CIF_H #include #include #include #include #include #include #include #include "ObjCryst/Quirks/ci_string.h" namespace ObjCryst {// Forward declaration class CIF; } #include "ObjCryst/ObjCryst/PowderPattern.h" // For CreatePowderPatternFromCIF only. #include "ObjCryst/ObjCryst/DiffractionDataSingleCrystal.h" // For CreateSingleCrystalDataFromCIF only. #include "ObjCryst/ObjCryst/Crystal.h" // For CreateCrystalFromCIF only. #include "ObjCryst/ObjCryst/General.h" // TO identify wavelength type in CIFData::ExtractPowderPattern. namespace ObjCryst { /// Convert one CIF value to a floating-point value /// Return 0 if no value can be converted (e.g. if '.' or '?' is encountered) REAL CIFNumeric2REAL(const std::string &s); /// Convert one CIF value to a floating-point value /// Return 0 if no value can be converted (e.g. if '.' or '?' is encountered) int CIFNumeric2Int(const std::string &s); /** The CIFData class holds all the information from a \e single data_ block from a cif file. * * It is a placeholder for all comments, item and loop data, as raw strings copied from * a cif file. * * It is also used to interpret this data to extract parts of the cif data, i.e. * only part of the core cif dictionnary are recognized. CIF tags currently recognized * include ("tag1 > tag2" means tag1 is preferred to tag2 when extracting the info, only one is reported): * - crystal name: _chemical_name_systematic > _chemical_name_mineral > _chemical_name_structure_type > _chemical_name_common * - crystal formula: _chemical_formula_analytical > _chemical_formula_structural > _chemical_formula_iupac > _chemical_formula_moiety * - unit cell: _cell_length_{a,b,c} ; _cell_angle_{alpha,beta,gamma} * - spacegroup number: _space_group_IT_number > _symmetry_Int_Tables_number * - spacegroup Hall symbol: _space_group_name_Hall > _symmetry_space_group_name_Hall * - spacegroup Hermann-Mauguin symbol:_space_group_name_H-M_alt > _symmetry_space_group_name_H-M * - atom coordinates: _atom_site_fract_{x} ; _atom_site_Cartn_{x,y,z} * - atom occupancy: _atom_site_occupancy * - atom label & symbol: _atom_site_type_symbol ; _atom_site_label * - atom adps: _atom_site_aniso_{U,B}_{11,22,33,12,13,23} > _atom_site_{U,B}_iso_or_equiv * * * Cartesian coordinates are stored in Angstroems, angles in radians. * * To import PowderPattern data, the following tags are used: * - observed intensity: _pd_meas_counts_total > _pd_meas_intensity_total > _pd_proc_intensity_total > _pd_proc_intensity_net * - uncertainty on intensity: deducted from _pd_proc_ls_weight or square root of intensity * - coordinates: _pd_proc_2theta_corrected > _pd_meas_angle_2theta > _pd_meas_time_of_flight > _pd_proc_2theta_range_{min,max,inc} * - intensity normalizer (optional): _pd_meas_intensity_monitor > _pd_meas_step_count_time * * If another data field is needed, it is possible to directly access the string data * (CIFData::mvComment , CIFData::mvItem and CIFData::mvLoop) to search for the correct tags. */ class CIFData { public: CIFData(); /// Extract lattice parameters, spacegroup (symbol or number), atomic positions, /// chemical name and formula if available. /// All other data is ignored void ExtractAll(const bool verbose=false); /// Extract name & formula for the crystal void ExtractName(const bool verbose=false); /// Extract unit cell void ExtractUnitCell(const bool verbose=false); /// Extract spacegroup number or symbol void ExtractSpacegroup(const bool verbose=false); /// Extract all atomic positions. Will generate cartesian from fractional /// coordinates or vice-versa if only cartesian coordinates are available. void ExtractAtomicPositions(const bool verbose=false); /// Extract anisotropic atomic displacement parameters. Isotropic ADPs // may be extracted in ExtractAtomicPositions. This takes prescedent. void ExtractAnisotropicADPs(const bool verbose=false); /// Extract Powder Diffraction data, with Iobs, sigma(Iobs) and either 2theta /// or time-of-flight position. void ExtractPowderPattern(const bool verbose=false); /// Extract single crystal data, with Iobs, sigma(Iobs) and h,k,l void ExtractSingleCrystalData(const bool verbose=false); /// Generate fractional coordinates from cartesian ones for all atoms /// CIFData::CalcMatrices() must be called first void Cartesian2FractionalCoord(); /// Generate cartesian coordinates from fractional ones for all atoms /// CIFData::CalcMatrices() must be called first void Fractional2CartesianCoord(); /// Convert from fractional to cartesian coordinates /// CIFData::CalcMatrices() must be called first void f2c(REAL &x,REAL &y, REAL &z); /// Convert from cartesia to fractional coordinates /// CIFData::CalcMatrices() must be called first void c2f(REAL &x,REAL &y, REAL &z); /// Calculate real space transformation matrices /// requires unit cell parameters void CalcMatrices(const bool verbose=false); /// Comments from CIF file, in the order they were read std::list mvComment; /// Individual CIF items std::map mvItem; /// CIF Loop data std::map,std::map > > mvLoop; /// Lattice parameters, in ansgtroem and degrees - vector size is 0 if no /// parameters have been obtained yet. std::vector mvLatticePar; /// Spacegroup number from International Tables (_space_group_IT_number), or -1. std::string mSpacegroupNumberIT; /// Spacegroup Hall symbol (or empty string) (_space_group_name_Hall) std::string mSpacegroupSymbolHall; /// Spacegroup Hermann-Mauguin symbol (or empty string) (_space_group_name_H-M_alt) std::string mSpacegroupHermannMauguin; /// Map of _symmetry_equiv_pos_as_xyz strings std::set mvSymmetry_equiv_pos_as_xyz; /// Crystal name. Or empty string if none is available. std::string mName; /// Formula. Or empty string if none is available. std::string mFormula; /// Atom record struct CIFAtom { CIFAtom(); /// Label of the atom, or empty string (_atom_site_label). std::string mLabel; /// Symbol of the atom, or empty string (_atom_type_symbol or _atom_site_type_symbol). std::string mSymbol; /// Fractionnal coordinates (_atom_site_fract_{x,y,z}) or empty vector. std::vector mCoordFrac; /// Cartesian coordinates in Angstroem (_atom_site_Cartn_{x,y,z}) or empty vector. /// Transformation to fractionnal coordinates currently assumes /// "a parallel to x; b in the plane of y and z" (see _atom_sites_Cartn_transform_axes) std::vector mCoordCart; /// Site occupancy, or -1 REAL mOccupancy; /// ADP tensor std::vector mBeta; /// Biso REAL mBiso; }; /// Atoms, if any are found std::vector mvAtom; /// Fractionnal2Cartesian matrix REAL mOrthMatrix[3][3]; /// Cartesian2Fractionnal matrix REAL mOrthMatrixInvert[3][3]; /// Powder pattern data std::vector mPowderPatternObs,mPowderPatternX,mPowderPatternSigma; /// Single crystal data CrystVector_long mH,mK,mL; /// Single crystal data CrystVector_REAL mIobs,mSigma; /// Is this X-Ray 2theta, time-of-flight ? WavelengthType mDataType; /// Wavelength REAL mWavelength; }; /** Main CIF class - parses the stream and separates data blocks, comments, items, loops. * All values are stored as string, and Each CIF block is stored in a separate CIFData object. * No interpretaion is made here - this must be done from all CIFData objects. */ class CIF { public: /// Creates the CIF object from a stream /// /// \param interpret: if true, interpret all data blocks. See CIFData::ExtractAll() CIF(std::istream &in, const bool interpret=true,const bool verbose=false); //private: /// Separate the file in data blocks and parse them to sort tags, loops and comments. /// All is stored in the original strings. void Parse(std::stringstream &in); /// The data blocks, after parsing. The key is the name of the data block std::map mvData; /// Global comments, outside and data block std::list mvComment; }; // Forward declarations class Crystal; class PowderPattern; /** Extract Crystal object(s) from a CIF, if possible. * Returns a null pointer if no crystal structure could be extracted * (the minimum data is the unit cell parameters). * * \param checkSymAsXYZ: if true, and the CIF file does not have a Hall symbol * but has a list of symmetry_equiv_pos_as_xyz, check we have the correct * setting by trying different ones using cctbx */ Crystal* CreateCrystalFromCIF(CIF &cif,const bool verbose=true,const bool checkSymAsXYZ=true); /** Extract Crystal object(s) from a CIF, if possible. * Returns a null pointer if no crystal structure could be extracted * (the minimum data is the unit cell parameters). * * \param checkSymAsXYZ: if true, and the CIF file does not have a Hall symbol * but has a list of symmetry_equiv_pos_as_xyz, check we have the correct * setting by trying different ones using cctbx * \param oneScatteringPowerPerElement: if false (the default), then there will be as many * ScatteringPowerAtom created as there are different elements. If true, * only one will be created per element, avoiding a large number of scattering powers * e.g. when importing CIFs obtained from single crystal data refinement. * \param connectAtoms: if true, call Crystal::ConnectAtoms to try to create as many Molecules * as possible from the list of imported atoms. * \param pcryst: a pointer to an existing Crystal can be given. In this case, * only the first Crystal structure found is imported from the CIF. The given * Crystal is assumed to be empty. * \warning The behaviour of oneScatteringPowerPerElement has changed [2016/11/11]: * when set to false, it will return one scattering power per atom, where as prior to this * change, scattering powers where identical for identical Debye-Waller factors. */ Crystal* CreateCrystalFromCIF(CIF &cif,const bool verbose,const bool checkSymAsXYZ, const bool oneScatteringPowerPerElement, const bool connectAtoms, Crystal *pcryst=NULL); /// Create PowderPattern object(s) from a CIF, if possible. /// Returns a null pointer if no pattern could be extracted. /// No components (background, crystal data) are created. PowderPattern* CreatePowderPatternFromCIF(CIF &cif); /// Create DiffractionDataSingleCrystal object(s) from a CIF, if possible. /// Returns a null pointer if no data could be extracted. /// A Crystal object must be supplied - if none is given, the last Crystal /// object will be used. If no Cyrstal data exists, a new one will be created. DiffractionDataSingleCrystal* CreateSingleCrystalDataFromCIF(CIF &cif, Crystal *pryst=0); } #endif objcryst-2022.1/ObjCryst/ObjCryst/Colours.h000066400000000000000000000260011430515525000205330ustar00rootroot00000000000000/* Colour definitions from POVRay (http://www.povray.org) */ #ifndef __OBJCRYST_COULOURS_H #define __OBJCRYST_COULOURS_H struct POVRayColours { const char *mName; REAL mRGB[3]; }; /** Colours from POVRay (first part) and Jmol *(converted to floats from jmol_constants.java) */ const POVRayColours gPOVRayColours[]= { {"Red", { 1, 0, 0}}, {"Green", { 0, 1, 0}}, {"Blue", { 0, 0, 1}}, {"Yellow", { 1, 1, 0}}, {"Cyan", { 0, 1, 1}}, {"Magenta", { 1, 0, 1}}, {"Clear", { 1, 1, 1}}, {"White", { 1, 1, 1}}, {"Black", { 0, 0, 0}}, {"Gray05", { 0.05, 0.05, 0.05}}, {"Gray10", { .10, .10, .10}}, {"Gray15", { 0.15, 0.15, 0.15}}, {"Gray20", { 0.20, 0.20, 0.20}}, {"Gray25", { 0.25, 0.25, 0.25}}, {"Gray30", { 0.30, 0.30, 0.30}}, {"Gray35", { 0.35, 0.35, 0.35}}, {"Gray40", { 0.40, 0.40, 0.40}}, {"Gray45", { 0.45, 0.45, 0.45}}, {"Gray50", { 0.50, 0.50, 0.50}}, {"Gray55", { 0.55, 0.55, 0.55}}, {"Gray60", { 0.60, 0.60, 0.60}}, {"Gray65", { 0.65, 0.65, 0.65}}, {"Gray70", { 0.70, 0.70, 0.70}}, {"Gray75", { 0.75, 0.75, 0.75}}, {"Gray80", { 0.80, 0.80, 0.80}}, {"Gray85", { 0.85, 0.85, 0.85}}, {"Gray90", { 0.90, 0.90, 0.90}}, {"Gray95", { 0.95, 0.95, 0.95}}, {"DimGray", { 0.329412 , 0.329412 , 0.329412}}, {"DimGrey", { 0.329412 , 0.329412 , 0.329412}}, {"Gray", { 0.752941 , 0.752941 , 0.752941}}, {"Grey", { 0.752941 , 0.752941 , 0.752941}}, {"LightGray", { 0.658824 , 0.658824 , 0.658824}}, {"LightGrey", { 0.658824 , 0.658824 , 0.658824}}, {"VLightGray", { 0.80 , 0.80 , 0.80}}, {"VLightGrey", { 0.80 , 0.80 , 0.80}}, {"Aquamarine", { 0.439216 , 0.858824 , 0.576471}}, {"BlueViolet", { 0.62352 , 0.372549 , 0.623529}}, {"Brown", { 0.647059 , 0.164706 , 0.164706}}, {"CadetBlue", { 0.372549 , 0.623529 , 0.623529}}, {"Coral", { 1.0 , 0.498039 , 0.0}}, {"CornflowerBlue", { 0.258824 , 0.258824 , 0.435294}}, {"DarkGreen", { 0.184314 , 0.309804 , 0.184314}}, {"DarkOliveGreen", { 0.309804 , 0.309804 , 0.184314}}, {"DarkOrchid", { 0.6 , 0.196078 , 0.8}}, {"DarkSlateBlue", { 0.119608 , 0.137255 , 0.556863}}, {"DarkSlateGray", { 0.184314 , 0.309804 , 0.309804}}, {"DarkSlateGrey", { 0.184314 , 0.309804 , 0.309804}}, {"DarkTurquoise", { 0.439216 , 0.576471 , 0.858824}}, {"Firebrick", { 0.556863 , 0.137255 , 0.137255}}, {"ForestGreen", { 0.137255 , 0.556863 , 0.137255}}, {"Gold", { 0.8 , 0.498039 , 0.196078}}, {"Goldenrod", { 0.858824 , 0.858824 , 0.439216}}, {"GreenYellow", { 0.576471 , 0.858824 , 0.439216}}, {"IndianRed", { 0.309804 , 0.184314 , 0.184314}}, {"Khaki", { 0.623529 , 0.623529 , 0.372549}}, {"LightBlue", { 0.74902 , 0.847059 , 0.847059}}, {"LightSteelBlue", { 0.560784 , 0.560784 , 0.737255}}, {"LimeGreen", { 0.196078 , 0.8 , 0.196078}}, {"Maroon", { 0.556863 , 0.137255 , 0.419608}}, {"MediumAquamarine", { 0.196078 , 0.8 , 0.6}}, {"MediumBlue", { 0.196078 , 0.196078 , 0.8}}, {"MediumForestGreen", { 0.419608 , 0.556863 , 0.137255}}, {"MediumGoldenrod", { 0.917647 , 0.917647 , 0.678431}}, {"MediumOrchid", { 0.576471 , 0.439216 , 0.858824}}, {"MediumSeaGreen", { 0.258824 , 0.435294 , 0.258824}}, {"MediumSlateBlue", { 0.498039 , 1.0}}, {"MediumSpringGreen", { 0.498039 , 1.0}}, {"MediumTurquoise", { 0.439216 , 0.858824 , 0.858824}}, {"MediumVioletRed", { 0.858824 , 0.439216 , 0.576471}}, {"MidnightBlue", { 0.184314 , 0.184314 , 0.309804}}, {"Navy", { 0.137255 , 0.137255 , 0.556863}}, {"NavyBlue", { 0.137255 , 0.137255 , 0.556863}}, {"Orange", { 1 , 0.5 , 0.0}}, {"OrangeRed", { 1.0 , 0.25}}, {"Orchid", { 0.858824 , 0.439216 , 0.858824}}, {"PaleGreen", { 0.560784 , 0.737255 , 0.560784}}, {"Pink", { 0.737255 , 0.560784 , 0.560784}}, {"Plum", { 0.917647 , 0.678431 , 0.917647}}, {"Salmon", { 0.435294 , 0.258824 , 0.258824}}, {"SeaGreen", { 0.137255 , 0.556863 , 0.419608}}, {"Sienna", { 0.556863 , 0.419608 , 0.137255}}, {"SkyBlue", { 0.196078 , 0.6 , 0.8}}, {"SlateBlue", { 0., 0.498039 , 1.0}}, {"SpringGreen", {0. , 1.0 , 0.498039}}, {"SteelBlue", { 0.137255 , 0.419608 , 0.556863}}, {"Tan", { 0.858824 , 0.576471 , 0.439216}}, {"Thistle", { 0.847059 , 0.74902 , 0.847059}}, {"Turquoise", { 0.678431 , 0.917647 , 0.917647}}, {"Violet", { 0.309804 , 0.184314 , 0.309804}}, {"VioletRed", { 0.8 , 0.196078 , 0.6}}, {"Wheat", { 0.847059 , 0.847059 , 0.74902}}, {"YellowGreen", { 0.6 , 0.8 , 0.196078}}, {"SummerSky", { 0.22 , 0.69 , 0.87}}, {"RichBlue", { 0.35 , 0.35 , 0.67}}, {"Brass", { 0.71 , 0.65 , 0.26}}, {"Copper", { 0.72 , 0.45 , 0.20}}, {"Bronze", { 0.55 , 0.47 , 0.14}}, {"Bronze2", { 0.65 , 0.49 , 0.24}}, {"Silver", { 0.90 , 0.91 , 0.98}}, {"BrightGold", { 0.85 , 0.85 , 0.10}}, {"OldGold", { 0.81 , 0.71 , 0.23}}, {"Feldspar", { 0.82 , 0.57 , 0.46}}, {"Quartz", { 0.85 , 0.85 , 0.95}}, {"Mica", { 0, 0, 0}}, {"NeonPink", { 1.00 , 0.43 , 0.78}}, {"DarkPurple", { 0.53 , 0.12 , 0.47}}, {"NeonBlue", { 0.30 , 0.30 , 1.00}}, {"CoolCopper", { 0.85 , 0.53 , 0.10}}, {"MandarinOrange", { 0.89 , 0.47 , 0.20}}, {"LightWood", { 0.91 , 0.76 , 0.65}}, {"MediumWood", { 0.65 , 0.50 , 0.39}}, {"DarkWood", { 0.52 , 0.37 , 0.26}}, {"SpicyPink", { 1.00 , 0.11 , 0.68}}, {"SemiSweetChoc", { 0.42 , 0.26 , 0.15}}, {"BakersChoc", { 0.36 , 0.20 , 0.09}}, {"Flesh", { 0.96 , 0.80 , 0.69}}, {"NewTan", { 0.92 , 0.78 , 0.62}}, {"NewMidnightBlue", { 0.00 , 0.00 , 0.61}}, {"VeryDarkBrown", { 0.35 , 0.16 , 0.14}}, {"DarkBrown", { 0.36 , 0.25 , 0.20}}, {"DarkTan", { 0.59 , 0.41 , 0.31}}, {"GreenCopper", { 0.32 , 0.49 , 0.46}}, {"DkGreenCopper", { 0.29 , 0.46 , 0.43}}, {"DustyRose", { 0.52 , 0.39 , 0.39}}, {"HuntersGreen", { 0.13 , 0.37 , 0.31}}, {"Scarlet", { 0.55 , 0.09 , 0.09}}, {"Med_Purple", { 0.73 , 0.16 , 0.96}}, {"Light_Purple", { 0.87 , 0.58 , 0.98}}, {"Very_Light_Purple", { 0.94 , 0.81 , 0.99}}, {"H", {1.000, 1.000, 1.000}}, //Z= 1 {"He", {0.851, 1.000, 1.000}}, //Z= 2 {"Li", {0.800, 0.502, 1.000}}, //Z= 3 {"Be", {0.761, 1.000, 0.000}}, //Z= 4 {"B", {1.000, 0.710, 0.710}}, //Z= 5 {"C", {0.565, 0.565, 0.565}}, //Z= 6 {"N", {0.188, 0.314, 0.973}}, //Z= 7 {"O", {1.000, 0.051, 0.051}}, //Z= 8 {"F", {0.565, 0.878, 0.314}}, //Z= 9 {"Ne", {0.702, 0.890, 0.961}}, //Z= 10 {"Na", {0.671, 0.361, 0.949}}, //Z= 11 {"Mg", {0.541, 1.000, 0.000}}, //Z= 12 {"Al", {0.749, 0.651, 0.651}}, //Z= 13 {"Si", {0.941, 0.784, 0.627}}, //Z= 14 {"P", {1.000, 0.502, 0.000}}, //Z= 15 {"S", {1.000, 1.000, 0.188}}, //Z= 16 {"Cl", {0.122, 0.941, 0.122}}, //Z= 17 {"Ar", {0.502, 0.820, 0.890}}, //Z= 18 {"K", {0.561, 0.251, 0.831}}, //Z= 19 {"Ca", {0.239, 1.000, 0.000}}, //Z= 20 {"Sc", {0.902, 0.902, 0.902}}, //Z= 21 {"Ti", {0.749, 0.761, 0.780}}, //Z= 22 {"V", {0.651, 0.651, 0.671}}, //Z= 23 {"Cr", {0.541, 0.600, 0.780}}, //Z= 24 {"Mn", {0.612, 0.478, 0.780}}, //Z= 25 {"Fe", {0.878, 0.400, 0.200}}, //Z= 26 {"Co", {0.941, 0.565, 0.627}}, //Z= 27 {"Ni", {0.314, 0.816, 0.314}}, //Z= 28 {"Cu", {0.784, 0.502, 0.200}}, //Z= 29 {"Zn", {0.490, 0.502, 0.690}}, //Z= 30 {"Ga", {0.761, 0.561, 0.561}}, //Z= 31 {"Ge", {0.400, 0.561, 0.561}}, //Z= 32 {"As", {0.741, 0.502, 0.890}}, //Z= 33 {"Se", {1.000, 0.631, 0.000}}, //Z= 34 {"Br", {0.651, 0.161, 0.161}}, //Z= 35 {"Kr", {0.361, 0.722, 0.820}}, //Z= 36 {"Rb", {0.439, 0.180, 0.690}}, //Z= 37 {"Sr", {0.000, 1.000, 0.000}}, //Z= 38 {"Y", {0.580, 1.000, 1.000}}, //Z= 39 {"Zr", {0.580, 0.878, 0.878}}, //Z= 40 {"Nb", {0.451, 0.761, 0.788}}, //Z= 41 {"Mo", {0.329, 0.710, 0.710}}, //Z= 42 {"Tc", {0.231, 0.620, 0.620}}, //Z= 43 {"Ru", {0.141, 0.561, 0.561}}, //Z= 44 {"Rh", {0.039, 0.490, 0.549}}, //Z= 45 {"Pd", {0.000, 0.412, 0.522}}, //Z= 46 {"Ag", {0.753, 0.753, 0.753}}, //Z= 47 {"Cd", {1.000, 0.851, 0.561}}, //Z= 48 {"In", {0.651, 0.459, 0.451}}, //Z= 49 {"Sn", {0.400, 0.502, 0.502}}, //Z= 50 {"Sb", {0.620, 0.388, 0.710}}, //Z= 51 {"Te", {0.831, 0.478, 0.000}}, //Z= 52 {"I", {0.580, 0.000, 0.580}}, //Z= 53 {"Xe", {0.259, 0.620, 0.690}}, //Z= 54 {"Cs", {0.341, 0.090, 0.561}}, //Z= 55 {"Ba", {0.000, 0.788, 0.000}}, //Z= 56 {"La", {0.439, 0.831, 1.000}}, //Z= 57 {"Ce", {1.000, 1.000, 0.780}}, //Z= 58 {"Pr", {0.851, 1.000, 0.780}}, //Z= 59 {"Nd", {0.780, 1.000, 0.780}}, //Z= 60 {"Pm", {0.639, 1.000, 0.780}}, //Z= 61 {"Sm", {0.561, 1.000, 0.780}}, //Z= 62 {"Eu", {0.380, 1.000, 0.780}}, //Z= 63 {"Gd", {0.271, 1.000, 0.780}}, //Z= 64 {"Tb", {0.188, 1.000, 0.780}}, //Z= 65 {"Dy", {0.122, 1.000, 0.780}}, //Z= 66 {"Ho", {0.000, 1.000, 0.612}}, //Z= 67 {"Er", {0.000, 0.902, 0.459}}, //Z= 68 {"Tm", {0.000, 0.831, 0.322}}, //Z= 69 {"Yb", {0.000, 0.749, 0.220}}, //Z= 70 {"Lu", {0.000, 0.671, 0.141}}, //Z= 71 {"Hf", {0.302, 0.761, 1.000}}, //Z= 72 {"Ta", {0.302, 0.651, 1.000}}, //Z= 73 {"W", {0.129, 0.580, 0.839}}, //Z= 74 {"Re", {0.149, 0.490, 0.671}}, //Z= 75 {"Os", {0.149, 0.400, 0.588}}, //Z= 76 {"Ir", {0.090, 0.329, 0.529}}, //Z= 77 {"Pt", {0.816, 0.816, 0.878}}, //Z= 78 {"Au", {1.000, 0.820, 0.137}}, //Z= 79 {"Hg", {0.722, 0.722, 0.816}}, //Z= 80 {"Tl", {0.651, 0.329, 0.302}}, //Z= 81 {"Pb", {0.341, 0.349, 0.380}}, //Z= 82 {"Bi", {0.620, 0.310, 0.710}}, //Z= 83 {"Po", {0.671, 0.361, 0.000}}, //Z= 84 {"At", {0.459, 0.310, 0.271}}, //Z= 85 {"Rn", {0.259, 0.510, 0.588}}, //Z= 86 {"Fr", {0.259, 0.000, 0.400}}, //Z= 87 {"Ra", {0.000, 0.490, 0.000}}, //Z= 88 {"Ac", {0.439, 0.671, 0.980}}, //Z= 89 {"Th", {0.000, 0.729, 1.000}}, //Z= 90 {"Pa", {0.000, 0.631, 1.000}}, //Z= 91 {"U", {0.000, 0.561, 1.000}}, //Z= 92 {"Np", {0.000, 0.502, 1.000}}, //Z= 93 {"Pu", {0.000, 0.420, 1.000}}, //Z= 94 {"Am", {0.329, 0.361, 0.949}}, //Z= 95 {"Cm", {0.471, 0.361, 0.890}}, //Z= 96 {"Bk", {0.541, 0.310, 0.890}}, //Z= 97 {"Cf", {0.631, 0.212, 0.831}}, //Z= 98 {"Es", {0.702, 0.122, 0.831}}, //Z= 99 {"Fm", {0.702, 0.122, 0.729}}, //Z=100 {"Md", {0.702, 0.051, 0.651}}, //Z=101 {"No", {0.741, 0.051, 0.529}}, //Z=102 {"Lr", {0.780, 0.000, 0.400}}, //Z=103 {"Rf", {0.800, 0.000, 0.349}}, //Z=104 {"Db", {0.820, 0.000, 0.310}}, //Z=105 {"Sg", {0.851, 0.000, 0.271}}, //Z=106 {"Bh", {0.878, 0.000, 0.220}}, //Z=107 {"Hs", {0.902, 0.000, 0.180}}, //Z=108 {"Mt", {0.922, 0.000, 0.149}}, //Z=109 {"",{0. , 0. , 0.}}, }; #endif objcryst-2022.1/ObjCryst/ObjCryst/Crystal.cpp000066400000000000000000002507351430515525000210760ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * source file LibCryst++ Crystal class * */ #include #include #include #include #include #include "cctbx/sgtbx/space_group.h" #include "ObjCryst/ObjCryst/Crystal.h" #include "ObjCryst/ObjCryst/Molecule.h" #include "ObjCryst/ObjCryst/Atom.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" //simple formatting of integers, REALs.. #include "ObjCryst/Quirks/VFNDebug.h" #ifdef __WX__CRYST__ #include "ObjCryst/wxCryst/wxCrystal.h" #endif #include #include namespace ObjCryst { const RefParType *gpRefParTypeCrystal=0; long NiftyStaticGlobalObjectsInitializer_Crystal::mCount=0; //////////////////////////////////////////////////////////////////////// // // CRYSTAL : the crystal (Unit cell, spaceGroup, scatterers) // //////////////////////////////////////////////////////////////////////// ObjRegistry gCrystalRegistry("List of all Crystals"); Crystal::Crystal(): mScattererRegistry("List of Crystal Scatterers"), mBumpMergeCost(0.0),mBumpMergeScale(1.0), mDistTableMaxDistance(1.0), mScatteringPowerRegistry("List of Crystal ScatteringPowers"), mBondValenceCost(0.0),mBondValenceCostScale(1.0),mDeleteSubObjInDestructor(1) { VFN_DEBUG_MESSAGE("Crystal::Crystal()",10) this->InitOptions(); this->Init(10,11,12,M_PI/2+.1,M_PI/2+.2,M_PI/2+.3,"P 1",""); gCrystalRegistry.Register(*this); gTopRefinableObjRegistry.Register(*this); mClockMaster.AddChild(mLatticeClock); mClockMaster.AddChild(this->mScattererRegistry.GetRegistryClock()); mClockMaster.AddChild(this->mScatteringPowerRegistry.GetRegistryClock()); } Crystal::Crystal(const REAL a, const REAL b, const REAL c, const string &SpaceGroupId): mScattererRegistry("List of Crystal Scatterers"), mBumpMergeCost(0.0),mBumpMergeScale(1.0), mDistTableMaxDistance(1.0), mScatteringPowerRegistry("List of Crystal ScatteringPowers"), mBondValenceCost(0.0),mBondValenceCostScale(1.0),mDeleteSubObjInDestructor(1) { VFN_DEBUG_MESSAGE("Crystal::Crystal(a,b,c,Sg)",10) this->Init(a,b,c,M_PI/2,M_PI/2,M_PI/2,SpaceGroupId,""); this->InitOptions(); gCrystalRegistry.Register(*this); gTopRefinableObjRegistry.Register(*this); mClockMaster.AddChild(mLatticeClock); mClockMaster.AddChild(this->mScattererRegistry.GetRegistryClock()); mClockMaster.AddChild(this->mScatteringPowerRegistry.GetRegistryClock()); } Crystal::Crystal(const REAL a, const REAL b, const REAL c, const REAL alpha, const REAL beta, const REAL gamma,const string &SpaceGroupId): mScattererRegistry("List of Crystal Scatterers"), mBumpMergeCost(0.0),mBumpMergeScale(1.0), mDistTableMaxDistance(1.0), mScatteringPowerRegistry("List of Crystal ScatteringPowers"), mBondValenceCost(0.0),mBondValenceCostScale(1.0),mDeleteSubObjInDestructor(1) { VFN_DEBUG_MESSAGE("Crystal::Crystal(a,b,c,alpha,beta,gamma,Sg)",10) this->Init(a,b,c,alpha,beta,gamma,SpaceGroupId,""); this->InitOptions(); gCrystalRegistry.Register(*this); gTopRefinableObjRegistry.Register(*this); mClockMaster.AddChild(mLatticeClock); mClockMaster.AddChild(this->mScattererRegistry.GetRegistryClock()); mClockMaster.AddChild(this->mScatteringPowerRegistry.GetRegistryClock()); } Crystal::Crystal(const Crystal &old): mScattererRegistry("List of Crystal Scatterers"), mBumpMergeCost(0.0),mBumpMergeScale(1.0), mDistTableMaxDistance(1.0), mScatteringPowerRegistry("List of Crystal ScatteringPowers"), mBondValenceCost(0.0),mBondValenceCostScale(1.0),mDeleteSubObjInDestructor(1) { VFN_DEBUG_MESSAGE("Crystal::Crystal()",10) // Only create a default crystal, then copy old using XML this->InitOptions(); this->Init(10,11,12,M_PI/2+.1,M_PI/2+.2,M_PI/2+.3,"P 1",""); gCrystalRegistry.Register(*this); gTopRefinableObjRegistry.Register(*this); mClockMaster.AddChild(mLatticeClock); mClockMaster.AddChild(this->mScattererRegistry.GetRegistryClock()); mClockMaster.AddChild(this->mScatteringPowerRegistry.GetRegistryClock()); stringstream sst; old.XMLOutput(sst); XMLCrystTag tag(sst); this->XMLInput(sst,tag); } Crystal::~Crystal() { VFN_DEBUG_ENTRY("Crystal::~Crystal()",5) for(long i=0;iRemoveSubRefObj(mScattererRegistry.GetObj(i)); mScattererRegistry.GetObj(i).DeRegisterClient(*this); } if( mDeleteSubObjInDestructor ) { mScattererRegistry.DeleteAll(); } else { mScattererRegistry.DeRegisterAll(); } for(long i=0;iRemoveSubRefObj(mScatteringPowerRegistry.GetObj(i)); mScatteringPowerRegistry.GetObj(i).DeRegisterClient(*this); // :TODO: check if it is not used by another Crystal (forbidden!) } if( mDeleteSubObjInDestructor ) { mScatteringPowerRegistry.DeleteAll(); } else { mScatteringPowerRegistry.DeRegisterAll(); } gCrystalRegistry.DeRegister(*this); gTopRefinableObjRegistry.DeRegister(*this); VFN_DEBUG_EXIT("Crystal::~Crystal()",5) } const string& Crystal::GetClassName() const { const static string className="Crystal"; return className; } void Crystal::AddScatterer(Scatterer *scatt) { VFN_DEBUG_ENTRY("Crystal::AddScatterer(&scatt)",5) mScattererRegistry.Register(*scatt); scatt->RegisterClient(*this); this->AddSubRefObj(*scatt); scatt->SetCrystal(*this); mClockScattererList.Click(); VFN_DEBUG_EXIT("Crystal::AddScatterer(&scatt):Finished",5) } void Crystal::RemoveScatterer(Scatterer *scatt, const bool del) { VFN_DEBUG_MESSAGE("Crystal::RemoveScatterer(&scatt)",5) mScattererRegistry.DeRegister(*scatt); scatt->DeRegisterClient(*this); this->RemoveSubRefObj(*scatt); if(del) delete scatt; mClockScattererList.Click(); VFN_DEBUG_MESSAGE("Crystal::RemoveScatterer(&scatt):Finished",5) } long Crystal::GetNbScatterer()const {return mScattererRegistry.GetNb();} Scatterer& Crystal::GetScatt(const string &scattName) { return mScattererRegistry.GetObj(scattName); } const Scatterer& Crystal::GetScatt(const string &scattName) const { return mScattererRegistry.GetObj(scattName); } Scatterer& Crystal::GetScatt(const long scattIndex) { return mScattererRegistry.GetObj(scattIndex); } const Scatterer& Crystal::GetScatt(const long scattIndex) const { return mScattererRegistry.GetObj(scattIndex); } ObjRegistry& Crystal::GetScattererRegistry() {return mScattererRegistry;} const ObjRegistry& Crystal::GetScattererRegistry() const {return mScattererRegistry;} ObjRegistry& Crystal::GetScatteringPowerRegistry() {return mScatteringPowerRegistry;} const ObjRegistry& Crystal::GetScatteringPowerRegistry() const {return mScatteringPowerRegistry;} void Crystal::AddScatteringPower(ScatteringPower *scattPow) { mScatteringPowerRegistry.Register(*scattPow); scattPow->RegisterClient(*this);//:TODO: Should register as (unique) 'owner'. this->AddSubRefObj(*scattPow); mClockMaster.AddChild(scattPow->GetClockMaster()); mClockMaster.AddChild(scattPow->GetMaximumLikelihoodParClock()); mMasterClockScatteringPower.AddChild(scattPow->GetClockMaster()); } void Crystal::RemoveScatteringPower(ScatteringPower *scattPow, const bool del) { VFN_DEBUG_ENTRY("Crystal::RemoveScatteringPower()",2) mScatteringPowerRegistry.DeRegister(*scattPow); this->RemoveSubRefObj(*scattPow); mClockMaster.RemoveChild(scattPow->GetClockMaster()); mClockMaster.RemoveChild(scattPow->GetMaximumLikelihoodParClock()); mMasterClockScatteringPower.RemoveChild(scattPow->GetClockMaster()); if(del) delete scattPow; for(Crystal::VBumpMergePar::iterator pos=mvBumpMergePar.begin();pos!=mvBumpMergePar.end();) { if((pos->first.first==scattPow)||(pos->first.second==scattPow)) { mvBumpMergePar.erase(pos++); mBumpMergeParClock.Click(); } else ++pos;// See Josuttis Std C++ Lib p.205 for safe method } for(map, REAL>::iterator pos=mvBondValenceRo.begin();pos!=mvBondValenceRo.end();) { if((pos->first.first==scattPow)||(pos->first.second==scattPow)) { mvBondValenceRo.erase(pos++); mBondValenceParClock.Click(); } else ++pos;// See Josuttis Std C++ Lib p.205 for safe method } VFN_DEBUG_EXIT("Crystal::RemoveScatteringPower()",2) } ScatteringPower& Crystal::GetScatteringPower(const string &name) { return mScatteringPowerRegistry.GetObj(name); } const ScatteringPower& Crystal::GetScatteringPower(const string &name)const { return mScatteringPowerRegistry.GetObj(name); } const RefinableObjClock& Crystal::GetMasterClockScatteringPower()const { return mMasterClockScatteringPower;} const ScatteringComponentList& Crystal::GetScatteringComponentList()const { if(mClockScattCompList>mClockMaster) return mScattCompList; bool update=false; if(mClockScattCompListGetClockLatticePar()) update=true; if(update==false) for(long i=0;iGetScatt(i).GetClockScatterer().Print(); if(mClockScattCompListGetScatt(i).GetClockScatterer()) {update=true;break;} } if(true==update) { VFN_DEBUG_MESSAGE("Crystal::GetScatteringComponentList()",2) TAU_PROFILE("Crystal::GetScatteringComponentList()","ScattCompList& ()",TAU_DEFAULT); mScattCompList.Reset(); for(long i=0;iGetScatt(i).GetScatteringComponentList().Print(); mScattCompList += this->GetScatt(i).GetScatteringComponentList(); } //:KLUDGE: this must be *before* calling CalcDynPopCorr() to avoid an infinite loop.. mClockScattCompList.Click(); if(1==mUseDynPopCorr.GetChoice()) this->CalcDynPopCorr(1.,.5); else this->ResetDynPopCorr(); VFN_DEBUG_MESSAGE("Crystal::GetScatteringComponentList():End",2) } #ifdef __DEBUG__ if(gVFNDebugMessageLevel<2) mScattCompList.Print(); #endif return mScattCompList; } const RefinableObjClock& Crystal::GetClockScattCompList()const { return mClockScattCompList; } void Crystal::Print(ostream &os)const { VFN_DEBUG_MESSAGE("Crystal::Print()",5) this->UnitCell::Print(os); this->GetScatteringComponentList(); this->CalcBondValenceSum(); os << "List of scattering components (atoms): " << mScattCompList.GetNbComponent() << endl ; long k=0; std::map::const_iterator posBV; for(int i=0;iPrint(); const ScatteringComponentList list=this->GetScatt(i).GetScatteringComponentList(); for(int j=0;jGetScatt(i).GetComponentName(j),16) << " at : " << FormatFloat(list(j).mX,7,4) << FormatFloat(list(j).mY,7,4) << FormatFloat(list(j).mZ,7,4) << ", Occup=" << FormatFloat(list(j).mOccupancy,6,4) << " * " << FormatFloat(mScattCompList(k).mDynPopCorr,6,4); // Check for dummy atoms if( NULL != list(j).mpScattPow ) { os << ", ScattPow:" << FormatString(list(j).mpScattPow->GetName(),16) << ", Biso=" << FormatFloat(list(j).mpScattPow->GetBiso()); } else { os << ", ScattPow: dummy"; } // Check for dummy atoms if( NULL != this->mScattCompList(k).mpScattPow ) { posBV=this->mvBondValenceCalc.find(k); if(posBV!=this->mvBondValenceCalc.end()) os <<": Valence="<second<<" (expected=" <mScattCompList(k).mpScattPow->GetFormalCharge()<<")"; } os << endl; k++; } } os < atom on a symetry plane / 2fold axis.."<< endl << " -> OR 2 atoms strictly overlapping)"<< endl <GetSpaceGroup().GetNbSymmetrics(); for(int i=0;iGetFormula() << endl << " Weight: "<< this->GetWeight()<< " g/mol" << endl; VFN_DEBUG_MESSAGE("Crystal::Print():End",5) } std::string Crystal::GetFormula() const { this->GetScatteringComponentList(); if(mScattCompList.GetNbComponent() == 0) return ""; std::map velts; for(unsigned int i=0; impScattPow == 0) continue; if(psi->mpScattPow->GetClassName().compare("ScatteringPowerAtom")!=0) continue; const ScatteringPowerAtom *pat=dynamic_cast(psi->mpScattPow); string p=pat->GetSymbol(); if(velts.count(p)==0) velts[p] = psi->mOccupancy * psi->mDynPopCorr ; else velts[p] += psi->mOccupancy * psi->mDynPopCorr; } stringstream s; s<::const_iterator pos=velts.begin();pos!=velts.end();++pos) { if(pos!=velts.begin()) s<<" "; float nb=pos->second; if(abs(round(nb)-nb)<0.005) { if(int(round(nb))==1) s<first; else s<first<first<GetScatteringComponentList(); if(mScattCompList.GetNbComponent() == 0) return 0; REAL w=0; for(unsigned int i=0; impScattPow == 0) continue; if(psi->mpScattPow->GetClassName().compare("ScatteringPowerAtom")!=0) continue; const ScatteringPowerAtom *pat=dynamic_cast(psi->mpScattPow); w += pat->GetAtomicWeight() * psi->mOccupancy * psi->mDynPopCorr ; } return w; } CrystMatrix_REAL Crystal::GetMinDistanceTable(const REAL minDistance) const { VFN_DEBUG_MESSAGE("Crystal::MinDistanceTable()",5) this->CalcDistTable(true); const long nbComponent=mScattCompList.GetNbComponent(); CrystMatrix_REAL minDistTable(nbComponent,nbComponent); REAL dist; REAL tmp; REAL min=minDistance*minDistance; if(minDistance<0) min = -1.;// no min distance minDistTable=10000.; for(int i=0;iGetMinDistanceTable(minDistance); VFN_DEBUG_MESSAGE("Crystal::PrintMinDistanceTable():0",5) os << "Table of minimal distances between all components (atoms)"<GetScatt(i).GetNbComponent();j++) os << FormatString(this->GetScatt(i).GetComponentName(j),7); } os << endl; long l=0; const long nbComponent=mScattCompList.GetNbComponent(); for(long i=0;iGetScatt(i).GetNbComponent();j++) { VFN_DEBUG_MESSAGE("Crystal::PrintMinDistanceTable()2:Scatt,comp:"<GetScatt(i).GetComponentName(j),14); for(long k=0;k0) os << FormatFloat(minDistTable(l,k),6,3) ; else os<<" >10 "; } os << endl; l++; } VFN_DEBUG_MESSAGE("Crystal::PrintMinDistanceTable():End",3) } ostream& Crystal::POVRayDescription(ostream &os,const CrystalPOVRayOptions &options)const { VFN_DEBUG_MESSAGE("Crystal::POVRayDescription(os,bool)",5) os <<"/////////////////////// MACROS////////////////////"<,atomr"<,"<,"<FractionalToOrthonormalCoords(x,y,z); os << " //box{ <0,0,0>, <"<< x << "," << y << "," << z << ">" <}" << endl; os << " // hollow" << endl; os << " //}" <FractionalToOrthonormalCoords(x0,y0,z0);\ this->FractionalToOrthonormalCoords(x1,y1,z1);\ os << " ObjCrystBond("\ <,1.0,1.0)"<;"<< endl; } os << "// Bond colours"<;"<< endl << " #declare colour_nonfreebond= rgb <0.3,0.3,0.3>;"<< endl; os<GetScatt(i).POVRayDescription(os,options) ; return os; } #ifdef OBJCRYST_GL void Crystal::GLInitDisplayList(const bool onlyIndependentAtoms, const REAL xMin,const REAL xMax, const REAL yMin,const REAL yMax, const REAL zMin,const REAL zMax, const bool displayNames, const bool hideHydrogens, const REAL fadeDistance, const bool fullMoleculeInLimits)const { VFN_DEBUG_ENTRY("Crystal::GLInitDisplayList()",5) REAL en=1;// if -1, display enantiomeric structure if(mDisplayEnantiomer.GetChoice()==1) en=-1; //Center of displayed unit REAL xc=(xMin+xMax)/2.; REAL yc=(yMin+yMax)/2.; REAL zc=(zMin+zMax)/2.; if(false==displayNames) { //Describe Unit Cell REAL x111= 1.; REAL y111= 1.; REAL z111= 1.; this->FractionalToOrthonormalCoords(x111,y111,z111); REAL x110= 1.; REAL y110= 1.; REAL z110= 0.; this->FractionalToOrthonormalCoords(x110,y110,z110); REAL x101= 1.; REAL y101= 0.; REAL z101= 1.; this->FractionalToOrthonormalCoords(x101,y101,z101); REAL x100= 1.; REAL y100= 0.; REAL z100= 0.; this->FractionalToOrthonormalCoords(x100,y100,z100); REAL x011= 0.; REAL y011= 1.; REAL z011= 1.; this->FractionalToOrthonormalCoords(x011,y011,z011); REAL x010= 0.; REAL y010= 1.; REAL z010= 0.; this->FractionalToOrthonormalCoords(x010,y010,z010); REAL x001= 0.; REAL y001= 0.; REAL z001= 1.; this->FractionalToOrthonormalCoords(x001,y001,z001); REAL x000= 0.; REAL y000= 0.; REAL z000= 0.; this->FractionalToOrthonormalCoords(x000,y000,z000); REAL xM= 0.5; REAL yM= 0.5; REAL zM= 0.5; this->FractionalToOrthonormalCoords(xM,yM,zM); xM*=2;yM*=2;zM*=2; glPushMatrix(); //Add Axis & axis names const GLfloat colour0 [] = {0.00, 0.00, 0.00, 0.00}; const GLfloat colour1 [] = {0.50, 0.50, 0.50, 1.00}; const GLfloat colour2 [] = {1.00, 1.00, 1.00, 1.00}; glMaterialfv(GL_FRONT, GL_AMBIENT, colour1); glMaterialfv(GL_FRONT, GL_DIFFUSE, colour0); glMaterialfv(GL_FRONT, GL_SPECULAR, colour0); glMaterialfv(GL_FRONT, GL_EMISSION, colour1); glMaterialfv(GL_FRONT, GL_SHININESS, colour0); REAL x,y,z; x=1.2-xc;y=-yc;z=-zc; this->FractionalToOrthonormalCoords(x,y,z); glRasterPos3f(en*x,y,z); crystGLPrint("a"); x=-xc;y=1.2-yc;z=-zc; this->FractionalToOrthonormalCoords(x,y,z); glRasterPos3f(en*x,y,z); crystGLPrint("b"); x=-xc;y=-yc;z=1.2-zc; this->FractionalToOrthonormalCoords(x,y,z); glRasterPos3f(en*x,y,z); crystGLPrint("c"); // Cell glMaterialfv(GL_FRONT, GL_AMBIENT, colour1); glMaterialfv(GL_FRONT, GL_DIFFUSE, colour1); glMaterialfv(GL_FRONT, GL_SPECULAR, colour1); glMaterialfv(GL_FRONT, GL_EMISSION, colour0); glMaterialfv(GL_FRONT, GL_SHININESS, colour0); this->FractionalToOrthonormalCoords(xc,yc,zc); glTranslatef(-xc*en, -yc, -zc); glBegin(GL_LINES); //top glNormal3f((x110+x010-xM)*en,y110+y010-yM,z110+z010-zM); glVertex3f( x110*en, y110, z110); glVertex3f( x010*en, y010, z010); glNormal3f((x011+x010-xM)*en,y011+y010-yM,z011+z010-zM); glVertex3f( x010*en, y010, z010); glVertex3f( x011*en, y011, z011); glNormal3f((x011+x111-xM)*en,y011+y111-yM,z011+z111-zM); glVertex3f( x011*en, y011, z011); glVertex3f( x111*en, y111, z111); glNormal3f((x110+x111-xM)*en,y110+y111-yM,z110+z111-zM); glVertex3f( x111*en, y111, z111); glVertex3f( x110*en, y110, z110); //bottom glNormal3f((x101+x001-xM)*en,y101+y001-yM,z101+z001-zM); glVertex3f( x101*en, y101, z101); glVertex3f( x001*en, y001, z001); glNormal3f((x000+x001-xM)*en,y000+y001-yM,z000+z001-zM); glVertex3f( x001*en, y001, z001); glVertex3f( x000*en, y000, z000); glNormal3f((x000+x100-xM)*en,y000+y100-yM,z000+z100-zM); glVertex3f( x000*en, y000, z000); glVertex3f( x100*en, y100, z100); glNormal3f((x101+x100-xM)*en,y101+y100-yM,z101+z100-zM); glVertex3f( x100*en, y100, z100); glVertex3f( x101*en, y101, z101); //sides glNormal3f((x101+x111-xM)*en,y101+y111-yM,z101+z111-zM); glVertex3f( x101*en, y101, z101); glVertex3f( x111*en, y111, z111); glNormal3f((x001+x011-xM)*en,y001+y011-yM,z001+z011-zM); glVertex3f( x001*en, y001, z001); glVertex3f( x011*en, y011, z011); glNormal3f((x000+x010-xM)*en,y000+y010-yM,z000+z010-zM); glVertex3f( x000*en, y000, z000); glVertex3f( x010*en, y010, z010); glNormal3f((x100+x110-xM)*en,y100+y110-yM,z100+z110-zM); glVertex3f( x100*en, y100, z100); glVertex3f( x110*en, y110, z110); glEnd(); glPopMatrix(); } //Describe all Scatterers VFN_DEBUG_MESSAGE("Crystal::GLView(bool):Scatterers...",5) glPushMatrix(); if(displayNames) this->FractionalToOrthonormalCoords(xc,yc,zc); glTranslatef(-xc*en, -yc, -zc); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); { bool displayEnantiomer=false; if(mDisplayEnantiomer.GetChoice()==1) displayEnantiomer=true; for(int i=0;iGetScatt(i).GLInitDisplayList(onlyIndependentAtoms, xMin,xMax,yMin,yMax,zMin,zMax, displayEnantiomer,displayNames,hideHydrogens,fadeDistance,fullMoleculeInLimits); } glPopMatrix(); VFN_DEBUG_EXIT("Crystal::GLInitDisplayList(bool)",5) } #endif // OBJCRYST_GL void Crystal::CalcDynPopCorr(const REAL overlapDist, const REAL mergeDist) const { VFN_DEBUG_ENTRY("Crystal::CalcDynPopCorr(REAL)",4) TAU_PROFILE("Crystal::CalcDynPopCorr()","void (REAL)",TAU_DEFAULT); this->CalcDistTable(true); if(mClockDynPopCorr>mDistTableClock) return; const long nbComponent=mScattCompList.GetNbComponent(); const int nbSymmetrics=this->GetSpaceGroup().GetNbSymmetrics(); CrystVector_REAL neighborsDist(nbComponent*nbSymmetrics); long nbNeighbors=0; REAL corr; int atomicNumber; const REAL overlapDistSq=overlapDist*overlapDist; REAL dist; for(long i=0;iGetDynPopCorrIndex(); nbNeighbors=0; std::vector::const_iterator pos; for(pos=mvDistTableSq[i].mvNeighbour.begin(); posmNeighbourIndex,0) if(0==mScattCompList(pos->mNeighbourIndex).mpScattPow)continue; if(atomicNumber==mScattCompList(pos->mNeighbourIndex).mpScattPow->GetDynPopCorrIndex()) { if(overlapDistSq > pos->mDist2) { //resizing can be necessary if the unit cell is small, so that an atom two unit cells away is //still considered a neighbor... if(nbNeighbors==neighborsDist.numElements()) neighborsDist.resizeAndPreserve(nbNeighbors+20); neighborsDist(nbNeighbors++)=sqrt(pos->mDist2); } } } corr=0.; for(long j=0;jGetUseDynPopCorr()==0) return 1.0; this->GetScatteringComponentList(); unsigned int j=0; for(long i=0;iGetScatt(i))) { return mScattCompList(j+component).mDynPopCorr; } else j+=this->GetScatt(i).GetScatteringComponentList().GetNbComponent(); } // Something is wrong if we got here ! throw ObjCrystException("Crystal::GetDynPopCorr(): did not find this scatterer !"); return 1.0; } void Crystal::SetUseDynPopCorr(const int b) { VFN_DEBUG_MESSAGE("Crystal::SetUseDynPopCorr()",1) mUseDynPopCorr.SetChoice(b); mClockDynPopCorr.Reset(); } int Crystal::GetUseDynPopCorr() const { return mUseDynPopCorr.GetChoice(); } int Crystal::FindScatterer(const string &scattName)const { VFN_DEBUG_MESSAGE("Crystal::FindScatterer(name)",0) for(int i=0;iGetNbScatterer();i++) { if( mScattererRegistry.GetObj(i).GetName() == scattName) return i; } throw ObjCrystException("Crystal::FindScatterer(string)\ Cannot find this scatterer:"+scattName); } Crystal::BumpMergePar::BumpMergePar(): mDist2(1.),mCanOverlap(false){} Crystal::BumpMergePar::BumpMergePar(const REAL dist, const bool canOverlap): mDist2(dist*dist),mCanOverlap(canOverlap){} REAL Crystal::GetBumpMergeCost() const { if(mvBumpMergePar.size()==0) return 0; if(mBumpMergeScale<1e-5) return 0; this->CalcDistTable(true); VFN_DEBUG_ENTRY("Crystal::GetBumpMergeCost()",4) if( (mBumpMergeCostClock>mBumpMergeParClock) &&(mBumpMergeCostClock>mDistTableClock)) return mBumpMergeCost*mBumpMergeScale; TAU_PROFILE("Crystal::GetBumpMergeCost()","REAL (REAL)",TAU_DEFAULT); mBumpMergeCost=0; std::vector::const_iterator pos; std::vector::const_iterator neigh; REAL tmp; const ScatteringPower *i1,*i2; VBumpMergePar::const_iterator par; for(pos=mvDistTableSq.begin();posmIndex).mpScattPow; for(neigh=pos->mvNeighbour.begin();neighmvNeighbour.end();neigh++) { i2=mScattCompList(neigh->mNeighbourIndex).mpScattPow; if(i1mDist2 > par->second.mDist2) continue; if(true==par->second.mCanOverlap) tmp = 0.5*sin(M_PI*(1.-sqrt(neigh->mDist2/par->second.mDist2)))/0.1; else tmp = tan(M_PI*0.49999*(1.-sqrt(neigh->mDist2/par->second.mDist2)))/0.1; mBumpMergeCost += tmp*tmp; } } mBumpMergeCost *= this->GetSpaceGroup().GetNbSymmetrics(); mBumpMergeCostClock.Click(); VFN_DEBUG_EXIT("Crystal::GetBumpMergeCost():"<SetBumpMergeDistance(scatt1,scatt2,dist,true) ; else this->SetBumpMergeDistance(scatt1,scatt2,dist,false); } void Crystal::SetBumpMergeDistance(const ScatteringPower &scatt1, const ScatteringPower &scatt2,const REAL dist, const bool allowMerge) { VFN_DEBUG_MESSAGE("Crystal::SetBumpMergeDistance("<GetNbScatterer(); if( ((rand()/(REAL)RAND_MAX)<.02) && (nb>1)) { // This is safe even if one scatterer is partially fixed, // since we the SetX/SetY/SetZ actually use the MutateTo() function. const unsigned long n1=rand()%nb; const unsigned long n2=( (rand()%(nb-1)) +n1+1) %nb; const float x1=this->GetScatt(n1).GetX(); const float y1=this->GetScatt(n1).GetY(); const float z1=this->GetScatt(n1).GetZ(); this->GetScatt(n1).SetX(this->GetScatt(n2).GetX()); this->GetScatt(n1).SetY(this->GetScatt(n2).GetY()); this->GetScatt(n1).SetZ(this->GetScatt(n2).GetZ()); this->GetScatt(n2).SetX(x1); this->GetScatt(n2).SetY(y1); this->GetScatt(n2).SetZ(z1); } else { this->RefinableObj::GlobalOptRandomMove(mutationAmplitude,type); } mRandomMoveIsDone=true; VFN_DEBUG_EXIT("Crystal::GlobalOptRandomMove()",2) } REAL Crystal::GetLogLikelihood()const { return this->GetBumpMergeCost()+this->GetBondValenceCost(); } void Crystal::CIFOutput(ostream &os, double mindist)const { VFN_DEBUG_ENTRY("Crystal::OutputCIF()",5) //Data block name (must have no spaces) string tempname = mName; int where, size; size = tempname.size(); if (size > 32) { tempname = tempname.substr(0,32); size = tempname.size(); } if (size == 0) { tempname = "3D"; size = 2; } where = tempname.find(" ",0); while (where != (int)string::npos) { tempname.replace(where,1,"_"); where = tempname.find(" ",0); //cout << tempname << endl; } os << "data_" << tempname <GetScatteringPowerRegistry().GetNb();i++) os << " " << this->GetScatteringPowerRegistry().GetObj(i).GetName()<<" " <GetScatteringPowerRegistry().GetObj(i).GetSymbol()<<" " <<"'International Tables for Crystallography (Vol. IV)'" <GetSpaceGroup().GetCCTbxSpg().match_tabulated_settings().hermann_mauguin(); const char ext = this->GetSpaceGroup().GetExtension(); if(isalnum(ext)) os <<":"<GetSpaceGroup().GetCCTbxSpg().match_tabulated_settings().hall()<<"'"<GetLatticePar(0),8,5) << endl << "_cell_length_b " << FormatFloat(this->GetLatticePar(1),8,5) << endl << "_cell_length_c " << FormatFloat(this->GetLatticePar(2),8,5) << endl << "_cell_angle_alpha " << FormatFloat(this->GetLatticePar(3)*RAD2DEG,7,3) << endl << "_cell_angle_beta " << FormatFloat(this->GetLatticePar(4)*RAD2DEG,7,3) << endl << "_cell_angle_gamma " << FormatFloat(this->GetLatticePar(5)*RAD2DEG,7,3) << endl << "_cell_volume " << FormatFloat(this->GetVolume(),7,2); os <GetScatteringComponentList(); /* TODO: loop_ _symmetry_equiv_pos_site_id _symmetry_equiv_pos_as_xyz */ os << "loop_" << endl << " _atom_site_label" < anisovec; std::vector namevec; CrystMatrix_REAL minDistTable; minDistTable=this->GetMinDistanceTable(-1.); unsigned long k=0; for(int i=0;iPrint(); const ScatteringComponentList list=this->GetScatt(i).GetScatteringComponentList(); for(int j=0;j 10A if(!redundant) { // We can't have spaces in atom labels string s=this->GetScatt(i).GetComponentName(j); size_t posc=s.find(' '); while(posc!=string::npos){s[posc]='~';posc=s.find(' ');} bool isiso = list(j).mpScattPow->IsIsotropic(); if(!isiso) { anisovec.push_back(list(j).mpScattPow); namevec.push_back(s); } os << " " << FormatString(s,10) << " " << FormatString(list(j).mpScattPow->GetSymbol(),8) << " " << FormatFloat(list(j).mX,9,6) << " " << FormatFloat(list(j).mY,9,6) << " " << FormatFloat(list(j).mZ,9,6) << " " << FormatFloat(list(j).mpScattPow->GetBiso()*BtoU,9,6) << " " << FormatFloat(list(j).mOccupancy,6,4) << (isiso ? " Uiso" : " Uani") << endl; } k++; } } // Handle anisotropic atoms if( anisovec.size() > 0 ) { os << endl << "loop_" << endl << " _atom_site_aniso_label" << endl << " _atom_site_aniso_U_11" << endl << " _atom_site_aniso_U_22" << endl << " _atom_site_aniso_U_33" << endl << " _atom_site_aniso_U_12" << endl << " _atom_site_aniso_U_13" << endl << " _atom_site_aniso_U_23" << endl; for(size_t i = 0; i < anisovec.size(); ++i) { os << " " << FormatString(namevec[i],8) << " "; for(int j=0; j<6; ++j) os << FormatFloat(anisovec[i]->GetBij(j)*BtoU,9,6) << " "; os << endl; } } bool first=true; k=0; for(int i=0;iGetScatt(i).GetScatteringComponentList(); for(int j=0;j 10A if(redundant) { if(first) { first=false; os <GetName(),8) << " " << FormatString(this->GetScatt(i).GetComponentName(j),10) << " " << FormatFloat(list(j).mX,9,6) << " " << FormatFloat(list(j).mY,9,6) << " " << FormatFloat(list(j).mZ,9,6) << " " << FormatFloat(list(j).mpScattPow->GetBiso()*BtoU,9,6) << " " << FormatFloat(list(j).mOccupancy,6,4) << " Uiso" << endl; } k++; } } os <Print(); const ScatteringComponentList list=this->GetScatt(i).GetScatteringComponentList(); for(int j=0;jGetScatt(i).GetComponentName(j),16) << " : " << FormatFloat(mScattCompList(k).mDynPopCorr,6,4) << endl; k++; } } os << "#"<GetNbPar();j++) if(&(obj.GetPar(i)) == &(this->GetPar(j))) { //if(this->GetPar(j).GetType()->IsDescendantFromOrSameAs(gpRefParTypeUnitCell)) //{ if(latticeIndex==0) latticeIndex=first++; groupIndex(i)=latticeIndex; //} //else //no parameters other than unit cell } } void Crystal::BeginOptimization(const bool allowApproximations,const bool enableRestraints) { if(this->IsBeingRefined()) { // RefinableObj::BeginOptimization() will increase the optimization depth this->RefinableObj::BeginOptimization(allowApproximations,enableRestraints); return; } for(int i=0;iGetScattererRegistry().GetNb();i++) { this->GetScattererRegistry().GetObj(i). SetGlobalOptimStep(gpRefParTypeScattTranslX,0.1/this->GetLatticePar(0)); this->GetScattererRegistry().GetObj(i). SetGlobalOptimStep(gpRefParTypeScattTranslY,0.1/this->GetLatticePar(1)); this->GetScattererRegistry().GetObj(i). SetGlobalOptimStep(gpRefParTypeScattTranslZ,0.1/this->GetLatticePar(2)); } this->RefinableObj::BeginOptimization(allowApproximations,enableRestraints); // Calculate mDistTableMaxDistance: Default 1 Angstroem, for dynamical occupancy correction mDistTableMaxDistance=1.0; // Up to 4 Angstroem if bond-valence is used if((mvBondValenceRo.size()>0) && (mBondValenceCostScale>1e-5)) mDistTableMaxDistance=4; // Up to whatever antibump distance the user requires (hopefully not too large !) for(Crystal::VBumpMergePar::iterator pos=mvBumpMergePar.begin();pos!=mvBumpMergePar.end();++pos) if(sqrt(pos->second.mDist2)>mDistTableMaxDistance) mDistTableMaxDistance=sqrt(pos->second.mDist2); VFN_DEBUG_MESSAGE("Crystal::BeginOptimization():mDistTableMaxDistance="<UpdateDisplay(); } void Crystal::RemoveBondValenceRo(const ScatteringPower &pow1,const ScatteringPower &pow2) { map, REAL>::iterator pos; if(&pow1 < &pow2) pos=mvBondValenceRo.find(make_pair(&pow1 , &pow2)); else pos=mvBondValenceRo.find(make_pair(&pow2 , &pow1)); if(pos!=mvBondValenceRo.end()) mvBondValenceRo.erase(pos); mBondValenceParClock.Click(); } REAL Crystal::GetBondValenceCost() const { VFN_DEBUG_MESSAGE("Crystal::GetBondValenceCost()?",4) if(mBondValenceCostScale<1e-5) return 0.0; if(mvBondValenceRo.size()==0) { mBondValenceCost=0.0; return mBondValenceCost*mBondValenceCostScale; } this->CalcBondValenceSum(); if( (mBondValenceCostClock>mBondValenceCalcClock) &&(mBondValenceCostClock>this->GetMasterClockScatteringPower())) return mBondValenceCost*mBondValenceCostScale; VFN_DEBUG_MESSAGE("Crystal::GetBondValenceCost():"<::const_iterator pos; for(pos=mvBondValenceCalc.begin();pos!=mvBondValenceCalc.end();++pos) { const REAL a=pos->second-mScattCompList(pos->first).mpScattPow->GetFormalCharge(); mBondValenceCost += a*a; VFN_DEBUG_MESSAGE("Crystal::GetBondValenceCost():" <first).mpScattPow->GetName() <<"="<second,4) } mBondValenceCostClock.Click(); return mBondValenceCost*mBondValenceCostScale; } std::map, REAL>& Crystal::GetBondValenceRoList() { return mvBondValenceRo;} const std::map, REAL>& Crystal::GetBondValenceRoList()const { return mvBondValenceRo;} void Crystal::CalcBondValenceSum()const { if(mvBondValenceRo.size()==0) return; this->CalcDistTable(true); VFN_DEBUG_MESSAGE("Crystal::CalcBondValenceSum()?",4) if( (mBondValenceCalcClock>mDistTableClock) &&(mBondValenceCalcClock>mBondValenceParClock)) return; VFN_DEBUG_MESSAGE("Crystal::CalcBondValenceSum()",4) TAU_PROFILE("Crystal::CalcBondValenceSum()","void ()",TAU_DEFAULT); mvBondValenceCalc.clear(); for(long i=0;i::const_iterator pos; for(pos=mvDistTableSq[i].mvNeighbour.begin(); posmDist2); const REAL occup= mScattCompList(pos->mNeighbourIndex).mOccupancy *mScattCompList(pos->mNeighbourIndex).mDynPopCorr; const ScatteringPower *pow2=mScattCompList(pos->mNeighbourIndex).mpScattPow; map,REAL>::const_iterator pos; if(pow1second-dist)/0.37); val += occup * v; nb++; } } if(nb!=0) mvBondValenceCalc[i]=val; } mBondValenceCalcClock.Click(); } void Crystal::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) { VFN_DEBUG_MESSAGE("Crystal::Init(a,b,c,alpha,beta,gamma,Sg,name)",10) this->UnitCell::Init(a,b,c,alpha,beta,gamma,SpaceGroupId,name); mClockScattCompList.Reset(); mClockNeighborTable.Reset(); mClockDynPopCorr.Reset(); VFN_DEBUG_MESSAGE("Crystal::Init(a,b,c,alpha,beta,gamma,Sg,name):End",10) } bool CompareBondDist(MolBond* b1, MolBond* b2) { return b1->GetLength()GetLength(); } bool ComparePairSecond(const std::pair &b1, const std::pair &b2) { return b1.second < b2.second; } void Crystal::ConnectAtoms(const REAL min_relat_dist, const REAL max_relat_dist, const bool warnuser_fail) { VFN_DEBUG_ENTRY("Crystal::ConnectAtoms(...)",10) // Make sure there are only atoms for(unsigned int i=0;iCalcDistTable(true); this->GetScatteringComponentList(); // Create first Molecule // start from start_carbon Molecule *pmol=NULL; std::set vAssignedAtoms;//atoms already assigned to a Molecule std::set vTriedAtom0;//atoms already tried as starting point for a Molecule VFN_DEBUG_MESSAGE("Crystal::ConnectAtoms(...)",10) while(long(vAssignedAtoms.size()) != mScattererRegistry.GetNb()) { VFN_DEBUG_MESSAGE("Crystal::ConnectAtoms(...): new Molecule ?",7) // We need at least one carbon atom to start int atom0=-1; int maxAtomicNumber = 0; for(unsigned int i=0;i0) || (vTriedAtom0.find(i)!=vTriedAtom0.end()) ) continue; if(mScattCompList(i).mpScattPow->GetClassName()=="ScatteringPowerAtom") { const ScatteringPowerAtom *p=dynamic_cast(mScattCompList(i).mpScattPow); if((p->GetAtomicNumber()==6)&&(maxAtomicNumber!=6)) {// Start from the first Carbon found atom0=i; maxAtomicNumber=6; } else if((p->GetAtomicNumber()>maxAtomicNumber) && (maxAtomicNumber!=6)) {// Else we'll try from the heaviest atom maxAtomicNumber=p->GetAtomicNumber(); atom0=i; } } else { if(warnuser_fail) (*fpObjCrystInformUser)("Crystal::ConnectAtoms(): cannot connect atoms unless there are only Atoms in a Crystal"); VFN_DEBUG_EXIT("Crystal::ConnectAtoms(...):cannot connect atoms unless there are only Atoms in the structure:"<GetClassName(),10) return; } } if(atom0<0) { if((pmol==NULL) && warnuser_fail) // We did not create any Molecule :-( { (*fpObjCrystInformUser)("Crystal::ConnectAtoms(): cannot connect atoms unless there is at least one carbon atom"); VFN_DEBUG_EXIT("Crystal::ConnectAtoms(...):cannot connect atoms unless there is at least one carbon atom",10) return; } break; } vTriedAtom0.insert(atom0); // Atoms in Molecule but for which neighbors have not yet been searched // first: index in the Crystal's scatt comp list, second: index in the Molecule std::mapnewAtoms; // List of all atoms in the Molecule. First is the MolAtom* in the molecule, second is the index in the Crystal std::map molAtoms; pmol=new Molecule(*this); // Add atom0 to Molecule. newAtoms[atom0]=0; vAssignedAtoms.insert(atom0); const ScatteringPowerAtom *p0=dynamic_cast(mScattCompList(atom0).mpScattPow); { REAL x=mScattCompList(atom0).mX; REAL y=mScattCompList(atom0).mY; REAL z=mScattCompList(atom0).mZ; const REAL occ=mScattCompList(atom0).mOccupancy; this->FractionalToOrthonormalCoords(x,y,z); pmol->AddAtom(x,y,z,p0,mScattererRegistry.GetObj(atom0).GetName(),false); pmol->GetAtomList().back()->SetOccupancy(occ); } molAtoms[pmol->GetAtomList().back()]=atom0; // Count atoms in the Molecule per element type vector vElementCount(140);// Should be safe pending a trans-uranian breakthrough for(vector::iterator pos=vElementCount.begin();pos!=vElementCount.end();++pos) *pos=0; vElementCount[p0->GetAtomicNumber()]+=1; while(newAtoms.size()>0) { atom0=newAtoms.begin()->first; p0=dynamic_cast(mScattCompList(atom0).mpScattPow); VFN_DEBUG_ENTRY("Crystal::ConnectAtoms(...):atom0="<GetSymbol()<<"],"< > vatomsneighbours; // Find neigbours between min and max * sum of covalent bonds for(std::vector::const_iterator pos=mvDistTableSq[atom0].mvNeighbour.begin(); pos!=mvDistTableSq[atom0].mvNeighbour.end();pos++) { const ScatteringPowerAtom *p1=dynamic_cast(mScattCompList(pos->mNeighbourIndex).mpScattPow); const REAL dcov= p0->GetCovalentRadius()+p1->GetCovalentRadius(); //if( (vAssignedAtoms.count(pos->mNeighbourIndex)!=0) || (p1->GetMaxCovBonds()==0)) if(p1->GetMaxCovBonds()==0) continue; if( ((min_relat_dist*dcov)mDist2)) &&((max_relat_dist*dcov)>sqrt(pos->mDist2))) { VFN_DEBUG_MESSAGE("Crystal::ConnectAtoms(...):atom0="<GetName()<<"("<GetMaxCovBonds()<<"):dcov="<mDist2),7) vatomsneighbours.push_back(std::make_pair(pos->mNeighbourIndex,sqrt(pos->mDist2))); } else { VFN_DEBUG_MESSAGE("Crystal::ConnectAtoms(...):atom0="<GetName()<<"("<GetMaxCovBonds()<<"):dcov="<mDist2),5) } } // Remove farthest neighbours if in excess of the maximum coordination. // But keep excess neighbours if close (5%) of the last neighbour within the normal coordination number. const unsigned int maxbonds=p0->GetMaxCovBonds(); float extra=vatomsneighbours.size()-maxbonds; if(extra>0) { // Check real number of bonds taking into account occupancy, and sort bonds by length REAL nbbond=0; for(std::vector >::const_iterator pos=vatomsneighbours.begin();pos!=vatomsneighbours.end();++pos) { nbbond+=mScattCompList(pos->first).mOccupancy; } extra = nbbond-maxbonds; if(extra>0.2) { std::sort(vatomsneighbours.begin(), vatomsneighbours.end(),ComparePairSecond); VFN_DEBUG_ENTRY("Crystal::ConnectAtoms(...): too many bonds for"<maxdist) { VFN_DEBUG_MESSAGE("Crystal::ConnectAtoms(...): Remove bond="<0) cout<<"Crystal::ConnectAtoms(): adding neighbours around "< >::const_iterator pos=vatomsneighbours.begin();pos!=vatomsneighbours.end();++pos) { if(vAssignedAtoms.count(pos->first)!=0) { if(extra>0) cout<<"("<first).GetName()<<") "; continue; } //if(extra>0) cout<first).GetName()<<" "; const ScatteringPowerAtom *p1=dynamic_cast(mScattCompList(pos->first).mpScattPow); vAssignedAtoms.insert(pos->first); REAL x=mScattCompList(pos->first).mX; REAL y=mScattCompList(pos->first).mY; REAL z=mScattCompList(pos->first).mZ; this->FractionalToOrthonormalCoords(x,y,z); const REAL occ=mScattCompList(pos->first).mOccupancy; pmol->AddAtom(x,y,z,p1,mScattererRegistry.GetObj(pos->first).GetName(),false); pmol->GetAtomList().back()->SetOccupancy(occ); newAtoms[pos->first]=pmol->GetNbComponent()-1; molAtoms[pmol->GetAtomList().back()]=pos->first; vElementCount[p1->GetAtomicNumber()]+=1; } //if(extra>0) cout<GetSymbol()<<"],"<GetFormula(),7) } // Check this is a valid Molecule object bool keep=false; if((vElementCount[6]>0) && (pmol->GetNbComponent()>=3)) keep=true; else {// no carbon ? std::vector vnb; #ifdef __DEBUG__ cout<<" Crystal::ConnectAtoms(..): Molecule ?"; #endif for(unsigned int i=0;i2)) keep=true; #endif // Accept any type of cluster with exactly two types of atoms keep=true; } } if(!keep) { VFN_DEBUG_MESSAGE("Crystal::ConnectAtoms(...):Rejected molecule: "<GetFormula(),10) delete pmol; for(std::map::const_iterator pos=molAtoms.begin();pos!=molAtoms.end();++pos) vAssignedAtoms.erase(pos->second); continue;// Will start from another atom to build a molecule } // Add bonds for(unsigned int i=0;iGetAtomList().size();i++) { for(unsigned int j=i+1;jGetAtomList().size();j++) { const REAL d=GetBondLength(pmol->GetAtom(i), pmol->GetAtom(j)); const REAL dcov= dynamic_cast(&(pmol->GetAtom(i).GetScatteringPower()))->GetCovalentRadius() +dynamic_cast(&(pmol->GetAtom(j).GetScatteringPower()))->GetCovalentRadius(); if( ((min_relat_dist*dcov)d)) { VFN_DEBUG_MESSAGE("Crystal::ConnectAtoms(...):Add bond="<GetAtom(i).GetName()<<"-"<GetAtom(j).GetName()<<", d="<AddBond(pmol->GetAtom(i),pmol->GetAtom(j),d,.01,.02,false); } } } // Remove longest bonds if it exceeds the expected coordination // :TODO: combined with the check already made, this is not fullproof, for atoms where the coordination number is not so well-defined, // e.g. Li and Na is defined as 1, but there could be more linked atoms... // If we still find a too great coordination number, remove excess ones but still keep those that are very close (5%) of the cutoff distance. for(vector::iterator pos=pmol->GetAtomList().begin();pos!=pmol->GetAtomList().end();) { pmol->BuildConnectivityTable(); map >::const_iterator p=pmol->GetConnectivityTable().find(*pos); if(p==pmol->GetConnectivityTable().end()) {// While cleaning the longest bond, this atom had all his bonds removed ! VFN_DEBUG_MESSAGE("Crystal::ConnectAtoms(...):no bond remaining for:"<<(*pos)->GetName()<<"! Removing atom from Molecule",10) //Remove MolAtom from Molecule and keep in Crystal. vAssignedAtoms.erase(molAtoms[*pos]); molAtoms.erase(*pos); pos=pmol->RemoveAtom(**pos); continue; } const unsigned int maxbonds=dynamic_cast(&(p->first->GetScatteringPower()))->GetMaxCovBonds(); int extra=p->second.size()-maxbonds; if(extra>0) { // Check real number of bonds taking into account occupancy, and sort bonds by length std::vector vbonds; REAL nbbond=0; for(std::set::iterator p1=p->second.begin();p1!=p->second.end();++p1) { vbonds.push_back(*(pmol->FindBond(**pos,**p1)));// We can assume that exactly one bond is found nbbond+=(*p1)->GetOccupancy(); } VFN_DEBUG_MESSAGE("Crystal::ConnectAtoms(...): too many bonds for"<<(*pos)->GetName()<<" ?(allowed="<second.size()<<",nb_occ="<0) { std::sort(vbonds.begin(), vbonds.end(),CompareBondDist); if(size_t(extra) < vbonds.size()) // Am I paranoid ? { const REAL maxdist=vbonds[vbonds.size()-extra]->GetLength()*1.05; while(vbonds.back()->GetLength()>maxdist) { VFN_DEBUG_MESSAGE("Crystal::ConnectAtoms(...): Remove bond="<GetAtom1().GetName()<<"-"<GetAtom2().GetName()<<", d="<GetLength(),10) pmol->RemoveBond(*(vbonds.back())); vbonds.pop_back(); VFN_DEBUG_MESSAGE("Crystal::ConnectAtoms(...): Next bond ="<GetAtom1().GetName()<<"-"<GetAtom2().GetName()<<", d="<GetLength(),10) } } } } ++pos; } // Add all bond angles pmol->BuildConnectivityTable(); for(map >::const_iterator pos=pmol->GetConnectivityTable().begin(); pos!=pmol->GetConnectivityTable().end();++pos) { for(set::const_iterator pos1=pos->second.begin(); pos1!=pos->second.end();++pos1) { for(set::const_iterator pos2=pos1; pos2!=pos->second.end();++pos2) { if(pos2==pos1) continue; if(pmol->FindBondAngle(**pos1,*(pos->first),**pos2)== pmol->GetBondAngleList().end()) pmol->AddBondAngle(**pos1,*(pos->first),**pos2, GetBondAngle(**pos1,*(pos->first),**pos2),0.01,0.02,false); } } } // Correct center of Molecule REAL xc=0,yc=0,zc=0; for(std::map::const_iterator pos=molAtoms.begin();pos!=molAtoms.end();++pos) { REAL x=mScattCompList(pos->second).mX; REAL y=mScattCompList(pos->second).mY; REAL z=mScattCompList(pos->second).mZ; this->FractionalToOrthonormalCoords(x,y,z); xc+=x; yc+=y; zc+=z; } xc /= pmol->GetNbComponent(); yc /= pmol->GetNbComponent(); zc /= pmol->GetNbComponent(); this->OrthonormalToFractionalCoords(xc,yc,zc); VFN_DEBUG_MESSAGE("Crystal::ConnectAtoms(...): center?"<GetNbComponent()<<","<SetX(xc); pmol->SetY(yc); pmol->SetZ(zc); this->AddScatterer(pmol); (*fpObjCrystInformUser)("ConnectAtoms: found Molecule: "+pmol->GetFormula()); } std::set vpAtom; for(std::set::const_iterator pos=vAssignedAtoms.begin();pos!=vAssignedAtoms.end();++pos) { Scatterer *s=&(this->GetScattererRegistry().GetObj(*pos)); vpAtom.insert(s); } while(vpAtom.size()>0) { VFN_DEBUG_MESSAGE("Crystal::ConnectAtoms(...): remove atom:"<<(*vpAtom.begin())->GetName()<<","<RemoveScatterer(*vpAtom.begin(),true); vpAtom.erase(vpAtom.begin()); } VFN_DEBUG_EXIT("Crystal::ConnectAtoms(...)",10) } void Crystal::MergeEqualScatteringPowers(const bool oneScatteringPowerPerElement) { VFN_DEBUG_ENTRY("Crystal::MergeEqualScatteringPowers("< vremovedpow; std::map > vequivpow; for(unsigned int i=0;iGetScatteringPowerRegistry().GetNb();i++) { ScatteringPower *p1 = &(this->GetScatteringPowerRegistry().GetObj(i)); if(vremovedpow.find(p1)!=vremovedpow.end()) continue; vequivpow[p1] = std::set(); for(unsigned int j=i+1;jGetScatteringPowerRegistry().GetNb();j++) { ScatteringPower *p2 = &(this->GetScatteringPowerRegistry().GetObj(j)); if(oneScatteringPowerPerElement) { if(p1->GetClassName() != p2->GetClassName()) continue; if(p1->GetSymbol() != p2->GetSymbol()) continue; } else { if(*p1 != *p2) continue; } vequivpow[p1].insert(p2); vremovedpow.insert(p2); } } if(oneScatteringPowerPerElement) { // Average Biso and Bij for(std::map >::iterator pos=vequivpow.begin();pos!=vequivpow.end();++pos) { if(pos->second.size()==0) continue; REAL b = pos->first->GetBiso(); CrystVector_REAL bij(6); for(unsigned int i=0;i<6;i++) bij(i) = pos->first->GetBij(i); for(std::set::const_iterator pos2=pos->second.begin(); pos2!=pos->second.end();++pos2) { b += (*pos2)->GetBiso(); for(unsigned int i=0;i<6;i++) bij(i) += (*pos2)->GetBij(i); } b /= pos->second.size() + 1; bij /= pos->second.size() + 1; pos->first->SetBiso(b); for(unsigned int i=0;i<6;i++) if(abs(bij(i)) > 1e-6) pos->first->SetBij(i,bij(i)); } } // Update Atoms or MolAtoms with new ScatteringPower for(std::map >::iterator pos=vequivpow.begin();pos!=vequivpow.end();++pos) { const unsigned int nb = pos->second.size(); if(oneScatteringPowerPerElement) pos->first->SetName(pos->first->GetSymbol()); if(nb>0) (*fpObjCrystInformUser)((boost::format("Merging ScatteringPower: %s[%s] (%d identical scattering powers)") % pos->first->GetName().c_str() % pos->first->GetSymbol().c_str() % pos->second.size()).str()); for(std::set::const_iterator pos2=pos->second.begin(); pos2!=pos->second.end();++pos2) { for(unsigned int i=0;iGetNbScatterer();++i) { Scatterer *p = &(this->GetScatt(i)); if(p->GetClassName()=="Atom") { Atom *pat=dynamic_cast(p); if(&(pat->GetScatteringPower()) == (*pos2)) { VFN_DEBUG_MESSAGE("Crystal:MergeEqualScatteringPowers() Atom "<GetName()<<": "<GetScatteringPower().GetName()<<"->"<first->GetName(), 10) pat->SetScatteringPower(*(pos->first)); } } else if (p->GetClassName()=="Molecule") { Molecule *pmol=dynamic_cast(p); for(std::vector::iterator pat=pmol->GetAtomList().begin();pat!=pmol->GetAtomList().end();++pat) { if(&((*pat)->GetScatteringPower()) == (*pos2)) (*pat)->SetScatteringPower(*(pos->first)); } } else { // This should only happen if a new type of scatterer was derived cout<<__FILE__<<":"<<__LINE__<<":Crystal::MergeEqualScatteringPowers(): unidentified scatterer, cannot merge scattering power..." <<(*pos2)->GetName()<<"["<<(*pos2)->GetClassName()<<"]"<::iterator pos=vremovedpow.begin();pos!=vremovedpow.end();++pos) { #ifdef __DEBUG__ const unsigned int nb=(*pos)->GetClientRegistry().GetNb(); if(nb>0) { VFN_DEBUG_MESSAGE("Crystal::MergeEqualScatteringPowers(): "<GetName()<<"["<<(*pos)->GetClassName()<<"]", 5) for(unsigned int i=0; iGetClientRegistry().GetObj(i))<<":"<<(*pos)->GetClientRegistry().GetObj(i).GetName()<<"["<<(*pos)->GetClientRegistry().GetObj(i).GetClassName()<<"]", 5) } } #endif this->RemoveScatteringPower(*pos,true); } this->UpdateDisplay(); VFN_DEBUG_EXIT("Crystal::MergeEqualScatteringPowers()", 10) } void Crystal::InitOptions() { VFN_DEBUG_ENTRY("Crystal::InitOptions",10) static string UseDynPopCorrname; static string UseDynPopCorrchoices[2]; static string DisplayEnantiomername; static string DisplayEnantiomerchoices[2]; static bool needInitNames=true; if(true==needInitNames) { UseDynPopCorrname="Use Dynamical Occupancy Correction"; UseDynPopCorrchoices[0]="No"; UseDynPopCorrchoices[1]="Yes"; DisplayEnantiomername="Display Enantiomer"; DisplayEnantiomerchoices[0]="No"; DisplayEnantiomerchoices[1]="Yes"; needInitNames=false;//Only once for the class } VFN_DEBUG_MESSAGE("Crystal::Init(a,b,c,alpha,beta,gamma,Sg,name):Init options",5) mUseDynPopCorr.Init(2,&UseDynPopCorrname,UseDynPopCorrchoices); mUseDynPopCorr.SetChoice(1); this->AddOption(&mUseDynPopCorr); mDisplayEnantiomer.Init(2,&DisplayEnantiomername,DisplayEnantiomerchoices); mDisplayEnantiomer.SetChoice(0); this->AddOption(&mDisplayEnantiomer); VFN_DEBUG_EXIT("Crystal::InitOptions",10) } Crystal::Neighbour::Neighbour(const unsigned long neighbourIndex,const int sym, const REAL dist2): mNeighbourIndex(neighbourIndex),mNeighbourSymmetryIndex(sym),mDist2(dist2) {} struct DistTableInternalPosition { DistTableInternalPosition(const long atomIndex, const int sym, const REAL x,const REAL y,const REAL z): mAtomIndex(atomIndex),mSymmetryIndex(sym),mX(x),mY(y),mZ(z) {} /// Index of the atom (order) in the component list long mAtomIndex; /// Which symmetry operation does this symmetric correspond to ? int mSymmetryIndex; /// Fractionnal coordinates REAL mX,mY,mZ; }; void Crystal::CalcDistTable(const bool fast) const { this->GetScatteringComponentList(); if(!this->IsBeingRefined()) { if(mDistTableMaxDistance!=10) mDistTableClock.Reset(); mDistTableMaxDistance=10; } if( (mDistTableClock>mClockScattCompList) &&(mDistTableClock>this->GetClockMetricMatrix())) return; VFN_DEBUG_ENTRY("Crystal::CalcDistTable(fast="<::iterator pos; for(pos=mvDistTableSq.begin();posmvNeighbour.clear(); } VFN_DEBUG_MESSAGE("Crystal::CalcDistTable():1",3) // Get range and origin of the (pseudo) asymmetric unit const REAL asux0=this->GetSpaceGroup().GetAsymUnit().Xmin(); const REAL asuy0=this->GetSpaceGroup().GetAsymUnit().Ymin(); const REAL asuz0=this->GetSpaceGroup().GetAsymUnit().Zmin(); const REAL asux1=this->GetSpaceGroup().GetAsymUnit().Xmax(); const REAL asuy1=this->GetSpaceGroup().GetAsymUnit().Ymax(); const REAL asuz1=this->GetSpaceGroup().GetAsymUnit().Zmax(); const REAL halfasuxrange=(asux1-asux0)*0.5+1e-5; const REAL halfasuyrange=(asuy1-asuy0)*0.5+1e-5; const REAL halfasuzrange=(asuz1-asuz0)*0.5+1e-5; const REAL asuxc=0.5*(asux0+asux1); const REAL asuyc=0.5*(asuy0+asuy1); const REAL asuzc=0.5*(asuz0+asuz1); const REAL maxdx=halfasuxrange+mDistTableMaxDistance/GetLatticePar(0); const REAL maxdy=halfasuyrange+mDistTableMaxDistance/GetLatticePar(1); const REAL maxdz=halfasuzrange+mDistTableMaxDistance/GetLatticePar(2); // List of all positions within or near the first atom generated std::vector vPos; // index of unique atoms in vPos, which are strictly in the asymmetric unit std::vector vUniqueIndex(nbComponent); const REAL asymUnitMargin2 = mDistTableMaxDistance*mDistTableMaxDistance; if(true)//(true==fast) { VFN_DEBUG_MESSAGE("Crystal::CalcDistTable(fast):2",3) TAU_PROFILE("Crystal::CalcDistTable(fast=true)","Matrix (string&)",TAU_DEFAULT); TAU_PROFILE_TIMER(timer1,"DiffractionData::CalcDistTable1","", TAU_FIELD); TAU_PROFILE_TIMER(timer2,"DiffractionData::CalcDistTable2","", TAU_FIELD); TAU_PROFILE_START(timer1); // No need to loop on a,b,c translations if mDistTableMaxDistance is small enough bool loopOnLattice=true; if( ((this->GetLatticePar(0)*.5)>mDistTableMaxDistance) &&((this->GetLatticePar(1)*.5)>mDistTableMaxDistance) &&((this->GetLatticePar(2)*.5)>mDistTableMaxDistance)) loopOnLattice=false; CrystMatrix_REAL symmetricsCoords; const int nbSymmetrics=this->GetSpaceGroup().GetNbSymmetrics(false,false); // Get the list of all atoms within or near the asymmetric unit for(long i=0;iGetSpaceGroup().GetAllSymmetrics(mScattCompList(i).mX, mScattCompList(i).mY, mScattCompList(i).mZ, false,false,false); mvDistTableSq[i].mIndex=i;//USELESS ? bool hasUnique=false; for(int j=0;j.5)x-=1; REAL y=fmod(symmetricsCoords(j,1)-asuyc,(REAL)1.0);if(y<-.5)y+=1;else if(y>.5)y-=1; REAL z=fmod(symmetricsCoords(j,2)-asuzc,(REAL)1.0);if(z<-.5)z+=1;else if(z>.5)z-=1; //cout<GetOrthMatrix()); const REAL m00=(*pOrthMatrix)(0,0); const REAL m01=(*pOrthMatrix)(0,1); const REAL m02=(*pOrthMatrix)(0,2); const REAL m11=(*pOrthMatrix)(1,1); const REAL m12=(*pOrthMatrix)(1,2); const REAL m22=(*pOrthMatrix)(2,2); for(long i=0;iIsBeingRefined()) cout<GetName()<<":" < * const vnb=&(mvDistTableSq[i].mvNeighbour); const REAL x0i=vPos[vUniqueIndex[i] ].mX; const REAL y0i=vPos[vUniqueIndex[i] ].mY; const REAL z0i=vPos[vUniqueIndex[i] ].mZ; for(unsigned long j=0;j.5)x-=1; REAL y=fmod(vPos[j].mY - y0i,(REAL)1.0);if(y<-.5)y+=1;if(y>.5)y-=1; REAL z=fmod(vPos[j].mZ - z0i,(REAL)1.0);if(z<-.5)z+=1;if(z>.5)z-=1; const REAL x0=m00 * x + m01 * y + m02 * z; const REAL y0= m11 * y + m12 * z; const REAL z0= m22 * z; if(loopOnLattice)// distance to self ! {//Now loop over lattice translations for(int sz=-1;sz<=1;sz+=2)// Sign of translation { for(int nz=(sz+1)/2;;++nz) { const REAL z=z0+sz*nz*m22; if(abs(z)>mDistTableMaxDistance) break; for(int sy=-1;sy<=1;sy+=2)// Sign of translation { for(int ny=(sy+1)/2;;++ny) { const REAL y=y0 + sy*ny*m11 + sz*nz*m12; if(abs(y)>mDistTableMaxDistance) break; for(int sx=-1;sx<=1;sx+=2)// Sign of translation { for(int nx=(sx+1)/2;;++nx) { if((vUniqueIndex[i]==j) && (nx==0) && (ny==0) && (nz==0)) continue;// distance to self ! const REAL x=x0 + sx*nx*m00 + sy*ny*m01 + sz*nz*m02; if(abs(x)>mDistTableMaxDistance) break; const REAL d2=x*x+y*y+z*z; if(d2<=asymUnitMargin2) { Neighbour neigh(vPos[j].mAtomIndex,vPos[j].mSymmetryIndex,d2); vnb->push_back(neigh); #if 0 if(!this->IsBeingRefined()) cout<<" "<GetName()<<":" <push_back(neigh); #if 0 if(!this->IsBeingRefined()) cout<GetName()<<":" < #include //#include //#include //#include //#include //#include namespace ObjCryst { class Scatterer; //forward declaration of another header's class :KLUDGE: extern const RefParType *gpRefParTypeCrystal; class NiftyStaticGlobalObjectsInitializer_Crystal { public: NiftyStaticGlobalObjectsInitializer_Crystal() { if (mCount++ == 0) { gpRefParTypeCrystal=new RefParType (gpRefParTypeUnitCell,"Crystal"); } } ~NiftyStaticGlobalObjectsInitializer_Crystal() { if (--mCount == 0) { delete gpRefParTypeCrystal; gpRefParTypeCrystal=0; } } private: static long mCount; }; static NiftyStaticGlobalObjectsInitializer_Crystal NiftyStaticGlobalObjectsInitializer_Crystal_counter; //###################################################################### /** \brief Crystal class: Unit cell, spacegroup, scatterers * * A Crystal object has several main characteristics : (1) a unit cell, * (2) a Spacegroup and (3) a list of Scatterer. Also stored in the Crystal * is a list of the ScttaringPower used by all the scatterers of this crystal. * * The crystal is capable of giving a list of all scattering components * (ie the list of all unique scattering 'points' (ScatteringComponent, ie atoms) * in the unit cell, each associated to a ScatteringPower). * * When those scattering components are on a special position or overlapping with * another component of the same type, it is possible to correct * dynamically the occupancy of this/these components to effectively have * only one component instead of several due to the overlapping. This * method is interesting for global optimization where atoms must not be "locked" * on a special position. If this "Dynamical Occupancy Correction" * is used then no occupancy should be corrected for special positions, since * this will be done dynamically. * * A crystal structure can be viewed in 3D using OpenGL. * * \todo exporting (and importing) crystal structures to/from other files * format than ObjCryst's XML (eg CIF, and format used by refinement software) * * Currently only 3D crystal structures can be handled, with no magnetic * structure (that may be done later) and no incommensurate structure. */ //###################################################################### class Crystal:public UnitCell { public: /// Default Constructor Crystal(); /** \brief Crystal Constructor (orthorombic) * \param a,b,c : unit cell dimension, in angstroems * \param SpaceGroupId: space group symbol or number */ Crystal(const REAL a, const REAL b, const REAL c, const string &SpaceGroupId); /** \brief Crystal Constructor (triclinic) * \param a,b,c : unit cell dimension, in angstroems * \param alpha,beta,gamma : unit cell angles, in radians. * \param SpaceGroupId: space group symbol or number */ Crystal(const REAL a, const REAL b, const REAL c, const REAL alpha, const REAL beta, const REAL gamma,const string &SpaceGroupId); /// Crystal copy constructor Crystal(const Crystal &oldCryst); /// Crystal destructor ~Crystal(); virtual const string& GetClassName() const; /** \brief Add a scatterer to the crystal. * * \warning the scatterer \e must be allocated in the heap, since the scatterer * will \e not be copied but used directly. A Scatterer can only belong to one Crystal. It * will be detroyed when removed or when the Crystal is destroyed. * \param scatt : the address of the scatterer to be included in the crystal * scatterer names \b must be unique in a given crystal. * \note that the ScatteringPower used in the Scatterer should be one * of the Crystal (see Crystal::AddScatteringPower()) * */ void AddScatterer(Scatterer *scatt); /// Remove a Scatterer. This also deletes the scatterer unless del=false. void RemoveScatterer(Scatterer *scatt, const bool del=true); /// Number of scatterers in the crystal long GetNbScatterer()const; /** \brief Provides an access to the scatterers * * \param scattName the name of the scatterer to access */ Scatterer & GetScatt(const string &scattName); /** \brief Provides a const access to the scatterers * * \param scattName the name of the scatterer to access */ const Scatterer & GetScatt(const string &scattName) const; /** \brief Provides an access to the scatterers * * \param scattIndex the number of the scatterer to access */ Scatterer & GetScatt(const long scattIndex); /** \brief Provides a const access to the scatterers * * \param scattIndex the number of the scatterer to access */ const Scatterer & GetScatt(const long scattIndex) const; /// Get the registry of scatterers ObjRegistry& GetScattererRegistry(); /// Get the registry of scatterers const ObjRegistry& GetScattererRegistry()const; /// Get the registry of ScatteringPower included in this Crystal. ObjRegistry& GetScatteringPowerRegistry(); /// Get the registry of ScatteringPower included in this Crystal. const ObjRegistry& GetScatteringPowerRegistry()const; /// Add a ScatteringPower for this Crystal. It must be allocated in the heap, /// and not used by any other Crystal. void AddScatteringPower(ScatteringPower *scattPow); /// Remove a ScatteringPower for this Crystal. (the Scattering power is deleted unless del=false). /// This function should check that it is not used any more before removing it. void RemoveScatteringPower(ScatteringPower *scattPow, const bool del=true); /// Find a ScatteringPower from its name. Names must be unique in a given Crystal. ScatteringPower& GetScatteringPower(const string &name); /// Find a ScatteringPower from its name. Names must be unique in a given Crystal. const ScatteringPower& GetScatteringPower(const string &name)const; /// Get the clock which reports all changes in ScatteringPowers const RefinableObjClock& GetMasterClockScatteringPower()const; /** \brief Get the list of all scattering components */ virtual const ScatteringComponentList& GetScatteringComponentList()const; /** \brief Get the list of all scattering components */ const RefinableObjClock& GetClockScattCompList()const; /// Prints some info about the crystal /// \todo one function to print on one line and a PrintLong() function /// \param os the stream to which the information is outputed (default=cout) void Print(ostream &os=cout) const; /// Formula with atoms in alphabetic order std::string GetFormula() const; /// Weight for the crystal formula, in atomic units (g/mol). This should be /// multiplied by the spacegroup multiplity to get the unit cell weight. REAL GetWeight() const; /** \brief Minimum interatomic distance between all scattering components (atoms) in * the crystal. * * This will return a symmetrical matrix with NbComp rows and cols, where * NbComp is the number of independent scattering components in the unit cell. * All distances are given in Angstroems. * * Note that the distance of a given atom with 'itself' is not generally equal * to 0 (except full special position), but equal to the min distance with its * symmetrics. * * \param minDistance : atoms who are less distant than (minDistance,in Angstroems) * are considered equivalent. So the smallest distance between any atoms will * be at least minDistance. */ CrystMatrix_REAL GetMinDistanceTable(const REAL minDistance=0.1) const; /** \brief Print the minimum distance table between all scattering centers * (atoms) in the crystal. * \param os the stream to which the information is outputed (default=cout) */ void PrintMinDistanceTable(const REAL minDistance=0.1,ostream &os=cout) const; /** \brief XMLOutput POV-Ray Description for this Crystal * * \param onlyIndependentAtoms if false, all symmetrics are showed in the * drawing. * * \warning This currently needs some fixing (ZScatterer does not work ?) * Use rather the OpenGL 3D display which is more useful. * * \param os the stream to which the information is outputed (default=cout) */ ostream& POVRayDescription(ostream &os,const CrystalPOVRayOptions &options)const; #ifdef OBJCRYST_GL /** Create an OpenGL DisplayList of the crystal. * \param onlyIndependentAtoms if false (the default), then all symmetrics * are displayed within the given limits * \ param xMin,xMax,yMin,yMax,zMin,zMax: in fractionnal coordinates, the region * in which we want scaterrers to be displayed. The test is made on the center * of the scatterer (eg a ZScatterer (molecule) will not be 'cut' on the border). * \param displayNames: if true, only the names of the scatterers will be displayed, * at the position of the scatterers (to actually see them, they will have to * be translated with respect to the drawing of the scatterers). * \param hideHydrogens: if true, do not display hydrogens/deuterium and their bonds * \param fadeDistance: atoms which are beyond the display limits are still showm, but * with transparency which is progressively fading up to a certain distance. */ virtual void GLInitDisplayList(const bool onlyIndependentAtoms=false, const REAL xMin=-.1,const REAL xMax=1.1, const REAL yMin=-.1,const REAL yMax=1.1, const REAL zMin=-.1,const REAL zMax=1.1, const bool displayNames=false, const bool hideHydrogens=false, const REAL fadeDistance=0, const bool fullMoleculeInLimits=false)const; #endif // OBJCRYST_GL /** \internal \brief Compute the 'Dynamical population correction for all atoms. * Atoms which are considered "equivalent" (ie currently with the same Z number) * and which are overlapping see their Dynamical occupancy changed so that when they * fully overlap, they are equivalent to 1 atom. * * *\param overlapDist : distance below which atoms (ScatteringComponents, to be more precise) * are considered overlapping and * should be corrected. The correction changes the dynamical occupancy from * 1 to 1/nbAtomOverlapping, progressively as the distance falls from \e overlapDist * to \e mergeDist. *\param mergeDist : distance below which atoms are considered fully overlapping. * If 3 atoms are 'fully' overlapping, then all have a dynamical population * correction equal to 1/3 * * This is const since ScatteringComponent::mDynPopCorr is mutable. * * \warning. Do not call this function, which will turn private. This is * called by \e only Crystal::GetScatteringComponentList() */ void CalcDynPopCorr(const REAL overlapDist=1., const REAL mergeDist=.0)const ; /// Reset Dynamical Population Correction factors (ie set it to 1) void ResetDynPopCorr()const ; /** Access the Dynamical Occupancy Correction for a given component (atom) * in a given Scatterer */ REAL GetDynPopCorr(const Scatterer* pscatt, unsigned int component)const; /** Set the use of dynamical population correction (Crystal::mUseDynPopCorr). * Atoms which are considered "equivalent" (ie currently with the same Z number) * and which are overlapping see their Dynamical occupancy changed so that when they * fully overlap, they are equivalent to 1 atom. * * The Dynamical Occupancy correction will be performed in * Crystal::GetScatteringComponentList() automatically. * * This \e seriously affects the speed of the calculation, since computing * interatomic distances is lenghty. * \param use set to 1 to use, 0 not to use it. */ void SetUseDynPopCorr(const int use); /** Get dynamical population correction setting. * See SetUseDynPopCorr. */ int GetUseDynPopCorr() const; /** Get the Anti-bumping/pro-Merging cost function. Only works (ie returnes a non-null * value) if you have added antibump distances using Crystal::SetBumpMergeDistance(). * */ REAL GetBumpMergeCost() const; /** Set the Anti-bumping distance between two scattering types * */ void SetBumpMergeDistance(const ScatteringPower &scatt1, const ScatteringPower &scatt2, const REAL dist=1.5); /// Set the Anti-bumping distance between two scattering types. void SetBumpMergeDistance(const ScatteringPower &scatt1, const ScatteringPower &scatt2, const REAL dist, const bool allowMerge); /// Remove an Anti-bumping distance between two scattering types. void RemoveBumpMergeDistance(const ScatteringPower &scatt1, const ScatteringPower &scatt2); /// Storage for anti-bump/merge parameters struct BumpMergePar { BumpMergePar(); /** Constructor * * \param dist: the bump/merge distance in Angstroems */ BumpMergePar(const REAL dist, const bool canOverlap=false); /// The squared antibump interatomic distance REAL mDist2; /// Can the two atoms completely overlap ? bool mCanOverlap; }; /// Anti-bump parameters. Each atom type (ScatteringPower is referenced /// using a reference number) typedef std::map,Crystal::BumpMergePar > VBumpMergePar; const VBumpMergePar& GetBumpMergeParList()const; VBumpMergePar& GetBumpMergeParList(); /// When was the list of scatterers last changed ? const RefinableObjClock& GetClockScattererList()const; virtual void XMLOutput(ostream &os,int indent=0)const; /** \brief Input the crystal structure from a stream. * * This will destroy any Scatterer of ScatteringPower if * mDeleteSubObjInDestructor is true. Otherwise they will just * be de-registered and should be deleted somewhere else, * but there is a special hook implemented where any * previously existing ScatteringPowerAtom will be re-used if * equivalent to the one in the input. */ virtual void XMLInput(istream &is,const XMLCrystTag &tag); //virtual void XMLInputOld(istream &is,const IOCrystTag &tag); virtual void GlobalOptRandomMove(const REAL mutationAmplitude, const RefParType *type=gpRefParTypeObjCryst); virtual REAL GetLogLikelihood()const; /** \brief output Crystal structure as a cif file * \param mindist : minimum distance between atoms to consider them * overlapping. Overlapping atoms are only included as comments in the * CIF file. * */ virtual void CIFOutput(ostream &os, double mindist = 0.5)const; virtual void GetGeneGroup(const RefinableObj &obj, CrystVector_uint & groupIndex, unsigned int &firstGroup) const; virtual void BeginOptimization(const bool allowApproximations=false, const bool enableRestraints=false); void AddBondValenceRo(const ScatteringPower&,const ScatteringPower&,const REAL ro); void RemoveBondValenceRo(const ScatteringPower&,const ScatteringPower&); /** Get the Bond-Valence cost function, which compares the expected valence * to the one computed from Bond-Valence Ro parameters. */ REAL GetBondValenceCost() const; std::map, REAL>& GetBondValenceRoList(); const std::map, REAL>& GetBondValenceRoList()const; /** \brief Init all Crystal parameters * \param a,b,c : unit cell dimension, in angstroems * \param alpha,beta,gamma : unit cell angles * \param SpcGroup: space group number (1..230) * \param name: name for the crystal, : '(TaSe4)2I' */ 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); /** Set whether to delete the Scatterers and ScatteringPowers in the * destructor. By default these sub-objects are deleted. */ void SetDeleteSubObjInDestructor(const bool b); /** Convert as much as possible the crystal's atoms to molecule(s). * * \param min_relat_dist, max_relat_dist: this compares all interatomic distances with the sum of atomic covalent radii d_cov, *if d_cov*min_relat_dist < d < d_cov*max_relat_dist, the atoms are assumed to be connected by a bond. * This function only works if the Crystal contains only atoms. * \param warnuser_fail: if true, will pass a message to the end user that auto-creating at least one Molecule failed. * \warning: experimental, unstable */ void ConnectAtoms(const REAL min_relat_dist=0.4, const REAL max_relat_dist=1.3, const bool warnuser_fail=false); /** Merge all equal scattering powers * * \param oneScatteringPowerPerElement: if true, all scattering powers corresponding to the same elemnt of the periodic * classification will be merged into one, with the averaged isotropic Debye-Waller factor. Otherwise, the scattering * powers will be merged only if the Debye Waller factors (isotropic and anisotropic, if any) are identical. * * \warning: this currently only works if the Crystal is only made of Atoms and ScatteringPowerAtoms (it is used at the end * of a CIF import). */ void MergeEqualScatteringPowers(const bool oneScatteringPowerPerElement); private: /** Init options. * * Need only be done once per Crystal. */ void InitOptions(); /// Find a scatterer (its index # in mpScatterrer[]) with a given name /// \warning There should be no duplicate names !!! :TODO: test in AddScatterer() int FindScatterer(const string &scattName)const; /** \internal \brief Compute the distance Table (mDistTable) for all scattering components * \param fast : if true, the distance calculations will be made using * integers, thus with a lower precision but faster. Less atoms will also * be involved (using the AsymmetricUnit and mDistTableMaxDistance2) to make it even faster. * * \warning Crystal::GetScatteringComponentList() \b must be called beforehand, * since this will not be done here. * * \return see Crystal::mDistTableSq and Crystal::mDistTableIndex * \todo sanitize the result distance table in a more usable structure than the currently * used Crystal::mDistTableSq and Crystal::mDistTableIndex. * \warning \e not using the fast option has not been very much tested... * \todo optimize again. Test if recomputation is needed using Clocks. * Use a global option instead of asymUnitMargin. */ void CalcDistTable(const bool fast)const; /** Calculate all Bond Valences. * */ void CalcBondValenceSum()const; /// The registry of scatterers for this UnitCell ObjRegistry mScattererRegistry ; /// Anti-bump parameters map VBumpMergePar mvBumpMergePar; /// Last Time Anti-bump parameters were changed RefinableObjClock mBumpMergeParClock; /// Last Time Anti-bump parameters were changed mutable RefinableObjClock mBumpMergeCostClock; /// Current bump-merge cost mutable REAL mBumpMergeCost; /// Bump-merge scale factor REAL mBumpMergeScale; /// Interatomic distance for a given neighbour struct Neighbour { Neighbour(const unsigned long neighbourIndex,const int sym, const REAL dist2); /// The number associated to the neighbour /// (its index in the Crystal's scattering component list) unsigned long mNeighbourIndex; /// The symmetry position associated to the neighbour /// (its index in the Crystal's scattering component list) unsigned int mNeighbourSymmetryIndex; /// The squared distance, in square Angstroems REAL mDist2; }; /// Table of neighbours for a given unique atom struct NeighbourHood { /// Index of the atom in the scattering component list unsigned long mIndex; /// Index of the symmetry operation for the chosen unique position in the /// (pseudo) asymmetric unit unsigned int mUniquePosSymmetryIndex; /// List of neighbours std::vector mvNeighbour; }; /** Interatomic distance table for all unique atoms * */ mutable std::vector mvDistTableSq; /// The time when the distance table was last calculated mutable RefinableObjClock mDistTableClock; /// The distance up to which the distance table & neighbours needs to be calculated mutable REAL mDistTableMaxDistance; /// The list of all scattering components in the crystal mutable ScatteringComponentList mScattCompList; /// Clock for lattice paramaters. RefinableObjClock mLatticeClock; /// Use Dynamical population correction (ScatteringComponent::mDynPopCorr) during Structure /// factor calculation ? RefObjOpt mUseDynPopCorr; /// The registry of ScatteringPower for this Crystal. ObjRegistry mScatteringPowerRegistry; //Clocks /// Last time the list of Scatterers was changed RefinableObjClock mClockScattererList; /// \internal Last time the ScatteringComponentList was generated mutable RefinableObjClock mClockScattCompList; /// \internal Last time the Neighbor Table was generated mutable RefinableObjClock mClockNeighborTable; /// \internal Last time the dynamical population correction was computed mutable RefinableObjClock mClockDynPopCorr; /// master clock recording every change in Scattering Powers RefinableObjClock mMasterClockScatteringPower; /// Display the enantiomeric (mirror along x) structure in 3D? This can /// be helpful for non-centrosymmetric structure which have been solved using /// powder diffraction (which only gives the relative configuration). RefObjOpt mDisplayEnantiomer; /** Map of Bond Valence "Ro" parameters for each couple of * ScatteringPower */ map, REAL> mvBondValenceRo; /// Last Time Bond Valence parameters were changed RefinableObjClock mBondValenceParClock; /// Last time Bond Valences were calculated mutable RefinableObjClock mBondValenceCalcClock; /// Last time the Bond Valence cost was calculated mutable RefinableObjClock mBondValenceCostClock; /// Current Bond Valence cost mutable REAL mBondValenceCost; /// Bond Valence cost scale factor REAL mBondValenceCostScale; /// List of calculated bond valences, as a map, the key being the index /// of the atom in Crystal::mScattCompList. mutable std::map mvBondValenceCalc; // Flag indicating whether to delete Scatterers and ScatteringPowers in // the destructor (default true). Modified by // SetDeleteSubObjInDestructor. bool mDeleteSubObjInDestructor; #ifdef __WX__CRYST__ public: virtual WXCrystObjBasic* WXCreate(wxWindow*); friend class WXCrystal; #endif }; /// Global registry for all Crystal objects extern ObjRegistry gCrystalRegistry; }// namespace #endif //_OBJCRYST_CRYSTAL_H_ objcryst-2022.1/ObjCryst/ObjCryst/DiffractionDataSingleCrystal.cpp000066400000000000000000001244711430515525000252000ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * source file for ObjCryst++ DiffractionData class * */ //#include #include #include #include "ObjCryst/ObjCryst/DiffractionDataSingleCrystal.h" #include "ObjCryst/ObjCryst/CIF.h" #include "ObjCryst/Quirks/VFNDebug.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" #ifdef __WX__CRYST__ #include "ObjCryst/wxCryst/wxDiffractionSingleCrystal.h" #endif #include #include #include //for sprintf() //#include #ifdef _MSC_VER // MS VC++ predefined macros.... #undef min #undef max #endif namespace ObjCryst { //###################################################################### // DiffractionDataSingleCrystal //###################################################################### ObjRegistry gDiffractionDataSingleCrystalRegistry("Global DiffractionDataSingleCrystal Registry"); DiffractionDataSingleCrystal::DiffractionDataSingleCrystal(const bool regist): mHasObservedData(false),mScaleFactor(1.) { VFN_DEBUG_MESSAGE("DiffractionDataSingleCrystal::DiffractionDataSingleCrystal()",5) this->InitRefParList(); this->InitOptions(); if(regist) gDiffractionDataSingleCrystalRegistry.Register(*this); if(regist) gTopRefinableObjRegistry.Register(*this); mClockMaster.AddChild(mClockScaleFactor); this->AddSubRefObj(mRadiation); } DiffractionDataSingleCrystal::DiffractionDataSingleCrystal(Crystal &cryst,const bool regist): mHasObservedData(false),mScaleFactor(1.) { VFN_DEBUG_MESSAGE("DiffractionDataSingleCrystal::DiffractionDataSingleCrystal()",5) this->InitRefParList(); this->SetCrystal(cryst); this->InitOptions(); if(regist) gDiffractionDataSingleCrystalRegistry.Register(*this); if(regist) gTopRefinableObjRegistry.Register(*this); mClockMaster.AddChild(mClockScaleFactor); this->AddSubRefObj(mRadiation); } DiffractionDataSingleCrystal::DiffractionDataSingleCrystal(const DiffractionDataSingleCrystal &old): ScatteringData(old), mHasObservedData(old.mHasObservedData),mRadiation(old.mRadiation) { mObsIntensity=old.mObsIntensity; // Keep a copy as squared F(hkl), to enable fourier maps // :TODO: stop using mObsIntensity and just keep mFhklObsSq ? mFhklObsSq=mObsIntensity; mClockFhklObsSq.Click(); mObsSigma=old.mObsSigma; mWeight=old.mWeight; mCalcIntensity=old.mCalcIntensity; mScaleFactor=old.mScaleFactor; this->InitOptions(); mGroupOption.SetChoice(old.mGroupOption.GetChoice()); gDiffractionDataSingleCrystalRegistry.Register(*this); gTopRefinableObjRegistry.Register(*this); mClockMaster.AddChild(mClockScaleFactor); this->AddSubRefObj(mRadiation); } DiffractionDataSingleCrystal::~DiffractionDataSingleCrystal() { VFN_DEBUG_MESSAGE("DiffractionDataSingleCrystal::~DiffractionDataSingleCrystal()",5) gDiffractionDataSingleCrystalRegistry.DeRegister(*this); gTopRefinableObjRegistry.DeRegister(*this); } DiffractionDataSingleCrystal* DiffractionDataSingleCrystal::CreateCopy()const { VFN_DEBUG_MESSAGE("DiffractionDataSingleCrystal::CreateCopy()",5) return new DiffractionDataSingleCrystal(*this); } const string& DiffractionDataSingleCrystal::GetClassName() const { const static string className="DiffractionDataSingleCrystal"; return className; } void DiffractionDataSingleCrystal::SetHklIobs(const CrystVector_long &h, const CrystVector_long &k, const CrystVector_long &l, const CrystVector_REAL &iObs, const CrystVector_REAL &sigma) { VFN_DEBUG_ENTRY("DiffractionDataSingleCrystal::SetHklIobs(h,k,l,i,s)",5) mNbRefl=h.numElements(); mH.resize(mNbRefl); mK.resize(mNbRefl); mL.resize(mNbRefl); mObsIntensity.resize(mNbRefl); mObsSigma.resize(mNbRefl); mWeight.resize(mNbRefl); mMultiplicity.resize(mNbRefl); mH=h; mK=k; mL=l; mObsIntensity=iObs; mObsSigma=sigma; mMultiplicity=1; this->PrepareHKLarrays(); this->CalcSinThetaLambda(); this->SortReflectionBySinThetaOverLambda(); this->SetWeightToInvSigma2(1e-4,0); mHasObservedData=true; // Keep a copy as squared F(hkl), to enable fourier maps // :TODO: stop using mObsIntensity and just keep mFhklObsSq ? mFhklObsSq=mObsIntensity; mClockFhklObsSq.Click(); /*{ char buf [200]; sprintf(buf,"Changed HKL list, with %d reflections",(int)mNbRefl); (*fpObjCrystInformUser)((string)buf); }*/ VFN_DEBUG_EXIT("DiffractionDataSingleCrystal::SetHklIobs(h,k,l,i,s)",5) } const CrystVector_REAL& DiffractionDataSingleCrystal::GetIcalc()const { this->CalcIcalc(); return mCalcIntensity; } std::map & DiffractionDataSingleCrystal::GetIcalc_FullDeriv(std::set &vPar) { this->CalcIcalc_FullDeriv(vPar); return mCalcIntensity_FullDeriv; } const CrystVector_REAL& DiffractionDataSingleCrystal::GetIobs()const { //if(mHasObservedData==false) DoSomething return mObsIntensity; } void DiffractionDataSingleCrystal::SetIobs(const CrystVector_REAL &obs) { mObsIntensity=obs; // Keep a copy as squared F(hkl), to enable fourier maps // :TODO: stop using mObsIntensity and just keep mFhklObsSq ? mFhklObsSq=mObsIntensity; mClockFhklObsSq.Click(); } const CrystVector_REAL& DiffractionDataSingleCrystal::GetSigma()const { //if(mHasObservedData=false) DoSomething return mObsSigma; } void DiffractionDataSingleCrystal::SetSigma(const CrystVector_REAL& sigma) {mObsSigma=sigma;} const CrystVector_REAL& DiffractionDataSingleCrystal::GetWeight()const { //if(mHasObservedData=false) DoSomething return mWeight; } void DiffractionDataSingleCrystal::SetWeight(const CrystVector_REAL& weight) { VFN_DEBUG_MESSAGE("DiffractionDataSingleCrystal::SetWeight(w)",5) mWeight=weight; mClockMaster.Click(); } void DiffractionDataSingleCrystal::SetIobsToIcalc() { VFN_DEBUG_MESSAGE("DiffractionDataSingleCrystal::SetIobsToIcalc()",5) mObsIntensity=this->GetIcalc(); mObsSigma.resize(mNbRefl); mWeight.resize(mNbRefl); mWeight=1; mObsSigma=0; mHasObservedData=true; // Keep a copy as squared F(hkl), to enable fourier maps // :TODO: stop using mObsIntensity and just keep mFhklObsSq ? mFhklObsSq=mObsIntensity; mClockFhklObsSq.Click(); mClockMaster.Click(); } void DiffractionDataSingleCrystal::ImportHklIobs(const string &fileName, const long nbRefl, const int skipLines) { //configure members mNbRefl=nbRefl; mH.resize(mNbRefl); mK.resize(mNbRefl); mL.resize(mNbRefl); mObsIntensity.resize(mNbRefl); mObsSigma.resize(mNbRefl); //Import data { //:TODO: Skip the lines if required !!! cout << "inputing reflections from file : "+fileName<> mH(i); fin >> mK(i); fin >> mL(i); fin >> mObsIntensity(i); mObsSigma(i)=sqrt(fabs(mObsIntensity(i))); //cout << mObsIntensity(i) <"<< endl; fin.close(); } //Finish mWeight.resize(mNbRefl); const REAL minIobs=mObsIntensity.max()*1e-6; for(int i=0;iPrepareHKLarrays(); this->SortReflectionBySinThetaOverLambda(); { char buf [200]; sprintf(buf,"Imported HKLIobs, with %d reflections",(int)mNbRefl); (*fpObjCrystInformUser)((string)buf); } cout << "Finished storing data..."<< endl ; } void DiffractionDataSingleCrystal::ImportHklIobsSigma(const string &fileName, const long nbRefl, const int skipLines) { //configure members mNbRefl=nbRefl; mH.resize(mNbRefl); mK.resize(mNbRefl); mL.resize(mNbRefl); mObsIntensity.resize(mNbRefl); mObsSigma.resize(mNbRefl); //Import data { cout << "inputing reflections from file : "+fileName<0) {//Get rid of first lines if required char tmpComment[200]; for(int i=0;i> mH(i); fin >> mK(i); fin >> mL(i); fin >> mObsIntensity(i); fin >> mObsSigma(i); //cout << mH(i)<<" "<"<< endl; fin.close(); } //Finish mWeight.resize(mNbRefl); this->SetWeightToInvSigma2(1e-4,0); mHasObservedData=true; mMultiplicity.resize(mNbRefl); mMultiplicity=1; // Keep a copy as squared F(hkl), to enable fourier maps // :TODO: stop using mObsIntensity and just keep mFhklObsSq ? mFhklObsSq=mObsIntensity; mClockFhklObsSq.Click(); this->PrepareHKLarrays(); this->SortReflectionBySinThetaOverLambda(); { char buf [200]; sprintf(buf,"Imported HKLIobsSigma, with %d reflections",(int)mNbRefl); (*fpObjCrystInformUser)((string)buf); } cout << "Finished storing data..."<< endl ; } void DiffractionDataSingleCrystal::ImportShelxHKLF4(const string &fileName) { VFN_DEBUG_ENTRY("DiffractionDataSingleCrystal::ImportShelxHKLF4():"<SetWeightToInvSigma2(1e-4,0); mHasObservedData=true; mMultiplicity.resize(mNbRefl); mMultiplicity=1; // Keep a copy as squared F(hkl), to enable fourier maps // :TODO: stop using mObsIntensity and just keep mFhklObsSq ? mFhklObsSq=mObsIntensity; mClockFhklObsSq.Click(); this->PrepareHKLarrays(); this->SortReflectionBySinThetaOverLambda(); { char buf [200]; sprintf(buf,"Imported Shelx HKLF 4 file, with %d reflections",(int)mNbRefl); (*fpObjCrystInformUser)((string)buf); } VFN_DEBUG_EXIT("DiffractionDataSingleCrystal::ImportShelxHKLF4() read "<::iterator pos=cif.mvData.begin();pos!=cif.mvData.end();++pos) { if(pos->second.mH.numElements()>0) { this->SetHklIobs(pos->second.mH,pos->second.mK,pos->second.mL,pos->second.mIobs,pos->second.mSigma); break; } } VFN_DEBUG_EXIT("DiffractionDataSingleCrystal::ImportCIF() read "<> tmpH; while(tmpH != 999) { // :TODO: A little faster.... //:TODO: Check for the end of the stream if(!fin.good()) {throw...} i++; if(i>=mNbRefl) { cout << mNbRefl << " reflections imported..." << endl; mNbRefl+=1000; mH.resizeAndPreserve(mNbRefl); mK.resizeAndPreserve(mNbRefl); mL.resizeAndPreserve(mNbRefl); mObsIntensity.resizeAndPreserve(mNbRefl); mObsSigma.resizeAndPreserve(mNbRefl); } mH(i)=tmpH; fin >> mK(i); fin >> mL(i); fin >> mObsIntensity(i); fin >> mObsSigma(i); fin >> junk; fin >> junk; fin >> junk; fin >> junk; fin >> tmpH; } fin.close(); mNbRefl=i; cout << mNbRefl << " reflections imported." << endl; mH.resizeAndPreserve(mNbRefl); mK.resizeAndPreserve(mNbRefl); mL.resizeAndPreserve(mNbRefl); mObsIntensity.resizeAndPreserve(mNbRefl); mObsSigma.resizeAndPreserve(mNbRefl); } //Finish mWeight.resize(mNbRefl); mWeight=1; mMultiplicity.resize(mNbRefl); mMultiplicity=1; // Keep a copy as squared F(hkl), to enable fourier maps // :TODO: stop using mObsIntensity and just keep mFhklObsSq ? mFhklObsSq=mObsIntensity; mClockFhklObsSq.Click(); this->PrepareHKLarrays(); this->SortReflectionBySinThetaOverLambda(); cout << "Finished storing data..."<< endl ; mHasObservedData=true; { char buf [200]; sprintf(buf,"Imported HKLIobsSigma from Jana, with %d reflections",(int)mNbRefl); (*fpObjCrystInformUser)((string)buf); } } void DiffractionDataSingleCrystal::ImportHklIobsGroup(const string &fileName,const unsigned int skipLines) { //configure members mNbRefl=0; mNbGroup=0; mH.resize(500); mK.resize(500); mL.resize(500); mObsIntensity.resize(500); mObsSigma.resize(500); mGroupIndex.resize(500); mGroupIobs.resize(500); mGroupSigma.resize(500); mGroupWeight.resize(500); //Import data { //:TODO: Skip the lines if required !!! cout << "inputing reflections from file : "+fileName<> h >> k >> l) ? 3 : 0; nn += bool(linestream >> iobs); nn += bool(linestream >> sigma); const int n = nn; if(n<3) break; mH(mNbRefl)=h; mK(mNbRefl)=k; mL(mNbRefl)=l; mGroupIndex(mNbRefl)=mNbGroup; //cout<SortReflectionBySinThetaOverLambda(); this->CalcIcalc(); } REAL DiffractionDataSingleCrystal::GetRw()const { TAU_PROFILE("DiffractionData::Rw()"," REAL()",TAU_DEFAULT); VFN_DEBUG_MESSAGE("DiffractionData::Rw()",3); if(mHasObservedData==false) { return 0; } REAL tmp1=0; REAL tmp2=0; const REAL *p1; const REAL *p2; const REAL *p3; long nb; if(mGroupOption.GetChoice()==0) { p1=mCalcIntensity.data(); p2=mObsIntensity.data(); p3=mWeight.data(); nb=mNbReflUsed; } else { p1=mGroupIcalc.data(); p2=mGroupIobs.data(); p3=mGroupWeight.data(); nb=mGroupIobs.numElements(); } for(long i=nb;i>0;i--) { tmp1 += *p3 * ( *p1 - *p2) * ( *p1 - *p2); tmp2 += *p3 * *p2 * *p2; p1++;p2++;p3++; } tmp1=sqrt(tmp1/tmp2); VFN_DEBUG_MESSAGE("DiffractionData::Rw()="<GetNbRefl(); } REAL DiffractionDataSingleCrystal::GetR()const { TAU_PROFILE("DiffractionData::R()"," REAL()",TAU_DEFAULT); VFN_DEBUG_MESSAGE("DiffractionData::R()",3); if(mHasObservedData==false) { return 0; } REAL tmp1=0; REAL tmp2=0; const REAL *p1; const REAL *p2; long nb; if(mGroupOption.GetChoice()==0) { p1=mCalcIntensity.data(); p2=mObsIntensity.data(); nb=mNbReflUsed; } else { p1=mGroupIcalc.data(); p2=mGroupIobs.data(); nb=mGroupIobs.numElements(); } for(long i=nb;i>0;i--) { tmp1 += ( *p1 - *p2) * ( *p1 - *p2); tmp2 += *p2 * *p2; p1++;p2++; } tmp1=sqrt(tmp1/tmp2); VFN_DEBUG_MESSAGE("DiffractionData::R()="<GetNbReflBelowMaxSinThetaOvLambda(); if(mClockChi2>mClockMaster) return mChi2; this->CalcIcalc(); if(mClockChi2>mClockIcalc) return mChi2; TAU_PROFILE("DiffractionData::Chi2()"," REAL()",TAU_DEFAULT); VFN_DEBUG_ENTRY("DiffractionData::Chi2()",3); this->FitScaleFactorForRw(); mChi2=0; const REAL *p1; const REAL *p2; const REAL *p3; long nb; if(mGroupOption.GetChoice()==0) { p1=mCalcIntensity.data(); p2=mObsIntensity.data(); p3=mWeight.data(); nb=mNbReflUsed; } else { p1=mGroupIcalc.data(); p2=mGroupIobs.data(); p3=mGroupWeight.data(); nb=mGroupIobs.numElements(); } for(long i=nb;i>0;i--) { mChi2 += *p3++ * ( *p1 - *p2) * ( *p1 - *p2); p1++;p2++; } /* // SSE code gives about 30% faster code on P3 (tested with 10000 reflections), // but scarcely any improvement on athlon-xp union sse4f { __m128 m128; struct { float x, y, z, w; }; } ; const long nb=mNbReflUsed/4; const float* p1=mCalcIntensity.data(); const float* p2=mObsIntensity.data(); const float* p3=mWeight.data(); for(long i=0;i0;i--) { tmp1 += *p3 * (*p1) * (*p2++); tmp2 += *p3++ * (*p1) * (*p1); p1++; } mScaleFactor *= tmp1/tmp2; mClockScaleFactor.Click(); mCalcIntensity *= tmp1/tmp2; if(0!=mGroupOption.GetChoice()) mGroupIcalc*= tmp1/tmp2; mClockIcalc.Click(); } void DiffractionDataSingleCrystal::FitScaleFactorForR() const { TAU_PROFILE("DiffractionData::FitScaleFactorForR()","void ()",TAU_DEFAULT); VFN_DEBUG_MESSAGE("DiffractionData::FitScaleFactorForR()",3); if(mHasObservedData==false) {//throw exception here ? return; //throw ObjCrystException("DiffractionData::FitScaleFactorForR() Cannot compute R // or scale factor: there is no observed data !"); } REAL tmp1=0; REAL tmp2=0; const REAL *p1; const REAL *p2; long nb; if(mGroupOption.GetChoice()==0) { p1=mCalcIntensity.data(); p2=mObsIntensity.data(); nb=mNbReflUsed; } else { p1=mGroupIcalc.data(); p2=mGroupIobs.data(); nb=mGroupIobs.numElements(); } for(long i=nb;i>0;i--) { tmp1 += (*p1) * (*p2++); tmp2 += (*p1) * (*p1); p1++; } mScaleFactor *= tmp1/tmp2; mClockScaleFactor.Click(); mCalcIntensity *= tmp1/tmp2; if(0!=mGroupOption.GetChoice()) mGroupIcalc*= tmp1/tmp2; mClockIcalc.Click(); } REAL DiffractionDataSingleCrystal::GetBestRFactor() const { TAU_PROFILE("DiffractionData::GetBestRFactor()","void ()",TAU_DEFAULT); VFN_DEBUG_MESSAGE("DiffractionData::GetBestRFactor()",3); this->FitScaleFactorForR(); return this->GetR(); } void DiffractionDataSingleCrystal::SetSigmaToSqrtIobs() { for(long i=0;iCalcSinThetaLambda(); cout << "DiffractionData : " << mName < (mH,mK,mL,mObsIntensity,mObsSigma,mSinThetaLambda,12,4); } void DiffractionDataSingleCrystal::PrintObsCalcData()const { this->CalcIcalc(); CrystVector_REAL tmpTheta=mTheta; tmpTheta*= RAD2DEG; /* CrystVector_REAL tmp=mObsIntensity; CrystVector_REAL tmpS=mObsSigma; if(true==mHasObservedData) { cout << "Scale factor : " << mScaleFactor <(mH,mK,mL, mObsIntensity,mObsSigma,mCalcIntensity, mMultiplicity,tmpTheta,mSinThetaLambda, mFhklCalcReal,mFhklCalcImag,mWeight,12,4); } void DiffractionDataSingleCrystal::SetUseOnlyLowAngleData( const bool useOnlyLowAngle,const REAL angle) { throw ObjCrystException("DiffractionDataSingleCrystal::SetUseOnlyLowAngleData() :\ not yet implemented for DiffractionDataSingleCrystal."); } void DiffractionDataSingleCrystal::SaveHKLIobsIcalc(const string &filename) { VFN_DEBUG_MESSAGE("DiffractionDataSingleCrystal::SaveHKLIobsIcalc",5) this->GetIcalc(); ofstream out(filename.c_str()); CrystVector_REAL theta; theta=mTheta; theta *= RAD2DEG; if(false == mHasObservedData) { out << "# H K L Icalc theta sin(theta)/lambda" <<" Re(F) Im(F)" << endl; out << FormatVertVectorHKLFloats(mH,mK,mL,mCalcIntensity, theta,mSinThetaLambda,mFhklCalcReal,mFhklCalcImag,12,4); } else { out << "# H K L Iobs Icalc theta" <<" sin(theta)/lambda Re(F) Im(F)" << endl; out << FormatVertVectorHKLFloats(mH,mK,mL,mObsIntensity,mCalcIntensity, theta,mSinThetaLambda,mFhklCalcReal,mFhklCalcImag,12,4); } out.close(); VFN_DEBUG_MESSAGE("DiffractionDataSingleCrystal::SaveHKLIobsIcalc:End",3) } void DiffractionDataSingleCrystal::GlobalOptRandomMove(const REAL mutationAmplitude, const RefParType *type) { this->RefinableObj::GlobalOptRandomMove(mutationAmplitude,type); //this->FitScaleFactorForRw(); } REAL DiffractionDataSingleCrystal::GetLogLikelihood()const { return this->GetChi2(); } void DiffractionDataSingleCrystal::InitRefParList() { VFN_DEBUG_MESSAGE("DiffractionDataSingleCrystal::InitRefParList()",5) RefinablePar tmp("Scale factor",&mScaleFactor, 1e-10,1e10,gpRefParTypeScattDataScale,REFPAR_DERIV_STEP_RELATIVE, false,true,true,false,1.); tmp.SetGlobalOptimStep(0.); tmp.AssignClock(mClockScaleFactor); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } unsigned int DiffractionDataSingleCrystal::GetNbLSQFunction()const{return 1;} const CrystVector_REAL& DiffractionDataSingleCrystal::GetLSQCalc(const unsigned int) const {return this->GetIcalc();} const CrystVector_REAL& DiffractionDataSingleCrystal::GetLSQObs(const unsigned int) const {return this->GetIobs();} const CrystVector_REAL& DiffractionDataSingleCrystal::GetLSQWeight(const unsigned int) const {return this->GetWeight();} std::map & DiffractionDataSingleCrystal::GetLSQ_FullDeriv(const unsigned int,std::set &vPar) { #if 0 this->GetIcalc_FullDeriv(vPar); std::map fullderiv_old; std::vector v; int n=0; for(std::map::reverse_iterator pos=mCalcIntensity_FullDeriv.rbegin();pos!=mCalcIntensity_FullDeriv.rend();++pos) { v.push_back(&(pos->second)); fullderiv_old[pos->first]=this->GetLSQDeriv(0,*(pos->first)); v.push_back(&(fullderiv_old[pos->first])); cout<first->GetName()<<":"<second.size()<<","<first].size()<8) break; } cout<(v,10)<GetIcalc_FullDeriv(vPar); } const Radiation& DiffractionDataSingleCrystal::GetRadiation()const { return mRadiation;} Radiation& DiffractionDataSingleCrystal::GetRadiation() { return mRadiation;} void DiffractionDataSingleCrystal::SetRadiationType(const RadiationType radiation) { VFN_DEBUG_MESSAGE("DiffractionDataSingleCrystal::SetRadiationType():End",5) mRadiation.SetRadiationType(radiation); } void DiffractionDataSingleCrystal::SetWavelength(const REAL lambda) { VFN_DEBUG_MESSAGE("DiffractionDataSingleCrystal::SetWavelength() to "<GetRadiation().SetWavelength(lambda); } void DiffractionDataSingleCrystal::SetWavelength(const string &XRayTubeElementName, const REAL alpha2Alpha2ratio) { VFN_DEBUG_MESSAGE("DiffractionDataSingleCrystal::SetWavelength() to "<GetRadiation().SetWavelength(XRayTubeElementName,alpha2Alpha2ratio); } void DiffractionDataSingleCrystal::SetEnergy(const REAL energy) { this->SetWavelength(12398.4/energy); } void DiffractionDataSingleCrystal::CalcIcalc() const { TAU_PROFILE("DiffractionData::CalcIcalc()","void ()",TAU_DEFAULT); VFN_DEBUG_MESSAGE("DiffractionData::CalcIcalc():"<GetName(),3) this->GetFhklCalcSq(); if( (mClockStructFactorSqPrepareTwinningCalc(); mGroupIcalc.resize(mNbGroup); mGroupIcalc=0; long first=0; for(long i=0;i"< Icalc="<< mGroupIcalc(i) <<" , Iobs="<< mGroupIobs(i)< &vPar) { TAU_PROFILE("DiffractionDataSingleCrystal::CalcIcalc_FullDeriv()","void ()",TAU_DEFAULT); this->GetFhklCalcSq_FullDeriv(vPar); // :TODO: instead of clear(), only add/remove when necessary ? mCalcIntensity_FullDeriv.clear(); mCalcIntensity_FullDeriv=mFhklCalcSq_FullDeriv; //:TODO: multiplication only up to mNbReflUsed for(std::map::iterator pos=mCalcIntensity_FullDeriv.begin(); pos!=mCalcIntensity_FullDeriv.end();pos++) { if(pos->first==0) {// This is Icalc, not derived pos->second *=mScaleFactor; continue; } if(pos->first->GetPointer()!=&mScaleFactor) { /*if(pos->second.size()>0) */ // not needed pos->second *=mScaleFactor; } else { pos->second=mFhklCalcSq; } } if(0!=mGroupOption.GetChoice()) {//:TODO: if(1==mGroupOption.GetChoice()) this->PrepareTwinningCalc(); // :TODO: instead of clear(), only add/remove when necessary ? mGroupIcalc_FullDeriv.clear(); for(std::map::iterator pos=mCalcIntensity_FullDeriv.begin(); pos!=mCalcIntensity_FullDeriv.end();pos++) { mGroupIcalc_FullDeriv[pos->first].resize(mNbGroup); mGroupIcalc_FullDeriv[pos->first]=0; long first=0; for(long i=0;ifirst](i)+=mCalcIntensity_FullDeriv[pos->first](j); } first=mGroupIndex(i); } } } } CrystVector_long DiffractionDataSingleCrystal::SortReflectionBySinThetaOverLambda(const REAL maxSTOL) { TAU_PROFILE("DiffractionDataSingleCrystal::SortReflectionBySinThetaOverLambda()","void ()",TAU_DEFAULT); VFN_DEBUG_ENTRY("DiffractionDataSingleCrystal::SortReflectionBySinThetaOverLambda()",5) // ScatteringData::SortReflectionBySinThetaOverLambda only sorts H,K,L and multiplicity. CrystVector_long index=this->ScatteringData::SortReflectionBySinThetaOverLambda(maxSTOL); if(mObsIntensity.numElements()==mNbRefl) { CrystVector_REAL tmpObs,tmpSigma,tmpWeight; tmpObs=mObsIntensity; tmpSigma=mObsSigma; tmpWeight=mWeight; for(long i=0;i"<PrepareHKLarrays(); this->CalcSinThetaLambda(); } // re-write mGroupIndex so that it marks the // last reflection of each group. index=mGroupIndex; mGroupIndex.resize(mNbGroup); long group=0; for(long i=0;iAddOption(&mGroupOption); } void DiffractionDataSingleCrystal::PrepareTwinningCalc() const { if(mClockPrepareTwinningCorr>mClockHKL) return; VFN_DEBUG_ENTRY("DiffractionDataSingleCrystal::PrepareTwinningCalc()",5) // first get the index of reflections which limit each block of summed reflections mNbGroup=0; { const REAL dSiThOvLa=.0001; mGroupIndex.resize(mNbReflUsed); this->CalcSinThetaLambda(); REAL sithol0=mSinThetaLambda(0)+dSiThOvLa; for(long i=1;isithol0) { mGroupIndex(mNbGroup++)=i; sithol0=mSinThetaLambda(i)+dSiThOvLa; } } mGroupIndex(mNbGroup++)=mNbReflUsed; mGroupIndex.resizeAndPreserve(mNbGroup); } // Calculate summed Iobs and weight { mGroupIobs.resize(mNbGroup); mGroupIobs=0; mGroupWeight.resize(mNbGroup); mGroupWeight=0; mGroupSigma.resize(mNbGroup); mGroupSigma=0; long first=0; for(long i=0;i #include //#include //#include //#include //#include //#include namespace ObjCryst { //###################################################################### // DiffractionDataSingleCrystal /** * \brief DiffractionData object for Single Crystal analysis. * * Currently this handles only in the simplest way single crystal dat: ie * only data which has been completely corrected for Lorentz/Polarization * and absorption. * * What needs to be developped: define the geometry of the experiment * (incident and emerging angles), the polarization of the beam, etc... */ //###################################################################### class DiffractionDataSingleCrystal:public ScatteringData { public: /** Default constructor * * \param regist: if false, do not add to the global registry of * single crystal data or refinable objects - this is only useful * for data to be used internally only. * * \deprecated Use the constructor passing a crystal structure instead. */ DiffractionDataSingleCrystal(const bool regist=true); /** Constructor, with an assigned crystal structure. * * \param regist: if false, do not add to the global registry of * single crystal data or refinable objects - this is only useful * for data to be used internally only. */ DiffractionDataSingleCrystal(Crystal &cryst,const bool regist=true); /// Copy constructor DiffractionDataSingleCrystal(const DiffractionDataSingleCrystal &old); ~DiffractionDataSingleCrystal(); virtual DiffractionDataSingleCrystal* CreateCopy()const; virtual const string& GetClassName() const; /** \brief returns the calculated diffracted intensity. * * This is an array of calculated intensities for each reflections in the * single crystal case, and the array with the full powder powder profile * for powder diffraction. */ const CrystVector_REAL& GetIcalc() const; /// \todo std::map & GetIcalc_FullDeriv(std::set &vPar); /// Return the array of observed intensities for all peaks const CrystVector_REAL& GetIobs() const; /// Return the array of observed intensities for all peaks void SetIobs(const CrystVector_REAL&); /// Return the array of sigmas for observed intensities, for all peaks. const CrystVector_REAL& GetSigma() const; /// Return the array of sigmas for observed intensities, for all peaks. void SetSigma(const CrystVector_REAL&); /// Set Iobs to current values of Icalc. Mostly used for tests. void SetIobsToIcalc(); /// Return the weights (for each reflection) used for computing Rw. const CrystVector_REAL& GetWeight() const; /// Change the weights (for each reflection) used for computing Rw. void SetWeight(const CrystVector_REAL&); /** \brief input H,K,L, Iobs and Sigma * * \param h,k,l: REAL arrays (vectors with NbRefl elements -same size) *with the h, k and l coordinates of all reflections. * \param iobs,sigma: REAL arrays (vectors with NbRefl elements -same size) *with the Observed intensity and sigma for all reflections. * */ void SetHklIobs(const CrystVector_long &h, const CrystVector_long &k, const CrystVector_long &l, const CrystVector_REAL &iObs, const CrystVector_REAL &sigma); /** \brief Import h,k,l,I from a file * *The file is assumed to correspond to a single crystal diffraction file. * \param fileName The name of the data file. This file should be formatted *with H,k,l, Iobs separated by spaces. * \param nbRefl The number of reflections to extract. * \param skipLines The number of lines to skip at the beginning of the file. */ void ImportHklIobs(const string &fileName,const long nbRefl,const int skipLines=0); /** \brief Import h,k,l,I,Sigma from a file * *The file is assumed to correspond to a single crystal diffraction file. * \param fileName The name of the data file. This file should be formatted *with H,k,l, Iobs and Sigma separated by spaces. * \param nbRefl The number of reflections to extract. * \param skipLines The number of lines to skip at the beginning of the file. */ void ImportHklIobsSigma(const string &fileName,const long nbRefl,const int skipLines=0); /** \brief Import h,k,l,I,Sigma from a file using shelx HKLF 4 format * *The file is assumed to correspond to a single crystal diffraction file.This file * should be formatted with H,k,l, Iobs and Sigma using a strict formatting 3I4+2F8, * and the last line should contain 0 0 0 for hkl values. * \param fileName The name of the data file. */ void ImportShelxHKLF4(const string &fileName); /** \brief Import diffraction data from a CIF file * *The file is assumed to correspond to a single crystal diffraction file. * \param fileName The name of the data file. */ void ImportCIF(const string &fileName); /** \brief Import h,k,l,I,Sigma from a Jana98 '*.m91' file * *The file is assumed to correspond to a single crystal diffraction file. * \param fileName The name of the data file. */ void ImportHklIobsSigmaJanaM91(const string &fileName); /** \brief Import h,k,l and grouped intensities from a file * *The file is assumed to correspond to a single crystal diffraction file. * \param fileName The name of the data file. This file should be formatted *with H,k,l, Iobs separated by spaces. * \param skipLines The number of lines to skip at the beginning of the file. * * File format (the reflection which has an intensity entry marks the end of the group) * h k l Igroup * -2 4 2 * -2 -4 2 100.4 * 2 -4 1 * 2 4 1 193.2 * ... */ void ImportHklIobsGroup(const string &fileName,const unsigned int skipLines=0); /** \brief Return the Crystal R-factor (weighted) * * \return \f$ R_{w}= \sqrt {\frac{\sum_i w_i\left( I_i^{obs}-I_i^{calc} \right)^2} * {\sum_i w_i (I_i^{obs})^2} }\f$ */ virtual REAL GetRw()const; /** \brief Return the Crystal R-factor (unweighted) * * \return \f$ R= \sqrt {\frac{\sum_i \left( I_i^{obs}-I_i^{calc} \right)^2} * {\sum_i (I_i^{obs})^2} }\f$ */ virtual REAL GetR()const; /** \brief Return conventionnal Chi^2 * \return \f$ \chi^2 = \sum_i w_i \left(I_i^{obs}-I_i^{calc} \right)^2 * \f$ */ // \return \f$ \chi^2 = \sum_i \left( \frac{ y_i^{obs}-y_i^{calc}}{\sigma_i} \right)^2 virtual REAL GetChi2()const; /* \brief Return Goodness of Fit * * \return \f$ GoF = \frac{\sum_i w_i\left( y_i^{obs}-y_i^{calc} \right)^2} * {N_{obs}-N_{indep.par}} \f$ virtual REAL GoF()const; */ /** Compute the best scale factor minimising Rw. * * The computed scale factor is \e immediatly applied to Icalc */ virtual void FitScaleFactorForRw() const; /** Compute the best scale factor minimising R. * * The computed scale factor is \e immediatly applied to Icalc */ virtual void FitScaleFactorForR() const; /// Compute the best scale factor to minimize R, apply this scale factor and return /// the R value obtained. virtual REAL GetBestRFactor() const; /** \brief Set sigma for all observed intensities to sqrt(obs) * */ virtual void SetSigmaToSqrtIobs(); /** \brief Set the weight for all observed intensities to 1/sigma^2 * *For sigmas which are smaller than minRelatSigma times the max value of sigma, *the output weight is set to 0. * * For reflections where the intensity is below minIobsSigmaRatio*sigma, the weight is set to zero * so that this reflection is ignored. */ virtual void SetWeightToInvSigma2(const REAL minRelatSigma=1e-4, const REAL minIobsSigmaRatio=0); /// Scale factor (applied to Icalc to match Iobs) REAL GetScaleFactor()const; // Set the Scale factor (applied to Icalc to match Iobs) //void SetScaleFactor(const REAL); /** \brief Print H, K, L Iobs sigma for all reflections * */ virtual void PrintObsData()const; /** \brief Print H, K, L Iobs sigma Icalc for all reflections *Iobs and sigma (if given) are scaled to Icalc (if available). * */ virtual void PrintObsCalcData()const; virtual void SetUseOnlyLowAngleData(const bool useOnlyLowAngle,const REAL angle=0.); ///Save H,K,L Iobs Icalc to a file, text format, 3 columns theta Iobs Icalc. ///If Iobs is missing, the column is omitted. void SaveHKLIobsIcalc(const string &filename="hklIobsIcalc.out"); virtual void GlobalOptRandomMove(const REAL mutationAmplitude, const RefParType *type=gpRefParTypeObjCryst); virtual REAL GetLogLikelihood()const; //LSQ functions virtual unsigned int GetNbLSQFunction()const; virtual const CrystVector_REAL& GetLSQCalc(const unsigned int) const; virtual const CrystVector_REAL& GetLSQObs(const unsigned int) const; virtual const CrystVector_REAL& GetLSQWeight(const unsigned int) const; virtual std::map & GetLSQ_FullDeriv(const unsigned int,std::set &vPar); virtual void XMLOutput(ostream &os,int indent=0)const; virtual void XMLInput(istream &is,const XMLCrystTag &tag); //virtual void XMLInputOld(istream &is,const IOCrystTag &tag); virtual const Radiation& GetRadiation()const; Radiation& GetRadiation(); /// Set : neutron or x-ray experiment ? Wavelength ? virtual void SetRadiationType(const RadiationType radiation); /// Set the (monochromatic) wavelength of the beam. void SetWavelength(const REAL ); /** \ brief Set X-Ray tube radiation. * *\param XRayTubeElementName : name of the anticathode element name. Known *ones are Cr, Fe, Cu, Mo, Ag. *\param alpha2Alpha2ratio: Kalpha2/Kalpha1 ratio (0.5 by default) * *the average wavelength is calculated *using the alpha2/alpha1 weight. All structure factors computation are made *using the average wavelength, and for powder diffraction, profiles are output *at the alpha1 and alpha2 ratio for the calculated pattern. * *NOTE : if the name of the wavelength is generic (eg"Cu"), *then the program considers that *there are both Alpha1 and Alpha2, and thus automatically changes the WavelengthType *to WAVELENGTH_ALPHA12. If instead either alpha1 or alpha2 (eg "CuA1") is asked for, *the WavelengthType is set to WAVELENGTH_MONOCHROMATIC. In both cases, * the radiation type is set to X-Ray. */ void SetWavelength(const string &XRayTubeElementName,const REAL alpha2Alpha2ratio=0.5); /// Set the (monochromatic) energy of the beam. void SetEnergy(const REAL ); protected: private: virtual void InitRefParList(); /// Calc intensities void CalcIcalc() const; void CalcIcalc_FullDeriv(std::set &vPar); virtual CrystVector_long SortReflectionBySinThetaOverLambda(const REAL maxTheta=-1.); /// Init options (currently only twinning). void InitOptions(); /// Determine the index of reflections to be summed because of twinning (GroupOption==1) /// The reflections \e must have been sorted by increasing theta beforehand. void PrepareTwinningCalc() const; /// Are there observed intensities ? bool mHasObservedData; /** \brief Observed intensity (after ABS and LP corrections) * * In the single crystal case, this is a list of intensity corresponding to (h,k,l). * For a powder sample, this is a list of all peaks intensities. */ CrystVector_REAL mObsIntensity ; /// Sigma for observed intensities (either individual reflections or spectrum) CrystVector_REAL mObsSigma ; /// weight for computing R-Factor, for each observed value. CrystVector_REAL mWeight ; /// Calculated intensities mutable CrystVector_REAL mCalcIntensity ; /// mutable std::map mCalcIntensity_FullDeriv; /// Scale factor. It is applied when computing intensities. The scale ///applies to intensities mutable REAL mScaleFactor; /// Chi^2 mutable REAL mChi2; //Clocks /// Last time Icalc was computed mutable RefinableObjClock mClockIcalc; /// Last modification of the scale factor mutable RefinableObjClock mClockScaleFactor; ///Clock the last time Chi^2 was computed mutable RefinableObjClock mClockChi2; // Grouped reflections /// Option for the type of grouping (0:no, 1:by theta values (twinning), 2:user-supplied groups) RefObjOpt mGroupOption; /// The observed intensities summed on all reflections that are (or could be) /// overlapped dur to a twinning mutable CrystVector_REAL mGroupIobs; /// The uncertainty on observed grouped intensities. mutable CrystVector_REAL mGroupSigma; /// The calculated intensities summed on all reflections that are grouped mutable CrystVector_REAL mGroupIcalc; mutable std::map mGroupIcalc_FullDeriv; /// The weight on each reflection sum in case of grouped reflections. The sum is the /// inverse of the sum of all sigma^2 mutable CrystVector_REAL mGroupWeight; /** The index of reflections which need to be summed. They must have been sorted * by increasing theta values. Each entry (the reflection index) marks the beginning * of a new batch of reflections to be summed. * * Here only the groups of reflections are \e roughly sorted by sin(theta)/lambda. * It is assumed, howver, that grouped reflections are of approximately the same * d_hkl. After ScatteringData::GetNbReflBelowMaxSinThetaOvLambda(), * the number of groups for which *all* reflections are below the limit are * taken into account for the statistics. * * Note that \before DiffractionDataSingleCrystal::SortReflectionBySinThetaOverLambda() * is called (i.e. immediately after importing the reflections) **/ mutable CrystVector_long mGroupIndex; /// Number of groups mutable long mNbGroup; /// Number of groups below max[sin(theta)/lambda] mutable long mNbGroupUsed; /// Clock for twinning, when the preparation of twinning correction was last made. mutable RefinableObjClock mClockPrepareTwinningCorr; // The Radiation for this object Radiation mRadiation; #ifdef __WX__CRYST__ public: virtual WXCrystObjBasic* WXCreate(wxWindow*); friend class WXDiffractionSingleCrystal;//to access the Radiation object #endif }; /// Global registry for all PowderPattern objects extern ObjRegistry gDiffractionDataSingleCrystalRegistry; } //namespace ObjCryst #endif //_OBJCRYST_DIFFDATA_SINGLECRYSTAL_H_ objcryst-2022.1/ObjCryst/ObjCryst/Exception.cpp000066400000000000000000000045561430515525000214110ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * source file for LibCryst++ ObjCrystException class * */ #include "ObjCryst/ObjCryst/General.h" #include #include #include "ObjCryst/ObjCryst/IO.h" namespace ObjCryst { bool ObjCrystException::verbose = true; ObjCrystException::ObjCrystException() : message() { if (ObjCrystException::verbose) { cout << "LibCryst ++ exception thrown!!" << endl; } } ObjCrystException::ObjCrystException(const string & _message) { message = _message; if (!ObjCrystException::verbose) { return; } static bool inException; cout << "LibCryst ++ exception thrown!!" << endl; cout << " Message: " + message < #include #include // Restricted pointers (useful for auto-vectorization) #ifdef __GNUG__ #define RESTRICT __restrict__ #elif defined(_MSC_VER) || defined(__ICL) // MS and VC++ compiler #define RESTRICT __restrict #else #define RESTRICT #endif //profiling #ifdef __MWERKS__ #include #endif #ifdef PROFILING_ON #include "Profile/Profiler.h" #else #define TAU_PROFILE(name, type, group) #define TAU_PROFILE_START(var) #define TAU_PROFILE_TIMER(var, name, type, group) #define TAU_PROFILE_STOP(var) #define TAU_PROFILE_INIT(argc, argv) #define TAU_PROFILE_SET_NODE(node) #define TAU_PROFILE_SET_CONTEXT(context) #define TAU_EVENT(event, data) #define TAU_REPORT_STATISTICS() #define TAU_REPORT_THREAD_STATISTICS() #endif #include "ObjCryst/Quirks/VFNDebug.h" using namespace std; /** The namespace which includes all objects (crystallographic and * algorithmic) in ObjCryst++. * * \note It may be a good idea to separate in 3 namespaces for ObjCryst, WXObjCryst, * and RefinableObj */ namespace ObjCryst { #ifndef M_PI #define M_PI 3.14159265358979323846264338327950288 #endif #define DEG2RAD (M_PI/180.) #define RAD2DEG (180./M_PI) #ifndef REAL #define REAL float #endif // Implemented in IO.cpp /// Function to convert a substring to a floating point value, imposing a C locale (using '.' as decimal separator). /// This is used for input/output from data file, which are only using the C locale, contrary to the GUI. float string2floatC(const string &s); //###################################################################### /// Type of radiation used. Only neutrons and X-Rays are used so far, /// electrons would require a very different treatment. enum RadiationType { RAD_NEUTRON, RAD_XRAY, RAD_ELECTRON}; /// Sample type (not used yet) enum SampleType { SAMPLE_SINGLE_CRYSTAL, SAMPLE_POWDER}; /// Incident beam characteristics : monochromatic, X-Ray tube with Alpha1 and alpha2, /// MAD (a few wavelengths-UNUSED YET), DAFS (continuous wavelength range-UNUSED YET) /// LAUE (UNUSED YET), WAVELENGTH_TOF (neutron Time Of Flight) enum WavelengthType { WAVELENGTH_MONOCHROMATIC, WAVELENGTH_ALPHA12, WAVELENGTH_TOF, WAVELENGTH_MAD, WAVELENGTH_DAFS, WAVELENGTH_LAUE}; /// Profile type for powder (could it be used fopr single crystals on 2D detectors ?) enum ReflectionProfileType { PROFILE_GAUSSIAN, PROFILE_LORENTZIAN, PROFILE_PSEUDO_VOIGT, PROFILE_PSEUDO_VOIGT_FINGER_COX_JEPHCOAT, PROFILE_PEARSON_VII }; enum PowderBackgroundInterpType{ POWDER_BACKGROUND_LINEAR, POWDER_BACKGROUND_CUBIC_SPLINE}; #define XRAY_WAVELENGTH_TO_ENERGY 12398.4 //###################################################################### // Exception. /** \brief Exception class for ObjCryst++ library * */ //###################################################################### //:TODO: This should go into VFNDebug.h class ObjCrystException { public: ObjCrystException(); ObjCrystException(const string & message); ~ObjCrystException(); static bool verbose; string message; protected: private: }; //###################################################################### /** Print some information for the user during long processes. */ void ObjCrystInformUserStdOut(const string &); //###################################################################### /** \brief Pointer to a function for passing info to the user during or * after long/important processes (use scarcely!) * * This function pointer is by default assigned to ObjCrystInformUserStdOut, * which outputs the message to the standard output. If a user interface is * used (eg in Fox), this pointer should be reassigned at the beginning of the * application to a more user-suitable function. */ extern void (*fpObjCrystInformUser)(const string &); /** Class to compare pairs of objects, with the two objects playing a * symmetric role. */ template class SymmetricPairCompare { public: bool operator()(const pair &p1, const pair &p2) const { const T* p1f= &(p1.first); const T* p1s= &(p1.second); const T* p2f= &(p2.first); const T* p2s= &(p2.second); if(*p1f < *p1s) { p1s= &(p1.first); p1f= &(p1.second);} if(*p2f < *p2s) { p2s= &(p2.first); p2f= &(p2.second);} if(*p1f != *p2f) return *p1f < *p2f; else return *p1s < *p2s; } }; #ifdef OBJCRYST_GL /// Print a string in 2D at the current OpenGL position /// This is actually implemented in wxCryst/wxCrystal.cpp void crystGLPrint(const string &); #endif /// Class to store POV-Ray output options struct CrystalPOVRayOptions { /// Display limits in reduced coordinates REAL mXmin, mXmax, mYmin, mYmax, mZmin, mZmax; /// Show labels ? bool mShowLabel; /// Show hydrogens ? bool mShowHydrogens; }; /// This class only serves to temporarilly set the LC_NUMERIC C locale to "C", /// in order to use '.' as the decimal separator. /// Just creating one object of type tmp_C_Numeric_locale will switch to the C locale, /// and when the object gets destroyed it will restore the old locale. class tmp_C_Numeric_locale {// Implemented in SpaceGroup.cpp public: tmp_C_Numeric_locale(); ~tmp_C_Numeric_locale(); private: std::string mLocale; }; }//Namespace #endif //_VFN_OBJCRYST_H_ objcryst-2022.1/ObjCryst/ObjCryst/GeomStructFactor.h000066400000000000000000000252251430515525000223470ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // This file declares all the functions used to compute the geometrical //structure factors //Use pointers for the calculation of geometrical structure factors ? //Else use the blitz library... //This is *not* useful for performance reasons, but rather //for memory /disk space reasons when using the GNU gcc compiler. //(complex array expressions using blitz take a *huge* space //on disk and in memory when compiling). Performance is still the best... #ifndef _VFN_RC_CRISTALLO_GEOM_STRUCT_FACTOR_H_ #define _VFN_RC_CRISTALLO_GEOM_STRUCT_FACTOR_H_ #include "ObjCryst/CrystVector/CrystVector.h" #include namespace ObjCryst { // This is the default fonction, which does *not* use //the geometrical structure factor, but calculates all the symmetric //positions of the atom. This is done for SpaceGroups which //do not yet have a coded Geom Structure factor, or for those //where it does not make much difference /// \deprecated void RealGeomStructFactor (const REAL x, const REAL y, const REAL z, const CrystVector_REAL&h, const CrystVector_REAL&k, const CrystVector_REAL&l, CrystVector_REAL& rsf); // Same for the imaginary part /// \deprecated void ImagGeomStructFactor (const REAL x, const REAL y, const REAL z, const CrystVector_REAL&h, const CrystVector_REAL&k, const CrystVector_REAL&l, CrystVector_REAL& rsf); /// \deprecated void RealGeomStructFactor_1 (const REAL x, const REAL y, const REAL z, const CrystVector_REAL&h, const CrystVector_REAL&k, const CrystVector_REAL&l, CrystVector_REAL& rsf); /// \deprecated void RealGeomStructFactor_2 (const REAL x, const REAL y, const REAL z, const CrystVector_REAL&h, const CrystVector_REAL&k, const CrystVector_REAL&l, CrystVector_REAL& rsf); /// \deprecated void RealGeomStructFactor_67 (const REAL x, const REAL y, const REAL z, const CrystVector_REAL&h, const CrystVector_REAL&k, const CrystVector_REAL&l, CrystVector_REAL& rsf); /// \deprecated void RealGeomStructFactor_67ba_c(const REAL x, const REAL y, const REAL z, const CrystVector_REAL&h, const CrystVector_REAL&k, const CrystVector_REAL&l, CrystVector_REAL& rsf); /// \deprecated void RealGeomStructFactor_67cab(const REAL x, const REAL y, const REAL z, const CrystVector_REAL&h, const CrystVector_REAL&k, const CrystVector_REAL&l, CrystVector_REAL& rsf); /// \deprecated void RealGeomStructFactor_67_cba(const REAL x, const REAL y, const REAL z, const CrystVector_REAL&h, const CrystVector_REAL&k, const CrystVector_REAL&l, CrystVector_REAL& rsf); /// \deprecated void RealGeomStructFactor_67bca(const REAL x, const REAL y, const REAL z, const CrystVector_REAL&h, const CrystVector_REAL&k, const CrystVector_REAL&l, CrystVector_REAL& rsf); /// \deprecated void RealGeomStructFactor_67a_cb(const REAL x, const REAL y, const REAL z, const CrystVector_REAL&h, const CrystVector_REAL&k, const CrystVector_REAL&l, CrystVector_REAL& rsf); /// \deprecated void RealGeomStructFactor_97 (const REAL x, const REAL y, const REAL z, const CrystVector_REAL&h, const CrystVector_REAL&k, const CrystVector_REAL&l, CrystVector_REAL& rsf); /// \deprecated void RealGeomStructFactor_230 (const REAL x, const REAL y, const REAL z, const CrystVector_REAL&h, const CrystVector_REAL&k, const CrystVector_REAL&l, CrystVector_REAL& rsf); /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// /// \deprecated void ImagGeomStructFactor_centro(const REAL x, const REAL y, const REAL z, const CrystVector_REAL&h, const CrystVector_REAL&k, const CrystVector_REAL&l, CrystVector_REAL& isf); //do nothing /// \deprecated void ImagGeomStructFactor_1 (const REAL x, const REAL y, const REAL z, const CrystVector_REAL&h, const CrystVector_REAL&k, const CrystVector_REAL&l, CrystVector_REAL& isf); /// \deprecated void ImagGeomStructFactor_2 (const REAL x, const REAL y, const REAL z, const CrystVector_REAL&h, const CrystVector_REAL&k, const CrystVector_REAL&l, CrystVector_REAL& isf); /// \deprecated void ImagGeomStructFactor_67 (const REAL x, const REAL y, const REAL z, const CrystVector_REAL&h, const CrystVector_REAL&k, const CrystVector_REAL&l, CrystVector_REAL& isf); /// \deprecated void ImagGeomStructFactor_67ba_c(const REAL x, const REAL y, const REAL z, const CrystVector_REAL&h, const CrystVector_REAL&k, const CrystVector_REAL&l, CrystVector_REAL& rsf); /// \deprecated void ImagGeomStructFactor_67cab(const REAL x, const REAL y, const REAL z, const CrystVector_REAL&h, const CrystVector_REAL&k, const CrystVector_REAL&l, CrystVector_REAL& rsf); /// \deprecated void ImagGeomStructFactor_67_cba(const REAL x, const REAL y, const REAL z, const CrystVector_REAL&h, const CrystVector_REAL&k, const CrystVector_REAL&l, CrystVector_REAL& rsf); /// \deprecated void ImagGeomStructFactor_67bca(const REAL x, const REAL y, const REAL z, const CrystVector_REAL&h, const CrystVector_REAL&k, const CrystVector_REAL&l, CrystVector_REAL& rsf); /// \deprecated void ImagGeomStructFactor_67a_cb(const REAL x, const REAL y, const REAL z, const CrystVector_REAL&h, const CrystVector_REAL&k, const CrystVector_REAL&l, CrystVector_REAL& rsf); /// \deprecated void ImagGeomStructFactor_97 (const REAL x, const REAL y, const REAL z, const CrystVector_REAL&h, const CrystVector_REAL&k, const CrystVector_REAL&l, CrystVector_REAL& isf); /// \deprecated void ImagGeomStructFactor_230 (const REAL x, const REAL y, const REAL z, const CrystVector_REAL&h, const CrystVector_REAL&k, const CrystVector_REAL&l, CrystVector_REAL& isf); }//namespace #endif objcryst-2022.1/ObjCryst/ObjCryst/IO.cpp000066400000000000000000002337711430515525000177650ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2006 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * source file for XMLInput/XMLOutput in ObjCryst++ * */ #include //for sprintf #include "ObjCryst/ObjCryst/General.h" #include "ObjCryst/ObjCryst/IO.h" #include "ObjCryst/RefinableObj/IO.h" #include "ObjCryst/RefinableObj/GlobalOptimObj.h" //#include "ObjCryst/ObjCryst/SpaceGroup.h" #include "ObjCryst/ObjCryst/Scatterer.h" #include "ObjCryst/ObjCryst/Crystal.h" #include "ObjCryst/ObjCryst/ZScatterer.h" //#include "ObjCryst/ObjCryst/ScatteringData.h" #include "ObjCryst/ObjCryst/ScatteringPower.h" #include "ObjCryst/ObjCryst/ScatteringPowerSphere.h" #include "ObjCryst/ObjCryst/Atom.h" #include "ObjCryst/ObjCryst/DiffractionDataSingleCrystal.h" #include "ObjCryst/ObjCryst/PowderPattern.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" #include "ObjCryst/ObjCryst/Molecule.h" #include #include #include #include #include //#define USE_BACKGROUND_MAXLIKE_ERROR namespace ObjCryst { //////////////////////////////////////////////////////////////////////// // // Global functions // //////////////////////////////////////////////////////////////////////// float string2floatC(const string &s) { float v=0; stringstream ss(s); ss.imbue(std::locale::classic()); ss>>v; return v; } float InputFloat(istream &is, const char endchar) { float f; // Get rid of spaces, returns etc... while(0==isgraph(is.peek())) is.get(); stringstream tmp; char c; while((endchar!=is.peek())&&(' '!=is.peek())) { is.get(c) ; // Explicit typecasting to char otherwise it is understood as an integer number from type charT... tmp<<(char)(tolower(c)) ; } if(tmp.str().find("nan")!=string::npos) { VFN_DEBUG_MESSAGE("InputFloat(..):"< NAN ! -> 1",9); return 1; } if(tmp.str().find("inf")!=string::npos) { VFN_DEBUG_MESSAGE("InputFloat(..):"< INF ! -> 1",9); return 1; } tmp.imbue(std::locale::classic()); tmp>>f; VFN_DEBUG_MESSAGE("InputFloat(..):"< XMLCrystFileLoadObjectList(const string & filename) { VFN_DEBUG_ENTRY("XMLCrystFileLoadObjectList(filename)",5) ifstream is(filename.c_str()); if(!is){};//:TODO: is.imbue(std::locale::classic()); ObjRegistry reg; for(;;) { XMLCrystTag *pTag =new XMLCrystTag (is); if(true==is.eof()) { VFN_DEBUG_EXIT("XMLCrystFileLoadObjectList(filename):End",5) for(int i=0;iPrint(); if(("Crystal"==pTag->GetName()|| "DiffractionDataSingleCrystal"==pTag->GetName()|| "PowderPattern"==pTag->GetName()|| "GlobalOptimObj"==pTag->GetName()) && !(pTag->IsEndTag())) reg.Register(*pTag); else delete pTag; } return reg; } template void XMLCrystFileLoadObject(const string & filename, const string &tagName, const string &name, T*obj) { VFN_DEBUG_ENTRY("XMLCrystFileLoadObject(filename,IOCrystTag,T&)",5) ifstream is(filename.c_str()); if(!is){};//:TODO: is.imbue(std::locale::classic()); XMLCrystTag tag; while(true) { is>>tag; if(true==is.eof()) { cout<<"XMLCrystFileLoadObject(filename,IOCrystTag,T&):Not Found !"<XMLInput(is,tag); is.close(); VFN_DEBUG_EXIT("XMLCrystFileLoadObject(filename,IOCrystTag,T&)",5) } template void XMLCrystFileLoadObject(const string & ,const string &,const string &, Crystal*); template void XMLCrystFileLoadObject(const string & ,const string &,const string &, PowderPattern*); template void XMLCrystFileLoadObject(const string & ,const string &,const string &, DiffractionDataSingleCrystal*); //template void IOCrystFileLoadObject(const string &,const IOCrystTag &, // ZScatterer*); template void XMLCrystFileLoadObject(const string & ,const string &,const string &, PowderPatternBackground*); template void XMLCrystFileLoadObject(const string & ,const string &,const string &, PowderPatternDiffraction*); template void XMLCrystFileLoadObject(const string & ,const string &,const string &, MonteCarloObj*); void XMLCrystFileLoadAllObject(const string & filename) { VFN_DEBUG_ENTRY("XMLCrystFileLoadAllObject(filename,)",5) ifstream is(filename.c_str()); if(is.fail()) throw ObjCrystException("XMLCrystFileLoadAllObject() failed input"); XMLCrystFileLoadAllObject(is); (*fpObjCrystInformUser)("Finished loading XML file:"+filename); VFN_DEBUG_EXIT("XMLCrystFileLoadAllObject(filename,)",5) } void XMLCrystFileLoadAllObject(istream &is) { VFN_DEBUG_ENTRY("XMLCrystFileLoadAllObject(istream)",5) is.imbue(std::locale::classic()); XMLCrystTag tag; do {is>>tag;} while(("ObjCryst"!=tag.GetName()) && (false==is.eof())); while(true) { XMLCrystTag tag(is); if(true==is.eof()) break; if(tag.GetName()=="Crystal") { Crystal* obj = new Crystal; obj->XMLInput(is,tag); (*fpObjCrystInformUser)("XML: finished reading Crystal object:"+obj->GetName()); } if(tag.GetName()=="PowderPattern") { PowderPattern* obj = new PowderPattern; obj->XMLInput(is,tag); (*fpObjCrystInformUser)("XML: finished reading Powder Pattern object:"+obj->GetName()); } if(tag.GetName()=="DiffractionDataSingleCrystal") { DiffractionDataSingleCrystal* obj = new DiffractionDataSingleCrystal; obj->XMLInput(is,tag); (*fpObjCrystInformUser)("XML: finished reading Single Crystal Diffraction object:"+obj->GetName()); } if(tag.GetName()=="GlobalOptimObj") { MonteCarloObj* obj = new MonteCarloObj; obj->XMLInput(is,tag); (*fpObjCrystInformUser)("XML: finished reading Global Optimization object:"+obj->GetName()); } } (*fpObjCrystInformUser)("Finished loading XML"); VFN_DEBUG_EXIT("XMLCrystFileLoadAllObject(istream)",5) } //////////////////////////////////////////////////////////////////////// // // I/O ScatteringPowerAtom // //////////////////////////////////////////////////////////////////////// void ScatteringPowerAtom::XMLOutput(ostream &os,int indent)const { VFN_DEBUG_ENTRY("ScatteringPowerAtom::XMLOutput():"<GetName(),5) for(int i=0;iGetPar(&mBiso).XMLOutput(os,"Biso",indent+1); os<mIsIsotropic) { REAL* bdata = (REAL*) mB.data(); this->GetPar(&bdata[0]).XMLOutput(os,"B11",indent+1); os<GetPar(&bdata[1]).XMLOutput(os,"B22",indent+1); os<GetPar(&bdata[2]).XMLOutput(os,"B33",indent+1); os<GetPar(&bdata[3]).XMLOutput(os,"B12",indent+1); os<GetPar(&bdata[4]).XMLOutput(os,"B13",indent+1); os<GetPar(&bdata[5]).XMLOutput(os,"B23",indent+1); os<GetPar("ML Error").XMLOutput(os,"ML Error",indent+1); os <GetPar("ML-Nb Ghost Atoms").XMLOutput(os,"ML-NbGhost",indent+1); os <GetPar("Formal Charge").XMLOutput(os,"Formal Charge",indent+1); os <GetName(),5) } void ScatteringPowerAtom::XMLInput(istream &is,const XMLCrystTag &tagg) { VFN_DEBUG_ENTRY("ScatteringPowerAtom::XMLInput():"<GetName(),5) for(unsigned int i=0;iSetName(tagg.GetAttributeValue(i)); if("Symbol"==tagg.GetAttributeName(i)) mSymbol=tagg.GetAttributeValue(i); } (*fpObjCrystInformUser)("Input ScatteringPowerAtom:"+mName+"("+mSymbol+")"); this->Init(mName,mSymbol,mBiso); while(true) { XMLCrystTag tag(is); if(("ScatteringPowerAtom"==tag.GetName())&&tag.IsEndTag()) { VFN_DEBUG_EXIT("ScatteringPowerAtom::Exit():"<GetName(),5) return; } if("RGBColour"==tag.GetName()) { float r,g,b; is>>r>>g>>b; this->SetColour(r,g,b); XMLCrystTag junk(is); } if("Par"==tag.GetName()) { for(unsigned int i=0;iGetPar(&mBiso).XMLInput(is,tag); this->mIsIsotropic = true; break; } if("B11"==tag.GetAttributeValue(i)) { this->GetPar(&mB.data()[0]).XMLInput(is,tag); this->mIsIsotropic = false; break; } if("B22"==tag.GetAttributeValue(i)) { this->GetPar(&mB.data()[1]).XMLInput(is,tag); this->mIsIsotropic = false; break; } if("B33"==tag.GetAttributeValue(i)) { this->GetPar(&mB.data()[2]).XMLInput(is,tag); this->mIsIsotropic = false; break; } if("B12"==tag.GetAttributeValue(i)) { this->GetPar(&mB.data()[3]).XMLInput(is,tag); this->mIsIsotropic = false; break; } if("B13"==tag.GetAttributeValue(i)) { this->GetPar(&mB.data()[4]).XMLInput(is,tag); this->mIsIsotropic = false; break; } if("B23"==tag.GetAttributeValue(i)) { this->GetPar(&mB.data()[5]).XMLInput(is,tag); this->mIsIsotropic = false; break; } if("ML Error"==tag.GetAttributeValue(i)) { this->GetPar("ML Error").XMLInput(is,tag); break; } if("ML-NbGhost"==tag.GetAttributeValue(i)) { this->GetPar("ML-Nb Ghost Atoms").XMLInput(is,tag); break; } if("Formal Charge"==tag.GetAttributeValue(i)) { this->GetPar("Formal Charge").XMLInput(is,tag); break; } } } continue; } } } //////////////////////////////////////////////////////////////////////// // // I/O Atom // //////////////////////////////////////////////////////////////////////// void Atom::XMLOutput(ostream &os,int indent)const { VFN_DEBUG_ENTRY("Atom::XMLOutput():"<GetName(),5) for(int i=0;iGetName()); os <GetPar(mXYZ.data()+0).XMLOutput(os,"x",indent); os <GetPar(mXYZ.data()+1).XMLOutput(os,"y",indent); os <GetPar(mXYZ.data()+2).XMLOutput(os,"z",indent); os <GetPar(&mOccupancy).XMLOutput(os,"Occup",indent); os <GetName(),5) } void Atom::XMLInput(istream &is,const XMLCrystTag &tagg) { VFN_DEBUG_ENTRY("Atom::XMLInput():"<GetName(),5) string scattPowName; for(unsigned int i=0;iSetName(tagg.GetAttributeValue(i)); if("ScattPow"==tagg.GetAttributeName(i)) scattPowName=tagg.GetAttributeValue(i); } (*fpObjCrystInformUser)("XML: Loading Atom:"+this->GetName()); const ScatteringPower* scattPow= &(this->GetCrystal().GetScatteringPowerRegistry().GetObj(scattPowName)); VFN_DEBUG_MESSAGE("Found Scattering Power:"<< scattPowName<<" at "<Init(0,0,0,mName,scattPow,1); while(true) { XMLCrystTag tag(is); if(("Atom"==tag.GetName())&&tag.IsEndTag()) { VFN_DEBUG_EXIT("Atom::Exit():"<GetName(),5) return; } if("Par"==tag.GetName()) { for(unsigned int i=0;iGetPar(mXYZ.data()+0).XMLInput(is,tag); break; } if("y"==tag.GetAttributeValue(i)) { this->GetPar(mXYZ.data()+1).XMLInput(is,tag); break; } if("z"==tag.GetAttributeValue(i)) { this->GetPar(mXYZ.data()+2).XMLInput(is,tag); break; } if("Occup"==tag.GetAttributeValue(i)) { this->GetPar(&mOccupancy).XMLInput(is,tag); break; } } } continue; } } } //////////////////////////////////////////////////////////////////////// // // I/O ZAtom // //////////////////////////////////////////////////////////////////////// void ZAtom::XMLOutput(ostream &os,int indent)const { VFN_DEBUG_ENTRY("ZAtom::XMLOutput():"<GetName(),5) for(int i=0;iGetScatteringPower())//else it is a dummy atom tag.AddAttribute("ScattPow",this->GetScatteringPower()->GetName()); tag.AddAttribute("BondAtom",this->GetZScatterer() .GetZAtomRegistry() .GetObj(this->GetZBondAtom()) .GetName()); tag.AddAttribute("AngleAtom",this->GetZScatterer() .GetZAtomRegistry() .GetObj(this->GetZAngleAtom()) .GetName()); tag.AddAttribute("DihedAtom",this->GetZScatterer() .GetZAtomRegistry() .GetObj(this->GetZDihedralAngleAtom()) .GetName()); os <GetZScatterer().GetPar(&mBondLength).XMLOutput(os,"BondLength",indent); os <GetZScatterer().GetPar(&mAngle).XMLOutput(os,"Angle",indent); os <GetZScatterer().GetPar(&mDihed).XMLOutput(os,"DihedAng",indent); os <GetZScatterer().GetPar(&mOccupancy).XMLOutput(os,"Occup",indent); os <GetName(),5) } void ZAtom::XMLInput(istream &is,const XMLCrystTag &tagg) { VFN_DEBUG_ENTRY("ZAtom::XMLInput():"<GetName(),5) for(unsigned int i=0;iSetName(tagg.GetAttributeValue(i)); continue; } if("ScattPow"==tagg.GetAttributeName(i)) { const ScatteringPower* scattPow=&(this->GetZScatterer() .GetCrystal() .GetScatteringPowerRegistry() .GetObj(tagg.GetAttributeValue(i))); this->SetScatteringPower(scattPow); continue; } if("BondAtom"==tagg.GetAttributeName(i)) { mAtomBond=this->GetZScatterer().GetZAtomRegistry().Find(tagg.GetAttributeValue(i)); continue; } if("AngleAtom"==tagg.GetAttributeName(i)) { mAtomAngle=this->GetZScatterer().GetZAtomRegistry().Find(tagg.GetAttributeValue(i)); continue; } if("DihedAtom"==tagg.GetAttributeName(i)) { mAtomDihed=this->GetZScatterer().GetZAtomRegistry().Find(tagg.GetAttributeValue(i)); continue; } } while(true) { XMLCrystTag tag(is); if(("ZAtom"==tag.GetName())&&tag.IsEndTag()) { VFN_DEBUG_EXIT("ZAtom::Exit():"<GetName(),5) return; } if("Par"==tag.GetName()) { for(unsigned int i=0;iGetZScatterer().GetPar(&mBondLength).XMLInput(is,tag); break; } if("Angle"==tag.GetAttributeValue(i)) { this->GetZScatterer().GetPar(&mAngle).XMLInput(is,tag); break; } if("DihedAng"==tag.GetAttributeValue(i)) { this->GetZScatterer().GetPar(&mDihed).XMLInput(is,tag); break; } if("Occup"==tag.GetAttributeValue(i)) { this->GetZScatterer().GetPar(&mOccupancy).XMLInput(is,tag); break; } } } continue; } } } //////////////////////////////////////////////////////////////////////// // // I/O ZScatterer // //////////////////////////////////////////////////////////////////////// void ZScatterer::XMLOutput(ostream &os,int indent)const { VFN_DEBUG_ENTRY("ZScatterer::XMLOutput():"<GetName(),5) for(int i=0;iGetPar(mXYZ.data()+0).XMLOutput(os,"x",indent); os <GetPar(mXYZ.data()+1).XMLOutput(os,"y",indent); os <GetPar(mXYZ.data()+2).XMLOutput(os,"z",indent); os <GetPar(&mOccupancy).XMLOutput(os,"Occup",indent); os <GetPar(&mPhi).XMLOutput(os,"Phi",indent); os <GetPar(&mChi).XMLOutput(os,"Chi",indent); os <GetPar(&mPsi).XMLOutput(os,"Psi",indent); os <0) { for(int i=0;i<=indent;i++) os << " " ; XMLCrystTag tag2("PivotAtom",false,true); tag2.AddAttribute("Name",this->GetZAtomRegistry().GetObj(mCenterAtomIndex).GetName()); os <GetName(),5) } void ZScatterer::XMLInput(istream &is,const XMLCrystTag &tagg) { VFN_DEBUG_ENTRY("ZScatterer::XMLInput():"<GetName(),5) for(unsigned int i=0;iSetName(tagg.GetAttributeValue(i)); } (*fpObjCrystInformUser)("XML: Loading ZScatterer:"+this->GetName()); while(true) { XMLCrystTag tag(is); if(("ZScatterer"==tag.GetName())&&tag.IsEndTag()) { VFN_DEBUG_EXIT("ZScatterer::Exit():"<GetName(),5) return; } if("Par"==tag.GetName()) { for(unsigned int i=0;iGetPar(mXYZ.data()+0).XMLInput(is,tag); break; } if("y"==tag.GetAttributeValue(i)) { this->GetPar(mXYZ.data()+1).XMLInput(is,tag); break; } if("z"==tag.GetAttributeValue(i)) { this->GetPar(mXYZ.data()+2).XMLInput(is,tag); break; } if("Occup"==tag.GetAttributeValue(i)) { this->GetPar(&mOccupancy).XMLInput(is,tag); break; } if("Phi"==tag.GetAttributeValue(i)) { this->GetPar(&mPhi).XMLInput(is,tag); break; } if("Chi"==tag.GetAttributeValue(i)) { this->GetPar(&mChi).XMLInput(is,tag); break; } if("Psi"==tag.GetAttributeValue(i)) { this->GetPar(&mPsi).XMLInput(is,tag); break; } } } continue; } if("ZAtom"==tag.GetName()) { //we must take care of possible dummy atoms const ScatteringPower* scattPow=0; for(unsigned int i=0;iGetCrystal().GetScatteringPowerRegistry() .GetObj(tag.GetAttributeValue(i))); const long nb=mZAtomRegistry.GetNb(); this->AddAtom("",scattPow,0,0,0,0,0,1); mZAtomRegistry.GetObj(nb).XMLInput(is,tag); // Update the name of refinable parameters { char buf [20]; sprintf(buf,"%d-%d",(int)nb,(int)(mZAtomRegistry.GetObj(nb).GetZBondAtom())); this->GetPar(&(mZAtomRegistry.GetObj(nb).mBondLength)) .SetName("Length"+(string)buf); sprintf(buf,"%d-%d-%d",(int)nb,(int)(mZAtomRegistry.GetObj(nb).GetZBondAtom()), (int)(mZAtomRegistry.GetObj(nb).GetZAngleAtom())); this->GetPar(&(mZAtomRegistry.GetObj(nb).mAngle)) .SetName("Angle"+(string)buf); sprintf(buf,"%d-%d-%d-%d",(int)nb,(int)(mZAtomRegistry.GetObj(nb).GetZBondAtom()), (int)(mZAtomRegistry.GetObj(nb).GetZAngleAtom()), (int)(mZAtomRegistry.GetObj(nb).GetZDihedralAngleAtom())); this->GetPar(&(mZAtomRegistry.GetObj(nb).mDihed)) .SetName("Dihed"+(string)buf); } } if("PivotAtom"==tag.GetName()) { for(unsigned int i=0;iGetZAtomRegistry().Find(tag.GetAttributeValue(i)); } } } } //////////////////////////////////////////////////////////////////////// // // I/O Crystal // //////////////////////////////////////////////////////////////////////// void Crystal::XMLOutput(ostream &os,int indent)const { VFN_DEBUG_ENTRY("Crystal::XMLOutput():"<GetName(),5) for(int i=0;iGetSpaceGroup().GetName()); os <GetPar("a").XMLOutput(os,"a",indent); os <GetPar("b").XMLOutput(os,"b",indent); os <GetPar("c").XMLOutput(os,"c",indent); os <GetPar("alpha").XMLOutput(os,"alpha",indent); os <GetPar("beta").XMLOutput(os,"beta",indent); os <GetPar("gamma").XMLOutput(os,"gamma",indent); os <GetNbOption();i++) { this->GetOption(i).XMLOutput(os,indent); os <0) { VBumpMergePar::const_iterator pos; for(pos=mvBumpMergePar.begin();pos!=mvBumpMergePar.end();pos++) { for(int k=0;k<=indent;k++) os << " " ; XMLCrystTag tagBump("AntiBumpDistance"); tagBump.AddAttribute("ScattPow1",pos->first.first->GetName()); tagBump.AddAttribute("ScattPow2",pos->first.second->GetName()); { stringstream ss; ss << pos->second.mCanOverlap; tagBump.AddAttribute("AllowMerge",ss.str()); } os<second.mDist2)<0) { map, REAL>::const_iterator pos; for(pos=mvBondValenceRo.begin();pos!=mvBondValenceRo.end();pos++) { for(int k=0;k<=indent;k++) os << " " ; XMLCrystTag tagBVRo("BondValenceRo"); tagBVRo.AddAttribute("ScattPow1",pos->first.first->GetName()); tagBVRo.AddAttribute("ScattPow2",pos->first.second->GetName()); os<second<GetName(),5) } void Crystal::XMLInput(istream &is,const XMLCrystTag &tagg) { VFN_DEBUG_ENTRY("Crystal::XMLInput():"<GetName(),5) (*fpObjCrystInformUser)("XML: Loading Crystal:"); //Remove Scatterers and Scattering Powers for(long i=0;iRemoveSubRefObj(mScatteringPowerRegistry.GetObj(i)); mScatteringPowerRegistry.GetObj(i).DeRegisterClient(*this); } std::list vold_scattpow; if(mDeleteSubObjInDestructor) { mScatteringPowerRegistry.DeleteAll(); } else { // Keep track of the old atomic scattering powers to see if they can be re-used for(std::vector::const_iterator pos=mScatteringPowerRegistry.begin() ; pos!=mScatteringPowerRegistry.end(); ++pos) { if((*pos)->GetClassName().compare("ScatteringPowerAtom")!=0) continue; vold_scattpow.push_back(dynamic_cast(*pos)); } mScatteringPowerRegistry.DeRegisterAll(); } for(long i=0;iRemoveSubRefObj(mScattererRegistry.GetObj(i)); mScattererRegistry.GetObj(i).DeRegisterClient(*this); } if(mDeleteSubObjInDestructor) { mScattererRegistry.DeleteAll(); } else { mScattererRegistry.DeRegisterAll(); } for(unsigned int i=0;iSetName(tagg.GetAttributeValue(i)); if("SpaceGroup"==tagg.GetAttributeName(i)) this->Init(1,2,3,M_PI/2,M_PI/2,M_PI/2,tagg.GetAttributeValue(i),this->GetName()); } (*fpObjCrystInformUser)("XML: Loading Crystal:"+this->GetName()+"(spg:"+this->GetSpaceGroup().GetName()+")"); while(true) { XMLCrystTag tag(is); if(("Crystal"==tag.GetName())&&tag.IsEndTag()) { this->UpdateDisplay(); VFN_DEBUG_EXIT("Crystal::Exit():"<GetName(),5) return; } if("Par"==tag.GetName()) { for(unsigned int i=0;iGetPar(tag.GetAttributeValue(i)).XMLInput(is,tag); } } continue; } if("Option"==tag.GetName()) { for(unsigned int i=0;iInitRefParList();// Fix the "used" tag of refinable par after options continue; } if("AntiBumpDistance"==tag.GetName()) { float dist; bool useMerge=false; bool allowMerge; string scattPow1; string scattPow2; for(unsigned int i=0;i>allowMerge; useMerge=true; continue; } if("ScattPow1"==tag.GetAttributeName(i)) scattPow1=tag.GetAttributeValue(i); if("ScattPow2"==tag.GetAttributeName(i)) scattPow2=tag.GetAttributeValue(i); } is>>dist; XMLCrystTag junk(is);//end tag if(useMerge) this->SetBumpMergeDistance(mScatteringPowerRegistry.GetObj(scattPow1), mScatteringPowerRegistry.GetObj(scattPow2), dist,allowMerge); else this->SetBumpMergeDistance(mScatteringPowerRegistry.GetObj(scattPow1), mScatteringPowerRegistry.GetObj(scattPow2), dist); continue; } if("BondValenceRo"==tag.GetName()) { float ro; string scattPow1; string scattPow2; for(unsigned int i=0;i>ro; XMLCrystTag junk(is);//end tag this->AddBondValenceRo(mScatteringPowerRegistry.GetObj(scattPow1), mScatteringPowerRegistry.GetObj(scattPow2),ro); continue; } if("AntiBumpScale"==tag.GetName()) { is>>mBumpMergeScale; XMLCrystTag junk(is); } if("BondValenceCostScale"==tag.GetName()) { is>>mBondValenceCostScale; XMLCrystTag junk(is); } if("Atom"==tag.GetName()) { VFN_DEBUG_ENTRY("Crystal::XMLInput():reading an Atom",5) Atom *at=new Atom; at->SetCrystal(*this); at->XMLInput(is,tag); this->AddScatterer(at); VFN_DEBUG_EXIT("Crystal::XMLInput():reading an Atom",5) continue; } if("ScatteringPowerAtom"==tag.GetName()) { VFN_DEBUG_ENTRY("Crystal::XMLInput():reading a ScatteringPowerAtom",5) VFN_DEBUG_MESSAGE("Crystal::XMLInput():reading a ScatteringPowerAtom",5) ScatteringPowerAtom *sc=new ScatteringPowerAtom; sc->XMLInput(is,tag); if(!mDeleteSubObjInDestructor) { // Can we re-use a previous scattering power since we did not delete them ? for(std::list::iterator pos= vold_scattpow.begin(); pos!=vold_scattpow.end();++pos) { if((*pos)->GetSymbol() != sc->GetSymbol()) continue; if((*pos)->GetName() != sc->GetName()) continue; if((*pos)->GetFormalCharge() != sc->GetFormalCharge()) continue; if((*pos)->GetMaximumLikelihoodNbGhostAtom() != sc->GetMaximumLikelihoodNbGhostAtom()) continue; if((*pos)->GetMaximumLikelihoodPositionError() != sc->GetMaximumLikelihoodPositionError()) continue; if((*pos)->IsIsotropic() != sc->IsIsotropic()) continue; if(fabs((*pos)->GetBiso() - sc->GetBiso()) > 1e-4f) continue; if(!(*pos)->IsIsotropic()) { if(fabs((*pos)->GetBij(0) - sc->GetBij(0)) > 1e-4f) continue; if(fabs((*pos)->GetBij(1) - sc->GetBij(1)) > 1e-4f) continue; if(fabs((*pos)->GetBij(2) - sc->GetBij(2)) > 1e-4f) continue; if(fabs((*pos)->GetBij(3) - sc->GetBij(3)) > 1e-4f) continue; if(fabs((*pos)->GetBij(4) - sc->GetBij(4)) > 1e-4f) continue; if(fabs((*pos)->GetBij(5) - sc->GetBij(5)) > 1e-4f) continue; } VFN_DEBUG_MESSAGE("Crystal::XMLInput(): reusing scattering power: "<GetName(),5); delete sc; sc = *pos; } } this->AddScatteringPower(sc); VFN_DEBUG_EXIT("Crystal::XMLInput():reading a ScatteringPowerAtom",5) continue; } if("ScatteringPowerSphere"==tag.GetName()) { VFN_DEBUG_ENTRY("Crystal::XMLInput():reading a ScatteringPowerSphere",5) VFN_DEBUG_MESSAGE("Crystal::XMLInput():reading a ScatteringPowerSphere",5) ScatteringPowerSphere *sc=new ScatteringPowerSphere; sc->XMLInput(is,tag); this->AddScatteringPower(sc); VFN_DEBUG_EXIT("Crystal::XMLInput():reading a ScatteringPowerSphere",5) continue; } if("ZScatterer"==tag.GetName()) { VFN_DEBUG_ENTRY("Crystal::XMLInput():reading a ZScatterer",5) VFN_DEBUG_MESSAGE("Crystal::XMLInput():reading a ZScatterer",5) ZScatterer *z=new ZScatterer("",*this); z->XMLInput(is,tag); this->AddScatterer(z); VFN_DEBUG_EXIT("Crystal::XMLInput():reading a ZScatterer",5) continue; } if("Molecule"==tag.GetName()) { VFN_DEBUG_ENTRY("Crystal::XMLInput():reading a Molecule",5) VFN_DEBUG_MESSAGE("Crystal::XMLInput():reading a Molecule",5) Molecule *z=new Molecule(*this,""); z->XMLInput(is,tag); this->AddScatterer(z); VFN_DEBUG_EXIT("Crystal::XMLInput():reading a Molecule",5) continue; } } (*fpObjCrystInformUser)("XML: Finished loading Crystal:"+this->GetName()); } //////////////////////////////////////////////////////////////////////// // // I/O Radiation // //////////////////////////////////////////////////////////////////////// void Radiation::XMLOutput(ostream &os,int indent)const { VFN_DEBUG_ENTRY("Radiation::XMLOutput():"<GetName(),5) XMLCrystTag tag("Radiation"); if(WAVELENGTH_ALPHA12==this->GetWavelengthType()) tag.AddAttribute("XRayTube",mXRayTubeName); for(int i=0;iGetWavelengthType()) { case WAVELENGTH_MONOCHROMATIC: this->GetPar(mWavelength.data()).XMLOutput(os,indent);break; case WAVELENGTH_ALPHA12: { this->GetPar(mWavelength.data()).XMLOutput(os,indent); os <GetPar("XRayTubeDeltaLambda").XMLOutput(os,indent); os <GetPar("XRayTubeAlpha2Alpha1Ratio").XMLOutput(os,indent); break; } case WAVELENGTH_TOF:break; default: throw ObjCrystException("This radiation is not implemented !!"); } os<GetName(),5) } void Radiation::XMLInput(istream &is,const XMLCrystTag &tagg) { VFN_DEBUG_ENTRY("Radiation::XMLInput():"<GetName(),5) string scattPowName; for(unsigned int i=0;iSetWavelength(tagg.GetAttributeValue(i)); } while(true) { XMLCrystTag tag(is); if(("Radiation"==tag.GetName())&&tag.IsEndTag()) { // This will force the update of the 'used' status of the alpha1/alpha2 and delta lambda parameters this->SetWavelengthType((WavelengthType) mWavelengthType.GetChoice()); VFN_DEBUG_EXIT("Radiation::Exit():"<GetName(),5) return; } if("Option"==tag.GetName()) { for(unsigned int i=0;i>mLinearPolarRate; XMLCrystTag junk(is); } if("XRayTubeDeltaLambda"==tag.GetName()) { is>>mXRayTubeDeltaLambda; XMLCrystTag junk(is); } if("XRayTubeAlpha2Alpha1Ratio"==tag.GetName()) { is>>mXRayTubeAlpha2Alpha1Ratio; XMLCrystTag junk(is); } if("Par"==tag.GetName()) { for(unsigned int i=0;iGetPar(mWavelength.data()).XMLInput(is,tag); break; } if("XRayTubeDeltaLambda"==tag.GetAttributeValue(i)) { this->GetPar("XRayTubeDeltaLambda").XMLInput(is,tag); break; } if("XRayTubeAlpha2Alpha1Ratio"==tag.GetAttributeValue(i)) { this->GetPar("XRayTubeAlpha2Alpha1Ratio").XMLInput(is,tag); break; } } } continue; } } } //////////////////////////////////////////////////////////////////////// // // I/O DiffractionDataSingleCrystal // //////////////////////////////////////////////////////////////////////// void DiffractionDataSingleCrystal::XMLOutput(ostream &os,int indent)const { VFN_DEBUG_ENTRY("DiffractionDataSingleCrystal::XMLOutput():"<GetName(),5) for(int i=0;iGetCrystal().GetName()); os <GetPar("Scale factor").XMLOutput(os,"Scale factor",indent); os <GetPar(&mGlobalBiso).XMLOutput(os,"globalBiso",indent); os <GetNbRefl();j++) { for(int i=0;i<=indent;i++) os << " " ; os << mIntH(j) <<" " << mIntK(j) <<" " << mIntL(j) <<" " << mObsIntensity(j) <<" " << mObsSigma(j) <<" " << mWeight(j) <<" " <GetName(),5) } void DiffractionDataSingleCrystal::XMLInput(istream &is,const XMLCrystTag &tagg) { VFN_DEBUG_ENTRY("DiffractionDataSingleCrystal::XMLInput():"<GetName(),5) for(unsigned int i=0;iSetName(tagg.GetAttributeValue(i)); if("Crystal"==tagg.GetAttributeName(i)) this->SetCrystal(gCrystalRegistry.GetObj(tagg.GetAttributeValue(i))); } while(true) { XMLCrystTag tag(is); if(("DiffractionDataSingleCrystal"==tag.GetName())&&tag.IsEndTag()) { this->UpdateDisplay(); VFN_DEBUG_EXIT("DiffractionDataSingleCrystal::XMLInput():"<GetName(),5) return; } if("Option"==tag.GetName()) { for(unsigned int i=0;iGetPar(&mScaleFactor).XMLInput(is,tag); break; } } } } if("Radiation"==tag.GetName()) mRadiation.XMLInput(is,tag); if("MaxSinThetaOvLambda"==tag.GetName()) { is>>mMaxSinThetaOvLambda; XMLCrystTag junk(is); } if("Par"==tag.GetName()) { for(unsigned int i=0;iGetPar(&mGlobalBiso).XMLInput(is,tag); break; } } } } if("HKLIobsSigmaWeightList"==tag.GetName()) { long nbrefl=0; CrystVector_long h(100),k(100),l(100); CrystVector_REAL iobs(100),sigma(100),weight(100); do { is >>h(nbrefl)>>k(nbrefl)>>l(nbrefl); iobs (nbrefl)=InputFloat(is); if(ISNAN_OR_INF(iobs (nbrefl))||(iobs (nbrefl)<0)) iobs (nbrefl)=1e-8; sigma (nbrefl)=InputFloat(is); if(ISNAN_OR_INF(sigma (nbrefl))||(sigma (nbrefl)<0)) sigma (nbrefl)=1e-8; weight(nbrefl)=InputFloat(is); if(ISNAN_OR_INF(weight(nbrefl))||(weight(nbrefl)<0)) weight(nbrefl)=1e-8; nbrefl++; if(nbrefl==iobs.numElements()) { h.resizeAndPreserve(nbrefl+100); k.resizeAndPreserve(nbrefl+100); l.resizeAndPreserve(nbrefl+100); iobs.resizeAndPreserve(nbrefl+100); sigma.resizeAndPreserve(nbrefl+100); weight.resizeAndPreserve(nbrefl+100); } while(0==isgraph(is.peek())) is.get(); //cout << is.peek()<<" "<SetHklIobs(h,k,l,iobs,sigma); this->SetWeight(weight); this->SortReflectionBySinThetaOverLambda(); this->CalcIcalc(); this->FitScaleFactorForRw(); } if("HKLIobsSigmaWeightGROUPList"==tag.GetName()) { mNbRefl=0; mNbGroup=0; // This must NOT be changed with this kind of data. mGroupOption.SetChoice(2); // So de-register the option so that it is hidden from the user's view mOptionRegistry.DeRegister(mGroupOption); mClockMaster.RemoveChild(mGroupOption.GetClock()); mH.resize(500); mK.resize(500); mL.resize(500); mObsIntensity.resize(500); mObsSigma.resize(500); mGroupIndex.resize(500); mGroupIobs.resize(500); mGroupSigma.resize(500); mGroupWeight.resize(500); while(true) { XMLCrystTag grouptag(is); if(grouptag.GetName()=="HKLIobsSigmaWeightGROUPList") break; if(grouptag.GetName()=="HKLGroup") { for(unsigned int i=0;i>mGroupIobs(mNbGroup); continue; } if(grouptag.GetAttributeName(i)=="IobsSigma") { stringstream sst; sst<>mGroupSigma(mNbGroup); continue; } if(grouptag.GetAttributeName(i)=="Weight") { stringstream sst; sst<>mGroupWeight(mNbGroup); continue; } } VFN_DEBUG_MESSAGE("Group #"<PrepareHKLarrays(); this->SortReflectionBySinThetaOverLambda(); } } } //////////////////////////////////////////////////////////////////////// // // I/O PowderPatternBackground // //////////////////////////////////////////////////////////////////////// void PowderPatternBackground::XMLOutput(ostream &os,int indent)const { VFN_DEBUG_ENTRY("PowderPatternBackground::XMLOutput():"<GetName(),5) for(int i=0;iGetName()); os <GetParentPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) scale=RAD2DEG; for(long j=0;jGetPar(mBackgroundInterpPointIntensity.data()+j).IsFixed()<<" " <GetPar("ML Model Error").XMLOutput(os,"ML Model Error",indent); os <GetName(),5) } void PowderPatternBackground::XMLInput(istream &is,const XMLCrystTag &tagg) { VFN_DEBUG_ENTRY("PowderPatternBackground::XMLInput():"<GetName(),5) for(unsigned int i=0;iSetName(tagg.GetAttributeValue(i)); if("Interpolation"==tagg.GetAttributeName(i)) {// Obsolete, but we must still read this if("Linear"==tagg.GetAttributeValue(i)) mInterpolationModel.SetChoice(0); if("Spline"==tagg.GetAttributeValue(i)) mInterpolationModel.SetChoice(1); } } while(true) { XMLCrystTag tag(is); if(("PowderPatternBackground"==tag.GetName())&&tag.IsEndTag()) { this->UpdateDisplay(); VFN_DEBUG_EXIT("PowderPatternBackground::Exit():"<GetName(),5) return; } if(("TThetaIntensityList"==tag.GetName())||("XIntensityList"==tag.GetName())) { long nbPoint=0; CrystVector_REAL bckgd2Theta(100); CrystVector_REAL bckgd(100); CrystVector_bool fix(100); do { VFN_DEBUG_MESSAGE("PowderPatternBackground::XMLInput():"<>bckgd2Theta(nbPoint) >>bckgd(nbPoint) >>fix(nbPoint); nbPoint++; if(nbPoint==bckgd2Theta.numElements()) { bckgd2Theta.resizeAndPreserve(nbPoint+100); bckgd.resizeAndPreserve(nbPoint+100); fix.resizeAndPreserve(nbPoint+100); } while(0==isgraph(is.peek())) is.get();//Why do I need that ? //cout << is.peek()<<" "<GetParentPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) bckgd2Theta*= DEG2RAD; this->SetInterpPoints(bckgd2Theta,bckgd); this->InitRefParList(); //read closing tag XMLCrystTag junkEndTag(is); } if("Par"==tag.GetName()) { for(unsigned int i=0;iGetPar("ML Model Error").XMLInput(is,tag); break; #endif } } } } if("Option"==tag.GetName()) { for(unsigned int i=0;iGetName(),5) for(int i=0;iGetName()); tag.AddAttribute("Crystal",this->GetCrystal().GetName()); { stringstream ss; ss<IsIgnoringImagScattFact(); tag.AddAttribute("IgnoreImagScattFact",ss.str()); } os <XMLOutput(os,indent); this->GetPar(&mGlobalBiso).XMLOutput(os,"globalBiso",indent); os <0) { mCorrTextureMarchDollase.XMLOutput(os,indent); } mCorrTextureEllipsoid.XMLOutput(os,indent); #if 0 if(mFhklObsSq.numElements()>0) { XMLCrystTag tag2("FhklObsSq"); for(int i=0;iGetNbRefl();j++) { for(int i=0;i<=indent;i++) os << " " ; os << mIntH(j) <<" " << mIntK(j) <<" " << mIntL(j) <<" " << mFhklObsSq(j) <XMLOutput(os,indent); #endif indent--; tag.SetIsEndTag(true); for(int i=0;iGetName(),5) } void PowderPatternDiffraction::XMLInput(istream &is,const XMLCrystTag &tagg) { VFN_DEBUG_ENTRY("PowderPatternDiffraction::XMLInput():"<GetName(),5) for(unsigned int i=0;iSetName(tagg.GetAttributeValue(i)); if("Crystal"==tagg.GetAttributeName(i)) this->SetCrystal(gCrystalRegistry.GetObj(tagg.GetAttributeValue(i))); if("NeedLorentzCorr"==tagg.GetAttributeName(i)) { stringstream ss(tagg.GetAttributeValue(i)); bool b; ss>>b; //mNeedLorentzCorr=b; //mClockLorentzPolarSlitCorrPar.Reset(); } if("NeedPolarCorr"==tagg.GetAttributeName(i)) { stringstream ss(tagg.GetAttributeValue(i)); bool b; ss>>b; //mNeedPolarCorr=b; //mClockLorentzPolarSlitCorrPar.Reset(); } if("Polar_AFactor"==tagg.GetAttributeName(i)) { stringstream ss(tagg.GetAttributeValue(i)); float b; ss>>b; //mPolarAfactor=b; //mClockLorentzPolarSlitCorrPar.Reset(); } if("NeedSlitApertureCorr"==tagg.GetAttributeName(i)) { stringstream ss(tagg.GetAttributeValue(i)); bool b; ss>>b; //mNeedSlitApertureCorr=b; //mClockLorentzPolarSlitCorrPar.Reset(); } if("IgnoreImagScattFact"==tagg.GetAttributeName(i)) { stringstream ss(tagg.GetAttributeValue(i)); bool b; ss>>b; this->SetIsIgnoringImagScattFact(b); mClockLorentzPolarSlitCorrPar.Reset(); } } while(true) { XMLCrystTag tag(is); if(("PowderPatternCrystal"==tag.GetName())&&tag.IsEndTag()) { this->UpdateDisplay(); VFN_DEBUG_EXIT("PowderPatternDiffraction::Exit():"<GetName(),5) return; } if("Par"==tag.GetName()) { for(unsigned int i=0;iGetPar(&mGlobalBiso).XMLInput(is,tag); break; } if("U"==tag.GetAttributeValue(i)) { mpReflectionProfile->GetPar("U").XMLInput(is,tag); break; } if("V"==tag.GetAttributeValue(i)) { mpReflectionProfile->GetPar("V").XMLInput(is,tag); break; } if("W"==tag.GetAttributeValue(i)) { mpReflectionProfile->GetPar("W").XMLInput(is,tag); break; } if("Eta0"==tag.GetAttributeValue(i)) { mpReflectionProfile->GetPar("Eta0").XMLInput(is,tag); break; } if("Eta1"==tag.GetAttributeValue(i)) { mpReflectionProfile->GetPar("Eta1").XMLInput(is,tag); break; } if("W0"==tag.GetAttributeValue(i)) { //:TODO: mpReflectionProfile->GetPar("Eta0").XMLInput(is,tag); break; } if("W1"==tag.GetAttributeValue(i)) { //:TODO: mpReflectionProfile->GetPar("Eta1").XMLInput(is,tag); break; } if("W2"==tag.GetAttributeValue(i)) { //:TODO: mpReflectionProfile->GetPar("Eta2").XMLInput(is,tag); break; } } } continue; } if("Option"==tag.GetName()) { for(unsigned int i=0;iGetClassName()!="ReflectionProfilePseudoVoigt") { this->SetProfile(new ReflectionProfilePseudoVoigt); } mpReflectionProfile->XMLInput(is,tag); continue; } if("ReflectionProfilePseudoVoigtAnisotropic"==tag.GetName()) { if(mpReflectionProfile==0) { mpReflectionProfile=new ReflectionProfilePseudoVoigtAnisotropic; } else if(mpReflectionProfile->GetClassName()!="ReflectionProfilePseudoVoigtAnisotropic") { this->SetProfile(new ReflectionProfilePseudoVoigtAnisotropic); } mpReflectionProfile->XMLInput(is,tag); continue; } if("ReflectionProfileDoubleExponentialPseudoVoigt"==tag.GetName()) { if(mpReflectionProfile==0) { mpReflectionProfile =new ReflectionProfileDoubleExponentialPseudoVoigt(this->GetCrystal()); } else if(mpReflectionProfile->GetClassName()!="ReflectionProfileDoubleExponentialPseudoVoigt") { this->SetProfile(new ReflectionProfileDoubleExponentialPseudoVoigt(this->GetCrystal())); } mpReflectionProfile->XMLInput(is,tag); continue; } if("FhklObsSq"==tag.GetName()) {// old-style extracted data long nbrefl=0; CrystVector_REAL iobs(100),sigma; CrystVector_long h(100),k(100),l(100); mFhklObsSq.resize(100); do { is >>h(nbrefl)>>k(nbrefl)>>l(nbrefl)>>iobs(nbrefl); nbrefl++; if(nbrefl==h.numElements()) { h.resizeAndPreserve(nbrefl+100); k.resizeAndPreserve(nbrefl+100); l.resizeAndPreserve(nbrefl+100); iobs.resizeAndPreserve(nbrefl+100); } while(0==isgraph(is.peek())) is.get(); } while(is.peek()!='<');//until next tag XMLCrystTag junkEndTag(is); h.resizeAndPreserve(nbrefl); k.resizeAndPreserve(nbrefl); l.resizeAndPreserve(nbrefl); iobs.resizeAndPreserve(nbrefl); sigma.resizeAndPreserve(nbrefl); sigma=1; if(mpLeBailData==0) mpLeBailData=new DiffractionDataSingleCrystal(this->GetCrystal(),false); mpLeBailData->SetHklIobs(h,k,l,iobs,sigma); mpLeBailData->SetWavelength(this->GetRadiation().GetWavelength()(0)); mpLeBailData->SetRadiationType(this->GetRadiation().GetRadiationType()); // Estimate resolution const REAL min=iobs.max()*1e-6; unsigned long iresol=0; for(long i=0;imin) iresol=i; char buf[200]; sprintf(buf,"LeBail (d=%4.2fA?):",1/(2*abs(mpLeBailData->GetSinThetaOverLambda()(iresol))+1e-6)); mpLeBailData->SetName(string(buf)+this->GetCrystal().GetName()); //mpLeBailData->SetName(string("LeBail (resol=?):")+this->GetCrystal().GetName()); } if("DiffractionDataSingleCrystal"==tag.GetName()) {// Le Bail data if(mpLeBailData==0) mpLeBailData=new DiffractionDataSingleCrystal(this->GetCrystal(),false); mpLeBailData->XMLInput(is,tag); } if("FrozenLatticePar"==tag.GetName()) { this->FreezeLatticePar(true); for(unsigned int i=0;i>v; this->SetFrozenLatticePar(0,v); } if("b"==tag.GetAttributeName(i)) { stringstream ss(tag.GetAttributeValue(i)); //ss.imbue(std::locale::classic()); float v; ss>>v; this->SetFrozenLatticePar(1,v); } if("c"==tag.GetAttributeName(i)) { stringstream ss(tag.GetAttributeValue(i)); //ss.imbue(std::locale::classic()); float v; ss>>v; this->SetFrozenLatticePar(2,v); } if("alpha"==tag.GetAttributeName(i)) { stringstream ss(tag.GetAttributeValue(i)); //ss.imbue(std::locale::classic()); float v; ss>>v; this->SetFrozenLatticePar(3,v*M_PI/180); } if("beta"==tag.GetAttributeName(i)) { stringstream ss(tag.GetAttributeValue(i)); //ss.imbue(std::locale::classic()); float v; ss>>v; this->SetFrozenLatticePar(4,v*M_PI/180); } if("gamma"==tag.GetAttributeName(i)) { stringstream ss(tag.GetAttributeValue(i)); //ss.imbue(std::locale::classic()); float v; ss>>v; this->SetFrozenLatticePar(5,v*M_PI/180); } } } } } //////////////////////////////////////////////////////////////////////// // // I/O PowderPattern // //////////////////////////////////////////////////////////////////////// void PowderPattern::XMLOutput(ostream &os,int indent)const { VFN_DEBUG_ENTRY("PowderPattern::XMLOutput():"<GetName(),5) for(int i=0;iGetPar(&mXZero).XMLOutput(os,"Zero",indent); os <GetRadiation().GetWavelengthType()==WAVELENGTH_TOF) { this->GetPar(&mDIFC).XMLOutput(os,"TOF-DIFC",indent); os <GetPar(&mDIFA).XMLOutput(os,"TOF-DIFA",indent); os <GetPar(&m2ThetaDisplacement).XMLOutput(os,"2ThetaDisplacement",indent); os <GetPar(&m2ThetaTransparency).XMLOutput(os,"2ThetaTransparency",indent); os <0) { this->GetPar(&mMuR).XMLOutput(os,"MuR",indent); os <GetNbOption();i++) { this->GetOption(i).XMLOutput(os,indent); os <GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) scale=RAD2DEG; for(unsigned long j=0;jGetNbPoint();j++) { for(int i=0;i<=indent;i++) os << " " ; os << scale*mX(j) <<" " << mPowderPatternObs(j) <<" " << mPowderPatternObsSigma(j) <<" " << mPowderPatternWeight(j) <<" " <GetRadiation().GetWavelengthType()==WAVELENGTH_TOF) { os << tag3 << mExcludedRegionMinX(j) <<" " << mExcludedRegionMaxX(j) ; } else { os << tag3 << mExcludedRegionMinX(j)*RAD2DEG <<" " << mExcludedRegionMaxX(j)*RAD2DEG ; } tag3.SetIsEndTag(true); os<GetName(),5) } void PowderPattern::XMLInput(istream &is,const XMLCrystTag &tagg) { VFN_DEBUG_ENTRY("PowderPattern::XMLInput():"<GetName(),5) for(unsigned int i=0;iSetName(tagg.GetAttributeValue(i)); } while(true) { XMLCrystTag tag(is); if(("PowderPattern"==tag.GetName())&&tag.IsEndTag()) { this->UpdateDisplay(); VFN_DEBUG_EXIT("PowderPattern::Exit():"<GetName(),5) return; } if("Radiation"==tag.GetName()) mRadiation.XMLInput(is,tag); if("MaxSinThetaOvLambda"==tag.GetName()) { is>>mMaxSinThetaOvLambda; XMLCrystTag junk(is); } if("Par"==tag.GetName()) { for(unsigned int i=0;iGetPar(&mXZero).XMLInput(is,tag); break; } if("2ThetaDisplacement"==tag.GetAttributeValue(i)) { this->GetPar(&m2ThetaDisplacement).XMLInput(is,tag); break; } if("2ThetaTransparency"==tag.GetAttributeValue(i)) { this->GetPar(&m2ThetaTransparency).XMLInput(is,tag); break; } if("TOF-DIFC"==tag.GetAttributeValue(i)) { this->GetPar(&mDIFC).XMLInput(is,tag); break; } if("TOF-DIFA"==tag.GetAttributeValue(i)) { this->GetPar(&mDIFA).XMLInput(is,tag); break; } if("MuR"==tag.GetAttributeValue(i)) { this->GetPar(&mMuR).XMLInput(is,tag); break; } } } continue; } if("Option"==tag.GetName()) { for(unsigned int i=0;iSetParentPowderPattern(*this); comp->XMLInput(is,tag); continue; } if("PowderPatternCrystal"==tag.GetName()) { PowderPatternDiffraction *comp=new PowderPatternDiffraction; comp->SetParentPowderPattern(*this); comp->XMLInput(is,tag); continue; } if("PowderPatternComponent"==tag.GetName()) { REAL scale=1.0; string name; for(unsigned int i=0;i>scale; continue; } if("Name"==tag.GetAttributeName(i)) name=tag.GetAttributeValue(i); } this->AddPowderPatternComponent(gPowderPatternComponentRegistry.GetObj(name)); mScaleFactor(mPowderPatternComponentRegistry.GetNb()-1)=scale; VFN_DEBUG_MESSAGE("->Adding Component :"<>min>>max; if(this->GetRadiation().GetWavelengthType()==WAVELENGTH_TOF) this->AddExcludedRegion(min,max); else this->AddExcludedRegion(min*DEG2RAD,max*DEG2RAD); XMLCrystTag end(is); continue; } if("IobsSigmaWeightList"==tag.GetName()) { // Old version, just for 2theta-intensity pattern (no TOF) VFN_DEBUG_ENTRY("Loading Iobs-Sigma-Weight List...",8); REAL min,step; for(unsigned int i=0;i>min; VFN_DEBUG_MESSAGE("2Theta min="<>step; VFN_DEBUG_MESSAGE("2Theta step="<>mPowderPatternObs(mNbPoint) >>mPowderPatternObsSigma(mNbPoint) >>mPowderPatternWeight(mNbPoint); mNbPoint++; VFN_DEBUG_MESSAGE("Point #"<SetPowderPatternPar(min,step,mNbPoint); mClockPowderPatternPar.Click(); XMLCrystTag junk(is); VFN_DEBUG_EXIT("Loading Iobs-Sigma-Weight List...",8); continue; } if("XIobsSigmaWeightList"==tag.GetName()) { VFN_DEBUG_ENTRY("Loading X-Iobs-Sigma-Weight List...",8); while(0==isgraph(is.peek())) is.get(); if(is.peek()=='<') { cout <<"PowderPattern::XMLInput(): no data point in the powder pattern !"<>mX(mNbPoint) >>mPowderPatternObs(mNbPoint) >>mPowderPatternObsSigma(mNbPoint) >>mPowderPatternWeight(mNbPoint); mNbPoint++; VFN_DEBUG_MESSAGE("Point #"<GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) mX*=DEG2RAD; this->SetPowderPatternX(mX); XMLCrystTag junk(is); VFN_DEBUG_EXIT("Loading X-Iobs-Sigma-Weight List...",8); continue; } } } } //namespace objcryst-2022.1/ObjCryst/ObjCryst/IO.h000066400000000000000000000073771430515525000174330ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* IO.h * */ #ifndef _OBJCRYST_IOCRYST_H_ #define _OBJCRYST_IOCRYST_H_ #endif //_OBJCRYST_IOCRYST_H_ #include "ObjCryst/RefinableObj/IO.h" #include "ObjCryst/RefinableObj/RefinableObj.h" namespace ObjCryst { /** \brief Save all Objcryst++ objects. * * This saves all Crystal, PowderPattern, DiffDataSingleCrystal and GlobalOptimObj objects, * using the global registries for these classes. All other objects (Scatterer, * ScatteringPower, PowderPatternComponent are saved as well since they are sub-objects * of Crystal or PowderPattern objects). * * Saving is done in well-formed xml format. */ void XMLCrystFileSaveGlobal(const string & filename); /** \brief Save all Objcryst++ objects. * * This saves all Crystal, PowderPattern, DiffDataSingleCrystal and GlobalOptimObj objects, * using the global registries for these classes. All other objects (Scatterer, * ScatteringPower, PowderPatternComponent are saved as well since they are sub-objects * of Crystal or PowderPattern objects). * * Saving is done in well-formed xml format. */ void XMLCrystFileSaveGlobal(std::ostream &out); /** \brief Get the list (tags) of ObjCryst objects in a file * * This will recognize only certain tags in the file (Crystal,PowderPattern, * DiffDataSingleCrystal, GlobalOptimObj). Eventually it should include also * the ZScatterer objects. * * \note It will be the duty of the caller to destroy all the tags which have been * allocated. * * NOT TESTED YET ! */ ObjRegistry XMLCrystFileLoadObjectList(const string & filename); /** \brief Load an object from a file, identifying it from its tag * * \param file: the filename from which the object will be loaded. * \param tagName: the name of the tag * \param name: the name of the object to be found (in a 'Name' attribute) * \param obj: the pointer to the object to be loaded. The allocation will be done * by the function, and the pointer changed accordingly. * * NOT TESTED YET ! */ template void XMLCrystFileLoadObject(const string & file, const string &tagName, const string &name, T*obj); /** \brief Load all 'top' objects from a file (Crystal, PowderPattern, DiffDataSingleCrystal * and GlobalOptimObj objects). All objects are directly allocated, and can be accessed through * their respective global registry (eg gCrystalRegistry fro a Crysta, etc...) * * \param file: the filename from which the objects will be loaded. */ void XMLCrystFileLoadAllObject(const string & file); /** \brief Load all 'top' objects from a file (Crystal, PowderPattern, DiffDataSingleCrystal * and GlobalOptimObj objects). All objects are directly allocated, and can be accessed through * their respective global registry (eg gCrystalRegistry fro a Crysta, etc...) * * \param file: the filename from which the objects will be loaded. */ void XMLCrystFileLoadAllObject(std::istream &is); } objcryst-2022.1/ObjCryst/ObjCryst/Indexing.cpp000066400000000000000000003231271430515525000212160ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2006- Vincent Favre-Nicolin vincefn@users.sourceforge.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * source file for Indexing classes & functions * */ #include #include #include "ObjCryst/ObjCryst/Indexing.h" #include "ObjCryst/Quirks/VFNDebug.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" #include "ObjCryst/Quirks/Chronometer.h" using namespace std; #ifndef M_PI #define M_PI 3.14159265358979323846264338327950288 #endif #ifndef DEG2RAD #define DEG2RAD (M_PI/180.) #endif #ifndef RAD2DEG #define RAD2DEG (180./M_PI) #endif namespace ObjCryst { float EstimateCellVolume(const float dmin, const float dmax, const float nbrefl, const CrystalSystem system,const CrystalCentering centering,const float kappa) { const float q1=dmin*dmin*dmin-dmax*dmax*dmax; const float q2=dmin*dmin -dmax*dmax; float D0,C0; if(system==TRICLINIC) { C0=2.095; return nbrefl/(C0*kappa*q1); } if(system==CUBIC) { if(centering==LATTICE_P) D0=0.862; if(centering==LATTICE_I) D0=0.475; if(centering==LATTICE_F) D0=0.354; return pow(nbrefl/(D0*kappa*q2),(float)1.5); } // "*.85" means using D0_min rather than D0 if(system==MONOCLINIC) {C0=1.047;D0=0.786*.85;} if(system==ORTHOROMBIC){C0=0.524;D0=1.36 *.85;} if(system==HEXAGONAL) {C0=0.150;D0=1.04 *.85;} if(system==RHOMBOEDRAL){C0=0.230;D0=1.04 *.85;} if(system==TETRAGONAL) {C0=0.214;D0=1.25 *.85;} if((centering==LATTICE_I)||(centering==LATTICE_A)||(centering==LATTICE_B)||(centering==LATTICE_C)) {C0/=2;D0/=2;} if(centering==LATTICE_F){C0/=4;D0/=4;} const float alpha=D0*q2/(3*C0*q1), beta=nbrefl/(2*kappa*C0*q1); const float eta=beta-alpha*alpha*alpha,gamma=sqrt(beta*beta-2*beta*alpha*alpha*alpha); const float v=pow(pow(eta+gamma,(float)(1/3.))+pow(fabs(eta-gamma),(float)(1/3.))-alpha,(float)3); return v; } /** light-weight class storing the reciprocal space unitcell */ RecUnitCell::RecUnitCell(const float zero,const float p0,const float p1,const float p2, const float p3,const float p4,const float p5,CrystalSystem lattice, const CrystalCentering cent, const unsigned int nbspurious): mlattice(lattice),mCentering(cent),mNbSpurious(nbspurious) { this->par[0]=zero; this->par[1]=p0; this->par[2]=p1; this->par[3]=p2; this->par[4]=p3; this->par[5]=p4; this->par[6]=p5; } RecUnitCell::RecUnitCell(const RecUnitCell &old) { *this=old; } void RecUnitCell::operator=(const RecUnitCell &rhs) { for(unsigned int i=0;i<7;++i) par[i]=rhs.par[i]; mlattice=rhs.mlattice; mCentering=rhs.mCentering; mNbSpurious=rhs.mNbSpurious; } float RecUnitCell::hkl2d(const float h,const float k,const float l,REAL *derivpar,const unsigned int derivhkl) const { if((derivpar==NULL)&&(derivhkl==0)) { switch(mlattice) { case TRICLINIC: { return par[0]+par[1]*h*h + par[2]*k*k + par[3]*l*l + par[4]*h*k + par[5]*k*l + par[6]*h*l; break; } case MONOCLINIC: { return par[0]+par[1]*par[1]*h*h + par[2]*par[2]*k*k + par[3]*par[3]*l*l + 2*par[1]*par[3]*par[4]*h*l; break; } case ORTHOROMBIC: { return par[0]+par[1]*par[1]*h*h + par[2]*par[2]*k*k + par[3]*par[3]*l*l; break; } case HEXAGONAL: { return par[0]+par[1]*par[1]*(h*h + k*k + h*k)+ par[2]*par[2]*l*l ; break; } case RHOMBOEDRAL: { return par[0]+par[1]*par[1]*(h*h + k*k + l*l + 2*par[2]*(h*k + k*l + h*l)); break; } case TETRAGONAL: { return par[0]+par[1]*par[1]*(h*h + k*k) + par[2]*par[2]*l*l; break; } case CUBIC: { return par[0]+par[1]*par[1]*(h*h+k*k+l*l); break; } } } if(derivhkl==1) { switch(mlattice) { case TRICLINIC: { return 2*par[1]*h + par[4]*k + par[6]*l; break; } case MONOCLINIC: { return 2*par[1]*par[1]*h + 2*par[1]*par[3]*par[4]*l; break; } case ORTHOROMBIC: { return 2*par[1]*par[1]*h; break; } case HEXAGONAL: { return par[1]*par[1]*(2*h + k); break; } case RHOMBOEDRAL: { return par[1]*par[1]*(2*h + 2*par[2]*(k + l)); break; } case TETRAGONAL: { return 2*par[1]*par[1]*h; break; } case CUBIC: { return 2*par[1]*par[1]*h; break; } } } if(derivhkl==2) { switch(mlattice) { case TRICLINIC: { return 2*par[2]*k + par[4]*h + par[5]*l; break; } case MONOCLINIC: { return 2*par[2]*par[2]*k; break; } case ORTHOROMBIC: { return 2*par[2]*par[2]*k; break; } case HEXAGONAL: { return par[1]*par[1]*(2*k + h); break; } case RHOMBOEDRAL: { return par[1]*par[1]*(2*k + l*l + 2*par[2]*(h + l)); break; } case TETRAGONAL: { return 2*par[1]*par[1]*k; break; } case CUBIC: { return 2*par[1]*par[1]*k; break; } } } if(derivhkl==3) { switch(mlattice) { case TRICLINIC: { return 2*par[3]*l + par[5]*k + par[6]*h; break; } case MONOCLINIC: { return 2*par[3]*par[3]*l + 2*par[1]*par[3]*par[4]*h; break; } case ORTHOROMBIC: { return 2*par[3]*par[3]*l; break; } case HEXAGONAL: { return 2*par[2]*par[2]*l; break; } case RHOMBOEDRAL: { return par[1]*par[1]*(2*l + 2*par[2]*(k + h)); break; } case TETRAGONAL: { return 2*par[2]*par[2]*l; break; } case CUBIC: { return 2*par[1]*par[1]*l; break; } } } if(derivpar==&par[0]) return 1.0; if(derivpar==(par+1)) { switch(mlattice) { case TRICLINIC: { return h*h; break; } case MONOCLINIC: { return 2*par[1]*h*h + 2*par[3]*par[4]*h*l; break; } case ORTHOROMBIC: { return 2*par[1]*h*h; break; } case HEXAGONAL: { return 2*par[1]*(h*h + k*k + h*k); break; } case RHOMBOEDRAL: { return 2*par[1]*(h*h + k*k + l*l + 2*par[2]*(h*k + k*l + h*l)); break; } case TETRAGONAL: { return 2*par[1]*(h*h + k*k); break; } case CUBIC: { return 2*par[1]*(h*h+k*k+l*l); break; } } } if(derivpar==(par+2)) { switch(mlattice) { case TRICLINIC: { return k*k; break; } case MONOCLINIC: { return 2*par[2]*k*k; break; } case ORTHOROMBIC: { return 2*par[2]*k*k; break; } case HEXAGONAL: { return 2*par[2]*l*l ; break; } case RHOMBOEDRAL: { return par[1]*par[1]*(h*h + k*k + l*l + 2*(h*k + k*l + h*l)); break; } case TETRAGONAL: { return 2*par[2]*l*l; break; } case CUBIC: { throw 0; break; } } } if(derivpar==(par+3)) { switch(mlattice) { case TRICLINIC: { return l*l; break; } case MONOCLINIC: { return 2*par[3]*l*l + 2*par[1]*par[4]*h*l; break; } case ORTHOROMBIC: { return 2*par[3]*l*l; break; } case HEXAGONAL: { throw 0; break; } case RHOMBOEDRAL: { throw 0; break; } case TETRAGONAL: { throw 0; break; } case CUBIC: { throw 0; break; } } } if(derivpar==(par+4)) { switch(mlattice) { case TRICLINIC: { return h*k; break; } case MONOCLINIC: { return 2*par[1]*par[3]*h*l; break; } default: { throw 0; break; } } } if(derivpar==(par+5)) { switch(mlattice) { case TRICLINIC: { return k*l; break; } default: { throw 0; break; } } } if(derivpar==(par+6)) { switch(mlattice) { case TRICLINIC: { return h*l; break; } default: { throw 0; break; } } } throw 0; return 0.0; } void RecUnitCell::hkl2d_delta(const float h,const float k,const float l, const RecUnitCell &delta, float & dmin, float &dmax) const { const float p0m=par[0]-delta.par[0] , p0p=par[0]+delta.par[0], p1m=par[1]-delta.par[1] , p1p=par[1]+delta.par[1], p2m=par[2]-delta.par[2] , p2p=par[2]+delta.par[2], p3m=par[3]-delta.par[3] , p3p=par[3]+delta.par[3], p4m=par[4]-delta.par[4] , p4p=par[4]+delta.par[4], p5m=par[5]-delta.par[5] , p5p=par[5]+delta.par[5], p6m=par[6]-delta.par[6] , p6p=par[6]+delta.par[6]; switch(mlattice) { case TRICLINIC: {//par[0]+par[1]*h*h + par[2]*k*k + par[3]*l*l + par[4]*h*k + par[5]*k*l + par[6]*h*l; float p4mm,p5mm,p6mm,p4pp,p5pp,p6pp; if((h*k)>0){p4mm=p4m;p4pp=p4p;}else{p4mm=p4p;p4pp=p4m;} if((k*l)>0){p5mm=p5m;p5pp=p5p;}else{p5mm=p5p;p5pp=p5m;} if((h*l)>0){p6mm=p6m;p6pp=p6p;}else{p6mm=p6p;p6pp=p6m;} dmin=p0m+p1m*h*h+p2m*k*k+p3m*l*l+p4mm*h*k+p5mm*k*l+p6mm*h*l; dmax=p0p+p1p*h*h+p2p*k*k+p3p*l*l+p4pp*h*k+p5pp*k*l+p6pp*h*l; /* if(dmin<0) { cout<<"hkl2d_delta: dmin<0 ! "<0) { dmin = p0m + p1m*p1m*h*h + p2m*p2m*k*k + p3m*p3m*l*l + 2*p1m*p3m*p4m*h*l; dmax = p0p + p1p*p1p*h*h + p2p*p2p*k*k + p3p*p3p*l*l + 2*p1p*p3p*p4p*h*l; return; } else { const bool b1=(h*(par[1]*h+par[3]*par[4]*l))>0;// d(d*^2)/dp1 const bool b3=(l*(par[3]*l+par[1]*par[4]*h))>0;// d(d*^2)/dp2 if(b1 && b3) { dmin = p0m + p1m*p1m*h*h + p2m*p2m*k*k + p3m*p3m*l*l + 2*p1m*p3m*p4p*h*l; dmax = p0p + p1p*p1p*h*h + p2p*p2p*k*k + p3p*p3p*l*l + 2*p1p*p3p*p4m*h*l; return; } else if(b1 && (!b3)) { dmin = p0m + p1m*p1m*h*h + p2m*p2m*k*k + p3p*p3p*l*l + 2*p1m*p3p*p4p*h*l; dmax = p0p + p1p*p1p*h*h + p2p*p2p*k*k + p3m*p3m*l*l + 2*p1p*p3m*p4m*h*l; return; } else if((!b1) && b3) { dmin = p0m + p1p*p1p*h*h + p2m*p2m*k*k + p3m*p3m*l*l + 2*p1p*p3m*p4p*h*l; dmax = p0p + p1m*p1m*h*h + p2p*p2p*k*k + p3p*p3p*l*l + 2*p1m*p3p*p4m*h*l; return; } else { dmin = p0m + p1p*p1p*h*h + p2m*p2m*k*k + p3p*p3p*l*l + 2*p1p*p3p*p4p*h*l; dmax = p0p + p1m*p1m*h*h + p2p*p2p*k*k + p3m*p3m*l*l + 2*p1m*p3m*p4m*h*l; return; } } } case ORTHOROMBIC: //OK { dmin= p0m + p1m*p1m*h*h + p2m*p2m*k*k + p3m*p3m*l*l; dmax= p0p + p1p*p1p*h*h + p2p*p2p*k*k + p3p*p3p*l*l; return; } case HEXAGONAL: //OK { dmin=p0m+p1m*p1m*(h*h + k*k + h*k)+ p2m*p2m*l*l ; dmax=p0p+p1p*p1p*(h*h + k*k + h*k)+ p2p*p2p*l*l ; return; } case RHOMBOEDRAL: { if((h*k + k*l + h*l)>=0) { dmin= p0m+p1m*p1m*(h*h + k*k + l*l + 2*p2m*(h*k + k*l + h*l)); dmax= p0p+p1p*p1p*(h*h + k*k + l*l + 2*p2p*(h*k + k*l + h*l)); } else { dmin= p0m+p1m*p1m*(h*h + k*k + l*l + 2*p2p*(h*k + k*l + h*l)); dmax= p0p+p1p*p1p*(h*h + k*k + l*l + 2*p2m*(h*k + k*l + h*l)); } return; } case TETRAGONAL: //OK { dmin= p0m + p1m*p1m*(h*h + k*k) + p2m*p2m*l*l; dmax= p0p + p1p*p1p*(h*h + k*k) + p2p*p2p*l*l; return; } case CUBIC: //OK { dmin=p0m + p1m*p1m*(h*h+k*k+l*l); dmax=p0p + p1p*p1p*(h*h+k*k+l*l); return; } } } vector RecUnitCell::DirectUnitCell(const bool equiv)const { // reciprocal unit cell parameters float aa,bb,cc,calphaa,cbetaa,cgammaa,salphaa,sbetaa,sgammaa; switch(mlattice) { case TRICLINIC: { aa=sqrt(par[1]); bb=sqrt(par[2]); cc=sqrt(par[3]); calphaa=par[5]/(2*bb*cc); cbetaa =par[6]/(2*aa*cc); cgammaa=par[4]/(2*aa*bb); salphaa=sqrt(abs(1-calphaa*calphaa)); sbetaa =sqrt(abs(1-cbetaa *cbetaa)); sgammaa=sqrt(abs(1-cgammaa*cgammaa)); break; } case MONOCLINIC: { aa=par[1]; bb=par[2]; cc=par[3]; calphaa=0; cbetaa=par[4]; cgammaa=0; salphaa=1; sbetaa =sqrt(abs(1-cbetaa *cbetaa)); sgammaa=1; break; } case ORTHOROMBIC: { aa=par[1]; bb=par[2]; cc=par[3]; calphaa=0; cbetaa =0; cgammaa=0; salphaa=1; sbetaa =1; sgammaa=1; break; } case HEXAGONAL: { aa=par[1]; bb=par[1]; cc=par[2]; calphaa=0; cbetaa =0; cgammaa=0.5; salphaa=1; sbetaa =1; sgammaa=0.8660254037844386; break; } case RHOMBOEDRAL: { aa=par[1]; bb=par[1]; cc=par[1]; calphaa=par[4]; cbetaa =par[4]; cgammaa=par[4]; salphaa=sqrt(abs(1-calphaa *calphaa)); sbetaa =salphaa; sgammaa=salphaa; break; } case TETRAGONAL: { aa=par[1]; bb=par[1]; cc=par[2]; calphaa=0; cbetaa =0; cgammaa=0; salphaa=1; sbetaa =1; sgammaa=1; break; } case CUBIC: { aa=par[1]; bb=par[1]; cc=par[1]; calphaa=0; cbetaa =0; cgammaa=0; salphaa=1; sbetaa =1; sgammaa=1; break; } // This should never happen. Avoid using unitialized cell parameters. default: throw 0; } // Volume of reciprocal unit cell const float vv=sqrt(abs(1-calphaa*calphaa-cbetaa*cbetaa-cgammaa*cgammaa+2*calphaa*cbetaa*cgammaa)); const float a=salphaa/(aa*vv); const float b=sbetaa /(bb*vv); const float c=sgammaa/(cc*vv); const float calpha=(cbetaa *cgammaa-calphaa)/(sbetaa *sgammaa); const float cbeta =(calphaa*cgammaa-cbetaa )/(salphaa*sgammaa); const float cgamma=(calphaa*cbetaa -cgammaa)/(salphaa*sbetaa ); const float alpha=acos( calpha ); const float beta =acos( cbeta ); const float gamma=acos( cgamma ); const float v=a*b*c*sqrt(1-calpha*calpha-cbeta*cbeta-cgamma*cgamma+2*calpha*cbeta*cgamma); vector par(7); par[0]=a; par[1]=b; par[2]=c; par[3]=alpha; par[4]=beta; par[5]=gamma; par[6]=v; return par; } ///////////////////////////////////////////////// PEAKLIST:HKL0 ///////////////////// PeakList::hkl0::hkl0(const int h0,const int k0, const int l0): h(h0),k(k0),l(l0) {} ///////////////////////////////////////////////// PEAKLIST:HKL ///////////////////// PeakList::hkl::hkl(const float d,const float i,const float ds,const float is, const int h0,const int k0, const int l0,const float dc0): dobs(d),dobssigma(ds),d2obs(d*d),d2obsmin((d-ds/2)*(d-ds/2)),d2obsmax((d+ds/2)*(d+ds/2)),iobs(i),iobssigma(is), h(h0),k(k0),l(l0),isIndexed(false),isSpurious(false),stats(0), d2calc(dc0),d2diff(0) {} bool compareHKL_d(const PeakList::hkl &d1, const PeakList::hkl &d2) { return d1.dobs < d2.dobs; } ///////////////////////////////////////////////// PEAKLIST ///////////////////// PeakList::PeakList() {} PeakList::PeakList(const PeakList &old) { *this=old; } void PeakList::operator=(const PeakList &rhs) { VFN_DEBUG_ENTRY("PeakList::operator=(PeakList &old)",10); mvHKL=rhs.mvHKL; VFN_DEBUG_EXIT("PeakList::operator=(PeakList &old)",10); } PeakList::~PeakList() {} void PeakList::ImportDhklDSigmaIntensity(istream &is,float defaultsigma) { float d,sigma,iobs; while(true) {// :TODO: use readline to make sure when the end is reached is >>d; cout<<__FILE__<<":"<<__LINE__<<" "<>sigma; if(is.good()==false) break; is>>iobs; if(sigma<=0) sigma=d*defaultsigma; if(iobs<=0) iobs=1.0; mvHKL.push_back(hkl(1/d,iobs,1/(d-sigma/2)-1/(d+sigma/2))); cout<<"+/-"<>d; if(is.eof()) break; is>>iobs; mvHKL.push_back(hkl(1/d,iobs)); cout<<__FILE__<<":"<<__LINE__<<" "< > v; float d; while(true) {// :TODO: use readline to make sure when the end is reached is >>d; if(is.eof()) break; mvHKL.push_back(hkl(1/d)); cout<<__FILE__<<":"<<__LINE__<<" "< bool comparePairFirst(std::pair &p1, std::pair &p2) { return p1.first < p2.first; } void PeakList::Import2ThetaIntensity(istream &is, const float wavelength) { std::list > v; float d,iobs; while(true) {// :TODO: use readline to make sure when the end is reached is >>d; if(is.eof()) break; is>>iobs; d=2*sin(d/2*DEG2RAD)/wavelength; mvHKL.push_back(hkl(1/d,iobs)); cout<<__FILE__<<":"<<__LINE__<<" "< vd2; for(int h=0;h<=20;h++) for(int k=-20;k<=20;k++) { if((h==0) && (k<0)) k=0; for(int l=-20;l<=20;l++) { if((h==0) && (k==0) && (l<=0)) l=1; vd2.push_back(sqrt(ruc.hkl2d(h,k,l))); } } // std::list::iterator pos=vd2.begin(); if(percentMissing>0.90) percentMissing=0.90; for(;pos!=vd2.end();++pos) { if((rand()/float(RAND_MAX))::const_iterator pos=mvHKL.begin();pos!=mvHKL.end();++pos) { const float sigma=1/(pos->dobs-pos->dobssigma/2)-1/(pos->dobs+pos->dobssigma/2); os<< std::fixed << setw(6) << setprecision(3) << 1/pos->dobs <<" "<< sigma <<" "<< std::scientific << pos->iobs <::const_iterator pos=mvHKL.begin();pos!=mvHKL.end();++pos) s+= pos->dobssigma; s/=mvHKL.size(); if(s>0) mvHKL.push_back(hkl(d,iobs,s,iobssigma,h,k,l,d2calc)); else mvHKL.push_back(hkl(d,iobs,1e-4,iobssigma,h,k,l,d2calc)); } else mvHKL.push_back(hkl(d,iobs,dobssigma,iobssigma,h,k,l,d2calc)); sort(mvHKL.begin(),mvHKL.end(),compareHKL_d); //this->Print(cout); } void PeakList::RemovePeak(unsigned int idx) { for(unsigned int i=idx;i<(mvHKL.size()-1);++i) mvHKL[i]=mvHKL[i+1]; mvHKL.pop_back(); } void PeakList::Print(std::ostream &os) const { unsigned int i=0; char buf[200]; os<<"PeakList, with "<::const_iterator pos=mvHKL.begin();pos!=mvHKL.end();++pos) { const float sigma=1/(pos->dobs-pos->dobssigma/2)-1/(pos->dobs+pos->dobssigma/2); if(pos->isIndexed) sprintf(buf,"#%3d d=%6.3f+/-%7.4f dcalc=%6.3f, diff=%7.4f, iobs=%6.3f HKL=%2d %2d %2d Spurious=%1d stats=%6lu", i++,1/pos->dobs,sigma, 1/sqrt(abs(pos->d2calc)),1/sqrt(abs(pos->d2calc))-1/pos->dobs, pos->iobs,pos->h,pos->k,pos->l,pos->isSpurious,pos->stats); else sprintf(buf,"#%3d d=%6.3f+/-%6.3f iobs=%6.3f UNINDEXED Spurious=%1d stats=%6lu", i++,1/pos->dobs,1/(pos->dobs-pos->dobssigma/2)-1/(pos->dobs+pos->dobssigma/2), pos->iobs,pos->isSpurious,pos->stats); os< & PeakList::GetPeakList(){return mvHKL;} const vector & PeakList::GetPeakList()const {return mvHKL;} /////////////////////////////////////////////////////// SCORE /////////////////////////////////////// float Score(const PeakList &dhkl, const RecUnitCell &rpar, const unsigned int nbSpurious, const bool verbose,const bool storehkl,const bool storePredictedHKL) { const bool autozero=false; vector::const_iterator pos,first,last; for(pos=dhkl.GetPeakList().begin();pos!=dhkl.GetPeakList().end();++pos) { if(storehkl) pos->isIndexed=false; pos->d2calc=0; pos->d2diff=1000; } const unsigned long nb=dhkl.GetPeakList().size(); if(storePredictedHKL) dhkl.mvPredictedHKL.clear(); unsigned long nbCalc=0; int h,k,l; float predict_coeff=1; if(storePredictedHKL)predict_coeff=2; const float dmax=dhkl.mvHKL[nb-1].d2obs*predict_coeff*1.05; int sk0,sl0;// do we need >0 *and* <0 indices for k,l ? switch(rpar.mlattice) { case TRICLINIC: sk0=-1;sl0=-1; break; case MONOCLINIC: sk0=1;sl0=-1; break; case ORTHOROMBIC: sk0=1;sl0=1; break; case HEXAGONAL: sk0=-1;sl0=1; break; case RHOMBOEDRAL: sk0=-1;sl0=-1; break; case TETRAGONAL: sk0=1;sl0=1; break; case CUBIC: sk0=1;sl0=1; break; // This should never happen. Avoid using unitialized values. default: throw 0; } int stepk,stepl;// steps in k,l to use for centered lattices switch(rpar.mCentering) { case LATTICE_P:stepk=1;stepl=1;break; case LATTICE_I:stepk=1;stepl=2;break; case LATTICE_A:stepk=1;stepl=2;break; case LATTICE_B:stepk=1;stepl=2;break; case LATTICE_C:stepk=2;stepl=1;break; case LATTICE_F:stepk=2;stepl=2;break; // This should never happen. Avoid using unitialized values. default: throw 0; } first=dhkl.GetPeakList().begin();last=dhkl.GetPeakList().end(); unsigned long nbCalcH,nbCalcK;// Number of calculated lines below dmax for each h,k for(h=0;;++h) { nbCalcH=0; for(int sk=sk0;sk<=1;sk+=2) { if(h==0) sk=1;// no need to explore 0kl with both sk -1 and 1 if(stepk==2) k=(h%2);// For LATTICE_C,LATTICE_F: h odd => k odd else k=0; for(;;k+=stepk) { nbCalcK=0; for(int sl=sl0;sl<=1;sl+=2) { if((h+k)==0) { sl=1;// No need to list 0 0 l with l<0 l=1; } else { if(h==0) { if(rpar.mlattice==MONOCLINIC) sl=1;// 0 k l and 0 k -l are equivalent if((sk<0)||(sl<0)) l=1;// Do not list 0 k 0 with k<0 else l=0;// h==k==0 already covered } else { if(sl<0) l=1;// Do not list h k 0 twice else l=0; } } if(stepl==2) { if(rpar.mCentering==LATTICE_I) l+=(h+k+l)%2; if(rpar.mCentering==LATTICE_A) l+=(k+l)%2;// Start at hk1 if k odd if( (rpar.mCentering==LATTICE_B) ||(rpar.mCentering==LATTICE_F)) l+=(h+l)%2;// Start at hk1 if h odd } for(;;l+=stepl) { const float d2=rpar.hkl2d(h,sk*k,sl*l); if(d2>dmax) { //cout<<__FILE__<<":"<<__LINE__<<" hkl: "<=0) break; else continue; } nbCalc++;nbCalcK++;nbCalcH++; if(storePredictedHKL) { dhkl.mvPredictedHKL.push_back(PeakList::hkl(0,0,0,0,h,sk*k,sl*l,d2)); //continue; } for(pos=first;pos!=last;++pos) { const float tmp=d2-pos->d2obs; if(tmp<.1) { if(tmp<-.1) break; if(fabs(tmp)d2diff)) { pos->d2diff=tmp; if(storehkl) { pos->h=h; pos->k=sk*k; pos->l=sl*l; pos->isIndexed=true; pos->d2calc=d2; } } /* if((verbose)&&(fabs(tmp)<.01)) cout<<__FILE__<<":"<<__LINE__<<" hkl: "< epsilon="<="< >::iterator pos=vRUC.begin();pos!=vRUC.end();++pos) { if(pos==bestpos) continue; for(unsigned int k=0;kfirst.par[k]=mMin[k]+mAmp[k]*rand()/(float)RAND_MAX; } } } /* for(vector >::iterator pos=vRUC.begin();pos!=vRUC.end();++pos) { // Final cost vector par=pos->first.DirectUnitCell(); cout<<__FILE__<<":"<<__LINE__<<" Trial: a="<mMinScoreReport*.5) { // Now, do a least-squares refinement on best mRecUnitCell=bestpos->first; this->LSQRefine(10,true,true); par=mRecUnitCell.DirectUnitCell(); score=Score(*mpPeakList,mRecUnitCell,mNbSpurious,false,true); cout<<__FILE__<<":"<<__LINE__<<" Best-LSQ: a="<RefinableObj::Print(); } unsigned int CellExplorer::GetNbLSQFunction() const {return 1;} const CrystVector_REAL& CellExplorer::GetLSQCalc(const unsigned int) const { VFN_DEBUG_ENTRY("CellExplorer::GetLSQCalc()",2) unsigned int j=0; for(vector::const_iterator pos=mpPeakList->GetPeakList().begin();pos!=mpPeakList->GetPeakList().end();++pos) { if(pos->isIndexed) mCalc(j++)=mRecUnitCell.hkl2d(pos->h,pos->k,pos->l); } //cout<<__FILE__<<":"<<__LINE__<<"LSQCalc : Score:"<::const_iterator pos=mpPeakList->GetPeakList().begin();pos!=mpPeakList->GetPeakList().end();++pos) { VFN_DEBUG_MESSAGE("CellExplorer::GetLSQDeriv():"<GetPeakList().size(),2) VFN_DEBUG_MESSAGE("CellExplorer::GetLSQDeriv():"<h<<","<k<<","<l,2) if(pos->isIndexed) mDeriv(j++)=mRecUnitCell.hkl2d(pos->h,pos->k,pos->l,par); } VFN_DEBUG_EXIT("CellExplorer::GetLSQDeriv()",2) return mDeriv; } void CellExplorer::BeginOptimization(const bool allowApproximations, const bool enableRestraints) { VFN_DEBUG_ENTRY("CellExplorer::BeginOptimization()",5) Score(*mpPeakList,mRecUnitCell,mNbSpurious,false,true,false); const unsigned int nb=mpPeakList->GetPeakList().size(); mCalc.resize(nb-mNbSpurious); mObs.resize(nb-mNbSpurious); mWeight.resize(nb-mNbSpurious); mDeriv.resize(nb-mNbSpurious); int j=0; float thres=0.0; for(vector::const_iterator pos=mpPeakList->GetPeakList().begin();pos!=mpPeakList->GetPeakList().end();++pos) if(thresiobs) thres=pos->iobs; thres/=10;// weight=1 for intensities up to Imax/10 //cout <<"Beginning optimization with reflexions:"<::const_iterator pos=mpPeakList->GetPeakList().begin();pos!=mpPeakList->GetPeakList().end();++pos) { if(pos->isIndexed) { mObs(j)=pos->d2obs; if(mObs(j)>thres) mWeight(j)=1; else mWeight(j)=mObs(j)/thres; /* sprintf(buf,"#%2d (%3d %3d %3d) dobs=%6.3f dcalc=%6.3f iobs=%6.3f weight=%6.4f", i,mpPeakList->mvHKL[i].h,mpPeakList->mvHKL[i].k,mpPeakList->mvHKL[i].l, 1/mpPeakList->mvdobs[i],1/sqrt(mRecUnitCell.hkl2d(mpPeakList->mvHKL[i].h,mpPeakList->mvHKL[i].k,mpPeakList->mvHKL[i].l)), mpPeakList->mviobs[i],mWeight(j)); */ j++; } /* else { sprintf(buf,"#%2d (%3d %3d %3d) dobs=%6.3f dcalc=%6.3f iobs=%6.3f SPURIOUS", i,mpPeakList->mvHKL[i].h,mpPeakList->mvHKL[i].k,mpPeakList->mvHKL[i].l, 1/mpPeakList->mvdobs[i],1/sqrt(mRecUnitCell.hkl2d(mpPeakList->mvHKL[i].h,mpPeakList->mvHKL[i].k,mpPeakList->mvHKL[i].l)), mpPeakList->mviobs[i]); } cout<RefinableObj::BeginOptimization(allowApproximations,enableRestraints); VFN_DEBUG_EXIT("CellExplorer::BeginOptimization()",5) } void CellExplorer::LSQRefine(int nbCycle, bool useLevenbergMarquardt, const bool silent) { if(mNbLSQExcept>100) { if(!silent) cout<<"CellExplorer::LSQRefine(): LSQ was disabled, too many (>100) exceptions caught. Weird unit cell parameters ?"; return; } VFN_DEBUG_ENTRY("CellExplorer::LSQRefine()",5) mLSQObj.SetRefinedObj(*this); mLSQObj.PrepareRefParList(true); //this->BeginOptimization(); //cout<(this->GetLSQObs(0),this->GetLSQCalc(0),this->GetLSQWeight(0),this->GetLSQDeriv(0,this->GetPar((long)0)))<100) cout<<"WARNING CellExplorer::LSQRefine(): LSQ was disabled, too many (>100) exceptions caught. Weird unit cell parameters ?"<Print(cout); VFN_DEBUG_EXIT("CellExplorer::LSQRefine()",5) } /** Number of reflexions found in the intervals calculated between par+dpar and par-dpar * * \param useStoredHKL: * - if equal to 0, explore all possible hkl values to find possible Miller indices. * - if useStoredHKL=1, use the Miller indices already stored in hkl.vDicVolHKL * for each observed line as the only possible indices. * - if useStoredHKL=2, search all the possible Miller indices for all reflections * and store them in hkl.vDicVolHKL for each observed line. * \param maxNbMissingBelow5: the maximum number of lines that have been calculated before * the d-value of the 5th observed line, but which have not been observed. * If nbMissingBelow5>0 and more than nbMissingBelow5 lines have not been observed, * return false. Recommended to speed up triclinic, with nbMissingBelow5=5 */ bool DichoIndexed(const PeakList &dhkl, const RecUnitCell &par,const RecUnitCell &dpar, const unsigned int nbUnindexed=0,const bool verbose=false,unsigned int useStoredHKL=0, const unsigned int maxNbMissingBelow5=0) { const unsigned int nb=dhkl.GetPeakList().size(); int nbIndexed=nb-nbUnindexed;// Number of reflections we require to be indexed float d5=0; if(maxNbMissingBelow5>0) d5=dhkl.GetPeakList()[4].d2obs; // number of missing reflections calculated below 5th observed line unsigned int nbMissingBelow5=0; // List of indexed reflections vector::const_iterator pos,first,last,end; if(useStoredHKL==1) {// We already now possible Miller indices for all reflections unsigned int nbUnIx = 0; for(pos=dhkl.GetPeakList().begin();pos!=dhkl.GetPeakList().end();++pos) { pos->isIndexed=false; for(list::const_iterator phkl0=pos->vDicVolHKL.begin();phkl0!=pos->vDicVolHKL.end();++phkl0) { float d0,d1; par.hkl2d_delta(phkl0->h,phkl0->k,phkl0->l,dpar,d0,d1); if((pos->d2obsmax>=d0) && (d1>=pos->d2obsmin)) { pos->d2calc=(d0+d1)/2; pos->isIndexed=true; if(--nbIndexed==0) return true; break; } } if(!(pos->isIndexed)) if(++nbUnIx>nbUnindexed) return false; } return false; } const bool storePossibleHKL=(useStoredHKL==2); if(storePossibleHKL) for(pos=dhkl.GetPeakList().begin();pos!=dhkl.GetPeakList().end();++pos) { pos->isIndexed=false; pos->vDicVolHKL.clear(); } else for(pos=dhkl.GetPeakList().begin();pos!=dhkl.GetPeakList().end();++pos) pos->isIndexed=false; int h,k,l; float dmax=dhkl.GetPeakList()[nb-1].d2obs; float dmin=dhkl.GetPeakList()[0 ].d2obs; int sk0,sl0;// do we need >0 *and* <0 indices for k,l ? switch(par.mlattice) { case TRICLINIC: sk0=-1;sl0=-1; break; case MONOCLINIC: { sk0=1;sl0=-1; break; } case ORTHOROMBIC: sk0=1;sl0=1; break; case HEXAGONAL: sk0=-1;sl0=1; break; case RHOMBOEDRAL: sk0=-1;sl0=-1; break; case TETRAGONAL: sk0=1;sl0=1; break; case CUBIC: sk0=1;sl0=1; break; // This should never happen. Avoid using unitialized values. default: throw 0; } int stepk,stepl;// steps in k,l to use for centered lattices switch(par.mCentering) { case LATTICE_P:stepk=1;stepl=1;break; case LATTICE_I:stepk=1;stepl=2;break; case LATTICE_A:stepk=1;stepl=2;break; case LATTICE_B:stepk=1;stepl=2;break; case LATTICE_C:stepk=2;stepl=1;break; case LATTICE_F:stepk=2;stepl=2;break; // This should never happen. Avoid using unitialized values. default: throw 0; } //RecUnitCell par0(par),par1(par); //for(unsigned int i=0;i<7;++i) {par0.par[i]-=dpar.par[i];par1.par[i]+=dpar.par[i];} //currently first & last unindexed dhkl first=dhkl.GetPeakList().begin(),last=dhkl.GetPeakList().end(),end=dhkl.GetPeakList().end(); unsigned long nbCalcH,nbCalcK;// Number of calculated lines below dmax for each h,k for(h=0;;++h) { if(verbose) cout<<"H="< k odd else k=0; for(;;k+=stepk) { if(verbose) cout<<"K="<dmax) { if(par.mlattice==TRICLINIC) { // Must check that d is increasing with l, otherwise we still need to increase it if(verbose) cout<<"L?="<< par.hkl2d(h,sk*k,sl*l,NULL,3)*sl <<", dmax="<0) break; } else break; } bool missing=(d00); for(pos=first;pos!=end;++pos) { if(pos==last) break; if((!storePossibleHKL)&&(pos->isIndexed)&&missing) continue; const float d2obs=pos->d2obs,d2obsmin=pos->d2obsmin, d2obsmax=pos->d2obsmax; if((d2obsmax>=d0) && (d1>=d2obsmin)) { missing=false; if(!(pos->isIndexed)) { pos->d2calc=(d0+d1)/2; --nbIndexed; pos->isIndexed=true; } if(verbose) cout<vDicVolHKL.push_back(PeakList::hkl0(h,sk*k,sl*l)); else { if((!storePossibleHKL)&&(nbIndexed==0)) return true; if(pos==first){first++;dmin=first->d2obsmin;} if(pos==last){last--;dmax=last->d2obsmax;} } } } if(missing) if(++nbMissingBelow5>=maxNbMissingBelow5)return false; } } if(nbCalcK==0) break;// && ((par.hkl2d(h,sk*k,0,NULL,2)*sk)>0)) break; // k too large } } if(nbCalcH==0) break;//h too large } if(verbose) { dhkl.Print(cout); } return nbIndexed<=0; } float CellExplorer::GetBestScore()const{return mBestScore;} const std::list >& CellExplorer::GetSolutions()const {return mvSolution;} std::list >& CellExplorer::GetSolutions() {return mvSolution;} unsigned int CellExplorer::RDicVol(RecUnitCell par0,RecUnitCell dpar, unsigned int depth,unsigned long &nbCalc,const float minV,const float maxV,vector vdepth) { static bool localverbose=false; if(mlattice==TRICLINIC) { const float p1=par0.par[1] , p2=par0.par[2] , p3=par0.par[3] , p4=par0.par[4] , p5=par0.par[5] , p6=par0.par[6]; const float p1m=p1-dpar.par[1], p2m=p2-dpar.par[2], p3m=p3-dpar.par[3], p4m=p4-dpar.par[4], p5m=p5-dpar.par[5], p6m=p6-dpar.par[6]; const float p1p=p1+dpar.par[1], p2p=p2+dpar.par[2], p3p=p3+dpar.par[3], p4p=p4+dpar.par[4], p5p=p5+dpar.par[5], p6p=p6+dpar.par[6]; // a*p2p)||(p2m>p3p)) return 0; // max/min absolute values for p4,p5,p6 if((p4m>p1p)||(-p4p>p1p)) return 0;//abs(p4) b* < b*+/-a* if((p5m>p2p)||(-p5p>p2p)) return 0;//abs(p5) c* < c*+/-b* if((p6m>p1p)||(-p6p>p1p)) return 0;//abs(p6) c* < c*+/-a* const float max6=p1p+p2p-p4m-p5m; if((p6m>max6)||(-p6p>max6)) return 0;//abs(p6) c* < c*+/-a*+/-b* float p6mm,p6pp,p5mm,p5pp,p4mm,p4pp; // p6pp: smaller V*, larger V, etc.. // derivative of V*^2 with p6 if((p4*p5-2*p2*p6)>0) {p6pp=p6p;p6mm=p6m;} else{p6pp=p6m;p6mm=p6p;} // derivative of V*^2 with p5 if((p4*p6-2*p1*p5)>0) {p5pp=p5p;p5mm=p5m;} else{p5pp=p5m;p5mm=p5p;} // derivative of V*^2 with p5 if((p5*p6-2*p3*p4)>0) {p4pp=p4p;p4mm=p4m;} else{p4pp=p4m;p4mm=p4p;} //const float vmin0=1/sqrt(abs(p1p*p2p*p3p*(1-p5mm*p5mm/(4*p2p*p3p)-p6mm*p6mm/(4*p1p*p3p)-p4mm*p4mm/(4*p1p*p2p)+p4mm*p5mm*p6mm/(4*p1m*p2m*p3m)))); //const float vmax0=1/sqrt(abs(p1m*p2m*p3m*(1-p5pp*p5pp/(4*p2m*p3m)-p6pp*p6pp/(4*p1m*p3m)-p4pp*p4pp/(4*p1m*p2m)+p4pp*p5pp*p6pp/(4*p1m*p2m*p3m)))); const float vmin0=1/sqrt(abs(p1p*p2p*p3p*(1-p5mm*p5mm/(4*p2p*p3p)-p6mm*p6mm/(4*p1p*p3p)-p4mm*p4mm/(4*p1p*p2p)+p4mm*p5mm*p6mm/(4*p1m*p2m*p3m)))); const float vmax0=1/sqrt(abs(p1m*p2m*p3m*(1-p5pp*p5pp/(4*p2m*p3m)-p6pp*p6pp/(4*p1m*p3m)-p4pp*p4pp/(4*p1m*p2m)+p4pp*p5pp*p6pp/(4*p1m*p2m*p3m)))); if((vmin0>maxV)||(vmax00)&&(depth<=2))// test if volume is within range { RecUnitCell parm=par0,parp=par0; for(unsigned int i=0;i<6;++i) {parm.par[i]-=dpar.par[i];parp.par[i]+=dpar.par[i];} vector parmd=parm.DirectUnitCell(); vector parpd=parp.DirectUnitCell(); if((parpd[6]>maxV)||(parmd[6]=4, try adding a zero ? if( (!indexed) && (depth>=4)) {//:TODO: Check if this is OK ! Vary value with depth dpar.par[0]=.0001; indexed=DichoIndexed(*mpPeakList,par0,dpar,mNbSpurious,false,useStoredHKL,maxMissingBelow5); //if(indexed) cout<<"Added zero - SUCCESS !"<::const_iterator pos=mpPeakList->GetPeakList().begin();pos!=mpPeakList->GetPeakList().end();) { if(pos->vDicVolHKL.size()==1) { const PeakList::hkl0 h0=pos->vDicVolHKL.front(); if(++pos==mpPeakList->GetPeakList().end()) break; if(pos->vDicVolHKL.size()==1) { const PeakList::hkl0 h1=pos->vDicVolHKL.front(); if((h0.h==h1.h)&&(h0.k==h1.k)&&(h0.l==h1.l)) nbident++; if(nbident>mNbSpurious) {indexed=false;break;} } } else ++pos; } } // if we can zoom in for one parameter directly, we need per-parameter depth if(vdepth.size()==0) { vdepth.resize(mnpar-1); for(vector::iterator pos=vdepth.begin();pos!=vdepth.end();) *pos++=depth; } else for(vector::iterator pos=vdepth.begin();pos!=vdepth.end();++pos) if(*pos > vq0(3); for(unsigned int i=0;i<3;++i) {vq0[i].first=0;vq0[i].second=0.0;} RecUnitCell par0orig=par0,dparorig=dpar; for(vector::const_iterator pos=mpPeakList->GetPeakList().begin();pos!=mpPeakList->GetPeakList().end();++pos) { if(pos->vDicVolHKL.size()==1) { const PeakList::hkl0 h0=pos->vDicVolHKL.front(); if((h0.k==0)&&(h0.l==0)) {vq0[0].first+=1 ; vq0[0].second+=pos->dobs/h0.h;} else if((h0.h==0)&&(h0.l==0)) {vq0[1].first+=1 ; vq0[1].second+=pos->dobs/h0.k;} else if((h0.h==0)&&(h0.k==0)) {vq0[2].first+=1 ; vq0[2].second+=pos->dobs/h0.l;if(localverbose) cout<=2)) { vector shifts(mpPeakList->GetPeakList().size()); vector::const_iterator peakpos=mpPeakList->GetPeakList().begin(); for(vector::iterator spos=shifts.begin();spos!=shifts.end();) { *spos++ = peakpos->d2diff * (float)(peakpos->isIndexed&&(!peakpos->isSpurious));peakpos++;} sort(shifts.begin(),shifts.end()); par0.par[0]=shifts[mpPeakList->GetPeakList().size()/2];//use median value indexed=DichoIndexed(*mpPeakList,par0,dpar,mNbSpurious); if(indexed) cout<<"Failed Dicho ? Trying auto-zero shifting :Worked !"<=5) { RecUnitCell parm=par0,parp=par0; for(unsigned int i=0;i<6;++i) {parm.par[i]-=dpar.par[i];parp.par[i]+=dpar.par[i];} vector parmd=parm.DirectUnitCell(); vector parpd=parp.DirectUnitCell(); char buf[200]; sprintf(buf,"a=%5.2f-%5.2f b=%5.2f-%5.2f c=%5.2f-%5.2f alpha=%5.2f-%5.2f beta=%5.2f-%5.2f gamma=%5.2f-%5.2f V=%5.2f-%5.2f", parpd[0],parmd[0],parpd[1],parmd[1],parpd[2],parmd[2],parpd[3]*RAD2DEG,parmd[3]*RAD2DEG, parpd[4]*RAD2DEG,parmd[4]*RAD2DEG,parpd[5]*RAD2DEG,parmd[5]*RAD2DEG,parpd[6],parmd[6]); for(unsigned int i=0;idepth)); for(int i0=-1;i0<=1;i0+=2) { //:TODO: dichotomy on zero shift ? if(localverbose) cout<<__FILE__<<":"<<__LINE__<<":"<=mDicVolDepthReport)) { mRecUnitCell=par0; vector par=mRecUnitCell.DirectUnitCell(); float score=Score(*mpPeakList,mRecUnitCell,mNbSpurious,false,true,false); // If we already have enough reports at higher depths (depth+2), don't bother record this one bool report=true; if(depth<(mMaxDicVolDepth-1)) if(mvNbSolutionDepth[depth+2]>100)report=false; if(report && (((score>(mMinScoreReport*.5))&&(depth>=mDicVolDepthReport)) || (depth>=mMaxDicVolDepth))) { if(false)//score>) mBestScore//((score>mMinScoreReport)||(depth>=mDicVolDepthReport)) cout<<__FILE__<<":"<<__LINE__<<" Depth="<1100)&&(rand()%1000==0)) { cout<ReduceSolutions(true);// This will update the min report score cout<<"-> "< linspace(float min, float max,unsigned int nb) { vector v(nb); for(unsigned int i=0;iInit(); if(minDepth>mMaxDicVolDepth) mMaxDicVolDepth=minDepth; mvNbSolutionDepth.resize(mMaxDicVolDepth+1); for(unsigned int i=0;i<=mMaxDicVolDepth;++i) mvNbSolutionDepth[i]=0; float latstep=0.5, vstep=(mVolumeMax-mVolumeMin)/(ceil((mVolumeMax-mVolumeMin)/500)-0.0001); mCosAngMax=abs(cos(mAngleMax)); const float cosangstep=mCosAngMax/(ceil(mCosAngMax/.08)-.0001); if(((mVolumeMax-mVolumeMin)/vstep)>10) vstep=(mVolumeMax-mVolumeMin)/9.999; if(((mLengthMax-mLengthMin)/latstep)>25) latstep=(mLengthMax-mLengthMin)/24.9999; cout<"<"<"< >::iterator bestpos; bool breakDepth=false; // In the triclinic case, first try assigning a* and b* from the first reflections if(false) //mlattice==TRICLINIC) for(float minv=mVolumeMin;minvmVolumeMax)maxv=mVolumeMax; cout<<"Starting: V="<"<GetPeakList()[0].d2obs ;p2=mpPeakList->GetPeakList()[1].d2obs ; break; case 1: p1=mpPeakList->GetPeakList()[0].d2obs ;p2=mpPeakList->GetPeakList()[2].d2obs ; break; case 2: p1=mpPeakList->GetPeakList()[1].d2obs/2;p2=mpPeakList->GetPeakList()[0].d2obs ; break; case 3: p1=mpPeakList->GetPeakList()[1].d2obs/2;p2=mpPeakList->GetPeakList()[2].d2obs ; break; case 4: p1=mpPeakList->GetPeakList()[2].d2obs/2;p2=mpPeakList->GetPeakList()[0].d2obs ; break; case 5: p1=mpPeakList->GetPeakList()[2].d2obs/2;p2=mpPeakList->GetPeakList()[1].d2obs ; break; } //if(i>0) exit(0); if(p1>p2) continue; cout<<"Trying #"<0) for(unsigned int i=stopOnDepth; i1) {breakDepth=true;break;} if((mBestScore>stopOnScore)&&(breakDepth)) break; }//cases cout<<"Finished triclinic QUICK tests for: V="<"<"< v1=linspace(mLengthMin,mLengthMax,nbstep); const float lstep=v1[1]-v1[0]; for(unsigned int i1=0;i1<(nbstep-1);++i1) { const float p1 =(1/(v1[i1]*v1[i1])+1/(v1[i1+1]*v1[i1+1]))/2; const float dp1=(1/(v1[i1]*v1[i1])-1/(v1[i1+1]*v1[i1+1]))/2; //cout<<"p1="< v2=linspace(mLengthMin,v1[i1+1],nb2); //for(unsigned int i2=0;i2 v4=linspace(0,p1+dp1,nb4); for(unsigned int i4=0;i4<(nb4-1);++i4) { const float p4 =(v4[i4+1]+v4[i4])/2; const float dp4=(v4[i4+1]-v4[i4])/2; //cout<<" p4="< v5=linspace(0,p2+dp2,nb5); for(unsigned int i5=0;i5<(nb5-1);++i5) { const float p5 =(v5[i5+1]+v5[i5])/2; const float dp5=(v5[i5+1]-v5[i5])/2; //cout<<" p5="<(p1+dp1)) vmax6=p1+dp1; if(vmax6<0) continue; const unsigned int nb6=int((2*vmax6)/(4*dp1)+2.001); vector v6=linspace(-vmax6,vmax6,nb6); //cout<<" p6="< parlarged,parsmalld; latstep=(mLengthMax-mLengthMin)/24.999; for(float x4=0;x4x1) break;// | c * cos(beta) | maxv) break; const float largev=(x1+latstep)*(x2+latstep)*(x3+latstep)*(sinbeta+cosangstep); if(largevminv)) { //cout<mLengthMax) break; } break; } case RHOMBOEDRAL: //:TODO: { latstep=(mLengthMax-mLengthMin)/24.999; for(float x1=mLengthMin;x1<(mLengthMax+latstep);x1+=latstep) { for(float x2=0;x2 par=par0.DirectUnitCell(); if((par[6]minv)) { RDicVol(par0,dpar,0,nbCalc,minv,maxv); } } } break; } case TETRAGONAL: { vector parlarged,parsmalld;// Small & large UC in direct space latstep=(mLengthMax-mLengthMin)/24.999; for(float x1=mLengthMin;x1minv)) { RDicVol(par0,dpar,0,nbCalc,minv,maxv); } if(parsmalld[6]>maxv) break; } if((x1*mLengthMin*mLengthMin)>maxv) break; } break; } case CUBIC: { latstep=(mLengthMax-mLengthMin)/24.999; cout<maxv)break; if(vmax>minv) RDicVol(par0,dpar,0,nbCalc,minv,maxv); } break; } } cout<<"Finished: V="<"< >::iterator pos=mvSolution.begin();pos!=mvSolution.end();++pos) { const float score=pos->second;//Score(*mpPeakList,pos->first,mNbSpurious); if(score>bestscore) {bestscore=score;bestpos=pos;} } bool breakDepth=false; if(stopOnDepth>0) for(unsigned int i=stopOnDepth; i1) {breakDepth=true;break;} if((bestscore>stopOnScore)&&(breakDepth)) break; } /* {// Tag spurious lines vector vSpuriousScore; for(vector::const_iterator pos=mpPeakList->GetPeakList().begin();pos!=mpPeakList->GetPeakList().end();++pos) vSpuriousScore.push_back(pos->stats); sort(vSpuriousScore.begin(),vSpuriousScore.end()); const int threshold=vSpuriousScore[vSpuriousScore.size()/2]*5; for(vector::iterator pos=mpPeakList->mvHKL.begin();pos!=mpPeakList->mvHKL.end();++pos) if(pos->stats > threshold) pos->isSpurious=true; else pos->isSpurious=false; mpPeakList->Print(cout); } */ this->ReduceSolutions(true); bestscore=0;bestpos=mvSolution.end(); for(list >::iterator pos=mvSolution.begin();pos!=mvSolution.end();++pos) { const float score=Score(*mpPeakList,pos->first,mNbSpurious); if(score>bestscore) {bestpos=pos;bestscore=score;} vector par=pos->first.DirectUnitCell(); cout<<__FILE__<<":"<<__LINE__<<" Solution ? a="< par0=c0.DirectUnitCell(); vector par1=c1.DirectUnitCell(); float diff=0; for(unsigned int i=0;i<6;++i) diff += abs(par0[i]-par1[i]); return (diff/6) &p1, std::pair &p2) { return p1.second > p2.second; } void CellExplorer::ReduceSolutions(const bool updateReportThreshold) { const bool verbose=false; std::list > vSolution2; // TODO: take into account number of spurious lines for cutoff value. // keep only solutions above mBestScore/5 for(list >::iterator pos=mvSolution.begin();pos!=mvSolution.end();) { if(pos->second<(mBestScore/5)) pos=mvSolution.erase(pos); else ++pos; } if(updateReportThreshold&& ((mBestScore/5)>mMinScoreReport)) { cout<<"CellExplorer::ReduceSolutions(): update threshold for report from " <0) { vSolution2.push_back(mvSolution.front()); mvSolution.pop_front(); vector par=vSolution2.back().first.DirectUnitCell(); if(verbose) cout<<__FILE__<<":"<<__LINE__<<" SOLUTION: a="< >::iterator pos=mvSolution.begin();pos!=mvSolution.end();) { if(SimilarRUC(pos->first,vSolution2.back().first)) { par=pos->first.DirectUnitCell(); if(verbose) cout<<__FILE__<<":"<<__LINE__<<" 1: a="<first.mlattice) { if(pos->second>vSolution2.back().second) vSolution2.back()=*pos; } else if(vSolution2.back().first.mlatticefirst.mlattice) vSolution2.back()=*pos; pos=mvSolution.erase(pos); } else { par=pos->first.DirectUnitCell(); if(verbose) cout<<__FILE__<<":"<<__LINE__<<" 0: a="<100) { mvSolution.resize(100); if(updateReportThreshold && (mvSolution.back().second>mMinScoreReport)) { cout<<"CellExplorer::ReduceSolutions(): update threshold for report from " <nb;++i) // cout<<__FILE__<<":"<<__LINE__<<":d*="<mvdobs[i]<<", d*^2="<mvd2obs[i]< >::iterator pos; const float min_latt=1./mLengthMax; const float max_latt=1./mLengthMin; const float amp_crossp=abs(cos(mAngleMax)); //mMin[0]=-.002;mAmp[0]=.004; mMin[0]=.00;mAmp[0]=.00; switch(mlattice) { case TRICLINIC: mMin[1]=min_latt;mAmp[1]=max_latt-min_latt; mMin[2]=min_latt;mAmp[2]=max_latt-min_latt; mMin[3]=min_latt;mAmp[3]=max_latt-min_latt; mMin[4]=0;mAmp[4]=amp_crossp; mMin[5]=0;mAmp[5]=amp_crossp; mMin[6]=0;mAmp[6]=amp_crossp; mnpar=7; break; case MONOCLINIC: mMin[1]=min_latt;mAmp[1]=max_latt-min_latt; mMin[2]=min_latt;mAmp[2]=max_latt-min_latt; mMin[3]=min_latt;mAmp[3]=max_latt-min_latt; mMin[4]=0;mAmp[4]=amp_crossp; mnpar=5; break; case ORTHOROMBIC: mMin[1]=min_latt;mAmp[1]=max_latt-min_latt; mMin[2]=min_latt;mAmp[2]=max_latt-min_latt; mMin[3]=min_latt;mAmp[3]=max_latt-min_latt; mnpar=4; break; case HEXAGONAL: mMin[1]=min_latt;mAmp[1]=max_latt-min_latt; mMin[2]=min_latt;mAmp[2]=max_latt-min_latt; mnpar=3; break; case RHOMBOEDRAL: mMin[1]=min_latt;mAmp[1]=max_latt-min_latt; mMin[2]=-amp_crossp;mAmp[2]=2*amp_crossp; mnpar=3; break; case TETRAGONAL: mMin[1]=min_latt;mAmp[1]=max_latt-min_latt; mMin[2]=min_latt;mAmp[2]=max_latt-min_latt; mnpar=3; break; case CUBIC: mMin[1]=min_latt;mAmp[1]=max_latt-min_latt; mnpar=2; break; } //for(unsigned int k=0;k"<ResetParList(); { RefinablePar tmp("Zero",mRecUnitCell.par+0,-0.01,0.01,gpRefParTypeObjCryst,REFPAR_DERIV_STEP_ABSOLUTE, true,false,true,false); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } char buf [50]; string str="Reciprocal unit cell par #"; for(unsigned int i=0;iAddPar(tmp); } for(unsigned int i=nb1;i<(nb1+nb2);++i) { sprintf(buf,"%i",i); RefinablePar tmp(str+(string)buf,mRecUnitCell.par+i+1, 0.0,0.5,gpRefParTypeObjCryst,REFPAR_DERIV_STEP_ABSOLUTE, false,false,true,false); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } } }//namespace objcryst-2022.1/ObjCryst/ObjCryst/Indexing.h000066400000000000000000000322201430515525000206520ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2006- Vincent Favre-Nicolin vincefn@users.sourceforge.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * source file for Indexing classes & functions * */ #ifndef _OBJCRYST_INDEXING_H_ #define _OBJCRYST_INDEXING_H_ #include #include #include #include #include #include #include "ObjCryst/RefinableObj/RefinableObj.h" #include "ObjCryst/RefinableObj/LSQNumObj.h" #include "ObjCryst/ObjCryst/PowderPattern.h" namespace ObjCryst { /** Different lattice types. * */ enum CrystalSystem { TRICLINIC, MONOCLINIC, ORTHOROMBIC, HEXAGONAL, RHOMBOEDRAL, TETRAGONAL, CUBIC}; enum CrystalCentering { LATTICE_P,LATTICE_I,LATTICE_A,LATTICE_B,LATTICE_C,LATTICE_F}; /** Estimate volume from number of peaks at a given dmin * See J. Appl. Cryst. 20 (1987), 161 * * \param dmin,dmax: 1/d limits between which the number of reflections has been observed * \param nbrefl: number of observed reflections * \param kappa: estimated percentage of reflections actually observed (default=1.0) */ float EstimateCellVolume(const float dmin, const float dmax, const float nbrefl, const CrystalSystem system,const CrystalCentering centering,const float kappa=1); /** Lightweight class describing the reciprocal unit cell, for the fast computation of d*_hkl^2. * * */ class RecUnitCell { public: RecUnitCell(const float zero=0,const float par0=0,const float par1=0,const float par2=0, const float par3=0,const float par4=0,const float par5=0,CrystalSystem lattice=CUBIC, const CrystalCentering cent=LATTICE_P, const unsigned int nbspurious=0); RecUnitCell(const RecUnitCell &old); void operator=(const RecUnitCell &rhs); // access to ith parameter //float operator[](const unsigned int i); /// Compute d*^2 for hkl reflection /// if deriv != -1, compute derivate versus the corresponding parameter /// /// If derivhkl=1,2,3, compute derivative versus h,k or l. float hkl2d(const float h,const float k,const float l,REAL *derivpar=NULL,const unsigned int derivhkl=0) const; /// Compute d*^2 for one hkl reflection: this functions computes a d*^2 range (min,max) /// for a given range of unit cell parameter (given in the delta parameter) around the /// current parameters. /// /// Used for DicVol algorithm void hkl2d_delta(const float h,const float k,const float l,const RecUnitCell &delta, float & dmin, float &dmax) const; /** Compute real space unit cell from reciprocal one * *\param equiv: if true, return real unit cell \e equivalent to the one computed from the reciprocal one, * so that alpha, beta and gamma are larger or equal to pi/2, and minimum. This is done * by adding multiples of \b a to \b b and multiples of \b a and \b b to \b c. */ std::vector DirectUnitCell(const bool equiv=false)const; /** The 6 parameters defining 1/d_hkl^2 = d*_hkl^2, for different crystal classes, from: * d*_hkl^2 = zero + a*^2 h^2 + b*^2 k^2 + c*^2 l^2 + 2 a*.b* hk + 2 b*.c* kl + 2 a*.c* hl * * for triclinic: * d*_hkl^2 = par[0] + par[1] h^2 + par[1] k^2 + par[2]^2 l^2 + par[3] hk + par[4] kl + par[5] hl * for monoclinic: * d*_hkl^2 = zero + par[0]^2 h^2 + par[1]^2 k^2 + par[2]^2 l^2 + par[0]*par[2]*par[3] hl * for orthorombic: * d*_hkl^2 = zero + par[0]^2 h^2 + par[1]^2 k^2 + par[2]^2 l^2 * for hexagonal: * d*_hkl^2 = zero + par[0]^2 h^2 + par[0]^2 k^2 + par[2]^2 l^2 + sqrt(3)/2*par[0]^2 hk * for rhomboedral: * d*_hkl^2 = zero + par[0]^2 h^2 + par[1]^2 k^2 + par[2]^2 l^2 + par[3] (hk + kl + hl) * for quadratic: * d*_hkl^2 = zero + par[0]^2 h^2 + par[0]^2 k^2 + par[1]^2 l^2 * for cubic * d*_hkl^2 = zero + par[0]^2 (h^2 + k^2 + l^2) */ REAL par[7]; CrystalSystem mlattice; CrystalCentering mCentering; /// The number of spurious lines used to match this RecUnitCell unsigned int mNbSpurious; }; /** Class to store positions of observed reflections. * * */ class PeakList { public: PeakList(); PeakList(const PeakList &old); void operator=(const PeakList &rhs); ~PeakList(); void ImportDhklDSigmaIntensity(std::istream &is,float defaultsigma=.001); void ImportDhklIntensity(std::istream &is); void ImportDhkl(std::istream &is); void Import2ThetaIntensity(std::istream &is, const float wavelength=1.5418); /** Generate a list of simulated peak positions, from given lattice parameters * * \param zero: the zero, given for d*^2 (in Angstroems^-2) * \param a,b,c,alpha,beta,gamma: lattice parameters * \param deg: if true, angles are in degrees instead of radians * \param nb: the number of peak positions to generate * \param nbspurious: number of spurious lines to be included in the list * \param sigma: the maximum relative error for d* - the d* values will be within [d_calc*(1-sigma) ;d_calc*(1+sigma)] * \param percentMissing: percentage (between 0 and 1) of missing reflections - maximum allowed 0.9 * \param verbose: print some info * \return: the volume of the simulated unit cell */ float Simulate(float zero, float a, float b, float c, float alpha, float beta, float gamma, bool deg, unsigned int nb=20, unsigned int nbspurious=0, float sigma=0, float percentMissing=0, const bool verbose=false); void ExportDhklDSigmaIntensity(std::ostream &out)const; /// Add one peak ///\param d: 1/d for this peak (Angstroem) void AddPeak(const float d, const float iobs=1.0,const float dobssigma=0.0,const float iobssigma=0.0, const int h=0,const int k=0, const int l=0,const float d2calc=0); void RemovePeak(unsigned int i); void Print(std::ostream &os) const; /// One set of Miller indices, a possible indexation for a reflection struct hkl0 { hkl0(const int h=0,const int k=0, const int l=0); /// Miller indices int h,k,l; }; /** One observed diffraction line, to be indexed * */ struct hkl { hkl(const float dobs=1.0,const float iobs=0.0,const float dobssigma=0.0,const float iobssigma=0.0, const int h=0,const int k=0, const int l=0,const float d2calc=0); /// Observed peak position 1/d float dobs; /// Error on peak position float dobssigma; /// Observed peak position 1/d^2 float d2obs; /// Min value for observed peak position 1/(d+disgma/2)^2 float d2obsmin; /// Min value for observed peak position 1/(d-disgma/2)^2 float d2obsmax; /// Observed peak intensity float iobs; /// Error on observed peak intensity float iobssigma; /// Miller indices, after line is indexed mutable int h,k,l; /// Possible Miller indices, stored during a dichotomy search. mutable std::list vDicVolHKL; /// Is this line indexed ? mutable bool isIndexed; /// Is this an impurity line ? mutable bool isSpurious; /// Indexing statistics mutable unsigned long stats; /// Calculated position, 1/d^2 mutable float d2calc; /// 1/d^2 difference, obs-calc mutable float d2diff; }; /// Get peak list vector & GetPeakList(); /// Get peak list const vector & GetPeakList()const ; /// Predict peak positions /// Best h,k,l for each observed peak (for least-squares refinement) /// This is stored by the Score function, optionnally. mutable vectormvHKL; /// Full list of calculated HKL positions for a given solution, up to a given resolution /// After finding a candidate solution, use score with pPredictedHKL=&mvPredictedHKL mutable list mvPredictedHKL; }; /// Compute score for a candidate RecUnitCell and a PeakList float Score(const PeakList &dhkl, const RecUnitCell &ruc, const unsigned int nbSpurious=0, const bool verbose=false,const bool storehkl=false, const bool storePredictedHKL=false); /** Algorithm class to find the correct indexing from observed peak positions. * */ class CellExplorer:public RefinableObj { public: CellExplorer(const PeakList &dhkl, const CrystalSystem lattice, const unsigned int nbSpurious); void Evolution(unsigned int ng,const bool randomize=true,const float f=0.7,const float cr=0.5,unsigned int np=100); void SetLengthMinMax(const float min,const float max); void SetAngleMinMax(const float min,const float max); void SetVolumeMinMax(const float min,const float max); void SetNbSpurious(const unsigned int nb); /// Allowed error on 1/d (squared!), used for dicvol void SetD2Error(const float err); void SetMinMaxZeroShift(const float min,const float max); void SetCrystalSystem(const CrystalSystem system); void SetCrystalCentering(const CrystalCentering cent); virtual const string& GetClassName() const; virtual const string& GetName() const; virtual void Print() const; virtual unsigned int GetNbLSQFunction() const; virtual const CrystVector_REAL& GetLSQCalc(const unsigned int) const; virtual const CrystVector_REAL & GetLSQObs(const unsigned int) const; virtual const CrystVector_REAL & GetLSQWeight(const unsigned int) const; virtual const CrystVector_REAL & GetLSQDeriv(const unsigned int, RefinablePar &); virtual void BeginOptimization(const bool allowApproximations=false, const bool enableRestraints=false); void LSQRefine(int nbCycle=1, bool useLevenbergMarquardt=true, const bool silent=false); /// Run DicVOl algorithm, store only solutions with score >minScore or depth>=minDepth, /// stop at the end of one volume interval (~400 A^3) if best score>stopOnScore, /// or if one solution was found at depth>=stopOnDepth /// /// If stopOnDepth==0, do not stop for any depth void DicVol(const float minScore=10,const unsigned int minDepth=3,const float stopOnScore=50.0,const unsigned int stopOnDepth=6); /** Sort all solutions by score, remove duplicates * * \param updateReportThreshold: if true, when too many solutions are produced, * the threshold above which solutions are reported will be updated to get less solutions. */ void ReduceSolutions(const bool updateReportThreshold=false); float GetBestScore()const; const std::list >& GetSolutions()const; std::list >& GetSolutions(); private: unsigned int RDicVol(RecUnitCell uc0, RecUnitCell uc1, unsigned int depth,unsigned long &nbCalc,const float minV,const float maxV,vector vdepth=vector()); void Init(); /// Max number of obs reflections to use std::list > mvSolution; unsigned int mnpar; const PeakList *mpPeakList; float mLengthMin,mLengthMax; float mAngleMin,mAngleMax; float mVolumeMin,mVolumeMax; float mZeroShiftMin,mZeroShiftMax; /// Min values for all parameters (7=unit cell +zero) float mMin[7]; /// Max amplitude (max=min+amplitude) for all parameters /// All parameters are treated as periodic for DE (??) float mAmp[7]; /// Lattice type for which we search CrystalSystem mlattice; /// Centering type CrystalCentering mCentering; unsigned int mNbSpurious; float mD2Error; LSQNumObj mLSQObj; mutable CrystVector_REAL mObs; mutable CrystVector_REAL mCalc; mutable CrystVector_REAL mWeight; mutable CrystVector_REAL mDeriv; /// Reciprocal unit cell used for least squares refinement RecUnitCell mRecUnitCell; /// Current best score float mBestScore; /// Number of solutions found during dicvol search, at each depth. std::vector mvNbSolutionDepth; float mMinScoreReport; unsigned int mMaxDicVolDepth,mDicVolDepthReport; /// Stored value of cos(max ang) for tricilinic search - we do /// not want to recompute the cos at every dicvol iteration mutable float mCosAngMax; /// Number of exceptions caught during LSQ, in a given search - above 20 LSQ is disabled unsigned int mNbLSQExcept; }; }//namespace #endif objcryst-2022.1/ObjCryst/ObjCryst/Molecule.cpp000066400000000000000000011541251430515525000212170ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2009 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Molecule.cpp * Source file for the Molecule scatterer * */ #include #include #include #include #include #include #include #include "ObjCryst/Quirks/VFNStreamFormat.h" #include "ObjCryst/ObjCryst/Molecule.h" #include "ObjCryst/ObjCryst/ZScatterer.h" #include "ObjCryst/RefinableObj/GlobalOptimObj.h" #ifdef OBJCRYST_GL #ifdef __DARWIN__ #include #else #include #endif #endif #ifdef __WX__CRYST__ #include "ObjCryst/wxCryst/wxMolecule.h" #endif //#include // Try new approach for rigid bodies ? #define RIGID_BODY_STRICT_EXPERIMENTAL // Tighter restraints x**2+x**4+x**6 instead of just X**2 #undef RESTRAINT_X2_X4_X6 using namespace std; namespace ObjCryst { XYZ::XYZ(REAL x0,REAL y0,REAL z0):x(x0),y(y0),z(z0){}; REAL GetBondLength(const MolAtom&at1,const MolAtom&at2) { //TAU_PROFILE("GetBondLength()","REAL (...)",TAU_DEFAULT); /* __m128 m128=_mm_set_ps(0.0f, at1.GetZ()-at2.GetZ(), at1.GetY()-at2.GetY(), at1.GetX()-at2.GetX()); __m128 a = _mm_mul_ps(m128,m128); // horizontal add __m128 b = _mm_add_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0,0,0,0)), _mm_add_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(1,1,1,1)), _mm_shuffle_ps(a, a, _MM_SHUFFLE(2,2,2,2)))); union m128_float { __m128 m128; struct { float x, y, z, pad; }; }; union m128_float l; l.m128 = _mm_sqrt_ss(b); return l.x; */ return sqrt( (at1.GetX()-at2.GetX()) *(at1.GetX()-at2.GetX()) +(at1.GetY()-at2.GetY()) *(at1.GetY()-at2.GetY()) +(at1.GetZ()-at2.GetZ()) *(at1.GetZ()-at2.GetZ()) ); } REAL GetBondAngle(const MolAtom &at1,const MolAtom &at2,const MolAtom &at3) { //TAU_PROFILE("GetBondAngle()","REAL (...)",TAU_DEFAULT); const REAL x21=at1.GetX()-at2.GetX(); const REAL y21=at1.GetY()-at2.GetY(); const REAL z21=at1.GetZ()-at2.GetZ(); const REAL x23=at3.GetX()-at2.GetX(); const REAL y23=at3.GetY()-at2.GetY(); const REAL z23=at3.GetZ()-at2.GetZ(); const REAL norm21_norm23= sqrt( (x21*x21+y21*y21+z21*z21) *(x23*x23+y23*y23+z23*z23)+1e-6); const REAL angle=(x21*x23+y21*y23+z21*z23)/norm21_norm23; if(angle>=1) return 0; if(angle<=-1) return M_PI; return acos(angle); } REAL GetDihedralAngle(const MolAtom &at1,const MolAtom &at2,const MolAtom &at3,const MolAtom &at4) { //TAU_PROFILE("GetDihedralAngle()","REAL (...)",TAU_DEFAULT); const REAL x21=at1.GetX()-at2.GetX(); const REAL y21=at1.GetY()-at2.GetY(); const REAL z21=at1.GetZ()-at2.GetZ(); const REAL x34=at4.GetX()-at3.GetX(); const REAL y34=at4.GetY()-at3.GetY(); const REAL z34=at4.GetZ()-at3.GetZ(); const REAL x23=at3.GetX()-at2.GetX(); const REAL y23=at3.GetY()-at2.GetY(); const REAL z23=at3.GetZ()-at2.GetZ(); // v21 x v23 const REAL x123= y21*z23-z21*y23; const REAL y123= z21*x23-x21*z23; const REAL z123= x21*y23-y21*x23; // v32 x v34 (= -v23 x v34) const REAL x234= -(y23*z34-z23*y34); const REAL y234= -(z23*x34-x23*z34); const REAL z234= -(x23*y34-y23*x34); const REAL norm123_norm234= sqrt( (x123*x123+y123*y123+z123*z123) *(x234*x234+y234*y234+z234*z234)+1e-6); REAL angle=(x123*x234+y123*y234+z123*z234)/norm123_norm234; if(angle>= 1) angle=0; else { if(angle<=-1) angle=M_PI; else angle=acos(angle); } if((x21*x234 + y21*y234 + z21*z234)<0) return -angle; return angle; } void ExpandAtomGroupRecursive(MolAtom* atom, const map > &connect, set &atomlist,const MolAtom* finalAtom) { const pair::iterator,bool> status=atomlist.insert(atom); if(false==status.second) return; if(finalAtom==atom) return; map >::const_iterator c=connect.find(atom); set::const_iterator pos; for(pos=c->second.begin();pos!=c->second.end();++pos) { ExpandAtomGroupRecursive(*pos,connect,atomlist,finalAtom); } } void ExpandAtomGroupRecursive(MolAtom* atom, const map > &connect, map &atomlist,const unsigned long maxdepth,unsigned long depth) { if(atomlist.count(atom)>0) if(atomlist[atom]<=depth) return; atomlist[atom]=depth; if(depth==maxdepth) return;//maxdepth reached map >::const_iterator c=connect.find(atom); set::const_iterator pos; for(pos=c->second.begin();pos!=c->second.end();++pos) { ExpandAtomGroupRecursive(*pos,connect,atomlist,maxdepth,depth+1); } } //###################################################################### // // MolAtom // //###################################################################### MolAtom::MolAtom(const REAL x, const REAL y, const REAL z, const ScatteringPower *pPow, const string &name, Molecule &parent): mName(name),mX(x),mY(y),mZ(z),mOccupancy(1.),mpScattPow(pPow),mpMol(&parent),mIsInRing(false),mIsNonFlipAtom(false) #ifdef __WX__CRYST__ ,mpWXCrystObj(0) #endif { VFN_DEBUG_MESSAGE("MolAtom::MolAtom()",4) } MolAtom::~MolAtom() { #ifdef __WX__CRYST__ this->WXDelete(); #endif } void MolAtom::SetName(const string &name) { mName=name; // Set parameter's name in the parent molecule // The atom should already be part of a Molecule, but just in case be careful if((mName!="") && (mpMol!=0)) { try { mpMol->GetPar(&mX).SetName(mpMol->GetName()+"_"+mName+"_x"); mpMol->GetPar(&mY).SetName(mpMol->GetName()+"_"+mName+"_y"); mpMol->GetPar(&mZ).SetName(mpMol->GetName()+"_"+mName+"_z"); } catch(const ObjCrystException &except) { cerr<<"MolAtom::SetName(): Atom parameters not yet declared in a Molecule ?"<GetAtomPositionClock().Click();} void MolAtom::SetY(const REAL a)const{ mY=a;mpMol->GetAtomPositionClock().Click();} void MolAtom::SetZ(const REAL a)const{ mZ=a;mpMol->GetAtomPositionClock().Click();} void MolAtom::SetOccupancy(const REAL a){ mOccupancy=a;} bool MolAtom::IsDummy()const{return mpScattPow==0;} const ScatteringPower& MolAtom::GetScatteringPower()const{return *mpScattPow;} void MolAtom::SetScatteringPower(const ScatteringPower& pow) { if(mpScattPow!=&pow) { mpScattPow=&pow; this->GetMolecule().GetAtomScattPowClock().Click(); } } void MolAtom::XMLOutput(ostream &os,int indent)const { VFN_DEBUG_ENTRY("MolAtom::XMLOutput()",4) for(int i=0;iGetName()); if(!this->IsDummy())tag.AddAttribute("ScattPow",this->GetScatteringPower().GetName()); { stringstream ss; ss.precision(os.precision()); ss <GetCrystal().GetScatteringPower(tag.GetAttributeValue(i))); } if("x"==tag.GetAttributeName(i)) { stringstream ss(tag.GetAttributeValue(i)); ss >>mX; } if("y"==tag.GetAttributeName(i)) { stringstream ss(tag.GetAttributeValue(i)); ss >>mY; } if("z"==tag.GetAttributeName(i)) { stringstream ss(tag.GetAttributeValue(i)); ss >>mZ; } if("Occup"==tag.GetAttributeName(i)) { stringstream ss(tag.GetAttributeValue(i)); ss >>mOccupancy; } if("NonFlip"==tag.GetAttributeName(i)) { stringstream ss(tag.GetAttributeValue(i)); ss >>mIsNonFlipAtom; } } this->SetName(name); VFN_DEBUG_EXIT("MolAtom::XMLInput()",7) } void MolAtom::SetIsInRing(const bool r)const{mIsInRing=r;} bool MolAtom::IsInRing()const{return mIsInRing;} void MolAtom::SetNonFlipAtom(const bool nonflip) { // :KLUDGE: should be using a specific clock ? if(mIsNonFlipAtom != nonflip) this->GetMolecule().GetRigidGroupClock().Click(); mIsNonFlipAtom = nonflip; } bool MolAtom::IsNonFlipAtom() const { return mIsNonFlipAtom; } size_t MolAtom::int_ptr() const {return (size_t)this;} #ifdef __WX__CRYST__ WXCrystObjBasic* MolAtom::WXCreate(wxWindow* parent) { VFN_DEBUG_ENTRY("MolAtom::WXCreate()",5) mpWXCrystObj=new WXMolAtom(parent,this); VFN_DEBUG_EXIT("MolAtom::WXCreate()",5) return mpWXCrystObj; } WXCrystObjBasic* MolAtom::WXGet(){return mpWXCrystObj;} void MolAtom::WXDelete(){if(0!=mpWXCrystObj) delete mpWXCrystObj;mpWXCrystObj=0;} void MolAtom::WXNotifyDelete(){mpWXCrystObj=0;} #endif //###################################################################### // // MolBond // //###################################################################### MolBond::MolBond(MolAtom &atom1, MolAtom &atom2, const REAL length0, const REAL sigma, const REAL delta, Molecule &parent,const REAL bondOrder): mAtomPair(make_pair(&atom1,&atom2)), mLength0(length0),mDelta(delta),mSigma(sigma), mBondOrder(bondOrder),mIsFreeTorsion(false),mpMol(&parent) #ifdef __WX__CRYST__ ,mpWXCrystObj(0) #endif {} MolBond::~MolBond() { #ifdef __WX__CRYST__ this->WXDelete(); #endif } const Molecule& MolBond::GetMolecule()const{return *mpMol;} Molecule& MolBond::GetMolecule() {return *mpMol;} string MolBond::GetName()const {return this->GetAtom1().GetName()+"-"+this->GetAtom2().GetName();} void MolBond::XMLOutput(ostream &os,int indent)const { VFN_DEBUG_ENTRY("MolBond::XMLOutput()",4) for(int i=0;iGetName()); tag.AddAttribute("Atom2",mAtomPair.second->GetName()); { stringstream ss; ss.precision(os.precision()); ss <GetAtom(tag.GetAttributeValue(i))); } if("Atom2"==tag.GetAttributeName(i)) { mAtomPair.second=&(mpMol->GetAtom(tag.GetAttributeValue(i))); } if("Length"==tag.GetAttributeName(i)) { stringstream ss(tag.GetAttributeValue(i)); ss >>mLength0; } if("Delta"==tag.GetAttributeName(i)) { stringstream ss(tag.GetAttributeValue(i)); ss >>mDelta; } if("Sigma"==tag.GetAttributeName(i)) { stringstream ss(tag.GetAttributeValue(i)); ss >>mSigma; } if("BondOrder"==tag.GetAttributeName(i)) { stringstream ss(tag.GetAttributeValue(i)); ss >>mBondOrder; } if("FreeTorsion"==tag.GetAttributeName(i)) { stringstream ss(tag.GetAttributeValue(i)); ss >>mIsFreeTorsion; } } VFN_DEBUG_EXIT("MolBond::XMLInput():",7) } REAL MolBond::GetLogLikelihood()const{return this->GetLogLikelihood(false,true);} REAL MolBond::GetLogLikelihood(const bool calcDeriv, const bool recalc)const { if(!recalc) return mLLK; VFN_DEBUG_ENTRY("MolBond::GetLogLikelihood():",2) //TAU_PROFILE("MolBond::GetLogLikelihood()","REAL (bool,bool)",TAU_DEFAULT); //const REAL length=this->GetLength(); const REAL x=this->GetAtom2().GetX()-this->GetAtom1().GetX(); const REAL y=this->GetAtom2().GetY()-this->GetAtom1().GetY(); const REAL z=this->GetAtom2().GetZ()-this->GetAtom1().GetZ(); const REAL length=sqrt(abs(x*x+y*y+z*z)); if(calcDeriv) { const REAL tmp2=1/(length+1e-10); mDerivAtom1.x=-x*tmp2; mDerivAtom1.y=-y*tmp2; mDerivAtom1.z=-z*tmp2; mDerivAtom2.x=-mDerivAtom1.x; mDerivAtom2.y=-mDerivAtom1.y; mDerivAtom2.z=-mDerivAtom1.z; } if(mSigma<1e-6) { if(calcDeriv) mDerivLLKCoeff=0; mLLK=0; return 0; } mLLK=length-(mLength0+mDelta); if(mLLK>0) { mLLK /= mSigma; if(calcDeriv) mDerivLLKCoeff=2*mLLK/mSigma; #ifdef RESTRAINT_X2_X4_X6 const float mLLK2=mLLK*mLLK; //if(calcDeriv) mDerivLLKCoeff=(2*mLLK+4*mLLK2+6*mLLK2*mLLK2)/mSigma; //mLLK=mLLK2*(1+mLLK2+mLLK2*mLLK2); if(calcDeriv) mDerivLLKCoeff=(2*mLLK+4*mLLK2)/mSigma; mLLK=mLLK2*(1+mLLK2); #else if(calcDeriv) mDerivLLKCoeff=2*mLLK/mSigma; mLLK *= mLLK; #endif VFN_DEBUG_EXIT("MolBond::GetLogLikelihood():",2) return mLLK; } mLLK=length-(mLength0-mDelta); if(mLLK<0) { mLLK /= mSigma; #ifdef RESTRAINT_X2_X4_X6 const float mLLK2=mLLK*mLLK; //if(calcDeriv) mDerivLLKCoeff=(2*mLLK+4*mLLK2+6*mLLK2*mLLK2)/mSigma; //mLLK=mLLK2*(1+mLLK2+mLLK2*mLLK2); if(calcDeriv) mDerivLLKCoeff=(2*mLLK+4*mLLK2)/mSigma; mLLK=mLLK2*(1+mLLK2); #else if(calcDeriv) mDerivLLKCoeff=2*mLLK/mSigma; mLLK *= mLLK; #endif VFN_DEBUG_EXIT("MolBond::GetLogLikelihood():",2) return mLLK; } if(calcDeriv) mDerivLLKCoeff=0; mLLK=0; VFN_DEBUG_EXIT("MolBond::GetLogLikelihood():",2) return mLLK; } REAL MolBond::GetDeriv(const map &m, const bool llk)const { //TAU_PROFILE("MolBond::GetDeriv()","REAL (mak,bool)",TAU_DEFAULT); REAL d=0; map::const_iterator pos; pos=m.find(mAtomPair.first); if(pos!=m.end()) d+= pos->second.x*mDerivAtom1.x +pos->second.y*mDerivAtom1.y +pos->second.z*mDerivAtom1.z; pos=m.find(mAtomPair.second); if(pos!=m.end()) d+= pos->second.x*mDerivAtom2.x +pos->second.y*mDerivAtom2.y +pos->second.z*mDerivAtom2.z; if(llk) return mDerivLLKCoeff*d; return d; } void MolBond::CalcGradient(std::map &m)const { this->GetLogLikelihood(true,true); map::iterator pos; pos=m.find(mAtomPair.first); if(pos!=m.end()) { pos->second.x+=mDerivLLKCoeff*mDerivAtom1.x; pos->second.y+=mDerivLLKCoeff*mDerivAtom1.y; pos->second.z+=mDerivLLKCoeff*mDerivAtom1.z; } pos=m.find(mAtomPair.second); if(pos!=m.end()) { pos->second.x+=mDerivLLKCoeff*mDerivAtom2.x; pos->second.y+=mDerivLLKCoeff*mDerivAtom2.y; pos->second.z+=mDerivLLKCoeff*mDerivAtom2.z; } #if 0 // Display gradient - for tests cout<GetName()<<" :LLK"<::const_iterator pos=m.begin();pos!=m.end();++pos) { char buf[100]; sprintf(buf,"%10s Grad LLK= (%8.3f %8.3f %8.3f)", pos->first->GetName().c_str(),pos->second.x,pos->second.y,pos->second.z); cout<GetAtom2()); } REAL MolBond::GetLength0()const{return mLength0;} REAL MolBond::GetLengthDelta()const{return mDelta;} REAL MolBond::GetLengthSigma()const{return mSigma;} REAL MolBond::GetBondOrder()const{return mBondOrder;} REAL& MolBond::Length0(){return mLength0;} REAL& MolBond::LengthDelta(){return mDelta;} REAL& MolBond::LengthSigma(){return mSigma;} REAL& MolBond::BondOrder(){return mBondOrder;} void MolBond::SetLength0(const REAL a){mLength0=a;} void MolBond::SetLengthDelta(const REAL a){mDelta=a;} void MolBond::SetLengthSigma(const REAL a){mSigma=a;} void MolBond::SetBondOrder(const REAL a){mBondOrder=a;} bool MolBond::IsFreeTorsion()const{return mIsFreeTorsion;} void MolBond::SetFreeTorsion(const bool isFreeTorsion) { if(mIsFreeTorsion==isFreeTorsion) return; mIsFreeTorsion=isFreeTorsion; mpMol->GetBondListClock().Click(); } size_t MolBond::int_ptr() const {return (size_t)this;} #ifdef __WX__CRYST__ WXCrystObjBasic* MolBond::WXCreate(wxWindow* parent) { VFN_DEBUG_ENTRY("MolBond::WXCreate()",5) mpWXCrystObj=new WXMolBond(parent,this); VFN_DEBUG_EXIT("MolBond::WXCreate()",5) return mpWXCrystObj; } WXCrystObjBasic* MolBond::WXGet(){return mpWXCrystObj;} void MolBond::WXDelete(){if(0!=mpWXCrystObj) delete mpWXCrystObj;mpWXCrystObj=0;} void MolBond::WXNotifyDelete(){mpWXCrystObj=0;} #endif //###################################################################### // // MolBondAngle // //###################################################################### MolBondAngle::MolBondAngle(MolAtom &atom1,MolAtom &atom2,MolAtom &atom3, const REAL angle, const REAL sigma, const REAL delta, Molecule &parent): mAngle0(angle),mDelta(delta),mSigma(sigma),mpMol(&parent) #ifdef __WX__CRYST__ ,mpWXCrystObj(0) #endif { mvpAtom.push_back(&atom1); mvpAtom.push_back(&atom2); mvpAtom.push_back(&atom3); } MolBondAngle::~MolBondAngle() { #ifdef __WX__CRYST__ this->WXDelete(); #endif } const Molecule& MolBondAngle::GetMolecule()const{return *mpMol;} Molecule& MolBondAngle::GetMolecule() {return *mpMol;} string MolBondAngle::GetName()const { return this->GetAtom1().GetName()+"-" +this->GetAtom2().GetName()+"-" +this->GetAtom3().GetName(); } void MolBondAngle::XMLOutput(ostream &os,int indent)const { VFN_DEBUG_ENTRY("MolBondAngle::XMLOutput()",4) for(int i=0;iGetAtom1().GetName()); tag.AddAttribute("Atom2",this->GetAtom2().GetName()); tag.AddAttribute("Atom3",this->GetAtom3().GetName()); { stringstream ss; ss.precision(os.precision()); ss <GetAtom(tag.GetAttributeValue(i))); } if("Atom2"==tag.GetAttributeName(i)) { mvpAtom[1]=&(mpMol->GetAtom(tag.GetAttributeValue(i))); } if("Atom3"==tag.GetAttributeName(i)) { mvpAtom[2]=&(mpMol->GetAtom(tag.GetAttributeValue(i))); } if("Angle"==tag.GetAttributeName(i)) { stringstream ss(tag.GetAttributeValue(i)); ss >>mAngle0; mAngle0*=DEG2RAD; } if("Delta"==tag.GetAttributeName(i)) { stringstream ss(tag.GetAttributeValue(i)); ss >>mDelta; mDelta*=DEG2RAD; } if("Sigma"==tag.GetAttributeName(i)) { stringstream ss(tag.GetAttributeValue(i)); ss >>mSigma; mSigma*=DEG2RAD; } } VFN_DEBUG_EXIT("MolBondAngle::XMLInput():",4) } REAL& MolBondAngle::Angle0() { return mAngle0; } REAL& MolBondAngle::AngleDelta(){return mDelta;} REAL& MolBondAngle::AngleSigma(){return mSigma;} REAL MolBondAngle::GetAngle0()const{return mAngle0;} REAL MolBondAngle::GetAngleDelta()const{return mDelta;} REAL MolBondAngle::GetAngleSigma()const{return mSigma;} void MolBondAngle::SetAngle0(const REAL angle){mAngle0=angle;} void MolBondAngle::SetAngleDelta(const REAL delta){mDelta=delta;} void MolBondAngle::SetAngleSigma(const REAL sigma){mSigma=sigma;} REAL MolBondAngle::GetAngle()const { return GetBondAngle(this->GetAtom1(),this->GetAtom2(),this->GetAtom3()); } REAL MolBondAngle::GetLogLikelihood()const{return this->GetLogLikelihood(false,true);} REAL MolBondAngle::GetLogLikelihood(const bool calcDeriv, const bool recalc)const { if(!recalc) return mLLK; VFN_DEBUG_ENTRY("MolBondAngle::GetLogLikelihood():",2) //TAU_PROFILE("MolBondAngle::GetLogLikelihood()","REAL (bool,bool)",TAU_DEFAULT); //const REAL angle=this->GetAngle(); const REAL x21=this->GetAtom1().GetX()-this->GetAtom2().GetX(); const REAL y21=this->GetAtom1().GetY()-this->GetAtom2().GetY(); const REAL z21=this->GetAtom1().GetZ()-this->GetAtom2().GetZ(); const REAL x23=this->GetAtom3().GetX()-this->GetAtom2().GetX(); const REAL y23=this->GetAtom3().GetY()-this->GetAtom2().GetY(); const REAL z23=this->GetAtom3().GetZ()-this->GetAtom2().GetZ(); const REAL n1=sqrt(abs(x21*x21+y21*y21+z21*z21)); const REAL n3=sqrt(abs(x23*x23+y23*y23+z23*z23)); const REAL p=x21*x23+y21*y23+z21*z23; const REAL a0=p/(n1*n3+1e-10); REAL angle; if(a0>=1) angle=0; else { if(a0<=-1) angle=M_PI; else angle=acos(a0); } if(calcDeriv) { const REAL s=1/(sqrt(1-a0*a0+1e-6)); const REAL s0=-s/(n1*n3+1e-10); const REAL s1= s*p/(n3*n1*n1*n1+1e-10); const REAL s3= s*p/(n1*n3*n3*n3+1e-10); mDerivAtom1.x=s0*x23+s1*x21; mDerivAtom1.y=s0*y23+s1*y21; mDerivAtom1.z=s0*z23+s1*z21; mDerivAtom3.x=s0*x21+s3*x23; mDerivAtom3.y=s0*y21+s3*y23; mDerivAtom3.z=s0*z21+s3*z23; mDerivAtom2.x=-(mDerivAtom1.x+mDerivAtom3.x); mDerivAtom2.y=-(mDerivAtom1.y+mDerivAtom3.y); mDerivAtom2.z=-(mDerivAtom1.z+mDerivAtom3.z); } if(mSigma<1e-6) { if(calcDeriv) mDerivLLKCoeff=0; mLLK=0; return 0; } mLLK=angle-(mAngle0+mDelta); if(mLLK>0) { mLLK/=mSigma; #ifdef RESTRAINT_X2_X4_X6 const float mLLK2=mLLK*mLLK; //if(calcDeriv) mDerivLLKCoeff=(2*mLLK+4*mLLK2+6*mLLK2*mLLK2)/mSigma; //mLLK=mLLK2*(1+mLLK2+mLLK2*mLLK2); if(calcDeriv) mDerivLLKCoeff=(2*mLLK+4*mLLK2)/mSigma; mLLK=mLLK2*(1+mLLK2); #else if(calcDeriv) mDerivLLKCoeff=2*mLLK/mSigma; mLLK *= mLLK; #endif VFN_DEBUG_EXIT("MolBondAngle::GetLogLikelihood():",2) return mLLK; } mLLK=angle-(mAngle0-mDelta); if(mLLK<0) { mLLK/=mSigma; #ifdef RESTRAINT_X2_X4_X6 const float mLLK2=mLLK*mLLK; //if(calcDeriv) mDerivLLKCoeff=(2*mLLK+4*mLLK2+6*mLLK2*mLLK2)/mSigma; //mLLK=mLLK2*(1+mLLK2+mLLK2*mLLK2); if(calcDeriv) mDerivLLKCoeff=(2*mLLK+4*mLLK2)/mSigma; mLLK=mLLK2*(1+mLLK2); #else if(calcDeriv) mDerivLLKCoeff=2*mLLK/mSigma; mLLK *= mLLK; #endif VFN_DEBUG_EXIT("MolBondAngle::GetLogLikelihood():",2) return mLLK; } VFN_DEBUG_EXIT("MolBondAngle::GetLogLikelihood():",2) if(calcDeriv) mDerivLLKCoeff=0; mLLK=0; return mLLK; } REAL MolBondAngle::GetDeriv(const std::map &m,const bool llk)const { //TAU_PROFILE("MolBondAngle::GetDeriv()","REAL (mak,bool)",TAU_DEFAULT); REAL d=0; map::const_iterator pos; pos=m.find(mvpAtom[0]); if(pos!=m.end()) d+= pos->second.x*mDerivAtom1.x +pos->second.y*mDerivAtom1.y +pos->second.z*mDerivAtom1.z; pos=m.find(mvpAtom[1]); if(pos!=m.end()) d+= pos->second.x*mDerivAtom2.x +pos->second.y*mDerivAtom2.y +pos->second.z*mDerivAtom2.z; pos=m.find(mvpAtom[2]); if(pos!=m.end()) d+= pos->second.x*mDerivAtom3.x +pos->second.y*mDerivAtom3.y +pos->second.z*mDerivAtom3.z; if(llk) return mDerivLLKCoeff*d; return d; } void MolBondAngle::CalcGradient(std::map &m)const { this->GetLogLikelihood(true,true); map::iterator pos; pos=m.find(mvpAtom[0]); if(pos!=m.end()) { pos->second.x+=mDerivLLKCoeff*mDerivAtom1.x; pos->second.y+=mDerivLLKCoeff*mDerivAtom1.y; pos->second.z+=mDerivLLKCoeff*mDerivAtom1.z; } pos=m.find(mvpAtom[1]); if(pos!=m.end()) { pos->second.x+=mDerivLLKCoeff*mDerivAtom2.x; pos->second.y+=mDerivLLKCoeff*mDerivAtom2.y; pos->second.z+=mDerivLLKCoeff*mDerivAtom2.z; } pos=m.find(mvpAtom[2]); if(pos!=m.end()) { pos->second.x+=mDerivLLKCoeff*mDerivAtom3.x; pos->second.y+=mDerivLLKCoeff*mDerivAtom3.y; pos->second.z+=mDerivLLKCoeff*mDerivAtom3.z; } #if 0 // Display gradient - for tests cout<GetName()<<" :LLK"<::const_iterator pos=m.begin();pos!=m.end();++pos) { char buf[100]; sprintf(buf,"%10s Grad LLK= (%8.3f %8.3f %8.3f)", pos->first->GetName().c_str(),pos->second.x,pos->second.y,pos->second.z); cout<::const_iterator MolBondAngle::begin() const {return mvpAtom.begin();} vector::const_iterator MolBondAngle::end() const {return mvpAtom.end();} size_t MolBondAngle::int_ptr() const {return (size_t)this;} #ifdef __WX__CRYST__ WXCrystObjBasic* MolBondAngle::WXCreate(wxWindow* parent) { VFN_DEBUG_ENTRY("MolBondAngle::WXCreate()",5) mpWXCrystObj=new WXMolBondAngle(parent,this); VFN_DEBUG_EXIT("MolBondAngle::WXCreate()",5) return mpWXCrystObj; } WXCrystObjBasic* MolBondAngle::WXGet(){return mpWXCrystObj;} void MolBondAngle::WXDelete(){if(0!=mpWXCrystObj) delete mpWXCrystObj;mpWXCrystObj=0;} void MolBondAngle::WXNotifyDelete(){mpWXCrystObj=0;} #endif //###################################################################### // // MolDihedralAngle // //###################################################################### MolDihedralAngle::MolDihedralAngle(MolAtom &atom1, MolAtom &atom2, MolAtom &atom3, MolAtom &atom4, const REAL angle, const REAL sigma, const REAL delta, Molecule &parent): mAngle0(angle),mDelta(delta),mSigma(sigma),mpMol(&parent) #ifdef __WX__CRYST__ ,mpWXCrystObj(0) #endif { VFN_DEBUG_ENTRY("MolDihedralAngle::MolDihedralAngle()",5) mvpAtom.push_back(&atom1); mvpAtom.push_back(&atom2); mvpAtom.push_back(&atom3); mvpAtom.push_back(&atom4); // We want the angle in [-pi;pi] mAngle0=fmod((REAL)mAngle0,(REAL)(2*M_PI)); if(mAngle0<(-M_PI)) mAngle0+=2*M_PI; if(mAngle0>M_PI) mAngle0-=2*M_PI; VFN_DEBUG_EXIT("MolDihedralAngle::MolDihedralAngle()",5) } MolDihedralAngle::~MolDihedralAngle() { #ifdef __WX__CRYST__ this->WXDelete(); #endif } const Molecule& MolDihedralAngle::GetMolecule()const{return *mpMol;} Molecule& MolDihedralAngle::GetMolecule() {return *mpMol;} string MolDihedralAngle::GetName()const { return this->GetAtom1().GetName()+"-" +this->GetAtom2().GetName()+"-" +this->GetAtom3().GetName()+"-" +this->GetAtom4().GetName(); } void MolDihedralAngle::XMLOutput(ostream &os,int indent)const { VFN_DEBUG_ENTRY("MolDihedralAngle::XMLOutput()",4) for(int i=0;iGetAtom1().GetName()); tag.AddAttribute("Atom2",this->GetAtom2().GetName()); tag.AddAttribute("Atom3",this->GetAtom3().GetName()); tag.AddAttribute("Atom4",this->GetAtom4().GetName()); { stringstream ss; ss.precision(os.precision()); ss <GetAtom(tag.GetAttributeValue(i))); } if("Atom2"==tag.GetAttributeName(i)) { mvpAtom[1]=&(mpMol->GetAtom(tag.GetAttributeValue(i))); } if("Atom3"==tag.GetAttributeName(i)) { mvpAtom[2]=&(mpMol->GetAtom(tag.GetAttributeValue(i))); } if("Atom4"==tag.GetAttributeName(i)) { mvpAtom[3]=&(mpMol->GetAtom(tag.GetAttributeValue(i))); } if("Angle"==tag.GetAttributeName(i)) { stringstream ss(tag.GetAttributeValue(i)); ss >>mAngle0; mAngle0*=DEG2RAD; } if("Delta"==tag.GetAttributeName(i)) { stringstream ss(tag.GetAttributeValue(i)); ss >>mDelta; mDelta*=DEG2RAD; } if("Sigma"==tag.GetAttributeName(i)) { stringstream ss(tag.GetAttributeValue(i)); ss >>mSigma; mSigma*=DEG2RAD; } } VFN_DEBUG_EXIT("MolDihedralAngle::XMLInput():",5) } REAL MolDihedralAngle::GetAngle()const { //Get the angle [2pi] closest to the restraint const REAL angle=GetDihedralAngle(this->GetAtom1(),this->GetAtom2(),this->GetAtom3(),this->GetAtom4()); if((angle-mAngle0)>M_PI) return angle-2*M_PI; else if((angle-mAngle0)<(-M_PI)) return angle+2*M_PI; return angle; } REAL& MolDihedralAngle::Angle0(){return mAngle0;} REAL& MolDihedralAngle::AngleDelta(){return mDelta;} REAL& MolDihedralAngle::AngleSigma(){return mSigma;} REAL MolDihedralAngle::GetAngle0()const{return mAngle0;} REAL MolDihedralAngle::GetAngleDelta()const{return mDelta;} REAL MolDihedralAngle::GetAngleSigma()const{return mSigma;} void MolDihedralAngle::SetAngle0(const REAL angle){mAngle0=angle;} void MolDihedralAngle::SetAngleDelta(const REAL delta){mDelta=delta;} void MolDihedralAngle::SetAngleSigma(const REAL sigma){mSigma=sigma;} REAL MolDihedralAngle::GetLogLikelihood()const{return this->GetLogLikelihood(false,true);} REAL MolDihedralAngle::GetLogLikelihood(const bool calcDeriv, const bool recalc)const { if(!recalc) return mLLK; VFN_DEBUG_ENTRY("MolDihedralAngle::GetLogLikelihood():",2) //TAU_PROFILE("MolDihedralAngle::GetLogLikelihood()","REAL (bool,bool)",TAU_DEFAULT); const REAL x21=this->GetAtom1().GetX()-this->GetAtom2().GetX(); const REAL y21=this->GetAtom1().GetY()-this->GetAtom2().GetY(); const REAL z21=this->GetAtom1().GetZ()-this->GetAtom2().GetZ(); const REAL x34=this->GetAtom4().GetX()-this->GetAtom3().GetX(); const REAL y34=this->GetAtom4().GetY()-this->GetAtom3().GetY(); const REAL z34=this->GetAtom4().GetZ()-this->GetAtom3().GetZ(); const REAL x23=this->GetAtom3().GetX()-this->GetAtom2().GetX(); const REAL y23=this->GetAtom3().GetY()-this->GetAtom2().GetY(); const REAL z23=this->GetAtom3().GetZ()-this->GetAtom2().GetZ(); // v21 x v23 const REAL x123= y21*z23-z21*y23; const REAL y123= z21*x23-x21*z23; const REAL z123= x21*y23-y21*x23; // v32 x v34 (= -v23 x v34) const REAL x234= -(y23*z34-z23*y34); const REAL y234= -(z23*x34-x23*z34); const REAL z234= -(x23*y34-y23*x34); const REAL n123= sqrt(x123*x123+y123*y123+z123*z123+1e-7); const REAL n234= sqrt(x234*x234+y234*y234+z234*z234+1e-6); const REAL p=x123*x234+y123*y234+z123*z234; const REAL a0=p/(n123*n234+1e-10); REAL angle; if(a0>= 1) angle=0; else { if(a0<=-1) angle=M_PI; else angle=acos(a0); } REAL sgn=1.0; if((x21*x34 + y21*y34 + z21*z34)<0) {angle=-angle;sgn=-1;} if(calcDeriv) { const REAL s=sgn/(sqrt(1-a0*a0+1e-6)); const REAL s0=-s/(n123*n234+1e-10); const REAL s1= s*p/(n234*n123*n123*n123+1e-10); const REAL s3= s*p/(n123*n234*n234*n234+1e-10); mDerivAtom1.x=s0*(-z23*y234+y23*z234)+s1*(-z23*y123+y23*z123); mDerivAtom1.y=s0*(-x23*z234+z23*x234)+s1*(-x23*z123+z23*x123); mDerivAtom1.z=s0*(-y23*x234+x23*y234)+s1*(-y23*x123+x23*y123); mDerivAtom4.x=s0*(-z23*y123+y23*z123)+s3*(-z23*y234+y23*z234); mDerivAtom4.y=s0*(-x23*z123+z23*x123)+s3*(-x23*z234+z23*x234); mDerivAtom4.z=s0*(-y23*x123+x23*y123)+s3*(-y23*x234+x23*y234); mDerivAtom2.x=s0*((z23-z21)*y234-y123*z34+(y21-y23)*z234+z123*y34)+s1*(y123*(z23-z21)+z123*(y21-y23))+s3*(-y234*z34+z234*y34); mDerivAtom2.y=s0*((x23-x21)*z234-z123*x34+(z21-z23)*x234+x123*z34)+s1*(z123*(x23-x21)+x123*(z21-z23))+s3*(-z234*x34+x234*z34); mDerivAtom2.z=s0*((y23-y21)*x234-x123*y34+(x21-x23)*y234+y123*x34)+s1*(x123*(y23-y21)+y123*(x21-x23))+s3*(-x234*y34+y234*x34); mDerivAtom3.x=-(mDerivAtom1.x+mDerivAtom2.x+mDerivAtom4.x); mDerivAtom3.y=-(mDerivAtom1.y+mDerivAtom2.y+mDerivAtom4.y); mDerivAtom3.z=-(mDerivAtom1.z+mDerivAtom2.z+mDerivAtom4.z); } if(mSigma<1e-6) { if(calcDeriv) mDerivLLKCoeff=0; mLLK=0; return mLLK; } mLLK=angle-(mAngle0+mDelta); if(mLLK<(-M_PI)) mLLK += 2*M_PI; if(mLLK> M_PI ) mLLK -= 2*M_PI; if(mLLK>0) { mLLK/=mSigma; #ifdef RESTRAINT_X2_X4_X6 const float mLLK2=mLLK*mLLK; //if(calcDeriv) mDerivLLKCoeff=(2*mLLK+4*mLLK2+6*mLLK2*mLLK2)/mSigma; //mLLK=mLLK2*(1+mLLK2+mLLK2*mLLK2); if(calcDeriv) mDerivLLKCoeff=(2*mLLK+4*mLLK2)/mSigma; mLLK=mLLK2*(1+mLLK2); #else if(calcDeriv) mDerivLLKCoeff=2*mLLK/mSigma; mLLK *= mLLK; #endif VFN_DEBUG_EXIT("MolDihedralAngle::GetLogLikelihood():",2) return mLLK; } mLLK=angle-(mAngle0-mDelta); if(mLLK<(-M_PI)) mLLK += 2*M_PI; if(mLLK> M_PI ) mLLK -= 2*M_PI; if(mLLK<0) { mLLK/=mSigma; #ifdef RESTRAINT_X2_X4_X6 const float mLLK2=mLLK*mLLK; //if(calcDeriv) mDerivLLKCoeff=(2*mLLK+4*mLLK2+6*mLLK2*mLLK2)/mSigma; //mLLK=mLLK2*(1+mLLK2+mLLK2*mLLK2); if(calcDeriv) mDerivLLKCoeff=(2*mLLK+4*mLLK2)/mSigma; mLLK=mLLK2*(1+mLLK2); #else if(calcDeriv) mDerivLLKCoeff=2*mLLK/mSigma; mLLK *= mLLK; #endif VFN_DEBUG_EXIT("MolDihedralAngle::GetLogLikelihood():",2) return mLLK; } VFN_DEBUG_EXIT("MolDihedralAngle::GetLogLikelihood():",2) if(calcDeriv) mDerivLLKCoeff=0; mLLK=0; return 0; } REAL MolDihedralAngle::GetDeriv(const std::map &m,const bool llk)const { //TAU_PROFILE("MolDihedralAngle::GetDeriv()","REAL (mak,bool)",TAU_DEFAULT); REAL d=0; map::const_iterator pos; pos=m.find(mvpAtom[0]); if(pos!=m.end()) d+= pos->second.x*mDerivAtom1.x +pos->second.y*mDerivAtom1.y +pos->second.z*mDerivAtom1.z; pos=m.find(mvpAtom[1]); if(pos!=m.end()) d+= pos->second.x*mDerivAtom2.x +pos->second.y*mDerivAtom2.y +pos->second.z*mDerivAtom2.z; pos=m.find(mvpAtom[2]); if(pos!=m.end()) d+= pos->second.x*mDerivAtom3.x +pos->second.y*mDerivAtom3.y +pos->second.z*mDerivAtom3.z; pos=m.find(mvpAtom[3]); if(pos!=m.end()) d+= pos->second.x*mDerivAtom4.x +pos->second.y*mDerivAtom4.y +pos->second.z*mDerivAtom4.z; if(llk) return mDerivLLKCoeff*d; return d; } void MolDihedralAngle::CalcGradient(std::map &m)const { this->GetLogLikelihood(true,true); map::iterator pos; pos=m.find(mvpAtom[0]); if(pos!=m.end()) { pos->second.x+=mDerivLLKCoeff*mDerivAtom1.x; pos->second.y+=mDerivLLKCoeff*mDerivAtom1.y; pos->second.z+=mDerivLLKCoeff*mDerivAtom1.z; } pos=m.find(mvpAtom[1]); if(pos!=m.end()) { pos->second.x+=mDerivLLKCoeff*mDerivAtom2.x; pos->second.y+=mDerivLLKCoeff*mDerivAtom2.y; pos->second.z+=mDerivLLKCoeff*mDerivAtom2.z; } pos=m.find(mvpAtom[2]); if(pos!=m.end()) { pos->second.x+=mDerivLLKCoeff*mDerivAtom3.x; pos->second.y+=mDerivLLKCoeff*mDerivAtom3.y; pos->second.z+=mDerivLLKCoeff*mDerivAtom3.z; } pos=m.find(mvpAtom[3]); if(pos!=m.end()) { pos->second.x+=mDerivLLKCoeff*mDerivAtom4.x; pos->second.y+=mDerivLLKCoeff*mDerivAtom4.y; pos->second.z+=mDerivLLKCoeff*mDerivAtom4.z; } #if 0 // Display gradient - for tests cout<GetName()<<" :LLK"<::const_iterator pos=m.begin();pos!=m.end();++pos) { char buf[100]; sprintf(buf,"%10s Grad LLK= (%8.3f %8.3f %8.3f)", pos->first->GetName().c_str(),pos->second.x,pos->second.y,pos->second.z); cout<::const_iterator MolDihedralAngle::begin() const {return mvpAtom.begin();} vector::const_iterator MolDihedralAngle::end() const {return mvpAtom.end();} size_t MolDihedralAngle::int_ptr() const {return (size_t)this;} #ifdef __WX__CRYST__ WXCrystObjBasic* MolDihedralAngle::WXCreate(wxWindow* parent) { VFN_DEBUG_ENTRY("MolDihedralAngle::WXCreate()",5) mpWXCrystObj=new WXMolDihedralAngle(parent,this); VFN_DEBUG_EXIT("MolDihedralAngle::WXCreate()",5) return mpWXCrystObj; } WXCrystObjBasic* MolDihedralAngle::WXGet(){return mpWXCrystObj;} void MolDihedralAngle::WXDelete(){if(0!=mpWXCrystObj) delete mpWXCrystObj;mpWXCrystObj=0;} void MolDihedralAngle::WXNotifyDelete(){mpWXCrystObj=0;} #endif //###################################################################### // // RigidGroup // //###################################################################### string RigidGroup::GetName()const { set::const_iterator at=this->begin(); string name=(*at++)->GetName(); for(;at!=this->end();++at) name+=", "+(*at)->GetName(); return name; } size_t RigidGroup::int_ptr() const {return (size_t)this;} //###################################################################### // // MolRing // //###################################################################### MolRing::MolRing() {} const std::list& MolRing::GetAtomList()const {return mvpAtom;} std::list& MolRing::GetAtomList() {return mvpAtom;} size_t MolRing::int_ptr() const {return (size_t)this;} //###################################################################### // // Quaternion // //###################################################################### Quaternion::Quaternion(): mQ0(1),mQ1(0),mQ2(0),mQ3(0),mIsUniQuaternion(true) { VFN_DEBUG_MESSAGE("Quaternion::Quaternion()",5) } Quaternion::Quaternion(const REAL q0, const REAL q1, const REAL q2, const REAL q3, bool unit): mQ0(q0),mQ1(q1),mQ2(q2),mQ3(q3),mIsUniQuaternion(unit) { VFN_DEBUG_MESSAGE("Quaternion::Quaternion()",5) if(unit) this->Normalize(); } Quaternion::~Quaternion() { VFN_DEBUG_MESSAGE("Quaternion::~Quaternion()",5) } Quaternion Quaternion::RotationQuaternion(const REAL ang, const REAL v1, const REAL v2, const REAL v3) { VFN_DEBUG_MESSAGE("Quaternion::RotationQuaternion()",4) const REAL s=sin(ang/2.)/sqrt(v1*v1+v2*v2+v3*v3+1e-7); return Quaternion(cos(ang/2.),s*v1,s*v2,s*v3, true); } Quaternion Quaternion::GetConjugate()const { return Quaternion(mQ0,-mQ1,-mQ2,-mQ3); } Quaternion Quaternion::operator*(const Quaternion &q)const { // http://www.cs.berkeley.edu/~laura/cs184/quat/quaternion.html return Quaternion (this->Q0()*q.Q0()-this->Q1()*q.Q1()-this->Q2()*q.Q2()-this->Q3()*q.Q3(), this->Q0()*q.Q1()+this->Q1()*q.Q0()+this->Q2()*q.Q3()-this->Q3()*q.Q2(), this->Q0()*q.Q2()-this->Q1()*q.Q3()+this->Q2()*q.Q0()+this->Q3()*q.Q1(), this->Q0()*q.Q3()+this->Q1()*q.Q2()-this->Q2()*q.Q1()+this->Q3()*q.Q0(),false); } void Quaternion::operator*=(const Quaternion &q) { //cout<<"Quaternion::operator*= before:";this->XMLOutput(cout); //cout<<"Quaternion::operator*= by :";q.XMLOutput(cout); const REAL q1=this->Q0()*q.Q1()+this->Q1()*q.Q0()+this->Q2()*q.Q3()-this->Q3()*q.Q2(); const REAL q2=this->Q0()*q.Q2()+this->Q2()*q.Q0()-this->Q1()*q.Q3()+this->Q3()*q.Q1(); const REAL q3=this->Q0()*q.Q3()+this->Q3()*q.Q0()+this->Q1()*q.Q2()-this->Q2()*q.Q1(); this->Q0()= this->Q0()*q.Q0()-this->Q1()*q.Q1()-this->Q2()*q.Q2()-this->Q3()*q.Q3(); this->Q1()=q1; this->Q2()=q2; this->Q3()=q3; this->Normalize(); //cout<<"Quaternion::operator*= after :";this->XMLOutput(cout); } void Quaternion::XMLOutput(ostream &os,int indent)const { VFN_DEBUG_ENTRY("Quaternion::XMLOutput()",4) for(int i=0;i>mQ0; } if("Q1"==tag.GetAttributeName(i)) { stringstream ss(tag.GetAttributeValue(i)); ss >>mQ1; } if("Q2"==tag.GetAttributeName(i)) { stringstream ss(tag.GetAttributeValue(i)); ss >>mQ2; } if("Q3"==tag.GetAttributeName(i)) { stringstream ss(tag.GetAttributeValue(i)); ss >>mQ3; } if("IsUnitQuaternion"==tag.GetAttributeName(i)) { stringstream ss(tag.GetAttributeValue(i)); ss >>mIsUniQuaternion; } } if(mIsUniQuaternion) this->Normalize(); VFN_DEBUG_EXIT("Quaternion::XMLInput()",5) } void Quaternion::RotateVector(REAL &v1,REAL &v2, REAL &v3)const { #if 0 //#error P should not be a _UNIT_ quaternion... Quaternion P(0,v1,v2,v3,false); //cout<<"RotQuat:(n="<GetNorm()<<")";this->XMLOutput(cout); //cout<<"before :(n="<GetConjugate(); //cout<<"rotated:(n="<Q0()*this->Q0() +this->Q1()*this->Q1() +this->Q2()*this->Q2() +this->Q3()*this->Q3()); mQ0 /= norm; mQ1 /= norm; mQ2 /= norm; mQ3 /= norm; } REAL Quaternion::GetNorm()const {return sqrt( this->Q0()*this->Q0() +this->Q1()*this->Q1() +this->Q2()*this->Q2() +this->Q3()*this->Q3());} const REAL& Quaternion::Q0()const{return mQ0;} const REAL& Quaternion::Q1()const{return mQ1;} const REAL& Quaternion::Q2()const{return mQ2;} const REAL& Quaternion::Q3()const{return mQ3;} REAL& Quaternion::Q0(){return mQ0;} REAL& Quaternion::Q1(){return mQ1;} REAL& Quaternion::Q2(){return mQ2;} REAL& Quaternion::Q3(){return mQ3;} //###################################################################### // // Molecule Stretch Modes // //###################################################################### StretchMode::~StretchMode(){} StretchModeBondLength::StretchModeBondLength(MolAtom &at0,MolAtom &at1, const MolBond *pBond): mpAtom0(&at0),mpAtom1(&at1),mpBond(pBond) { mBaseAmplitude=0.1; mpMol = &(at1.GetMolecule()); } StretchModeBondLength::~StretchModeBondLength(){} void StretchModeBondLength::CalcDeriv(const bool derivllk)const { //TAU_PROFILE("StretchModeBondLength::CalcDeriv()","void ()",TAU_DEFAULT); // Derivative of the atom positions //mDerivXYZ.clear(); REAL dx=mpAtom1->GetX()-mpAtom0->GetX(); REAL dy=mpAtom1->GetY()-mpAtom0->GetY(); REAL dz=mpAtom1->GetZ()-mpAtom0->GetZ(); const REAL n=sqrt(dx*dx+dy*dy+dz*dz+1e-7); if(n<1e-6) return;//:KLUDGE: ? dx/=n; dy/=n; dz/=n; for(set::const_iterator pos=mvTranslatedAtomList.begin(); pos!=mvTranslatedAtomList.end();++pos) { XYZ *const p=&(mDerivXYZ[*pos]); p->x=dx; p->y=dy; p->z=dz; } // Derivative of the LLK if(derivllk) { mLLKDeriv=0; for(map::const_iterator pos=this->mvpBrokenBond.begin(); pos!=this->mvpBrokenBond.end();++pos) mLLKDeriv += pos->first->GetDeriv(mDerivXYZ,true); for(map::const_iterator pos=this->mvpBrokenBondAngle.begin(); pos!=this->mvpBrokenBondAngle.end();++pos) mLLKDeriv += pos->first->GetDeriv(mDerivXYZ,true); for(map::const_iterator pos=this->mvpBrokenDihedralAngle.begin(); pos!=this->mvpBrokenDihedralAngle.end();++pos) mLLKDeriv += pos->first->GetDeriv(mDerivXYZ,true); } } void StretchModeBondLength::Print(ostream &os,bool full)const { cout<GetName()<<"-"<GetName(); if(full) { cout<<", Translated Atoms:"; for(set::const_iterator atom=mvTranslatedAtomList.begin(); atom!=mvTranslatedAtomList.end();++atom) { cout<<(*atom)->GetName()<<","; } } } void StretchModeBondLength::Stretch(const REAL amplitude, const bool keepCenter) { REAL dx=mpAtom1->GetX()-mpAtom0->GetX(); REAL dy=mpAtom1->GetY()-mpAtom0->GetY(); REAL dz=mpAtom1->GetZ()-mpAtom0->GetZ(); const REAL l=sqrt(dx*dx+dy*dy+dz*dz+1e-7); if(l<1e-6) return;// :KLUDGE: const REAL change=amplitude/l; dx*=change; dy*=change; dz*=change; mpMol->TranslateAtomGroup(mvTranslatedAtomList,dx,dy,dz,keepCenter); } void StretchModeBondLength::RandomStretch(const REAL amplitude, const bool keepCenter) { mpMol->BondLengthRandomChange(*this,amplitude,keepCenter); } StretchModeBondAngle::StretchModeBondAngle(MolAtom &at0,MolAtom &at1,MolAtom &at2, const MolBondAngle *pBondAngle): mpAtom0(&at0),mpAtom1(&at1),mpAtom2(&at2),mpBondAngle(pBondAngle) { mBaseAmplitude=M_PI*0.02; mpMol = &(at1.GetMolecule()); } StretchModeBondAngle::~StretchModeBondAngle(){} void StretchModeBondAngle::CalcDeriv(const bool derivllk)const { //TAU_PROFILE("StretchModeBondAngle::CalcDeriv()","void ()",TAU_DEFAULT); // Derivative of the atomic positions const REAL x1=mpAtom1->GetX(), y1=mpAtom1->GetY(), z1=mpAtom1->GetZ(); const REAL dx10=mpAtom0->GetX()-x1, dy10=mpAtom0->GetY()-y1, dz10=mpAtom0->GetZ()-z1, dx12=mpAtom2->GetX()-x1, dy12=mpAtom2->GetY()-y1, dz12=mpAtom2->GetZ()-z1; REAL vx=dy10*dz12-dz10*dy12, vy=dz10*dx12-dx10*dz12, vz=dx10*dy12-dy10*dx12; //const REAL n=sqrt((dx10*dx10+dy10*dy10+dz10*dz10)*(dx12*dx12+dy12*dy12+dz12*dz12))+1e-10; const REAL n=sqrt(vx*vx+vy*vy+vz*vz+1e-10); vx/=n; vy/=n; vz/=n; if(n<1e-6) { mDerivXYZ.clear(); return;//:KLUDGE: ? } for(set::const_iterator pos=mvRotatedAtomList.begin(); pos!=mvRotatedAtomList.end();++pos) { XYZ *const p=&(mDerivXYZ[*pos]); const REAL x=(*pos)->GetX()-x1, y=(*pos)->GetY()-y1, z=(*pos)->GetZ()-z1; p->x=z*vy-y*vz; p->y=x*vz-z*vx; p->z=y*vx-x*vy; } // Derivative of the LLK if(derivllk) { mLLKDeriv=0; for(map::const_iterator pos=this->mvpBrokenBond.begin(); pos!=this->mvpBrokenBond.end();++pos) mLLKDeriv += pos->first->GetDeriv(mDerivXYZ,true); for(map::const_iterator pos=this->mvpBrokenBondAngle.begin(); pos!=this->mvpBrokenBondAngle.end();++pos) mLLKDeriv += pos->first->GetDeriv(mDerivXYZ,true); for(map::const_iterator pos=this->mvpBrokenDihedralAngle.begin(); pos!=this->mvpBrokenDihedralAngle.end();++pos) mLLKDeriv += pos->first->GetDeriv(mDerivXYZ,true); } } void StretchModeBondAngle::Print(ostream &os,bool full)const { cout<GetName()<<"-"<GetName()<<"-"<GetName(); if(full) { cout<<", Rotated Atoms:"; for(set::const_iterator atom=mvRotatedAtomList.begin(); atom!=mvRotatedAtomList.end();++atom) { cout<<(*atom)->GetName()<<","; } } } void StretchModeBondAngle::Stretch(const REAL amplitude, const bool keepCenter) { REAL dx10=mpAtom0->GetX()-mpAtom1->GetX(); REAL dy10=mpAtom0->GetY()-mpAtom1->GetY(); REAL dz10=mpAtom0->GetZ()-mpAtom1->GetZ(); REAL dx12=mpAtom2->GetX()-mpAtom1->GetX(); REAL dy12=mpAtom2->GetY()-mpAtom1->GetY(); REAL dz12=mpAtom2->GetZ()-mpAtom1->GetZ(); const REAL vx=dy10*dz12-dz10*dy12; const REAL vy=dz10*dx12-dx10*dz12; const REAL vz=dx10*dy12-dy10*dx12; mpMol->RotateAtomGroup(*mpAtom1,vx,vy,vz,mvRotatedAtomList,amplitude,keepCenter); } void StretchModeBondAngle::RandomStretch(const REAL amplitude, const bool keepCenter) { mpMol->BondAngleRandomChange(*this,amplitude,keepCenter); } StretchModeTorsion::StretchModeTorsion(MolAtom &at1,MolAtom &at2, const MolDihedralAngle *pAngle): mpAtom1(&at1),mpAtom2(&at2),mpDihedralAngle(pAngle) { mBaseAmplitude=M_PI*0.02; mpMol = &(at1.GetMolecule()); } StretchModeTorsion::~StretchModeTorsion(){} void StretchModeTorsion::CalcDeriv(const bool derivllk)const { //TAU_PROFILE("StretchModeTorsion::CalcDeriv()","void ()",TAU_DEFAULT); // Derivative of the LLK //mDerivXYZ.clear(); const REAL x1=mpAtom1->GetX(), y1=mpAtom1->GetY(), z1=mpAtom1->GetZ(); REAL vx=mpAtom2->GetX()-x1, vy=mpAtom2->GetY()-y1, vz=mpAtom2->GetZ()-z1; const REAL n=sqrt(vx*vx+vy*vy+vz*vz+1e-10); vx/=n; vy/=n; vz/=n; for(set::const_iterator pos=mvRotatedAtomList.begin(); pos!=mvRotatedAtomList.end();++pos) { XYZ *const p=&(mDerivXYZ[*pos]); const REAL x=(*pos)->GetX()-x1, y=(*pos)->GetY()-y1, z=(*pos)->GetZ()-z1; p->x=z*vy-y*vz; p->y=x*vz-z*vx; p->z=y*vx-x*vy; } // Derivative of the LLK if(derivllk) { mLLKDeriv=0; for(map::const_iterator pos=this->mvpBrokenBond.begin(); pos!=this->mvpBrokenBond.end();++pos) mLLKDeriv += pos->first->GetDeriv(mDerivXYZ,true); for(map::const_iterator pos=this->mvpBrokenBondAngle.begin(); pos!=this->mvpBrokenBondAngle.end();++pos) mLLKDeriv += pos->first->GetDeriv(mDerivXYZ,true); for(map::const_iterator pos=this->mvpBrokenDihedralAngle.begin(); pos!=this->mvpBrokenDihedralAngle.end();++pos) mLLKDeriv += pos->first->GetDeriv(mDerivXYZ,true); } } void StretchModeTorsion::Print(ostream &os,bool full)const { cout<GetName()<<"-"<GetName(); if(full) { cout<<", Rotated Atoms:"; for(set::const_iterator atom=mvRotatedAtomList.begin(); atom!=mvRotatedAtomList.end();++atom) { cout<<(*atom)->GetName()<<","; } } } void StretchModeTorsion::Stretch(const REAL amplitude, const bool keepCenter) { mpMol->RotateAtomGroup(*mpAtom1,*mpAtom2,mvRotatedAtomList,amplitude,keepCenter); } void StretchModeTorsion::RandomStretch(const REAL amplitude, const bool keepCenter) { mpMol->DihedralAngleRandomChange(*this,amplitude,keepCenter); } //###################################################################### // // StretchModeTwist // //###################################################################### StretchModeTwist::StretchModeTwist(MolAtom &at1,MolAtom &at2): mpAtom1(&at1),mpAtom2(&at2) { mBaseAmplitude=M_PI*0.02; mpMol = &(at1.GetMolecule()); } StretchModeTwist::~StretchModeTwist(){} void StretchModeTwist::CalcDeriv(const bool derivllk)const {// Identical to StretchModeTorsion::CalcDeriv() // Derivative of the LLK //mDerivXYZ.clear(); const REAL x1=mpAtom1->GetX(), y1=mpAtom1->GetY(), z1=mpAtom1->GetZ(); REAL vx=mpAtom2->GetX()-x1, vy=mpAtom2->GetY()-y1, vz=mpAtom2->GetZ()-z1; const REAL n=sqrt(vx*vx+vy*vy+vz*vz+1e-10); vx/=n; vy/=n; vz/=n; for(set::const_iterator pos=mvRotatedAtomList.begin(); pos!=mvRotatedAtomList.end();++pos) { XYZ *const p=&(mDerivXYZ[*pos]); const REAL x=(*pos)->GetX()-x1, y=(*pos)->GetY()-y1, z=(*pos)->GetZ()-z1; p->x=z*vy-y*vz; p->y=x*vz-z*vx; p->z=y*vx-x*vy; } // Derivative of the LLK if(derivllk) { mLLKDeriv=0; for(map::const_iterator pos=this->mvpBrokenBond.begin(); pos!=this->mvpBrokenBond.end();++pos) mLLKDeriv += pos->first->GetDeriv(mDerivXYZ,true); for(map::const_iterator pos=this->mvpBrokenBondAngle.begin(); pos!=this->mvpBrokenBondAngle.end();++pos) mLLKDeriv += pos->first->GetDeriv(mDerivXYZ,true); for(map::const_iterator pos=this->mvpBrokenDihedralAngle.begin(); pos!=this->mvpBrokenDihedralAngle.end();++pos) mLLKDeriv += pos->first->GetDeriv(mDerivXYZ,true); } } void StretchModeTwist::Print(ostream &os,bool full)const { os<GetName()<<"/"<GetName()<<"-"<GetName(); if(full) { os<<", Rotated Atoms:"; for(set::const_iterator atom=mvRotatedAtomList.begin(); atom!=mvRotatedAtomList.end();++atom) { os<<(*atom)->GetName()<<","; } } } void StretchModeTwist::Stretch(const REAL amplitude, const bool keepCenter) { mpMol->RotateAtomGroup(*mpAtom1,*mpAtom2,mvRotatedAtomList,amplitude,keepCenter); } void StretchModeTwist::RandomStretch(const REAL amplitude, const bool keepCenter) { const REAL dx=mpAtom2->GetX()-mpAtom1->GetX(); const REAL dy=mpAtom2->GetY()-mpAtom1->GetY(); const REAL dz=mpAtom2->GetZ()-mpAtom1->GetZ(); if((abs(dx)+abs(dy)+abs(dz))<1e-6) return;// :KLUDGE: const REAL change=(REAL)(2.*rand()-RAND_MAX)/(REAL)RAND_MAX*mBaseAmplitude*amplitude; mpMol->RotateAtomGroup(*mpAtom1,*mpAtom2,mvRotatedAtomList,change,keepCenter); } //###################################################################### // // MDAtomGroup // //###################################################################### MDAtomGroup::MDAtomGroup(){}; MDAtomGroup::MDAtomGroup(set &vat, set &vb, set &va, set &vd): mvpAtom(vat) { // Use vector instead of sets for MolecularDynamicsEvolve & general // storage in molecule compatibility for(set::iterator pos=vb.begin();pos!=vb.end();++pos) mvpBond.push_back(*pos); for(set::iterator pos=va.begin();pos!=va.end();++pos) mvpBondAngle.push_back(*pos); for(set::iterator pos=vd.begin();pos!=vd.end();++pos) mvpDihedralAngle.push_back(*pos); } void MDAtomGroup::Print(ostream &os,bool full)const { if(full) os<<"MDAtomGroup: "; for(set::const_iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos) os<<(*pos)->GetName()<<" "; if(full) { os<::const_iterator pos=mvpBond.begin();pos!=mvpBond.end();++pos) os<<(*pos)->GetName()<<" "; os<::const_iterator pos=mvpBondAngle.begin();pos!=mvpBondAngle.end();++pos) os<<(*pos)->GetName()<<" "; os<::const_iterator pos=mvpDihedralAngle.begin();pos!=mvpDihedralAngle.end();++pos) os<<(*pos)->GetName()<<" "; os<AddPar(tmp); } { RefinablePar tmp(name+"_y",&mXYZ(1),0,1, gpRefParTypeScattTranslY, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,true,1.,1.); tmp.AssignClock(mClockScatterer); tmp.SetDerivStep(1e-5); this->AddPar(tmp); } { RefinablePar tmp(name+"_z",&mXYZ(2),0,1, gpRefParTypeScattTranslZ, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,true,1.,1.); tmp.AssignClock(mClockScatterer); tmp.SetDerivStep(1e-5); this->AddPar(tmp); } { RefinablePar tmp(name+"_Occ",&mOccupancy,0,1, gpRefParTypeScattOccup, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,1.,1.); tmp.AssignClock(mClockScatterer); tmp.SetDerivStep(1e-5); this->AddPar(tmp); } { RefinablePar tmp(name+"_Q0",&(mQuat.Q0()),0,1, gpRefParTypeScattOrient, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.); tmp.AssignClock(mClockScatterer); tmp.SetGlobalOptimStep(0.04); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { RefinablePar tmp(name+"_Q1",&(mQuat.Q1()),0,1, gpRefParTypeScattOrient, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.); tmp.AssignClock(mClockScatterer); tmp.SetGlobalOptimStep(0.04); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { RefinablePar tmp(name+"_Q2",&(mQuat.Q2()),0,1, gpRefParTypeScattOrient, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.); tmp.AssignClock(mClockScatterer); tmp.SetGlobalOptimStep(0.04); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { RefinablePar tmp(name+"_Q3",&(mQuat.Q3()),0,1, gpRefParTypeScattOrient, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.); tmp.AssignClock(mClockScatterer); tmp.SetGlobalOptimStep(0.04); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } this->SetName(name); mLocalParamSet=this->CreateParamSet("saved parameters for local minimization"); this->InitOptions(); mClockScatterer.AddChild(mClockAtomList); mClockScatterer.AddChild(mClockBondList); mClockScatterer.AddChild(mClockBondAngleList); mClockScatterer.AddChild(mClockDihedralAngleList); mClockScatterer.AddChild(mClockRingList); mClockScatterer.AddChild(mClockRigidGroup); mClockScatterer.AddChild(mClockAtomPosition); mClockScatterer.AddChild(mClockAtomScattPow); mClockScatterer.AddChild(mClockOrientation); } Molecule::Molecule(const Molecule &old): mDeleteSubObjInDestructor(old.mDeleteSubObjInDestructor), mIsSelfOptimizing(false), mpCenterAtom(0) { VFN_DEBUG_ENTRY("Molecule::Molecule(old&)",5) // a hack, but const-correct mpCryst=&(gCrystalRegistry.GetObj(gCrystalRegistry.Find(old.GetCrystal()))); { RefinablePar tmp(this->GetName()+"_x",&mXYZ(0),0.,1., gpRefParTypeScattTranslX, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,true,1.,1.); tmp.AssignClock(mClockScatterer); tmp.SetDerivStep(1e-5); this->AddPar(tmp); } { RefinablePar tmp(this->GetName()+"_y",&mXYZ(1),0,1, gpRefParTypeScattTranslY, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,true,1.,1.); tmp.AssignClock(mClockScatterer); tmp.SetDerivStep(1e-5); this->AddPar(tmp); } { RefinablePar tmp(this->GetName()+"_z",&mXYZ(2),0,1, gpRefParTypeScattTranslZ, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,true,1.,1.); tmp.AssignClock(mClockScatterer); tmp.SetDerivStep(1e-5); this->AddPar(tmp); } { RefinablePar tmp(this->GetName()+"_Occ",&mOccupancy,0,1, gpRefParTypeScattOccup, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,1.,1.); tmp.AssignClock(mClockScatterer); tmp.SetDerivStep(1e-5); this->AddPar(tmp); } { RefinablePar tmp(this->GetName()+"Q0",&(mQuat.Q0()),0,1, gpRefParTypeScattOrient, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.); tmp.AssignClock(mClockScatterer); tmp.SetGlobalOptimStep(0.04); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { RefinablePar tmp(this->GetName()+"Q1",&(mQuat.Q1()),0,1, gpRefParTypeScattOrient, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.); tmp.AssignClock(mClockScatterer); tmp.SetGlobalOptimStep(0.04); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { RefinablePar tmp(this->GetName()+"Q2",&(mQuat.Q2()),0,1, gpRefParTypeScattOrient, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.); tmp.AssignClock(mClockScatterer); tmp.SetGlobalOptimStep(0.04); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { RefinablePar tmp(this->GetName()+"Q3",&(mQuat.Q3()),0,1, gpRefParTypeScattOrient, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.); tmp.AssignClock(mClockScatterer); tmp.SetGlobalOptimStep(0.04); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } mLocalParamSet=this->CreateParamSet("saved parameters for local minimization"); this->InitOptions(); mClockScatterer.AddChild(mClockAtomList); mClockScatterer.AddChild(mClockBondList); mClockScatterer.AddChild(mClockBondAngleList); mClockScatterer.AddChild(mClockDihedralAngleList); mClockScatterer.AddChild(mClockRingList); mClockScatterer.AddChild(mClockRigidGroup); mClockScatterer.AddChild(mClockAtomPosition); mClockScatterer.AddChild(mClockAtomScattPow); mClockScatterer.AddChild(mClockOrientation); mClockRestraint.AddChild(mClockAtomList); mClockRestraint.AddChild(mClockBondList); mClockRestraint.AddChild(mClockBondAngleList); mClockRestraint.AddChild(mClockDihedralAngleList); mClockRestraint.AddChild(mClockRingList); mClockRestraint.AddChild(mClockRigidGroup); stringstream str; old.XMLOutput(str); XMLCrystTag tag(str); this->XMLInput(str,tag); VFN_DEBUG_EXIT("Molecule::Molecule(old&)",5) } Molecule::~Molecule() { VFN_DEBUG_ENTRY("Molecule::~Molecule()",5) if(mDeleteSubObjInDestructor) { { vector::iterator pos; for(pos=mvpAtom.begin();pos!=mvpAtom.end();pos++) delete *pos; } { vector::iterator pos; for(pos=mvpBond.begin();pos!=mvpBond.end();pos++) delete *pos; } { vector::iterator pos; for(pos=mvpBondAngle.begin();pos!=mvpBondAngle.end();pos++) delete *pos; } { vector::iterator pos; for(pos=mvpDihedralAngle.begin();pos!=mvpDihedralAngle.end();pos++) delete *pos; } } VFN_DEBUG_EXIT("Molecule::~Molecule()",5) } Molecule* Molecule::CreateCopy() const { VFN_DEBUG_MESSAGE("Molecule::CreateCopy()",5) return new Molecule(*this); } const string& Molecule::GetClassName() const { static const string className="Molecule"; return className; } void Molecule::SetName(const string &name) { if(mName==name) return; this->RefinableObj::SetName(name); // Set parameter's name including the Molecule's name try { this->GetPar(&mXYZ(0)).SetName(mName+"_x"); this->GetPar(&mXYZ(1)).SetName(mName+"_y"); this->GetPar(&mXYZ(2)).SetName(mName+"_z"); this->GetPar(&mOccupancy).SetName(mName+"_Occ"); this->GetPar(&(mQuat.Q0())).SetName(mName+"_Q0"); this->GetPar(&(mQuat.Q1())).SetName(mName+"_Q1"); this->GetPar(&(mQuat.Q2())).SetName(mName+"_Q2"); this->GetPar(&(mQuat.Q3())).SetName(mName+"_Q3"); } catch(const ObjCrystException &except) { cerr<<"Molecule::SetName(): parameters not yet declared in a Molecule ?"<GetNbComponent()==0) return ""; std::map velts; for(std::vector::const_iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos) { if((*pos)->IsDummy()) continue; string p=(*pos)->GetScatteringPower().GetSymbol(); if(velts.count(p)==0) velts[p]=(*pos)->GetOccupancy(); else velts[p]+=(*pos)->GetOccupancy(); } stringstream s; s<::const_iterator pos=velts.begin();pos!=velts.end();++pos) { if(pos!=velts.begin()) s<<" "; float nb=pos->second; if(abs(round(nb)-nb)<0.005) { if(int(round(nb))==1) s<first; else s<first<first<XMLOutput(cout); } void Molecule::XMLOutput(ostream &os,int indent)const { VFN_DEBUG_ENTRY("Molecule::XMLOutput()",4) // :KLUDGE: this may be dangerous if the molecule is beaing refined ! this->ResetRigidGroupsPar(); for(int i=0;iGetPar(mXYZ.data()+0).XMLOutput(os,"x",indent); os <GetPar(mXYZ.data()+1).XMLOutput(os,"y",indent); os <GetPar(mXYZ.data()+2).XMLOutput(os,"z",indent); os <GetPar(&mOccupancy).XMLOutput(os,"Occup",indent); os <GetNbOption();i++) { this->GetOption(i).XMLOutput(os,indent); os <::const_iterator pos; for(pos=mvpAtom.begin();pos!=mvpAtom.end();++pos) (*pos)->XMLOutput(os,indent); } { vector::const_iterator pos; for(pos=mvpBond.begin();pos!=mvpBond.end();++pos) (*pos)->XMLOutput(os,indent); } { vector::const_iterator pos; for(pos=mvpBondAngle.begin();pos!=mvpBondAngle.end();++pos) (*pos)->XMLOutput(os,indent); } { vector::const_iterator pos; for(pos=mvpDihedralAngle.begin();pos!=mvpDihedralAngle.end();++pos) (*pos)->XMLOutput(os,indent); } { vector::const_iterator pos; for(pos=mvRigidGroup.begin();pos!=mvRigidGroup.end();++pos) { XMLCrystTag tagg("RigidGroup",false,true); // Need to use Atom1, Atom2 etc.. so a valid XML is produced // See https://github.com/vincefn/objcryst/issues/52 // This won't be backwards-compatible int idx = 0; for (set::const_iterator at = (*pos)->begin(); at != (*pos)->end(); ++at) tagg.AddAttribute((boost::format("Atom%d") %idx++).str(), (*at)->GetName()); /* tagg.AddAttribute("Q0",(*pos)->mQuat.Q0()); tagg.AddAttribute("Q1",(*pos)->mQuat.Q1()); tagg.AddAttribute("Q2",(*pos)->mQuat.Q2()); tagg.AddAttribute("Q3",(*pos)->mQuat.Q3()); tagg.AddAttribute("dX",(*pos)->mX); tagg.AddAttribute("dY",(*pos)->mY); tagg.AddAttribute("dZ",(*pos)->mZ); */ for(int i=0;iGetCenterAtom()!=0) { XMLCrystTag tagg("CenterAtom",false,true); tagg.AddAttribute("Name",this->GetCenterAtom()->GetName()); for(int i=0;iXMLOutput(cout); this->UpdateDisplay(); VFN_DEBUG_EXIT("Molecule::XMLInput():"<GetName(),5) return; } if("Quaternion"==tagg.GetName()) { mQuat.XMLInput(is,tagg); } if("Atom"==tagg.GetName()) { this->AddAtom(0.,0.,0.,(ScatteringPower *)0,"",false); mvpAtom.back()->XMLInput(is,tagg); } if("Bond"==tagg.GetName()) { this->AddBond(this->GetAtom(0),this->GetAtom(1),1.5,.01,.05,1.,false); mvpBond.back()->XMLInput(is,tagg); } if("BondAngle"==tagg.GetName()) { this->AddBondAngle(this->GetAtom(0),this->GetAtom(1),this->GetAtom(2),1.5,.01,.05,false); mvpBondAngle.back()->XMLInput(is,tagg); } if("DihedralAngle"==tagg.GetName()) { this->AddDihedralAngle(this->GetAtom(0),this->GetAtom(1), this->GetAtom(2),this->GetAtom(3),1.5,.01,.05,false); mvpDihedralAngle.back()->XMLInput(is,tagg); } if("RigidGroup"==tagg.GetName()) { RigidGroup s; for(unsigned int i=0;iGetAtom(tagg.GetAttributeValue(i)))); this->AddRigidGroup(s); } if("CenterAtom"==tagg.GetName()) { RigidGroup s; for(unsigned int i=0;iSetCenterAtom(this->GetAtom(tagg.GetAttributeValue(i))); } if("Option"==tagg.GetName()) { for(unsigned int i=0;iGetPar(mXYZ.data()+0).XMLInput(is,tagg); break; } if("y"==tagg.GetAttributeValue(i)) { this->GetPar(mXYZ.data()+1).XMLInput(is,tagg); break; } if("z"==tagg.GetAttributeValue(i)) { this->GetPar(mXYZ.data()+2).XMLInput(is,tagg); break; } if("Occup"==tagg.GetAttributeValue(i)) { this->GetPar(&mOccupancy).XMLInput(is,tagg); break; } } } } } VFN_DEBUG_EXIT("Molecule::XMLInput()",5) } void Molecule::UpdateDisplay()const { this->ResetRigidGroupsPar(); this->RefinableObj::UpdateDisplay(); } void Molecule::BeginOptimization(const bool allowApproximations,const bool enableRestraints) { if(this->IsBeingRefined()) { // RefinableObj::BeginOptimization() will increase the optimization depth this->RefinableObj::BeginOptimization(allowApproximations,enableRestraints); return; } TAU_PROFILE("Molecule::BeginOptimization()","void (bool,bool)",TAU_DEFAULT); #if 1 // Is doing this automatically too dangerous ? if( (!mIsSelfOptimizing) &&(mAutoOptimizeConformation.GetChoice()==0)) { if(this->GetLogLikelihood()>(mvpRestraint.size()*500)) { (*fpObjCrystInformUser)("Optimizing initial conformation of Molecule:"+this->GetName()); this->OptimizeConformation(100000,(REAL)(mvpRestraint.size())); (*fpObjCrystInformUser)("Finished optimizing initial conformation of Molecule:"+this->GetName()); } mAutoOptimizeConformation.SetChoice(1); } #endif RefinableObjClock clockConf, clockMode; clockConf=mClockAtomList; if(clockConfBuildRotorGroup(); #endif if(mFlexModel.GetChoice()!=1) { this->BuildFlipGroup(); this->BuildRingList(); this->BuildStretchModeBondLength(); this->BuildStretchModeBondAngle(); this->BuildStretchModeTorsion(); //this->BuildStretchModeTwist(); this->TuneGlobalOptimRotationAmplitude(); this->BuildStretchModeGroups(); this->BuildMDAtomGroups(); } } if(mOptimizeOrientation.GetChoice()==1) { this->GetPar(&(mQuat.Q0())).SetIsFixed(true); this->GetPar(&(mQuat.Q1())).SetIsFixed(true); this->GetPar(&(mQuat.Q2())).SetIsFixed(true); this->GetPar(&(mQuat.Q3())).SetIsFixed(true); } else { this->GetPar(&(mQuat.Q0())).SetIsFixed(false); this->GetPar(&(mQuat.Q1())).SetIsFixed(false); this->GetPar(&(mQuat.Q2())).SetIsFixed(false); this->GetPar(&(mQuat.Q3())).SetIsFixed(false); } if(1==mFlexModel.GetChoice()) {// Molecule is a rigid body - fix all individual atomic parameters for(vector::iterator at=this->GetAtomList().begin();at!=this->GetAtomList().end();++at) { this->GetPar(&((*at)->X())).SetIsFixed(true); this->GetPar(&((*at)->Y())).SetIsFixed(true); this->GetPar(&((*at)->Z())).SetIsFixed(true); } } else {// Molecule is flexible - rigid groups are handled below for(vector::iterator at=this->GetAtomList().begin();at!=this->GetAtomList().end();++at) { this->GetPar(&((*at)->X())).SetIsFixed(false); this->GetPar(&((*at)->Y())).SetIsFixed(false); this->GetPar(&((*at)->Z())).SetIsFixed(false); } } #ifdef RIGID_BODY_STRICT_EXPERIMENTAL // Block individual refinable parameters from atoms in rigid groups // And create the index of the atoms for(vector::iterator pos=this->GetRigidGroupList().begin();pos!=this->GetRigidGroupList().end();++pos) { // Init the translation & rotation parameters (ignored outside an optimization) (*pos)->mX=0; (*pos)->mY=0; (*pos)->mZ=0; (*pos)->mQuat.Q0()=1; (*pos)->mQuat.Q1()=0; (*pos)->mQuat.Q2()=0; (*pos)->mQuat.Q3()=0; (*pos)->mvIdx.clear(); for(set::iterator at=(*pos)->begin();at!=(*pos)->end();++at) { this->GetPar(&((*at)->X())).SetIsFixed(true); this->GetPar(&((*at)->Y())).SetIsFixed(true); this->GetPar(&((*at)->Z())).SetIsFixed(true); for(int i = 0; i < this->GetNbComponent(); ++i) if(&(this->GetAtom(i))==*at) { (*pos)->mvIdx.insert(i); break; } } } #endif this->RefinableObj::BeginOptimization(allowApproximations,enableRestraints); mRandomConformChangeNbTest=0; mRandomConformChangeNbAccept=0; mRandomConformChangeTemp=1.;//(REAL)this->GetNbComponent(); } void Molecule::EndOptimization() { /* if(mOptimizationDepth>1) { this->RefinableObj::EndOptimization(); return; } */ #ifdef RIGID_BODY_STRICT_EXPERIMENTAL // Un-block individual refinable parameters from atoms in rigid groups for(vector::iterator pos=this->GetRigidGroupList().begin();pos!=this->GetRigidGroupList().end();++pos) { for(set::iterator at=(*pos)->begin();at!=(*pos)->end();++at) { this->GetPar(&((*at)->X())).SetIsFixed(false); this->GetPar(&((*at)->Y())).SetIsFixed(false); this->GetPar(&((*at)->Z())).SetIsFixed(false); } } // Apply the translations & rotations of the rigid group parameters, and // use this as the newly stored atomic coordinates. this->ResetRigidGroupsPar(); #endif this->RefinableObj::EndOptimization(); } void Molecule::RandomizeConfiguration() { TAU_PROFILE("Molecule::RandomizeConfiguration()","void ()",TAU_DEFAULT); VFN_DEBUG_ENTRY("Molecule::RandomizeConfiguration()",4) if( (!mIsSelfOptimizing) &&(this->GetLogLikelihood()>(mvpRestraint.size()*500)) &&(mAutoOptimizeConformation.GetChoice()==0)) {// This is only done once, for a newly-created molecule with atoms not conforming to restraints (*fpObjCrystInformUser)("Optimizing initial conformation of Molecule:"+this->GetName()); this->OptimizeConformation(100000,(REAL)(mvpRestraint.size())); (*fpObjCrystInformUser)("Finished optimizing initial conformation of Molecule:"+this->GetName()); mAutoOptimizeConformation.SetChoice(1); } if( (!(this->IsBeingRefined())) &&( (mClockStretchModeTorsionBuildStretchModeTorsion(); //this->BuildStretchModeGroups(); this->BuildMDAtomGroups(); // WARNING: TuneGlobalOptimRotationAmplitude() will call RandomizeConfiguration(), // so make sure we do not enter this code again by calling first BuildStretchModeTorsion and BuildMDAtomGroups this->TuneGlobalOptimRotationAmplitude(); } } #if 0 this->BuildRotorGroup(); if((mFlexModel.GetChoice()==0)||(mFlexModel.GetChoice()==2)) for(list::const_iterator pos=mvRotorGroupTorsion.begin(); pos!=mvRotorGroupTorsion.end();++pos) { const REAL angle=(REAL)rand()*2.*M_PI/(REAL)RAND_MAX; this->RotateAtomGroup(*(pos->mpAtom1),*(pos->mpAtom2), pos->mvRotatedAtomList,angle); } if(mFlexModel.GetChoice()==0) for(list::const_iterator pos=mvRotorGroupTorsionSingleChain.begin(); pos!=mvRotorGroupTorsionSingleChain.end();++pos) { const REAL angle=(REAL)rand()*2.*M_PI/(REAL)RAND_MAX; this->RotateAtomGroup(*(pos->mpAtom1),*(pos->mpAtom2), pos->mvRotatedAtomList,angle); } if(mFlexModel.GetChoice()==0) for(list::const_iterator pos=mvRotorGroupInternal.begin(); pos!=mvRotorGroupInternal.end();++pos) { const REAL angle=(REAL)rand()*2.*M_PI/(REAL)RAND_MAX; this->RotateAtomGroup(*(pos->mpAtom1),*(pos->mpAtom2), pos->mvRotatedAtomList,angle); } #else for(list::const_iterator pos=mvStretchModeTorsion.begin(); pos!=mvStretchModeTorsion.end();++pos) { const REAL amp=2*M_PI*rand()/(REAL)RAND_MAX; this->DihedralAngleRandomChange(*pos,amp,true); } // Molecular dynamics moves if((mvMDAtomGroup.size()>0)&&(mMDMoveFreq>0)&&(mMDMoveEnergy>0)) { // Random initial speed for all atoms map v0; for(vector::iterator at=this->GetAtomList().begin();at!=this->GetAtomList().end();++at) v0[*at]=XYZ(rand()/(REAL)RAND_MAX+0.5,rand()/(REAL)RAND_MAX+0.5,rand()/(REAL)RAND_MAX+0.5); const REAL nrj0=mMDMoveEnergy*( this->GetBondList().size() +this->GetBondAngleList().size() +this->GetDihedralAngleList().size()); map > vr; this->MolecularDynamicsEvolve(v0, 5000,0.004, this->GetBondList(), this->GetBondAngleList(), this->GetDihedralAngleList(), vr,nrj0); } #endif // this will only change limited parameters i.e. translation this->RefinableObj::RandomizeConfiguration(); #ifdef RIGID_BODY_STRICT_EXPERIMENTAL // Init rigid groups translation & rotation parameters to zero for(vector::iterator pos=this->GetRigidGroupList().begin();pos!=this->GetRigidGroupList().end();++pos) { // Init the translation & rotation parameters (ignored outside an optimization (*pos)->mX=0; (*pos)->mY=0; (*pos)->mZ=0; (*pos)->mQuat.Q0()=1; (*pos)->mQuat.Q1()=0; (*pos)->mQuat.Q2()=0; (*pos)->mQuat.Q3()=0; } #endif if(mOptimizeOrientation.GetChoice()==0) {//Rotate around an arbitrary vector const REAL amp=M_PI/RAND_MAX; mQuat *= Quaternion::RotationQuaternion ((2.*(REAL)rand()-(REAL)RAND_MAX)*amp, (REAL)rand(),(REAL)rand(),(REAL)rand()); mQuat.Normalize(); mClockOrientation.Click(); } VFN_DEBUG_EXIT("Molecule::RandomizeConfiguration()",4) } void Molecule::GlobalOptRandomMove(const REAL mutationAmplitude, const RefParType *type) { if(mRandomMoveIsDone) return; if(mIsSelfOptimizing) { this->RefinableObj::GlobalOptRandomMove(mutationAmplitude,type); mQuat.Normalize(); VFN_DEBUG_EXIT("Molecule::GlobalOptRandomMove()",4) return; } TAU_PROFILE("Molecule::GlobalOptRandomMove()","void (REAL,RefParType*)",TAU_DEFAULT); TAU_PROFILE_TIMER(timer1,"Molecule::GlobalOptRandomMove 1","", TAU_FIELD); TAU_PROFILE_TIMER(timer2,"Molecule::GlobalOptRandomMove 2","", TAU_FIELD); TAU_PROFILE_TIMER(timer3,"Molecule::GlobalOptRandomMove 3","", TAU_FIELD); TAU_PROFILE_TIMER(timer4,"Molecule::GlobalOptRandomMove 4","", TAU_FIELD); TAU_PROFILE_TIMER(timer5,"Molecule::GlobalOptRandomMove 5","", TAU_FIELD); VFN_DEBUG_ENTRY("Molecule::GlobalOptRandomMove()",4) mClockScatterer.Click(); #if 1 // From time to time, just do one flip if( (mFlexModel.GetChoice()!=1) &&(mFlipModel.GetChoice()==0) &&(gpRefParTypeScattConform->IsDescendantFromOrSameAs(type)) &&(mvFlipGroup.size()>0) &&(((rand()%100)==0))) { this->SaveParamSet(mLocalParamSet); const REAL llk0=this->GetLogLikelihood()/mLogLikelihoodScale; const unsigned long i=rand() % mvFlipGroup.size(); list::iterator pos=mvFlipGroup.begin(); for(unsigned long j=0;jFlipAtomGroup(*pos,true); #if 0 static unsigned long ctflip1=0,ctflip2=0; if(pos->mvRotatedChainList.begin()->first==pos->mpAtom0) { cout <<"TRYING: Flip group from atom " <mpAtom0->GetName()<<",exchanging bonds with " <mpAtom1->GetName()<<" and " <mpAtom2->GetName()<<", resulting in a 180deg rotation of atoms : "; for(set::iterator pos1=pos->mvRotatedChainList.begin()->second.begin(); pos1!=pos->mvRotatedChainList.begin()->second.end();++pos1) cout<<(*pos1)->GetName()<<" "; } else { cout <<"TRYING: Flip group with respect to: " <mpAtom1->GetName()<<"-" <mpAtom0->GetName()<<"-" <mpAtom2->GetName()<<" : "; for(list > >::const_iterator chain=pos->mvRotatedChainList.begin(); chain!=pos->mvRotatedChainList.end();++chain) { cout<<" -"<first->GetName()<<":"; for(set::const_iterator pos1=chain->second.begin(); pos1!=chain->second.end();++pos1) cout<<(*pos1)->GetName()<<" "; } } ctflip1++; if((this->GetLogLikelihood()/mLogLikelihoodScale-llk0)>.3*llk0) { cout<<" FLIP REJECTED ("< "<GetLogLikelihood()/mLogLikelihoodScale<RestoreParamSet(mLocalParamSet); } else { ctflip2++; cout<<" FLIP ACCEPTED ("<GetLogLikelihood()/mLogLikelihoodScale-llk0)>.3*llk0) this->RestoreParamSet(mLocalParamSet); #endif } else #endif { TAU_PROFILE_START(timer1); if(mOptimizeOrientation.GetChoice()==0) {//Rotate around an arbitrary vector static const REAL amp=mBaseRotationAmplitude/(REAL)RAND_MAX; REAL mult=1.0; if((1==mFlexModel.GetChoice())||(mvRotorGroupTorsion.size()<2)) mult=2.0; mQuat *= Quaternion::RotationQuaternion ((2.*(REAL)rand()-(REAL)RAND_MAX)*amp*mutationAmplitude*mult, (REAL)rand(),(REAL)rand(),(REAL)rand()); mQuat.Normalize(); mClockOrientation.Click(); } // Occupancy if(gpRefParTypeScattOccup->IsDescendantFromOrSameAs(type)) this->RefinableObj::GlobalOptRandomMove(mutationAmplitude,gpRefParTypeScattOccup); mRandomMoveIsDone=false; //translation if(gpRefParTypeScattTransl->IsDescendantFromOrSameAs(type)) this->RefinableObj::GlobalOptRandomMove(mutationAmplitude,gpRefParTypeScattTransl); mRandomMoveIsDone=false; TAU_PROFILE_STOP(timer1); if(gpRefParTypeScattConform->IsDescendantFromOrSameAs(type)) { if(mFlexModel.GetChoice()!=1) { #if 1 // Move as many atoms as possible if((mvMDFullAtomGroup.size()>3)&&(rand()<(RAND_MAX*mMDMoveFreq))) { #if 0 // Use one center for the position of an impulsion, applied to all atoms with an exponential decrease // Determine extent of atom group REAL xmin=(*mvMDFullAtomGroup.begin())->GetX(); REAL xmax=(*mvMDFullAtomGroup.begin())->GetX(); REAL ymin=(*mvMDFullAtomGroup.begin())->GetY(); REAL ymax=(*mvMDFullAtomGroup.begin())->GetY(); REAL zmin=(*mvMDFullAtomGroup.begin())->GetZ(); REAL zmax=(*mvMDFullAtomGroup.begin())->GetZ(); for(set::iterator at=mvMDFullAtomGroup.begin();at!=mvMDFullAtomGroup.end();++at) { if((*at)->GetX()GetX(); if((*at)->GetX()>xmax) xmax=(*at)->GetX(); if((*at)->GetY()GetY(); if((*at)->GetY()>ymax) ymax=(*at)->GetY(); if((*at)->GetZ()GetZ(); if((*at)->GetZ()>zmax) zmax=(*at)->GetZ(); } // Apply a gaussian impulsion to part of the atom group (FWHM=1/3 of group size) REAL dx=(xmax-xmin)/5.,dy=(ymax-ymin)/5.,dz=(zmax-zmin)/5.; if(dx<2) dx=2; if(dy<2) dy=2; if(dz<2) dz=2; const REAL xc=xmin+rand()/(REAL)RAND_MAX*(xmax-xmin); const REAL yc=ymin+rand()/(REAL)RAND_MAX*(ymax-ymin); const REAL zc=zmin+rand()/(REAL)RAND_MAX*(zmax-zmin); map v0; const REAL ax=-4.*log(2.)/(dx*dx); const REAL ay=-4.*log(2.)/(dy*dy); const REAL az=-4.*log(2.)/(dz*dz); for(set::iterator at=mvMDFullAtomGroup.begin();at!=mvMDFullAtomGroup.end();++at) v0[*at]=XYZ(exp(ax*((*at)->GetX()-xc)*((*at)->GetX()-xc)), exp(ay*((*at)->GetY()-yc)*((*at)->GetY()-yc)), exp(az*((*at)->GetZ()-zc)*((*at)->GetZ()-zc))); #else // Use one atom for the center of the impulsion, 'push' atoms depending on distance & connectivity table map v0; for(set::iterator at=this->mvMDFullAtomGroup.begin();at!=this->mvMDFullAtomGroup.end();++at) v0[*at]=XYZ(0,0,0); std::map pushedAtoms; unsigned long idx=rand()%v0.size(); set::iterator at0=this->mvMDFullAtomGroup.begin(); for(unsigned int i=0;iGetX(); const REAL yc=(*at0)->GetY(); const REAL zc=(*at0)->GetZ(); const map > *pConnect=&(this-> GetConnectivityTable()); ExpandAtomGroupRecursive(*at0,*pConnect,pushedAtoms,3); REAL ux,uy,uz,n=0; while(n<1) { ux=REAL(rand()-RAND_MAX/2); uy=REAL(rand()-RAND_MAX/2); uz=REAL(rand()-RAND_MAX/2); n=sqrt(ux*ux+uy*uy+uz*uz); } ux=ux/n;uy=uy/n;uz=uz/n; const REAL a=-4.*log(2.)/(2*2);//FWHM=2 Angstroems if(rand()%2==0) for(map::iterator at=pushedAtoms.begin() ;at!=pushedAtoms.end();++at) v0[at->first]=XYZ(ux*exp(a*(at->first->GetX()-xc)*(at->first->GetX()-xc)), uy*exp(a*(at->first->GetY()-yc)*(at->first->GetY()-yc)), uz*exp(a*(at->first->GetZ()-zc)*(at->first->GetZ()-zc))); else for(map::iterator at=pushedAtoms.begin() ;at!=pushedAtoms.end();++at) v0[at->first]=XYZ((at->first->GetX()-xc)*ux*exp(a*(at->first->GetX()-xc)*(at->first->GetX()-xc)), (at->first->GetY()-yc)*uy*exp(a*(at->first->GetY()-yc)*(at->first->GetY()-yc)), (at->first->GetZ()-zc)*uz*exp(a*(at->first->GetZ()-zc)*(at->first->GetZ()-zc))); #endif const REAL nrj0=mMDMoveEnergy*( this->GetBondList().size() +this->GetBondAngleList().size() +this->GetDihedralAngleList().size()); map > vr; this->MolecularDynamicsEvolve(v0, int(100*sqrt(mutationAmplitude)),0.004, this->GetBondList(), this->GetBondAngleList(), this->GetDihedralAngleList(), vr,nrj0); } #else // Move atoms belonging to a MD group if((mvMDAtomGroup.size()>0)&&(rand()<(RAND_MAX*mMDMoveFreq))) { const unsigned int n=rand()%mvMDAtomGroup.size(); list::iterator pos=mvMDAtomGroup.begin(); for(unsigned int i=0;i v0; for(set::iterator at=pos->mvpAtom.begin();at!=pos->mvpAtom.end();++at) v0[*at]=XYZ(rand()/(REAL)RAND_MAX+0.5,rand()/(REAL)RAND_MAX+0.5,rand()/(REAL)RAND_MAX+0.5); const REAL nrj0=mMDMoveEnergy*( pos->mvpBond.size() +pos->mvpBondAngle.size() +pos->mvpDihedralAngle.size()); map > vr; float nrjMult=1.0+mutationAmplitude*0.2; if((rand()%20)==0) nrjMult=4.0; this->MolecularDynamicsEvolve(v0, int(100*sqrt(mutationAmplitude)),0.004, pos->mvpBond, pos->mvpBondAngle, pos->mvpDihedralAngle, vr,nrj0*nrjMult); } #endif else { #if 0 // For tests mLogLikelihood=0; for(vector::const_iterator pos=mvpBond.begin();pos!=mvpBond.end();++pos) mLogLikelihood+=(*pos)->GetLogLikelihood(true,true); for(vector::const_iterator pos=mvpBondAngle.begin();pos!=mvpBondAngle.end();++pos) mLogLikelihood+=(*pos)->GetLogLikelihood(true,true); for(vector::const_iterator pos=mvpDihedralAngle.begin();pos!=mvpDihedralAngle.end();++pos) mLogLikelihood+=(*pos)->GetLogLikelihood(true,true); for(list::const_iterator mode=mvpStretchModeNotFree.begin(); mode!=mvpStretchModeNotFree.end();++mode) { //if((rand()%3)==0) { // 2) Get the derivative of the overall LLK for this mode (*mode)->CalcDeriv(); REAL llk=0; for(map::const_iterator pos=(*mode)->mvpBrokenBond.begin(); pos!=(*mode)->mvpBrokenBond.end();++pos) llk+=pos->first->GetLogLikelihood(false,false); for(map::const_iterator pos=(*mode)->mvpBrokenBondAngle.begin(); pos!=(*mode)->mvpBrokenBondAngle.end();++pos) llk+=pos->first->GetLogLikelihood(false,false); for(map::const_iterator pos=(*mode)->mvpBrokenDihedralAngle.begin(); pos!=(*mode)->mvpBrokenDihedralAngle.end();++pos) llk+=pos->first->GetLogLikelihood(false,false); // 3) Calculate MD move. base step =0.1 A (accelerated moves may go faster) REAL change=(2.*(REAL)rand()-(REAL)RAND_MAX)/(REAL)RAND_MAX; // if llk>100, change has to be in the opposite direction // For a single restraint, sqrt(llk)=dx/sigma, so do not go above 10*sigma if((*mode)->mLLKDeriv>0) { change -= 0.3*sqrt(llk); if(change<-1) change=-1; } else { change += 0.3*sqrt(llk); if(change>1) change=1; } (*mode)->Print(cout); change *= mutationAmplitude * (*mode)->mBaseAmplitude; cout <<" Change="<"<mLLKDeriv*change<mBaseAmplitude; (*mode)->Stretch(change); llk=0; //(*mode)->RandomStretch(change * mutationAmplitude * (*mode)->mBaseAmplitude); for(map::const_iterator pos=(*mode)->mvpBrokenBond.begin(); pos!=(*mode)->mvpBrokenBond.end();++pos) { cout<<" "<first->GetName()<<", llk= "<first->GetLogLikelihood(false,false) <<" ?->"<first->GetLogLikelihood(false,false)+pos->first->GetDeriv((*mode)->mDerivXYZ,true)*change <<"? (deriv="<first->GetDeriv((*mode)->mDerivXYZ)<<", "<first->GetDeriv((*mode)->mDerivXYZ,true); cout<<") ->" <first->GetLogLikelihood()<first->GetLogLikelihood(false,false); } for(map::const_iterator pos=(*mode)->mvpBrokenBondAngle.begin(); pos!=(*mode)->mvpBrokenBondAngle.end();++pos) { cout<<" "<first->GetName()<<", llk= "<first->GetLogLikelihood(false,false) <<" ?->"<first->GetLogLikelihood(false,false)+pos->first->GetDeriv((*mode)->mDerivXYZ,true)*change <<"? (deriv="<first->GetDeriv((*mode)->mDerivXYZ)<<", "<first->GetDeriv((*mode)->mDerivXYZ,true); cout<<") ->" <first->GetLogLikelihood()<first->GetLogLikelihood(false,false); } for(map::const_iterator pos=(*mode)->mvpBrokenDihedralAngle.begin(); pos!=(*mode)->mvpBrokenDihedralAngle.end();++pos) { cout<<" "<first->GetName()<<", llk= "<first->GetLogLikelihood(false,false) <<" ?->"<first->GetLogLikelihood(false,false)+pos->first->GetDeriv((*mode)->mDerivXYZ,true)*change <<"? (deriv="<first->GetDeriv((*mode)->mDerivXYZ)<<", "<first->GetDeriv((*mode)->mDerivXYZ,true); cout<<") ->" <first->GetLogLikelihood()<first->GetLogLikelihood(false,false); } cout <<" -> "<::iterator mode=mvpStretchModeFree.begin(); mode!=mvpStretchModeFree.end();++mode) { if((rand()%2)==0) (*mode)->RandomStretch(mutationAmplitude); } TAU_PROFILE_STOP(timer2); if((rand()%3)==0) { // Now do an hybrid move for other modes, with a smaller amplitude (<=0.5) // 1) Calc LLK and derivatives for restraints mLogLikelihood=0; TAU_PROFILE_START(timer3); for(vector::const_iterator pos=mvpBond.begin();pos!=mvpBond.end();++pos) mLogLikelihood+=(*pos)->GetLogLikelihood(true,true); for(vector::const_iterator pos=mvpBondAngle.begin();pos!=mvpBondAngle.end();++pos) mLogLikelihood+=(*pos)->GetLogLikelihood(true,true); for(vector::const_iterator pos=mvpDihedralAngle.begin();pos!=mvpDihedralAngle.end();++pos) mLogLikelihood+=(*pos)->GetLogLikelihood(true,true); TAU_PROFILE_STOP(timer3); TAU_PROFILE_START(timer4); for(list::const_iterator mode=mvpStretchModeNotFree.begin(); mode!=mvpStretchModeNotFree.end();++mode) { // 2) Choose Stretch modes if((rand()%3)==0) { // 2) Get the derivative of the overall LLK for this mode (*mode)->CalcDeriv(); REAL llk=0; for(map::const_iterator pos=(*mode)->mvpBrokenBond.begin(); pos!=(*mode)->mvpBrokenBond.end();++pos) llk+=pos->first->GetLogLikelihood(false,false); for(map::const_iterator pos=(*mode)->mvpBrokenBondAngle.begin(); pos!=(*mode)->mvpBrokenBondAngle.end();++pos) llk+=pos->first->GetLogLikelihood(false,false); for(map::const_iterator pos=(*mode)->mvpBrokenDihedralAngle.begin(); pos!=(*mode)->mvpBrokenDihedralAngle.end();++pos) llk+=pos->first->GetLogLikelihood(false,false); REAL change=(2.*(REAL)rand()-(REAL)RAND_MAX)/(REAL)RAND_MAX; // if llk>100, change has to be in the direction minimising the llk if((*mode)->mLLKDeriv>0) { change -= 0.01*llk; if(change<-1) change=-1; } else { change += 0.01*llk; if(change>1) change=1; } if(mutationAmplitude<0.5) change *= mutationAmplitude * (*mode)->mBaseAmplitude; else change *= 0.5 * (*mode)->mBaseAmplitude; (*mode)->Stretch(change); } } // Here we do not take mLogLikelihoodScale into account // :TODO: take into account cases where the lllk cannot go down to 0 because of // combined restraints. if( ((rand()%100)==0) && (mLogLikelihood>(mvpRestraint.size()*10))) this->OptimizeConformationSteepestDescent(0.02,5); TAU_PROFILE_STOP(timer4); } // Perform MD moves if there are MDAtomGroups #if 0 for(list::iterator pos=mvMDAtomGroup.begin();pos!=mvMDAtomGroup.end();++pos) { if((rand()%100)==0) { map v0; for(set::iterator at=pos->mvpAtom.begin();at!=pos->mvpAtom.end();++at) v0[*at]=XYZ(rand()/(REAL)RAND_MAX+0.5,rand()/(REAL)RAND_MAX+0.5,rand()/(REAL)RAND_MAX+0.5); const REAL nrj0=20*(pos->mvpBond.size()+pos->mvpBondAngle.size()+pos->mvpDihedralAngle.size()); map > vr; this->MolecularDynamicsEvolve(v0, int(100*sqrt(mutationAmplitude)),0.002, (const vector) (pos->mvpBond), (const vector) (pos->mvpBondAngle), (const vector) (pos->mvpDihedralAngle), vr,nrj0); } } #endif } // Do a steepest descent from time to time if((rand()%100)==0) this->OptimizeConformationSteepestDescent(0.02,1); mClockLogLikelihood.Click(); #endif } } } if((rand()%100)==0) {// From time to time, bring back average position to 0 REAL x0=0,y0=0,z0=0; for(vector::iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos) { x0 += (*pos)->X(); y0 += (*pos)->Y(); z0 += (*pos)->Z(); } x0 /= mvpAtom.size(); y0 /= mvpAtom.size(); z0 /= mvpAtom.size(); for(vector::iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos) { (*pos)->X() -= x0; (*pos)->Y() -= y0; (*pos)->Z() -= z0; } } mRandomMoveIsDone=true; VFN_DEBUG_EXIT("Molecule::GlobalOptRandomMove()",4) } REAL Molecule::GetLogLikelihood()const { if( (mClockLogLikelihood>mClockAtomList) &&(mClockLogLikelihood>mClockBondList) &&(mClockLogLikelihood>mClockBondAngleList) &&(mClockLogLikelihood>mClockDihedralAngleList) &&(mClockLogLikelihood>mClockAtomPosition) &&(mClockLogLikelihood>mClockScatterer)) return mLogLikelihood*mLogLikelihoodScale; TAU_PROFILE("Molecule::GetLogLikelihood()","REAL ()",TAU_DEFAULT); mLogLikelihood=this->RefinableObj::GetLogLikelihood(); mClockLogLikelihood.Click(); return mLogLikelihood*mLogLikelihoodScale; } unsigned int Molecule::GetNbLSQFunction()const { return 1; } const CrystVector_REAL& Molecule::GetLSQCalc(const unsigned int) const { mLSQCalc.resize(mvpRestraint.size()); REAL *p=mLSQCalc.data(); for(vector::const_iterator pos=this->GetBondList().begin();pos!=this->GetBondList().end();++pos) *p++=(*pos)->GetLength(); for(vector::const_iterator pos=this->GetBondAngleList().begin();pos!=this->GetBondAngleList().end();++pos) *p++=(*pos)->GetAngle(); for(vector::const_iterator pos=this->GetDihedralAngleList().begin();pos!=this->GetDihedralAngleList().end();++pos) *p++=(*pos)->GetAngle(); return mLSQCalc; } const CrystVector_REAL& Molecule::GetLSQObs(const unsigned int) const { mLSQObs.resize(mvpRestraint.size()); REAL *p=mLSQObs.data(); for(vector::const_iterator pos=this->GetBondList().begin();pos!=this->GetBondList().end();++pos) *p++=(*pos)->GetLength0(); for(vector::const_iterator pos=this->GetBondAngleList().begin();pos!=this->GetBondAngleList().end();++pos) *p++=(*pos)->GetAngle0(); for(vector::const_iterator pos=this->GetDihedralAngleList().begin();pos!=this->GetDihedralAngleList().end();++pos) *p++=(*pos)->GetAngle0(); return mLSQObs; } const CrystVector_REAL& Molecule::GetLSQWeight(const unsigned int) const { //:TODO: USe a clock to avoid re-computation mLSQWeight.resize(mvpRestraint.size()); REAL *p=mLSQWeight.data(); for(vector::const_iterator pos=this->GetBondList().begin();pos!=this->GetBondList().end();++pos) *p++=1/((*pos)->GetLengthSigma()* (*pos)->GetLengthSigma()+1e-6); for(vector::const_iterator pos=this->GetBondAngleList().begin();pos!=this->GetBondAngleList().end();++pos) *p++=1/((*pos)->GetAngleSigma()* (*pos)->GetAngleSigma()+1e-6); for(vector::const_iterator pos=this->GetDihedralAngleList().begin();pos!=this->GetDihedralAngleList().end();++pos) *p++=1/((*pos)->GetAngleSigma()* (*pos)->GetAngleSigma()+1e-6); mLSQWeight*=mLogLikelihoodScale; return mLSQWeight; } const CrystVector_REAL& Molecule::GetLSQDeriv(const unsigned int n, RefinablePar&par) { //:TODO: return analytical derivatives return RefinableObj::GetLSQDeriv(n,par); } void Molecule::TagNewBestConfig()const { this->ResetRigidGroupsPar(); #if 0 cout<<"Molecule::TagNewBestConfig()"<::const_iterator pos; for(pos=mvpBond.begin();pos!=mvpBond.end();++pos) { cout<<"BondLength="<<(*pos)->GetLength(); (*pos)->XMLOutput(cout); } } { vector::const_iterator pos; for(pos=mvpBondAngle.begin();pos!=mvpBondAngle.end();++pos) { cout<<"BondAngle="<<(*pos)->GetAngle(); (*pos)->XMLOutput(cout); } } { vector::const_iterator pos; for(pos=mvpDihedralAngle.begin();pos!=mvpDihedralAngle.end();++pos) { cout<<"DihedralAngle="<<(*pos)->GetAngle(); (*pos)->XMLOutput(cout); } } for(list::iterator pos=mvMDAtomGroup.begin();pos!=mvMDAtomGroup.end();++pos) { char buf[100]; for(set::iterator at1=pos->mvpAtom.begin();at1!=pos->mvpAtom.end();++at1) { sprintf(buf,"%5s : ",(*at1)->GetName().c_str()); cout<::iterator at2=at1;at2!=pos->mvpAtom.end();++at2) { if(at1==at2) continue; sprintf(buf,"%5s(%6.3f),",(*at2)->GetName().c_str(),GetBondLength(**at1,**at2)); cout<UpdateScattCompList(); VFN_DEBUG_EXIT("Molecule::GetScatteringComponentList()",3) return mScattCompList; } string Molecule::GetComponentName(const int i) const { //if(mvpAtom[i]->IsDummy()) return "Dummy"; return mvpAtom[i]->GetName(); } ostream& Molecule::POVRayDescription(ostream &os,const CrystalPOVRayOptions &options)const { VFN_DEBUG_ENTRY("Molecule::POVRayDescription()",3) const REAL xMin=options.mXmin; const REAL xMax=options.mXmax; const REAL yMin=options.mYmin; const REAL yMax=options.mYmax; const REAL zMin=options.mZmin; const REAL zMax=options.mZmax; if(mvpAtom.size()==0) { VFN_DEBUG_EXIT("Molecule::POVRayDescription():No atom to display !",4) return os; } this->UpdateScattCompList(); const REAL aa=this->GetCrystal().GetLatticePar(0); const REAL bb=this->GetCrystal().GetLatticePar(1); const REAL cc=this->GetCrystal().GetLatticePar(2); os << "// Description of Molecule :" << this->GetName() < vXYZCoords; { this->GetScatteringComponentList(); REAL x0,y0,z0; for(long i=0;iGetCrystal().GetSpaceGroup(). GetAllSymmetrics(x0,y0,z0,false,false,false)); } } CrystMatrix_int translate(27,3); translate= -1,-1,-1, -1,-1, 0, -1,-1, 1, -1, 0,-1, -1, 0, 0, -1, 0, 1, -1, 1,-1, -1, 1, 0, -1, 1, 1, 0,-1,-1, 0,-1, 0, 0,-1, 1, 0, 0,-1, 0, 0, 0, 0, 0, 1, 0, 1,-1, 0, 1, 0, 0, 1, 1, 1,-1,-1, 1,-1, 0, 1,-1, 1, 1, 0,-1, 1, 0, 0, 1, 0, 1, 1, 1,-1, 1, 1, 0, 1, 1, 1; REAL dx,dy,dz; CrystVector_REAL x(mvpAtom.size()),y(mvpAtom.size()),z(mvpAtom.size()); CrystVector_REAL xSave,ySave,zSave; const int nbSymmetrics=vXYZCoords[0].rows(); unsigned int ct=0; for(int i=0;i isinside(x.numElements()); CrystVector borderdist(x.numElements());//distance to display limit CrystVector x0,y0,z0; x0=x;y0=y;z0=z; if( ((x.min()xMin)) &&((y.min()yMin)) &&((z.min()zMin))) { os<<" //Symetric#"<<++ct<=xMin) && (x(k)<=xMax)) && ((y(k)>=yMin) && (y(k)<=yMax)) && ((z(k)>=zMin) && (z(k)<=zMax)); if(isinside(k)) borderdist(k)=0; else { borderdist(k)=0; if(xMin>x(k)) borderdist(k)+=(xMin-x(k))*aa*(xMin-x(k))*aa; if(yMin>y(k)) borderdist(k)+=(yMin-y(k))*bb*(yMin-y(k))*bb; if(zMin>z(k)) borderdist(k)+=(zMin-z(k))*cc*(zMin-z(k))*cc; if(xMaxGetCrystal().GetDynPopCorr(this,k); this->GetCrystal().FractionalToOrthonormalCoords(x(k),y(k),z(k)); if((mvpAtom[k]->IsDummy()) || (fout<0.001)) continue; if(options.mShowHydrogens==false && (mvpAtom[k]->GetScatteringPower().GetForwardScatteringFactor(RAD_XRAY)<1.5)) continue; // const float r=mvpAtom[k]->GetScatteringPower().GetColourRGB()[0]; // const float g=mvpAtom[k]->GetScatteringPower().GetColourRGB()[1]; // const float b=mvpAtom[k]->GetScatteringPower().GetColourRGB()[2]; const float f=mvpAtom[k]->GetOccupancy()*this->GetOccupancy(); if(options.mShowLabel) { /* const float colour0[] = {0.0f, 0.0f, 0.0f, 0.0f}; GLfloat colourChar [] = {1.0, 1.0, 1.0, 1.0}; if((r>0.8)&&(g>0.8)&&(b>0.8)) { colourChar[0] = 0.5; colourChar[1] = 0.5; colourChar[2] = 0.5; } glMaterialfv(GL_FRONT, GL_AMBIENT, colour0); glMaterialfv(GL_FRONT, GL_DIFFUSE, colour0); glMaterialfv(GL_FRONT, GL_SPECULAR, colour0); glMaterialfv(GL_FRONT, GL_EMISSION, colourChar); glMaterialfv(GL_FRONT, GL_SHININESS,colour0); glRasterPos3f(x(k), y(k), z(k)); crystGLPrint(mvpAtom[k]->GetName()); */ } os << " ObjCrystAtom(" <GetScatteringPower().GetRadius()/3.0<<"," <<"colour_"+mvpAtom[k]->GetScatteringPower().GetName()<<"," <GetAtom1().IsDummy()) ||(mvpBond[k]->GetAtom2().IsDummy()) ) continue; if(options.mShowHydrogens==false && ( (mvpBond[k]->GetAtom1().GetScatteringPower().GetForwardScatteringFactor(RAD_XRAY)<1.5) ||(mvpBond[k]->GetAtom2().GetScatteringPower().GetForwardScatteringFactor(RAD_XRAY)<1.5))) continue; unsigned long n1,n2; //:KLUDGE: Get the atoms for(n1=0;n1GetAtom1())) break; for(n2=0;n2GetAtom2())) break; REAL fout=1.0; if((isinside(n1)==false) || (isinside(n2)==false)) fout=exp(-(borderdist(n1)+borderdist(n2))/2)*(this->GetCrystal().GetDynPopCorr(this,n1)+this->GetCrystal().GetDynPopCorr(this,n2))/2; if(fout<0.001) continue; REAL x1=x(n1),y1=y(n1),z1=z(n1), x2=x(n2),y2=y(n2),z2=z(n2); REAL dx=x2-x1,dy=y2-y1,dz=z2-z1; const REAL r=sqrt(abs(dx*dx+dy*dy+dz*dz))+1e-6; const REAL r1=mvpAtom[n1]->GetScatteringPower().GetRadius()/3.0; const REAL r2=mvpAtom[n2]->GetScatteringPower().GetRadius()/3.0; x1+=dx/r*r1*sqrt(abs(1-0.1/r1)); y1+=dy/r*r1*sqrt(abs(1-0.1/r1)); z1+=dz/r*r1*sqrt(abs(1-0.1/r1)); x2-=dx/r*r2*sqrt(abs(1-0.1/r2)); y2-=dy/r*r2*sqrt(abs(1-0.1/r2)); z2-=dz/r*r2*sqrt(abs(1-0.1/r2)); const REAL f=this->GetOccupancy()*(mvpAtom[n1]->GetOccupancy()+mvpAtom[n2]->GetOccupancy())/2.0; os << " ObjCrystBond(" <IsFreeTorsion()) os<<"colour_freebond,"; else os<<"colour_nonfreebond,"; os<200) large=true; REAL en=1; if(displayEnantiomer==true) en=-1; this->UpdateScattCompList(); //this->BuildRingList(); //this->BuildStretchModeBondLength(); //this->BuildStretchModeBondAngle(); //this->BuildStretchModeTorsion(); const REAL aa=this->GetCrystal().GetLatticePar(0); const REAL bb=this->GetCrystal().GetLatticePar(1); const REAL cc=this->GetCrystal().GetLatticePar(2); const GLfloat colour0[] = {0.0f, 0.0f, 0.0f, 0.0f}; glMaterialfv(GL_FRONT, GL_SPECULAR, colour0); glMaterialfv(GL_FRONT, GL_EMISSION, colour0); glMaterialfv(GL_FRONT, GL_SHININESS, colour0); glPolygonMode(GL_FRONT, GL_FILL); GLUquadricObj* pQuadric = gluNewQuadric(); if(true==onlyIndependentAtoms)// { REAL xc=mXYZ(0),yc=mXYZ(1),zc=mXYZ(2); this->GetCrystal().FractionalToOrthonormalCoords(xc,yc,zc); vector::const_iterator pos; for(pos=mvpAtom.begin();pos!=mvpAtom.end();pos++) { if((*pos)->IsDummy())continue; if(hideHydrogens && ((*pos)->GetScatteringPower().GetForwardScatteringFactor(RAD_XRAY)<1.5)) continue; const float r=(*pos)->GetScatteringPower().GetColourRGB()[0]; const float g=(*pos)->GetScatteringPower().GetColourRGB()[1]; const float b=(*pos)->GetScatteringPower().GetColourRGB()[2]; const float f=(*pos)->GetOccupancy()*this->GetOccupancy(); glPushMatrix(); if(displayNames) { GLfloat colourChar [] = {1.0, 1.0, 1.0, 1.0}; GLfloat colourCharRing [] = {1.0, 1.0, 0.8, 1.0}; if((r>0.8)&&(g>0.8)&&(b>0.8)) { colourChar[0] = 0.5; colourChar[1] = 0.5; colourChar[2] = 0.5; } if((*pos)->IsInRing()) glMaterialfv(GL_FRONT, GL_EMISSION, colourCharRing); else glMaterialfv(GL_FRONT, GL_EMISSION, colourChar); glMaterialfv(GL_FRONT, GL_SHININESS, colour0); glTranslatef((*pos)->X()*en+xc, (*pos)->Y()+yc, (*pos)->Z()+zc); crystGLPrint((*pos)->GetName()); } else { const GLfloat colourAtom [] = {r, g, b, f}; glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, colourAtom); glTranslatef((*pos)->X()*en+xc, (*pos)->Y()+yc, (*pos)->Z()+zc); gluSphere(pQuadric,(*pos)->GetScatteringPower().GetRadius()/3.,20,20); } glPopMatrix(); } }//Only independent atoms ? else { VFN_DEBUG_ENTRY("Molecule::GLInitDisplayList():Show all symmetrics",3) // Reverse index of atoms map rix; { long i=0; for(vector::const_iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos) rix[*pos]=i++; } vector vXYZCoords; { this->GetScatteringComponentList(); REAL x0,y0,z0; for(long i=0;iGetCrystal().GetSpaceGroup(). GetAllSymmetrics(x0,y0,z0,false,false,false)); } } CrystMatrix_int translate(27,3); translate= -1,-1,-1, -1,-1, 0, -1,-1, 1, -1, 0,-1, -1, 0, 0, -1, 0, 1, -1, 1,-1, -1, 1, 0, -1, 1, 1, 0,-1,-1, 0,-1, 0, 0,-1, 1, 0, 0,-1, 0, 0, 0, 0, 0, 1, 0, 1,-1, 0, 1, 0, 0, 1, 1, 1,-1,-1, 1,-1, 0, 1,-1, 1, 1, 0,-1, 1, 0, 0, 1, 0, 1, 1, 1,-1, 1, 1, 0, 1, 1, 1; REAL dx,dy,dz; CrystVector_REAL x(mvpAtom.size()),y(mvpAtom.size()),z(mvpAtom.size()); CrystVector_REAL xSave,ySave,zSave; const int nbSymmetrics=vXYZCoords[0].rows(); for(int i=0;i isinside(x.numElements()); CrystVector borderdist(x.numElements());//distance to display limit const bool molcenter_isinside =( ((x.sum()/x.size())>=xMin) && ((x.sum()/x.size())<=xMax) && ((y.sum()/y.size())>=yMin) && ((y.sum()/y.size())<=yMax) && ((z.sum()/z.size())>=zMin) && ((z.sum()/z.size())<=zMax)); if( ((x.min()<(xMax+fadeDistance/aa)) && (x.max()>(xMin-fadeDistance/aa))) &&((y.min()<(yMax+fadeDistance/bb)) && (y.max()>(yMin-fadeDistance/bb))) &&((z.min()<(zMax+fadeDistance/cc)) && (z.max()>(zMin-fadeDistance/cc)))) { for(unsigned int k=0;k=xMin) && (x(k)<=xMax)) && ((y(k)>=yMin) && (y(k)<=yMax)) && ((z(k)>=zMin) && (z(k)<=zMax)); if(isinside(k)) borderdist(k)=0; else { borderdist(k)=0; if(xMin>x(k)) borderdist(k)+=(xMin-x(k))*aa*(xMin-x(k))*aa; if(yMin>y(k)) borderdist(k)+=(yMin-y(k))*bb*(yMin-y(k))*bb; if(zMin>z(k)) borderdist(k)+=(zMin-z(k))*cc*(zMin-z(k))*cc; if(xMaxfadeDistance) fout = 0; else fout*=(fadeDistance-borderdist(k))/fadeDistance*this->GetCrystal().GetDynPopCorr(this,k); } #ifdef __DEBUG__ char ch[100]; sprintf(ch,"%d %d %d %s %5.2f %5.2f %5.2f d=%5.2f fout=%5.3f",i,j,k,mvpAtom[k]->GetName().c_str(),x(k),y(k),z(k),borderdist(k),fout); VFN_DEBUG_MESSAGE(ch,4) #endif this->GetCrystal().FractionalToOrthonormalCoords(x(k),y(k),z(k)); if(mvpAtom[k]->IsDummy()) continue; if(hideHydrogens && (mvpAtom[k]->GetScatteringPower().GetForwardScatteringFactor(RAD_XRAY)<1.5)) continue; if(fout<0.01) continue; glPushMatrix(); const float r=mvpAtom[k]->GetScatteringPower().GetColourRGB()[0]; const float g=mvpAtom[k]->GetScatteringPower().GetColourRGB()[1]; const float b=mvpAtom[k]->GetScatteringPower().GetColourRGB()[2]; const float f=mvpAtom[k]->GetOccupancy()*this->GetOccupancy(); if(displayNames) { if((fout>0.99) || molcenter_isinside) { GLfloat colourChar [] = {1.0, 1.0, 1.0, f*fout}; GLfloat colourCharRing [] = {1.0, 1.0, 0.8, f*fout}; if((r>0.8)&&(g>0.8)&&(b>0.8)) { colourChar[0] = 0.5; colourChar[1] = 0.5; colourChar[2] = 0.5; } if(mvpAtom[k]->IsInRing()) glMaterialfv(GL_FRONT, GL_EMISSION, colourCharRing); else glMaterialfv(GL_FRONT, GL_EMISSION, colourChar); glRasterPos3f(x(k)*en, y(k), z(k)); crystGLPrint(mvpAtom[k]->GetName()); } } else { if(!large) { const GLfloat colourAtom [] = {r*fout, g*fout, b*fout, f*fout}; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,colourAtom); glTranslatef(x(k)*en, y(k), z(k)); gluSphere(pQuadric, mvpAtom[k]->GetScatteringPower().GetRadius()/3.,20,20); } else { const GLfloat colourAtom [] = {r*fout, g*fout, b*fout, f*fout}; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,colourAtom); glTranslatef(x(k)*en, y(k), z(k)); gluSphere(pQuadric,.15,10,10); } } glPopMatrix(); } if(displayNames==false) { if(large) { for(unsigned int k=0;kGetAtom1().IsDummy()) ||(mvpBond[k]->GetAtom2().IsDummy()) ) continue; if(hideHydrogens && ( (mvpBond[k]->GetAtom1().GetScatteringPower().GetForwardScatteringFactor(RAD_XRAY)<1.5) ||(mvpBond[k]->GetAtom2().GetScatteringPower().GetForwardScatteringFactor(RAD_XRAY)<1.5))) continue; const unsigned long n1=rix[&(mvpBond[k]->GetAtom1())], n2=rix[&(mvpBond[k]->GetAtom2())]; REAL fout=1.0; if(((isinside(n1)==false) || (isinside(n2)==false)) && ((molcenter_isinside==false) || (fullMoleculeInLimits==false))) { if((fadeDistance==0) || ((borderdist(n1)+borderdist(n2))/2)>fadeDistance) fout = 0; else fout*=(fadeDistance-(borderdist(n1)+borderdist(n2))/2)/fadeDistance* (this->GetCrystal().GetDynPopCorr(this,n1)+this->GetCrystal().GetDynPopCorr(this,n2))/2; } if(fout<0.01) continue; const float r1=mvpBond[k]->GetAtom1().GetScatteringPower().GetColourRGB()[0]; const float g1=mvpBond[k]->GetAtom1().GetScatteringPower().GetColourRGB()[1]; const float b1=mvpBond[k]->GetAtom1().GetScatteringPower().GetColourRGB()[2]; const float f1=mvpBond[k]->GetAtom1().GetOccupancy()*this->GetOccupancy(); const float r2=mvpBond[k]->GetAtom2().GetScatteringPower().GetColourRGB()[0]; const float g2=mvpBond[k]->GetAtom2().GetScatteringPower().GetColourRGB()[1]; const float b2=mvpBond[k]->GetAtom2().GetScatteringPower().GetColourRGB()[2]; const float f2=mvpBond[k]->GetAtom2().GetOccupancy()*this->GetOccupancy(); const GLfloat colourAtom1 [] = {r1, g1, b1, f1*fout}; const GLfloat colourAtom2 [] = {r2, g2, b2, f2*fout}; #if 0 glPushMatrix(); glBegin(GL_LINE_STRIP); glMaterialfv(GL_FRONT, GL_SPECULAR, colourAtom1); glMaterialfv(GL_FRONT, GL_EMISSION, colourAtom1); glMaterialfv(GL_FRONT, GL_SHININESS, colourAtom1); glVertex3f(x(n1)*en,y(n1),z(n1)); glVertex3f((x(n1)+x(n2))/2*en,(y(n1)+y(n2))/2,(z(n1)+z(n2))/2); glMaterialfv(GL_FRONT, GL_SPECULAR, colourAtom2); glMaterialfv(GL_FRONT, GL_EMISSION, colourAtom2); glMaterialfv(GL_FRONT, GL_SHININESS, colourAtom2); glVertex3f(x(n2)*en,y(n2),z(n2)); glEnd(); glPopMatrix(); #else const REAL height= sqrt(abs( (x(n2)-x(n1))*(x(n2)-x(n1)) +(y(n2)-y(n1))*(y(n2)-y(n1)) +(z(n2)-z(n1))*(z(n2)-z(n1)))); glPushMatrix(); glTranslatef(x(n1)*en, y(n1), z(n1)); GLUquadricObj *quadobj = gluNewQuadric(); glRotatef(180,(x(n2)-x(n1))*en,y(n2)-y(n1),z(n2)-z(n1)+height);// ?!?!?! glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,colourAtom1); gluCylinder(quadobj,.1,.1,height/2,10,1 ); gluDeleteQuadric(quadobj); glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,colourAtom2); GLUquadricObj *quadobj2 = gluNewQuadric(); glTranslatef(0, 0, height/2); gluCylinder(quadobj2,.1,.1,height/2,10,1 ); gluDeleteQuadric(quadobj2); glPopMatrix(); #endif } } else { for(unsigned int k=0;kGetAtom1().IsDummy()) ||(mvpBond[k]->GetAtom2().IsDummy()) ) continue; if(hideHydrogens && ( (mvpBond[k]->GetAtom1().GetScatteringPower().GetForwardScatteringFactor(RAD_XRAY)<1.5) ||(mvpBond[k]->GetAtom2().GetScatteringPower().GetForwardScatteringFactor(RAD_XRAY)<1.5))) continue; const unsigned long n1=rix[&(mvpBond[k]->GetAtom1())], n2=rix[&(mvpBond[k]->GetAtom2())]; REAL fout=1.0; //if((isinside(n1)==false) || (isinside(n2)==false)) fout=exp(-(borderdist(n1)+borderdist(n2))/2); if(((isinside(n1)==false) || (isinside(n2)==false)) && ((molcenter_isinside==false) || (fullMoleculeInLimits==false))) { if ((fadeDistance == 0) || ((borderdist(n1) + borderdist(n2)) / 2)>fadeDistance) fout = 0; else fout=(fadeDistance-(borderdist(n1)+borderdist(n2))/2)/fadeDistance* (this->GetCrystal().GetDynPopCorr(this,n1)+this->GetCrystal().GetDynPopCorr(this,n2))/2; } if(fout<0.01) continue; // Is the bond in a rigid group ? bool isRigidGroup=false; for(vector::const_iterator pos=this->GetRigidGroupList().begin();pos!=this->GetRigidGroupList().end();++pos) { if( ((*pos)->find(&(mvpBond[k]->GetAtom1()))!=(*pos)->end()) &&((*pos)->find(&(mvpBond[k]->GetAtom2()))!=(*pos)->end()) ) { isRigidGroup=true; break; } } const float f=(mvpBond[k]->GetAtom1().GetOccupancy()+mvpBond[k]->GetAtom2().GetOccupancy())/2*this->GetOccupancy(); const GLfloat colour_bondnonfree[]= { 0.2f*fout, .2f*fout, .2f*fout, f*fout }; const GLfloat colour_bondrigid[]= { 0.5f*fout, .3f*fout, .3f*fout, f*fout }; const GLfloat colour_bondfree[]= { 0.8f*fout, .8f*fout, .8f*fout, f*fout }; if(isRigidGroup) glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,colour_bondrigid); else { if(mvpBond[k]->IsFreeTorsion()) glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,colour_bondfree); else glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,colour_bondnonfree); } // Actually make the bond start/end at the surface of the spheres (matters when transparent) REAL x1=x(n1),y1=y(n1),z1=z(n1), x2=x(n2),y2=y(n2),z2=z(n2); REAL dx=x2-x1,dy=y2-y1,dz=z2-z1; const REAL r=sqrt(abs(dx*dx+dy*dy+dz*dz))+1e-6; const REAL r1=mvpAtom[n1]->GetScatteringPower().GetRadius()/3.0; const REAL r2=mvpAtom[n2]->GetScatteringPower().GetRadius()/3.0; x1+=dx/r*r1*sqrt(abs(1-0.1/r1)); y1+=dy/r*r1*sqrt(abs(1-0.1/r1)); z1+=dz/r*r1*sqrt(abs(1-0.1/r1)); x2-=dx/r*r2*sqrt(abs(1-0.1/r2)); y2-=dy/r*r2*sqrt(abs(1-0.1/r2)); z2-=dz/r*r2*sqrt(abs(1-0.1/r2)); glPushMatrix(); glTranslatef(x1*en, y1, z1); GLUquadricObj *quadobj = gluNewQuadric(); //glColor4f(1.0f,1.0f,1.0f,1.0); const REAL height= sqrt(abs( (x2-x1)*(x2-x1) +(y2-y1)*(y2-y1) +(z2-z1)*(z2-z1))); glRotatef(180,(x2-x1)*en,y2-y1,z2-z1+height);// ?!?!?! gluCylinder(quadobj,.1,.1,height,10,1 ); gluDeleteQuadric(quadobj); glPopMatrix(); } } } }//if in limits x=xSave; y=ySave; z=zSave; }//for translation VFN_DEBUG_EXIT("Molecule::GLInitDisplayList():Symmetric#"<GetName()==this->GetFormula(); string thename=name; if(thename==string("")) {// This should not be needed, the atom will reset the parameters name when its name is set char buf[100]; if(pPow!=0) sprintf(buf,"%s_%s_%lu",this->GetName().c_str(),pPow->GetName().c_str(),mvpAtom.size()+1); else sprintf(buf,"%s_X_%lu",this->GetName().c_str(),mvpAtom.size()+1); thename=buf; } mvpAtom.push_back(new MolAtom(x,y,z,pPow,thename,*this)); mClockAtomPosition.Click(); mClockAtomScattPow.Click(); ++mScattCompList; { RefinablePar tmp(thename+"_x",&(mvpAtom.back()->X()),0.,1., gpRefParTypeScattConformX, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.); tmp.AssignClock(mClockAtomPosition); tmp.SetGlobalOptimStep(0.05); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { RefinablePar tmp(thename+"_y",&(mvpAtom.back()->Y()),0.,1., gpRefParTypeScattConformY, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.); tmp.AssignClock(mClockAtomPosition); tmp.SetGlobalOptimStep(0.05); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { RefinablePar tmp(thename+"_z",&(mvpAtom.back()->Z()),0.,1., gpRefParTypeScattConformZ, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.); tmp.AssignClock(mClockAtomPosition); tmp.SetGlobalOptimStep(0.05); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } mClockScatterer.Click(); if(molnameasformula || (this->GetName().size()==0)) this->SetName(this->GetFormula()); if(updateDisplay) this->UpdateDisplay(); VFN_DEBUG_EXIT("Molecule::AddAtom()",5) } vector::iterator Molecule::RemoveAtom(MolAtom &atom, const bool del) { VFN_DEBUG_ENTRY("Molecule::RemoveAtom():"<::iterator pos=find(mvpAtom.begin(),mvpAtom.end(),&atom); if(pos==mvpAtom.end()) { throw ObjCrystException("Molecule::RemoveAtom():"+atom.GetName() +" is not in this Molecule:"+this->GetName()); } const bool molnameasformula= this->GetName()==this->GetFormula(); // Delete parameters this->RemovePar(&(this->GetPar(&(atom.X())))); this->RemovePar(&(this->GetPar(&(atom.Y())))); this->RemovePar(&(this->GetPar(&(atom.Z())))); // Delete relevant bonds, bond angles, dihedral angles... for(vector::iterator posb=mvpBond.begin();posb!=mvpBond.end();) { if( (&atom==&((*posb)->GetAtom1())) || (&atom==&((*posb)->GetAtom2())) ) { posb=this->RemoveBond(**posb, del); } else ++posb; } for(vector::iterator posb=mvpBondAngle.begin();posb!=mvpBondAngle.end();) { if( (&atom==&((*posb)->GetAtom1())) || (&atom==&((*posb)->GetAtom2())) ||(&atom==&((*posb)->GetAtom3()))) { posb=this->RemoveBondAngle(**posb, del); } else ++posb; } for(vector::iterator posb=mvpDihedralAngle.begin(); posb!=mvpDihedralAngle.end();) { if( (&atom==&((*posb)->GetAtom1())) || (&atom==&((*posb)->GetAtom2())) ||(&atom==&((*posb)->GetAtom3())) || (&atom==&((*posb)->GetAtom4()))) posb=this->RemoveDihedralAngle(**posb, del); else ++posb; } mClockAtomList.Click(); mClockScatterer.Click(); if(mpCenterAtom==*pos) mpCenterAtom=0; if(del) delete *pos; pos=mvpAtom.erase(pos); --mScattCompList; if(molnameasformula || (this->GetName().size()==0)) this->SetName(this->GetFormula()); this->UpdateDisplay(); VFN_DEBUG_EXIT("Molecule::RemoveAtom()",6) return pos; } void Molecule::AddBond(MolAtom &atom1, MolAtom &atom2, const REAL length, const REAL sigma, const REAL delta, const REAL bondOrder, const bool updateDisplay) { VFN_DEBUG_ENTRY("Molecule::AddBond()",5) mvpBond.push_back(new MolBond(atom1,atom2,length,sigma,delta,*this,bondOrder)); this->AddRestraint(mvpBond.back()); mClockBondList.Click(); if(updateDisplay) this->UpdateDisplay(); VFN_DEBUG_EXIT("Molecule::AddBond()",5) } vector::iterator Molecule::RemoveBond(const MolBond &bond, const bool del) { VFN_DEBUG_ENTRY("Molecule::RemoveBond():"<::iterator pos=find(mvpBond.begin(),mvpBond.end(),&bond); if(pos==mvpBond.end()) { throw ObjCrystException("Molecule::RemoveBond():"+bond.GetAtom1().GetName() +"-"+bond.GetAtom2().GetName() +" is not in this Molecule:"+this->GetName()); } this->RemoveRestraint(*pos); mClockBondList.Click(); if(del) delete *pos; pos= mvpBond.erase(pos); this->UpdateDisplay(); VFN_DEBUG_EXIT("Molecule::RemoveBond():",6) return pos; } vector::const_iterator Molecule::FindBond(const MolAtom &at1,const MolAtom &at2)const { for(vector::const_iterator pos=mvpBond.begin();pos!=mvpBond.end();++pos) { if( ((&((*pos)->GetAtom1())==&at1)&&(&((*pos)->GetAtom2())==&at2)) ||((&((*pos)->GetAtom1())==&at2)&&(&((*pos)->GetAtom2())==&at1))) return pos; } return mvpBond.end(); } vector::iterator Molecule::FindBond(const MolAtom &at1,const MolAtom &at2) { for(vector::iterator pos=mvpBond.begin();pos!=mvpBond.end();++pos) { if( ((&((*pos)->GetAtom1())==&at1)&&(&((*pos)->GetAtom2())==&at2)) ||((&((*pos)->GetAtom1())==&at2)&&(&((*pos)->GetAtom2())==&at1))) return pos; } return mvpBond.end(); } void Molecule::AddBondAngle(MolAtom &atom1, MolAtom &atom2, MolAtom &atom3, const REAL angle, const REAL sigma, const REAL delta, const bool updateDisplay) { VFN_DEBUG_ENTRY("Molecule::AddBondAngle()",5) mvpBondAngle.push_back(new MolBondAngle(atom1,atom2,atom3,angle,sigma,delta,*this)); this->AddRestraint(mvpBondAngle.back()); mClockBondAngleList.Click(); if(updateDisplay) this->UpdateDisplay(); VFN_DEBUG_EXIT("Molecule::AddBondAngle()",5) } vector::iterator Molecule::RemoveBondAngle(const MolBondAngle &angle, const bool del) { VFN_DEBUG_ENTRY("Molecule::RemoveBondAngle():"<::iterator pos=find(mvpBondAngle.begin(),mvpBondAngle.end(),&angle); if(pos==mvpBondAngle.end()) { throw ObjCrystException("Molecule::RemoveBondAngle():"+angle.GetAtom1().GetName() +"-"+angle.GetAtom2().GetName()+"-"+angle.GetAtom3().GetName() +" is not in this Molecule:"+this->GetName()); } this->RemoveRestraint(*pos); mClockBondAngleList.Click(); if(del) delete *pos; pos=mvpBondAngle.erase(pos); this->UpdateDisplay(); VFN_DEBUG_EXIT("Molecule::RemoveBondAngle():",6) return pos; } vector::const_iterator Molecule::FindBondAngle(const MolAtom &at1, const MolAtom &at2, const MolAtom &at3)const { for(vector::const_iterator pos=mvpBondAngle.begin(); pos!=mvpBondAngle.end();++pos) { if( (&((*pos)->GetAtom2())==&at2) &&( ((&((*pos)->GetAtom1())==&at1)&&(&((*pos)->GetAtom3())==&at3)) ||((&((*pos)->GetAtom1())==&at3)&&(&((*pos)->GetAtom3())==&at1)))) return pos; } return mvpBondAngle.end(); } void Molecule::AddDihedralAngle(MolAtom &atom1, MolAtom &atom2, MolAtom &atom3, MolAtom &atom4, const REAL angle, const REAL sigma, const REAL delta, const bool updateDisplay) { VFN_DEBUG_ENTRY("Molecule::AddDihedralAngle()",5) mvpDihedralAngle.push_back(new MolDihedralAngle(atom1,atom2,atom3,atom4, angle,sigma,delta,*this)); this->AddRestraint(mvpDihedralAngle.back()); mClockDihedralAngleList.Click(); if(updateDisplay) this->UpdateDisplay(); VFN_DEBUG_EXIT("Molecule::AddDihedralAngle()",5) } vector::iterator Molecule::RemoveDihedralAngle(const MolDihedralAngle &angle, const bool del) { VFN_DEBUG_ENTRY("Molecule::RemoveDihedralAngle():"<::iterator pos=find(mvpDihedralAngle.begin(), mvpDihedralAngle.end(),&angle); if(pos==mvpDihedralAngle.end()) { throw ObjCrystException("Molecule::RemoveDihedralAngle():"+angle.GetAtom1().GetName() +"-"+angle.GetAtom2().GetName()+"-"+angle.GetAtom3().GetName() +"-"+angle.GetAtom4().GetName() +" is not in this Molecule:"+this->GetName()); } this->RemoveRestraint(*pos); mClockDihedralAngleList.Click(); if(del) delete *pos; pos=mvpDihedralAngle.erase(pos); this->UpdateDisplay(); VFN_DEBUG_ENTRY("Molecule::RemoveDihedralAngle():",6) return pos; } vector::const_iterator Molecule::FindDihedralAngle(const MolAtom &at1, const MolAtom &at2, const MolAtom &at3, const MolAtom &at4)const { for(vector::const_iterator pos=mvpDihedralAngle.begin(); pos!=mvpDihedralAngle.end();++pos) { if( ( ((&((*pos)->GetAtom1())==&at1)&&(&((*pos)->GetAtom2())==&at2)) &&((&((*pos)->GetAtom3())==&at3)&&(&((*pos)->GetAtom4())==&at4))) ||( ((&((*pos)->GetAtom4())==&at1)&&(&((*pos)->GetAtom3())==&at2)) &&((&((*pos)->GetAtom2())==&at3)&&(&((*pos)->GetAtom1())==&at4)))) return pos; } return mvpDihedralAngle.end(); } void Molecule::AddRigidGroup(const RigidGroup &group, const bool updateDisplay) { mvRigidGroup.push_back(new RigidGroup(group)); #ifdef RIGID_BODY_STRICT_EXPERIMENTAL char buf[50]; const unsigned int i=mvRigidGroup.size(); RigidGroup* p=this->GetRigidGroupList().back(); p->mX=0; p->mY=0; p->mZ=0; p->mQuat.Q0()=1; p->mQuat.Q1()=0; p->mQuat.Q2()=0; p->mQuat.Q3()=0; { sprintf(buf,"RigidGroup%d_x",i); RefinablePar tmp(buf,&(p->mX),0.,1., gpRefParTypeScattConformX, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.); tmp.AssignClock(mClockAtomPosition); tmp.SetGlobalOptimStep(0.05); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { sprintf(buf,"RigidGroup%d_y",i); RefinablePar tmp(buf,&(p->mY),0.,1., gpRefParTypeScattConformY, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.); tmp.AssignClock(mClockAtomPosition); tmp.SetGlobalOptimStep(0.05); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { sprintf(buf,"RigidGroup%d_z",i); RefinablePar tmp(buf,&(p->mZ),0.,1., gpRefParTypeScattConformZ, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.); tmp.AssignClock(mClockAtomPosition); tmp.SetGlobalOptimStep(0.05); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { sprintf(buf,"RigidGroup%d_Q1",i); RefinablePar tmp(buf,&(p->mQuat.Q1()),-1,1., gpRefParTypeScattConform, REFPAR_DERIV_STEP_ABSOLUTE,true,false,true,false,1.,1.); tmp.AssignClock(mClockAtomPosition); tmp.SetGlobalOptimStep(0.01); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { sprintf(buf,"RigidGroup%d_Q2",i); RefinablePar tmp(buf,&(p->mQuat.Q2()),-1,1., gpRefParTypeScattConform, REFPAR_DERIV_STEP_ABSOLUTE,true,false,true,false,1.,1.); tmp.AssignClock(mClockAtomPosition); tmp.SetGlobalOptimStep(0.01); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { sprintf(buf,"RigidGroup%d_Q3",i); RefinablePar tmp(buf,&(p->mQuat.Q3()),-1,1., gpRefParTypeScattConform, REFPAR_DERIV_STEP_ABSOLUTE,true,false,true,false,1.,1.); tmp.AssignClock(mClockAtomPosition); tmp.SetGlobalOptimStep(0.01); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } #endif mClockRigidGroup.Click(); if(updateDisplay) this->UpdateDisplay(); } vector::iterator Molecule::RemoveRigidGroup(const RigidGroup &g,const bool updateDisplay, const bool del) { vector::iterator pos=find(mvRigidGroup.begin(),mvRigidGroup.end(),&g); if(pos==mvRigidGroup.end()) return pos; #ifdef RIGID_BODY_STRICT_EXPERIMENTAL // Remove the refinable parameters (even if del==False - used for python delayed deletion) // NOTE - this should only be done outside an optimization, since rigid group translationnal // and rotationnal parameters are resetted at the end of the optimization, and the atomic // parameters are directly the correct ones (thus deletion of the rigid group does not change // the final coordinates). this->RemovePar(&(this->GetPar(&((*pos)->mX)))); this->RemovePar(&(this->GetPar(&((*pos)->mY)))); this->RemovePar(&(this->GetPar(&((*pos)->mZ)))); this->RemovePar(&(this->GetPar(&((*pos)->mQuat.Q1())))); this->RemovePar(&(this->GetPar(&((*pos)->mQuat.Q2())))); this->RemovePar(&(this->GetPar(&((*pos)->mQuat.Q3())))); #endif if(del) delete *pos; pos=mvRigidGroup.erase(pos); if(updateDisplay) this->UpdateDisplay(); return pos; } MolAtom &Molecule::GetAtom(unsigned int i){return *mvpAtom[i];} const MolAtom &Molecule::GetAtom(unsigned int i)const{return *mvpAtom[i];} MolAtom &Molecule::GetAtom(const string &name){return **(this->FindAtom(name));} const MolAtom &Molecule::GetAtom(const string &name)const{return **(this->FindAtom(name));} void Molecule::OptimizeConformation(const long nbTrial,const REAL stopCost) { VFN_DEBUG_ENTRY("Molecule::OptimizeConformation()",5) MonteCarloObj globalOptObj(true); globalOptObj.AddRefinableObj(*this); globalOptObj.SetAlgorithmParallTempering(ANNEALING_EXPONENTIAL,10000.,1., ANNEALING_EXPONENTIAL,10,.1); long nb=nbTrial; mIsSelfOptimizing=true; globalOptObj.Optimize(nb,false,stopCost); mIsSelfOptimizing=false; // Must rebuild Flip & Rotor group, in case they were tested with an absurd conformation mClockFlipGroup.Reset(); mClockRotorGroup.Reset(); VFN_DEBUG_EXIT("Molecule::OptimizeConformation()",5) } void Molecule::OptimizeConformationSteepestDescent(const REAL maxStep,const unsigned nbStep) { //cout<<"LLK="<GetLogLikelihood()< grad; for(vector::iterator pos=this->GetAtomList().begin(); pos!=this->GetAtomList().end();++pos) grad[*pos]=XYZ(0,0,0); // :TODO: remove atoms that are in rigid groups ? for(vector::iterator pos=this->GetBondList().begin(); pos!=this->GetBondList().end();++pos) (*pos)->CalcGradient(grad); for(vector::iterator pos=this->GetBondAngleList().begin(); pos!=this->GetBondAngleList().end();++pos) (*pos)->CalcGradient(grad); for(vector::iterator pos=this->GetDihedralAngleList().begin(); pos!=this->GetDihedralAngleList().end();++pos) (*pos)->CalcGradient(grad); #if 0 // Display gradient - for tests for(map::const_iterator pos=grad.begin();pos!=grad.end();++pos) { char buf[100]; sprintf(buf,"%10s Grad LLK= (%8.3f %8.3f %8.3f)", pos->first->GetName().c_str(),pos->second.x,pos->second.y,pos->second.z); cout<::const_iterator pos=grad.begin();pos!=grad.end();++pos) { if(abs(pos->second.x)>f) f=abs(pos->second.x); if(abs(pos->second.y)>f) f=abs(pos->second.y); if(abs(pos->second.z)>f) f=abs(pos->second.z); } if(f>1e-6) f=maxStep/f; else break;//nothing to optimize ? // Average derivatives inside rigid groups //:TODO: still allow rotations of rigid groups ? //:TODO: Handle case when one atom belongs to several rigid groups... for(vector::const_iterator pos=this->GetRigidGroupList().begin();pos!=this->GetRigidGroupList().end();++pos) { if((*pos)->size()==0) continue; // Just in case... REAL dx=0,dy=0,dz=0; for(set::const_iterator at=(*pos)->begin();at!=(*pos)->end();++at) { dx+=(*at)->GetX(); dy+=(*at)->GetY(); dz+=(*at)->GetZ(); } dx/=(*pos)->size(); dy/=(*pos)->size(); dz/=(*pos)->size(); for(set::const_iterator at=(*pos)->begin();at!=(*pos)->end();++at) { grad[*at].x=dx; grad[*at].y=dy; grad[*at].z=dz; } } // Move according to max step to minimize LLK for(map::const_iterator pos=grad.begin();pos!=grad.end();++pos) { pos->first->SetX(pos->first->GetX()-pos->second.x*f); pos->first->SetY(pos->first->GetY()-pos->second.y*f); pos->first->SetZ(pos->first->GetZ()-pos->second.z*f); } //this->RestraintStatus(cout); //cout<<"LLK="<GetLogLikelihood()< &v0,const unsigned nbStep,const REAL dt, const vector &vb,const vector &va, const vector &vd, map > &vr, REAL nrj0) { const vector *pvb=&vb; const vector *pva=&va; const vector *pvd=&vd; map > *pvr=&vr; if((pvb->size()==0)&&(pva->size()==0)&&(pvd->size()==0)) { pvb=&(this->GetBondList()); pva=&(this->GetBondAngleList()); pvd=&(this->GetDihedralAngleList()); for(vector::iterator pos=this->GetRigidGroupList().begin();pos!=this->GetRigidGroupList().end();++pos) (*pvr)[*pos]=make_pair(XYZ(0,0,0),XYZ(0,0,0)); } const REAL m=500;// mass const REAL im=1./m; // Try to keep total energy constant REAL e_v,e_k,v_r=1.0; for(unsigned i = 0; i < nbStep; ++i) { // Calc full gradient map grad; for(map::iterator pos=v0.begin();pos!=v0.end();++pos) grad[pos->first]=XYZ(0,0,0); // :TODO: handle rigid groups ? e_v=0; for(vector::const_iterator pos=pvb->begin();pos!=pvb->end();++pos) { (*pos)->CalcGradient(grad); e_v+=(*pos)->GetLogLikelihood(false,false); } for(vector::const_iterator pos=pva->begin();pos!=pva->end();++pos) { (*pos)->CalcGradient(grad); e_v+=(*pos)->GetLogLikelihood(false,false); } for(vector::const_iterator pos=pvd->begin();pos!=pvd->end();++pos) { (*pos)->CalcGradient(grad); e_v+=(*pos)->GetLogLikelihood(false,false); } //kinetic energy e_k=0; for(map::const_iterator pos=v0.begin();pos!=v0.end();++pos) e_k += 0.5*m*(pos->second.x*pos->second.x + pos->second.y*pos->second.y + pos->second.z*pos->second.z); if(nrj0==0) nrj0=e_k+e_v; else { // Apply a coefficient to the speed to keep the overall energy constant const REAL de=e_k+e_v-nrj0; if(de::iterator pos=v0.begin();pos!=v0.end();++pos) { sprintf(buf,"%10s xyz= (%8.3f %8.3f %8.3f) v= (%8.3f %8.3f %8.3f) m*a= (%8.3f %8.3f %8.3f)", pos->first->GetName().c_str(), pos->first->GetX(),pos->first->GetY(),pos->first->GetZ(), v0[*pos].x ,v0[*pos].y ,v0[*pos].z, -grad[*pos].x*im,-grad[*pos].y*im,-grad[*pos].z*im); //cout<::const_iterator pos=v0.begin();pos!=v0.end();++pos) { const XYZ *pa=&(grad[pos->first]); pos->first->SetX(pos->first->GetX()+pos->second.x*dt*v_r-0.5*im*dt*dt*pa->x); pos->first->SetY(pos->first->GetY()+pos->second.y*dt*v_r-0.5*im*dt*dt*pa->y); pos->first->SetZ(pos->first->GetZ()+pos->second.z*dt*v_r-0.5*im*dt*dt*pa->z); } // Compute new speed for(map::iterator pos=v0.begin();pos!=v0.end();++pos) { const XYZ *pa=&(grad[pos->first]); pos->second.x = v_r*pos->second.x - pa->x*dt*im; pos->second.y = v_r*pos->second.y - pa->y*dt*im; pos->second.z = v_r*pos->second.z - pa->z*dt*im; } } } const vector& Molecule::GetAtomList()const{return mvpAtom;} const vector& Molecule::GetBondList()const{return mvpBond;} const vector& Molecule::GetBondAngleList()const{return mvpBondAngle;} const vector& Molecule::GetDihedralAngleList()const{return mvpDihedralAngle;} vector& Molecule::GetAtomList(){return mvpAtom;} vector& Molecule::GetBondList(){return mvpBond;} vector& Molecule::GetBondAngleList(){return mvpBondAngle;} vector& Molecule::GetDihedralAngleList(){return mvpDihedralAngle;} list& Molecule::GetStretchModeBondLengthList(){return mvStretchModeBondLength;} list& Molecule::GetStretchModeBondAngleList(){return mvStretchModeBondAngle;} list& Molecule::GetStretchModeTorsionList(){return mvStretchModeTorsion;} const list& Molecule::GetStretchModeBondLengthList()const{return mvStretchModeBondLength;} const list& Molecule::GetStretchModeBondAngleList()const{return mvStretchModeBondAngle;} const list& Molecule::GetStretchModeTorsionList()const{return mvStretchModeTorsion;} const std::vector& Molecule::GetRigidGroupList()const{return mvRigidGroup;} std::vector& Molecule::GetRigidGroupList() {return mvRigidGroup;} void Molecule::RotateAtomGroup(const MolAtom &at1,const MolAtom &at2, const set &atoms, const REAL angle, const bool keepCenter) { const REAL vx=at2.X()-at1.X(); const REAL vy=at2.Y()-at1.Y(); const REAL vz=at2.Z()-at1.Z(); this->RotateAtomGroup(at1,vx,vy,vz,atoms,angle,keepCenter); } void Molecule::RotateAtomGroup(const MolAtom &at,const REAL vx,const REAL vy,const REAL vz, const set &atoms, const REAL angle, const bool keepCenter) { TAU_PROFILE("Molecule::RotateAtomGroup(MolAtom&,vx,vy,vz,...)","void (...)",TAU_DEFAULT); if(atoms.size()==0) return; const REAL x0=at.X(); const REAL y0=at.Y(); const REAL z0=at.Z(); // :KLUDGE: ? Refuse to do anything if vector is not well defined if((fabs(vx)+fabs(vy)+fabs(vz))<1e-6) return; REAL dx=0.,dy=0.,dz=0.; bool keepc=keepCenter; if(keepc) if( (this->GetPar(mXYZ.data() ).IsFixed()) ||(this->GetPar(mXYZ.data()+1).IsFixed()) ||(this->GetPar(mXYZ.data()+2).IsFixed())) keepc=false; #if 0 const REAL ca=cos(angle),sa=sin(angle); const REAL ca1=1-ca; const REAL vnorm=1/sqrt(vx*vx+vy*vy+vz*vz); const REAL ux=vx*vnorm,uy=vy*vnorm,uz=vz*vnorm; const REAL m00=ca+ux*ux*ca1;// See http://en.wikipedia.org/wiki/Rotation_matrix const REAL m01=ux*uy*ca1-uz*sa; const REAL m02=ux*uz*ca1+uy*sa; const REAL m10=uy*ux*ca1+uz*sa; // :TODO: Check formulas ! const REAL m11=ca+uy*uy*ca1; const REAL m12=uy*uz*ca1-ux*sa; const REAL m20=uz*ux*ca1-uy*sa; const REAL m21=uz*uy*ca1+ux*sa; const REAL m22=ca+uz*uz*ca1; for(set::const_iterator pos=atoms.begin();pos!=atoms.end();++pos) { if(keepc) { dx -= (*pos)->X(); dy -= (*pos)->Y(); dz -= (*pos)->Z(); } const REAL x=(*pos)->X() - x0; const REAL y=(*pos)->Y() - y0; const REAL z=(*pos)->Z() - z0; (*pos)->X() = m00*x+m01*y+m02*z+x0; (*pos)->Y() = m10*x+m11*y+m12*z+y0; (*pos)->Z() = m20*x+m21*y+m22*z+z0; if(keepc) { dx += (*pos)->X(); dy += (*pos)->Y(); dz += (*pos)->Z(); } } #else const Quaternion quat=Quaternion::RotationQuaternion(angle,vx,vy,vz); for(set::const_iterator pos=atoms.begin();pos!=atoms.end();++pos) { if(keepc) { dx -= (*pos)->X(); dy -= (*pos)->Y(); dz -= (*pos)->Z(); } (*pos)->X() -= x0; (*pos)->Y() -= y0; (*pos)->Z() -= z0; quat.RotateVector((*pos)->X(),(*pos)->Y(),(*pos)->Z()); (*pos)->X() += x0; (*pos)->Y() += y0; (*pos)->Z() += z0; if(keepc) { dx += (*pos)->X(); dy += (*pos)->Y(); dz += (*pos)->Z(); } } #endif // (dx,dy,dz) = vector of the translation of the center of the molecule due to the rotation if(keepc) { dx /= (REAL)(this->GetNbComponent()); dy /= (REAL)(this->GetNbComponent()); dz /= (REAL)(this->GetNbComponent()); mQuat.RotateVector(dx,dy,dz); this->GetCrystal().OrthonormalToFractionalCoords(dx,dy,dz); mXYZ(0) += dx; mXYZ(1) += dy; mXYZ(2) += dz; } mClockAtomPosition.Click(); mClockScatterer.Click(); } void Molecule::TranslateAtomGroup(const set &atoms, const REAL dx,const REAL dy,const REAL dz, const bool keepCenter) { for(set::const_iterator pos=atoms.begin();pos!=atoms.end();++pos) { (*pos)->X() += dx; (*pos)->Y() += dy; (*pos)->Z() += dz; } bool keepc=keepCenter; if(keepc) if( (this->GetPar(mXYZ.data() ).IsFixed()) ||(this->GetPar(mXYZ.data()+1).IsFixed()) ||(this->GetPar(mXYZ.data()+2).IsFixed())) keepc=false; if(keepc) { const REAL r= (REAL)(atoms.size())/(REAL)(this->GetNbComponent()); REAL dxc=dx*r,dyc=dy*r,dzc=dz*r; this->GetCrystal().OrthonormalToFractionalCoords(dxc,dyc,dzc); mXYZ(0) += dxc; mXYZ(1) += dyc; mXYZ(2) += dzc; } mClockAtomPosition.Click(); mClockScatterer.Click(); } void Molecule::RestraintExport(ostream &os)const { VFN_DEBUG_ENTRY("Molecule::RestraintExport()",5) os<<"BondName, IdealLength, Length, log(likelihood)"<::const_iterator pos=mvpBond.begin();pos!=mvpBond.end();++pos) os <<(*pos)->GetName() <<", "<<(*pos)->GetLength0() <<", "<<(*pos)->GetLength() <<", "<<(*pos)->GetLogLikelihood()<::const_iterator pos=mvpBondAngle.begin(); pos!=mvpBondAngle.end();++pos) os <<(*pos)->GetName() <<", "<<(*pos)->Angle0()*180/M_PI <<", "<<(*pos)->GetAngle()*180/M_PI <<", "<<(*pos)->GetLogLikelihood()<::const_iterator pos=mvpDihedralAngle.begin(); pos!=mvpDihedralAngle.end();++pos) os <<(*pos)->GetName() <<", "<<(*pos)->Angle0()*180/M_PI <<", "<<(*pos)->GetAngle()*180/M_PI <<", "<<(*pos)->GetLogLikelihood()<::const_iterator pos=mvpBond.begin();pos!=mvpBond.end();++pos) cout <<"Bond "<<(*pos)->GetName() <<", IdealLength="<<(*pos)->GetLength0() <<", Length="<<(*pos)->GetLength() <<", log(likelihood)="<<(*pos)->GetLogLikelihood()<::const_iterator pos=mvpBondAngle.begin(); pos!=mvpBondAngle.end();++pos) cout <<"Bond Angle "<<(*pos)->GetName() <<", IdealAngle="<<(*pos)->Angle0()*180/M_PI <<", Angle="<<(*pos)->GetAngle()*180/M_PI <<", log(likelihood)="<<(*pos)->GetLogLikelihood()<::const_iterator pos=mvpDihedralAngle.begin(); pos!=mvpDihedralAngle.end();++pos) cout <<"Dihedral Angle "<<(*pos)->GetName() <<", IdealAngle="<<(*pos)->Angle0()*180/M_PI <<", Angle="<<(*pos)->GetAngle()*180/M_PI <<", log(likelihood)="<<(*pos)->GetLogLikelihood()< > &Molecule::GetConnectivityTable() { this->BuildConnectivityTable(); return mConnectivityTable; } RefinableObjClock& Molecule::GetBondListClock(){return mClockBondList;} const RefinableObjClock& Molecule::GetBondListClock()const{return mClockBondList;} RefinableObjClock& Molecule::GetAtomPositionClock(){return mClockAtomPosition;} const RefinableObjClock& Molecule::GetAtomPositionClock()const{return mClockAtomPosition;} const RefinableObjClock& Molecule::GetAtomScattPowClock()const { return mClockAtomScattPow;} RefinableObjClock& Molecule::GetAtomScattPowClock() { return mClockAtomScattPow;} RefinableObjClock& Molecule::GetRigidGroupClock(){return mClockRigidGroup;} const RefinableObjClock& Molecule::GetRigidGroupClock()const{return mClockRigidGroup;} void Molecule::RigidifyWithDihedralAngles() { this->BuildConnectivityTable(); for(vector::iterator bond=mvpBond.begin();bond!=mvpBond.end();++bond) { MolAtom* at2=&((*bond)->GetAtom1()); MolAtom* at3=&((*bond)->GetAtom2()); for(set::const_iterator c2=mConnectivityTable[at2].begin(); c2!=mConnectivityTable[at2].end();++c2) { //MolAtom* at1=mvpAtom[*c2]; if(*c2==at3) continue; if(GetBondAngle(**c2,*at2,*at3)<(10 *DEG2RAD)) continue; if(GetBondAngle(**c2,*at2,*at3)>(180*DEG2RAD)) continue; for(set::const_iterator c3=mConnectivityTable[at3].begin(); c3!=mConnectivityTable[at3].end();++c3) { //MolAtom* at4=mvpAtom[*c3]; if((*c3==at2)||(*c3==*c2)) continue; if(GetBondAngle(*at2,*at3,**c3)<(10 *DEG2RAD)) continue; if(GetBondAngle(*at2,*at3,**c3)>(180*DEG2RAD)) continue; if(this->FindDihedralAngle(**c2,*at2,*at3,**c3)==mvpDihedralAngle.end()) { const REAL dihed=GetDihedralAngle(**c2,*at2,*at3,**c3); this->AddDihedralAngle(**c2,*at2,*at3,**c3,dihed,.01,.05,false); } } } } this->UpdateDisplay(); } #if 0 /** x array for the Integral[0->x](exp(+t*t)dt) * */ static const REAL svGaussianIntX[51] ={0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. , 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2. , 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3. , 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4. , 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, 5. }; /** This is Integral[0->x](exp(+t*t)dt) * */ static const REAL svGaussianIntY[51] ={0.00000000e+00, 1.00285768e-01, 2.02498389e-01, 3.08782899e-01, 4.21537858e-01, 5.43577677e-01, 6.78339751e-01, 8.30161516e-01, 1.00466359e+00, 1.20929269e+00, 1.45410564e+00, 1.75292008e+00, 2.12502806e+00, 2.59778353e+00, 3.21056320e+00, 4.02091257e+00, 5.11421527e+00, 6.61911896e+00, 8.73249677e+00, 1.17604260e+01, 1.61864569e+01, 2.27870547e+01, 3.28297946e+01, 4.84189023e+01, 7.31071567e+01, 1.12996748e+02, 1.78751757e+02, 2.89337246e+02, 4.79080996e+02, 8.11232960e+02, 1.40443983e+03, 2.48531490e+03, 4.49461494e+03, 8.30539633e+03, 1.56790580e+04, 3.02354014e+04, 5.95525189e+04, 1.19793234e+05, 2.46080284e+05, 5.16182008e+05, 1.10556243e+06, 2.41765307e+06, 5.39775929e+06, 1.23033271e+07, 2.86288375e+07, 6.80050408e+07, 1.64899866e+08, 4.08157783e+08, 1.03122228e+09, 2.65938808e+09, 7.00012860e+09}; /** Spline giving x=f(y) for the Integral[0->x](exp(+t*t)dt) * */ static const CubicSpline sInvGaussianInt(svGaussianIntY,svGaussianIntX,51); REAL FlatGaussianProba(const REAL x, const REAL sigma, const REAL delta) { if(abs(x) delta)x= delta; if(x<-delta)x=-delta; return x; } // Compute xmin and xmax around x0 so that: // (x0-xmin)/(xmax-x0)=Integral[xmin->x0](P(x)dx)/Integral[x0->xmax](P(x)dx) REAL xmin; REAL xmax; #if 1 { REAL Pmax,Pmin; xmin=x0-amplitude; xmax=x0+amplitude; Pmin=FlatLorentzianProba((x0+xmin)/2,sigma,delta); Pmax=FlatLorentzianProba((x0+xmax)/2,sigma,delta); //Pmin=FlatLorentzianIntegral(xmin,x0,sigma,delta); //Pmax=FlatLorentzianIntegral(x0,xmax,sigma,delta); if(Pmin>Pmax) { for(int i=0;i<5;i++) { const REAL r=Pmax/Pmin; xmax=x0+r*amplitude; Pmax=FlatLorentzianProba((x0+xmax)/2,sigma,delta); //Pmax=FlatLorentzianIntegral(x0,xmax,sigma,delta); } } else { for(int i=0;i<5;i++) { const REAL r=Pmin/Pmax; xmin=x0-r*amplitude; Pmin=FlatLorentzianProba((x0+xmin)/2,sigma,delta); //Pmin=FlatLorentzianIntegral(xmin,x0,sigma,delta); } } } #else if(abs(x0)<=delta) { xmin=x0-amplitude; xmax=x0+amplitude; } else { REAL d=(abs(x0)-delta)/sigma; d=2*d*exp(-d*d); d=(1-amplitude*d/2)/(1+amplitude*d/2);//d<1 if(x0>0) { xmin=x0-amplitude*2/(1+d); xmax=x0+amplitude*2*d/(1+d); } else { xmax=x0+amplitude*2/(1+d); xmin=x0-amplitude*2*d/(1+d); } } #endif //xmin=x0-amplitude; //xmax=x0+amplitude; //Now get the biased move... if(xmax<=-delta) { REAL ymin=(abs(xmin)-delta)/sigma; ymin=atan(ymin); REAL ymax=(abs(xmax)-delta)/sigma; ymax=atan(ymax); const REAL y=ymin+(ymax-ymin)*r; return -tan(y)*sigma-delta; } if(xmin<=-delta) { if(xmax<=delta) { //probability of being in [xmin;-delta] rather than [-delta;xmax] REAL p0=atan((abs(xmin)-delta)/sigma)*sigma; REAL p1=xmax+delta; const REAL n=p0+p1; if(rdelta && xmin <= -delta { REAL p0=atan((abs(xmin)-delta)/sigma)*sigma;//probability of being in [xmin;-delta] REAL p1=2*delta;//probability of being in [-delta;delta] REAL p2=atan((xmax-delta)/sigma)*sigma;//probability of being in [delta;xmax] const REAL n=p0+p1+p2; if(r<(p0/n)) { REAL ymin=(abs(xmin)-delta)/sigma; ymin=atan(ymin);//exp(ymin*ymin); const REAL y=ymin*(REAL)rand()/(REAL)RAND_MAX; const REAL x=-delta-tan(y)*sigma; return x; } if(r<(p0+p1)/n) { const REAL x=-delta+(REAL)rand()/(REAL)RAND_MAX*2*delta; return x; } REAL ymax=(xmax-delta)/sigma; ymax=atan(ymax); const REAL y=ymax*(REAL)rand()/(REAL)RAND_MAX; const REAL x=delta+tan(y)*sigma; return x; } } if(xmindelta REAL ymin=(xmin-delta)/sigma; ymin=atan(ymin); REAL ymax=(xmax-delta)/sigma; ymax=atan(ymax); const REAL y=ymin+(ymax-ymin)*r; return tan(y)*sigma+delta; } void TestLorentzianBiasedRandomMove() { srand(time(NULL)); REAL x=0,sigma=0.1,delta=0.5,amplitude=0.05; ofstream f; f.open("test.dat"); for(long i=0;i<400000;i++) { f<hx[i])*(y<(hx[i]+step))) // return hx,hy // // //f=open("test.dat",'r') //ll=f.readlines() //f.close() //y=zeros(len(ll),Float) //for i in xrange(len(ll)): // y[i]=float(ll[i]) // //hx,hy=histogram(y) //gplt.plot(hx,hy) } REAL Molecule::BondLengthRandomChange(const StretchModeBondLength& mode, const REAL amplitude, const bool respectRestraint) { REAL dx=mode.mpAtom1->GetX()-mode.mpAtom0->GetX(); REAL dy=mode.mpAtom1->GetY()-mode.mpAtom0->GetY(); REAL dz=mode.mpAtom1->GetZ()-mode.mpAtom0->GetZ(); const REAL l=sqrt(dx*dx+dy*dy+dz*dz+1e-7); REAL change=0.0; if(l<1e-6) return change;// :KLUDGE: if(respectRestraint && mode.mpBond!=0) { const REAL d0=l-mode.mpBond->GetLength0(); const REAL sigma=mode.mpBond->GetLengthSigma(); const REAL delta=mode.mpBond->GetLengthDelta(); const REAL max=delta+sigma*5.0; if(sigma<1e-6) { REAL d1=d0+(REAL)(2*rand()-RAND_MAX)/(REAL)RAND_MAX*amplitude*0.1; if(d1> delta)d1= delta; if(d1<-delta)d1=-delta; change=d1-d0; } else change=LorentzianBiasedRandomMove(d0,sigma,delta,amplitude*0.1)-d0; if((d0+change)>max) change=max-d0; else if((d0+change)<(-max)) change=-max-d0; #if 0 if(rand()%10000==0) { cout<<"BOND LENGTH change("<GetName()<<"-" <GetName() <<"(Restraint="<"<TranslateAtomGroup(mode.mvTranslatedAtomList,dx,dy,dz,true); return change; } REAL Molecule::BondAngleRandomChange(const StretchModeBondAngle& mode, const REAL amplitude, const bool respectRestraint) { REAL dx10=mode.mpAtom0->GetX()-mode.mpAtom1->GetX(); REAL dy10=mode.mpAtom0->GetY()-mode.mpAtom1->GetY(); REAL dz10=mode.mpAtom0->GetZ()-mode.mpAtom1->GetZ(); REAL dx12=mode.mpAtom2->GetX()-mode.mpAtom1->GetX(); REAL dy12=mode.mpAtom2->GetY()-mode.mpAtom1->GetY(); REAL dz12=mode.mpAtom2->GetZ()-mode.mpAtom1->GetZ(); const REAL vx=dy10*dz12-dz10*dy12; const REAL vy=dz10*dx12-dx10*dz12; const REAL vz=dx10*dy12-dy10*dx12; REAL change=0.0; if((abs(vx)+abs(vy)+abs(vz))<1e-6) return change;// :KLUDGE: REAL angle0; if(respectRestraint && mode.mpBondAngle!=0) { const REAL norm= sqrt( (dx10*dx10+dy10*dy10+dz10*dz10)*(dx12*dx12+dy12*dy12+dz12*dz12)+1e-6); angle0=(dx10*dx12+dy10*dy12+dz10*dz12)/norm; if(angle0>=1) angle0=0; else { if(angle0<=-1) angle0=M_PI; else angle0= acos(angle0); } const REAL a0=angle0-mode.mpBondAngle->GetAngle0(); const REAL sigma=mode.mpBondAngle->GetAngleSigma(); const REAL delta=mode.mpBondAngle->GetAngleDelta(); if(sigma<1e-6) { REAL a1=a0+(REAL)(2*rand()-RAND_MAX)/(REAL)RAND_MAX*amplitude*mode.mBaseAmplitude; if(a1> delta)a1= delta; if(a1<-delta)a1=-delta; change=a1-a0; } else change=LorentzianBiasedRandomMove(a0,sigma,delta,amplitude*mode.mBaseAmplitude)-a0; if((a0+change)>(delta+sigma*5.0)) change= delta+sigma*5.0-a0; else if((a0+change)<(-delta-sigma*5.0)) change=-delta-sigma*5.0-a0; #if 0 if(rand()%1==0) { cout<<"ANGLE change("<GetName()<<"-" <GetName()<<"-" <GetName() <<"(Restraint="<<(angle0-a0)*RAD2DEG<<"s"<"<<(angle0+change)*RAD2DEG<RotateAtomGroup(*(mode.mpAtom1),vx,vy,vz,mode.mvRotatedAtomList,change,true); return change; } REAL Molecule::DihedralAngleRandomChange(const StretchModeTorsion& mode, const REAL amplitude, const bool respectRestraint) { const REAL dx=mode.mpAtom2->GetX()-mode.mpAtom1->GetX(); const REAL dy=mode.mpAtom2->GetY()-mode.mpAtom1->GetY(); const REAL dz=mode.mpAtom2->GetZ()-mode.mpAtom1->GetZ(); REAL change=0.0; if((abs(dx)+abs(dy)+abs(dz))<1e-6) return change;// :KLUDGE: if(respectRestraint && mode.mpDihedralAngle!=0) { const REAL angle0=mode.mpDihedralAngle->GetAngle(); const REAL a0=angle0-mode.mpDihedralAngle->GetAngle0(); const REAL sigma=mode.mpDihedralAngle->GetAngleSigma(); const REAL delta=mode.mpDihedralAngle->GetAngleDelta(); if(sigma<1e-6) { REAL a1=a0+(REAL)(2*rand()-RAND_MAX)/(REAL)RAND_MAX*amplitude*mode.mBaseAmplitude; if(a1> delta)a1= delta; if(a1<-delta)a1=-delta; change=a1-a0; } else change=LorentzianBiasedRandomMove(a0,sigma,delta,amplitude*mode.mBaseAmplitude)-a0; if((a0+change)>(delta+sigma*5.0)) change= delta+sigma*5.0-a0; else if((a0+change)<(-delta-sigma*5.0)) change=-delta-sigma*5.0-a0; #if 0 if(rand()%1==0) { cout<<"TORSION change (" <GetName()<<"-"<GetName()<<"):"<GetName()<<")=" <<(angle0-a0)*RAD2DEG<<"s"<0) { // Use the most recent atom in the z-matrix const long b=zconn[nc-1]; zmatrix[z].mBondAtom=b; zmatrix[z].mBondLength=GetBondLength(*vpAtom[vrZIndex[b]],*vpAtom[curr]); if(z>1) { const long a=zmatrix[b].mBondAtom; zmatrix[z].mBondAngleAtom=a; zmatrix[z].mBondAngle=GetBondAngle(*vpAtom[vrZIndex[a]],*vpAtom[vrZIndex[b]],*vpAtom[curr]); if(z>2) { const long d=zmatrix[b].mBondAngleAtom; zmatrix[z].mDihedralAtom=d; zmatrix[z].mDihedralAngle=fmod(GetDihedralAngle(*vpAtom[vrZIndex[d]],*vpAtom[vrZIndex[a]], *vpAtom[vrZIndex[b]],*vpAtom[curr])+2*M_PI, 2*M_PI); } else { zmatrix[z].mDihedralAtom=0; zmatrix[z].mDihedralAngle=0; } } else { zmatrix[z].mBondAngleAtom=0; zmatrix[z].mBondAngle=0; } } else { zmatrix[z].mBondAtom=0; zmatrix[z].mBondLength=0; } z++; // Continue filling up the zmatrix, beginning from thz first atoms not already in the zmatrix for(pos=conn.begin();pos!=conn.end();++pos) { if(*pos!=-1) { if(vZIndex[*pos]==-1) BuildZMatrixRecursive(z,*pos,vpAtom,connT,zmatrix,vIndex,vZIndex,vrZIndex); } } } const vector& Molecule::AsZMatrix(const bool keeporder)const { this->BuildConnectivityTable(); const long n=mvpAtom.size(); // index of the atoms in the list map vIndex; { long i=0; for(vector::const_iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos) vIndex[*pos]=i++; } mAsZMatrix.resize(n); if(keeporder) { for(long i=0;iGetScatteringPower()); if(i>0) { const set *pConn=&(mConnectivityTable.find(mvpAtom[i])->second); // Find a connected atom already in the mAsZMatrix, prefereably the most recent long b=-1; for(set::const_iterator pos=pConn->begin();pos!=pConn->end();++pos) if((vIndex[*pos]b)) b=vIndex[*pos]; // Did not find a connected atom already in the z-matrix ? Take the last one if(b==-1) b=i-1; mAsZMatrix[i].mBondAtom=b; mAsZMatrix[i].mBondLength=GetBondLength(*mvpAtom[b],*mvpAtom[i]); if(i>1) { const long a= (b==0)?1 : mAsZMatrix[b].mBondAtom; mAsZMatrix[i].mBondAngleAtom=a; mAsZMatrix[i].mBondAngle=GetBondAngle(*mvpAtom[a],*mvpAtom[b],*mvpAtom[i]); if(i>2) { long d= mAsZMatrix[a].mBondAtom; if(d==b) {// Dihedral atom is already bond atom, find another connected to angle atom d=-1; const set *pConn=&(mConnectivityTable.find(mvpAtom[a])->second); // Find a connected atom already in the mAsZMatrix, prefereably the most recent for(set::const_iterator pos=pConn->begin();pos!=pConn->end();++pos) if((vIndex[*pos]d)) d=vIndex[*pos]; } if(d==-1) {// Can't find an angle connected to angle atom, so find another with bond atom const set *pConn=&(mConnectivityTable.find(mvpAtom[b])->second); // Find a connected atom already in the mAsZMatrix, prefereably the most recent for(set::const_iterator pos=pConn->begin();pos!=pConn->end();++pos) if((vIndex[*pos]d)) d=vIndex[*pos]; } if(d==-1) {// Maybe another connected to this atom ?? const set *pConn=&(mConnectivityTable.find(mvpAtom[i])->second); // Find a connected atom already in the mAsZMatrix, prefereably the most recent for(set::const_iterator pos=pConn->begin();pos!=pConn->end();++pos) if( (vIndex[*pos]d)) d=vIndex[*pos]; } if(d==-1) {// OK, pick *any* (can this happen ? Really ?) for(long j=0;jd)) d=j; } mAsZMatrix[i].mDihedralAtom=d; mAsZMatrix[i].mDihedralAngle=fmod(GetDihedralAngle(*mvpAtom[d], *mvpAtom[a], *mvpAtom[b], *mvpAtom[i])+2*M_PI, 2*M_PI); } } } } } else { // vZIndex[i] tells where mvpAtom[i] is in the z-matrix vector vZIndex(n); // vrZIndex[i] tells where which index in vpAtom is ZAtom #i vector vrZIndex(n); for(long i=0;i > &connect, list &atomlist, map,list > &ringlist) { list::const_iterator f=find(atomlist.begin(),atomlist.end(),currentAtom); if(f!=atomlist.end()) {// This atom was already in the list ! We have found a ring ! #ifdef __DEBUG__ cout<GetName()<<" was already in the list : ring found !"<::const_iterator atom=atomlist.begin();atom!=atomlist.end();++atom) cout<<(*atom)->GetName()<<" "; cout< ring1; list ring2; for(list::const_iterator pos=f;pos!=atomlist.end();++pos) { ring1.insert(*pos); ring2.push_back(*pos); } ringlist.insert(make_pair(ring1,ring2)); } else { atomlist.push_back(currentAtom); map >::const_iterator c=connect.find(currentAtom); if(c != connect.end()) { set::const_iterator pos; for(pos=c->second.begin();pos!=c->second.end();++pos) { if(*pos==previousAtom) continue; BuildRingRecursive(*pos,currentAtom,connect,atomlist,ringlist); } } atomlist.pop_back(); //?? } } void Molecule::BuildRingList() { this->BuildConnectivityTable(); if(mClockRingList>mClockConnectivityTable) return; VFN_DEBUG_ENTRY("Molecule::BuildRingList()",7) for(vector::const_iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos) (*pos)->SetIsInRing(false); list atomlist; // Use a map with a set for key to eliminate duplicate rings map,list > ringlist; for(unsigned long i=0;i,list >::const_iterator pos0=ringlist.begin();pos0!=ringlist.end();pos0++) { mvRing.resize(mvRing.size()+1); std::list *pList=&(mvRing.back().GetAtomList()); #if 1//def __DEBUG__ cout<<"Found ring:"; #endif for(list::const_iterator atom=pos0->second.begin();atom!=pos0->second.end();++atom) { pList->push_back(*atom); (*atom)->SetIsInRing(true); #if 1//def __DEBUG__ cout<<(*atom)->GetName()<<" "; #endif } #if 1//def __DEBUG__ cout<mClockBondList) &&(mClockConnectivityTable>mClockAtomList)) return; VFN_DEBUG_ENTRY("Molecule::BuildConnectivityTable()",5) TAU_PROFILE("Molecule::BuildConnectivityTable()","void ()",TAU_DEFAULT); mConnectivityTable.clear(); for(unsigned long i=0;iGetAtom1())].insert(&(mvpBond[i]->GetAtom2())); mConnectivityTable[&(mvpBond[i]->GetAtom2())].insert(&(mvpBond[i]->GetAtom1())); } #ifdef __DEBUG__ { map >::const_iterator pos; for(pos=mConnectivityTable.begin();pos!=mConnectivityTable.end();++pos) { cout<<"Atom "<first->GetName()<<" is connected to atoms: "; set::const_iterator pos1; for(pos1=pos->second.begin();pos1!=pos->second.end();++pos1) { cout<<(*pos1)->GetName()<<" "; } cout<second.size()>24) throw ObjCrystException("Molecule: one atom ("+pos->first->GetName()+") has more than 24 bonds !"); } } #endif mClockConnectivityTable.Click(); VFN_DEBUG_EXIT("Molecule::BuildConnectivityTable()",5) } Molecule::RotorGroup::RotorGroup(const MolAtom &at1,const MolAtom &at2): mpAtom1(&at1),mpAtom2(&at2),mBaseRotationAmplitude(M_PI*0.04) {} void Molecule::BuildRotorGroup() { if( (mClockRotorGroup>mClockBondList) &&(mClockRotorGroup>mClockAtomList) &&(mClockRotorGroup>mClockBondAngleList) &&(mClockRotorGroup>mClockDihedralAngleList)) return; VFN_DEBUG_ENTRY("Molecule::BuildRotorGroup()",5) TAU_PROFILE("Molecule::BuildRotorGroup()","void ()",TAU_DEFAULT); this->BuildConnectivityTable(); mvRotorGroupTorsion.clear(); mvRotorGroupTorsionSingleChain.clear(); mvRotorGroupInternal.clear(); // Build Rotation groups around bonds for(unsigned long i=0;iIsFreeTorsion())) continue; MolAtom *const atom1=&(mvpBond[i]->GetAtom1()), *const atom2=&(mvpBond[i]->GetAtom2()); for(unsigned int j=1;j<=2;++j) { const set *pConn; if(j==1) pConn=&(mConnectivityTable[atom1]); else pConn=&(mConnectivityTable[atom2]); mvRotorGroupTorsion.push_back(RotorGroup(mvpBond[i]->GetAtom1(), mvpBond[i]->GetAtom2())); mvRotorGroupTorsion.back().mvRotatedAtomList.insert(atom1); mvRotorGroupTorsion.back().mvRotatedAtomList.insert(atom2); for(set::const_iterator pos=pConn->begin();pos!=pConn->end();++pos) { if((j==1)&&(*pos==atom2)) continue; if((j==2)&&(*pos==atom1)) continue; ExpandAtomGroupRecursive(*pos,mConnectivityTable, mvRotorGroupTorsion.back().mvRotatedAtomList); if(pConn->size()>2) { mvRotorGroupTorsionSingleChain.push_back(RotorGroup(mvpBond[i]->GetAtom1(), mvpBond[i]->GetAtom2())); mvRotorGroupTorsionSingleChain.back().mvRotatedAtomList.insert(atom1); mvRotorGroupTorsionSingleChain.back().mvRotatedAtomList.insert(atom2); ExpandAtomGroupRecursive(*pos,mConnectivityTable, mvRotorGroupTorsionSingleChain.back().mvRotatedAtomList); mvRotorGroupTorsionSingleChain.back().mvRotatedAtomList.erase(atom1); mvRotorGroupTorsionSingleChain.back().mvRotatedAtomList.erase(atom2); if( (mvRotorGroupTorsionSingleChain.back().mvRotatedAtomList.size()>=((mvpAtom.size()+1)/2)) ||(mvRotorGroupTorsionSingleChain.back().mvRotatedAtomList.size()==0)) mvRotorGroupTorsionSingleChain.pop_back(); } } mvRotorGroupTorsion.back().mvRotatedAtomList.erase(atom1); mvRotorGroupTorsion.back().mvRotatedAtomList.erase(atom2); if( (mvRotorGroupTorsion.back().mvRotatedAtomList.size()>=((mvpAtom.size()+1)/2)) ||(mvRotorGroupTorsion.back().mvRotatedAtomList.size()==0)) mvRotorGroupTorsion.pop_back(); } } #if 1 // Build 'internal' rotation groups between random atoms //:TODO: This should be tried for *random* configuration of free torsion angles... if(mFlexModel.GetChoice()==0) { for(vector::const_iterator atom1=this->GetAtomList().begin(); atom1!=this->GetAtomList().end();++atom1) { const set *pConn=&(mConnectivityTable[*atom1]); vector::const_iterator atom2=atom1; atom2++; for(;atom2!=this->GetAtomList().end();++atom2) { for(set::const_iterator pos=pConn->begin();pos!=pConn->end();++pos) { if(*pos==*atom2) continue; mvRotorGroupInternal.push_back(RotorGroup(**atom1,**atom2)); mvRotorGroupInternal.back().mvRotatedAtomList.insert(*atom1); ExpandAtomGroupRecursive(*pos,mConnectivityTable, mvRotorGroupInternal.back().mvRotatedAtomList, *atom2); //Check if this chains leads to atom2 set::const_iterator check =find(mvRotorGroupInternal.back().mvRotatedAtomList.begin(), mvRotorGroupInternal.back().mvRotatedAtomList.end(),*atom2); if( (check==mvRotorGroupInternal.back().mvRotatedAtomList.end()) ||(mvRotorGroupInternal.back().mvRotatedAtomList.size()<3) ||(mvRotorGroupInternal.back().mvRotatedAtomList.size()>=((mvpAtom.size()+1)/2))) { mvRotorGroupInternal.pop_back(); } else { mvRotorGroupInternal.back().mvRotatedAtomList.erase(*atom1); mvRotorGroupInternal.back().mvRotatedAtomList.erase(*atom2); } } } } } #endif // Remove identical groups for(unsigned int i=1;i<=3;++i) { list *pRotorGroup1; switch(i) { case 1: pRotorGroup1=&mvRotorGroupTorsion;break; case 2: pRotorGroup1=&mvRotorGroupTorsionSingleChain;break; case 3: pRotorGroup1=&mvRotorGroupInternal;break; } for(list::iterator pos1=pRotorGroup1->begin(); pos1!=pRotorGroup1->end();++pos1) { for(unsigned int j=i;j<=3;++j) { list *pRotorGroup2; switch(j) { case 1: pRotorGroup2=&mvRotorGroupTorsion;break; case 2: pRotorGroup2=&mvRotorGroupTorsionSingleChain;break; case 3: pRotorGroup2=&mvRotorGroupInternal;break; } for(list::iterator pos2=pRotorGroup2->begin(); pos2!=pRotorGroup2->end();) { if(pos2==pos1) {++pos2;continue;} if(( ((pos1->mpAtom1 == pos2->mpAtom1) && (pos1->mpAtom2 == pos2->mpAtom2)) ||((pos1->mpAtom2 == pos2->mpAtom1) && (pos1->mpAtom1 == pos2->mpAtom2))) &&pos1->mvRotatedAtomList.size() == pos2->mvRotatedAtomList.size()) { bool ident=true; for(set::const_iterator pos=pos1->mvRotatedAtomList.begin(); pos!=pos1->mvRotatedAtomList.end();++pos) { set::const_iterator tmp=pos2->mvRotatedAtomList.find(*pos); if(tmp == pos2->mvRotatedAtomList.end()) { ident=false; break; } } if(ident) { #if 0 cout<<"Identical groups:"<mpAtom1->GetName()<<"-" <mpAtom2->GetName()<<" : "; for(set::iterator pos=pos1->mvRotatedAtomList.begin(); pos!=pos1->mvRotatedAtomList.end();++pos) cout<<(*pos)->GetName()<<" "; cout<mpAtom1->GetName()<<"-" <mpAtom2->GetName()<<" : "; for(set::iterator pos=pos2->mvRotatedAtomList.begin(); pos!=pos2->mvRotatedAtomList.end();++pos) cout<<(*pos)->GetName()<<" "; cout<erase(pos2); } else ++pos2; } else ++pos2; } } } } // Remove all rotations which break restraints and therefore are not "free torsion" this->SaveParamSet(mLocalParamSet); const REAL llk0=this->GetLogLikelihood(); for(unsigned int i=1;i<=3;++i) { list *pRotorGroup1; switch(i) { case 1: pRotorGroup1=&mvRotorGroupTorsion;break; case 2: pRotorGroup1=&mvRotorGroupTorsionSingleChain;break; case 3: pRotorGroup1=&mvRotorGroupInternal;break; } for(list::iterator pos=pRotorGroup1->begin(); pos!=pRotorGroup1->end();) { REAL llk=0; for(unsigned int j=0;j<36;++j) { const REAL angle=(REAL)j*M_PI/36.; this->RotateAtomGroup(*(pos->mpAtom1),*(pos->mpAtom2), pos->mvRotatedAtomList,angle); // use fabs in case we are not starting from the minimum of a restraint.. llk += fabs(this->GetLogLikelihood() - llk0); this->RestoreParamSet(mLocalParamSet); } #ifdef __DEBUG__ switch(i) { case 1: cout<<"Rotation Group around bond :";break; case 2: cout<<"Rotation Group (single chain) around bond :";break; case 3: cout<<"Rotation Group (internal) between :";break; } cout <mpAtom1->GetName()<<"-" <mpAtom2->GetName()<<" : "; for(set::iterator pos1=pos->mvRotatedAtomList.begin(); pos1!=pos->mvRotatedAtomList.end();++pos1) cout<<(*pos1)->GetName()<<" "; cout<<" ="<< llk/36.; #endif if((llk/50.)>100.) { pos = pRotorGroup1->erase(pos); //cout <<" -> NOT a free torsion"< free torsion"<::iterator pos=mvpBond.begin();pos!=mvpBond.end();++pos) (*pos)->SetFreeTorsion(false); for(list::iterator pos=mvRotorGroupTorsion.begin(); pos!=mvRotorGroupTorsion.end();++pos) { vector::iterator bd=this->FindBond((*pos->mpAtom1),(*pos->mpAtom2)); if(bd!=mvpBond.end()) (*bd)->SetFreeTorsion(true); } mClockRotorGroup.Click(); VFN_DEBUG_EXIT("Molecule::BuildRotorGroup()",5) } void Molecule::BuildStretchModeBondLength() { #if 0 if( (mClockStretchModeBondLength>mClockBondList) &&(mClockStretchModeBondLength>mClockAtomList) &&(mClockStretchModeBondLength>mClockBondAngleList) &&(mClockStretchModeBondLength>mClockDihedralAngleList)) return; #endif VFN_DEBUG_ENTRY("Molecule::BuildStretchModeBondLength()",7) this->BuildConnectivityTable(); TAU_PROFILE("Molecule::BuildStretchModeBondLength()","void ()",TAU_DEFAULT); TAU_PROFILE_TIMER(timer1,"Molecule::BuildStretchModeBondLength 1","", TAU_FIELD); TAU_PROFILE_TIMER(timer2,"Molecule::BuildStretchModeBondLength 2","", TAU_FIELD); TAU_PROFILE_TIMER(timer3,"Molecule::BuildStretchModeBondLength 3","", TAU_FIELD); TAU_PROFILE_TIMER(timer4,"Molecule::BuildStretchModeBondLength 4","", TAU_FIELD); TAU_PROFILE_TIMER(timer5,"Molecule::BuildStretchModeBondLength 5","", TAU_FIELD); mvStretchModeBondLength.clear(); // Build list of atoms moved when stretching a bond length. Only keep the group // of atoms on the smaller side. TAU_PROFILE_START(timer1); for(unsigned long i=0;iIsFreeTorsion())) continue; MolAtom* const atom1=&(mvpBond[i]->GetAtom1()); MolAtom* const atom2=&(mvpBond[i]->GetAtom2()); for(unsigned int j=1;j<=2;++j) { const set *pConn; if(j==1) pConn=&(mConnectivityTable[atom1]); else pConn=&(mConnectivityTable[atom2]); if(j==1) mvStretchModeBondLength.push_back(StretchModeBondLength(mvpBond[i]->GetAtom2(), mvpBond[i]->GetAtom1(), mvpBond[i])); else mvStretchModeBondLength.push_back(StretchModeBondLength(mvpBond[i]->GetAtom1(), mvpBond[i]->GetAtom2(), mvpBond[i])); if(j==1) mvStretchModeBondLength.back().mvTranslatedAtomList.insert(atom1); if(j==2) mvStretchModeBondLength.back().mvTranslatedAtomList.insert(atom2); for(set::const_iterator pos=pConn->begin();pos!=pConn->end();++pos) { if((j==1)&&(*pos==atom2)) continue; if((j==2)&&(*pos==atom1)) continue; ExpandAtomGroupRecursive(*pos,mConnectivityTable, mvStretchModeBondLength.back().mvTranslatedAtomList); } const unsigned long ct1=mvStretchModeBondLength.back().mvTranslatedAtomList.count(atom1), ct2=mvStretchModeBondLength.back().mvTranslatedAtomList.count(atom2); if( ((j==1)&&(ct2>0)) || ((j==2)&&(ct1>0)) ) { // We have found a ring. No use looking at the other side. // :TODO: handle this properly.. mvStretchModeBondLength.pop_back(); break; } if( (mvStretchModeBondLength.back().mvTranslatedAtomList.size()>((mvpAtom.size()+1)/2)) ||(mvStretchModeBondLength.back().mvTranslatedAtomList.size()==0)) { #ifdef __DEBUG__ cout<<"Rejecting StretchModeBondLength ";mvStretchModeBondLength.back().Print(cout);cout<::iterator pos=mvStretchModeBondLength.begin(); pos!=mvStretchModeBondLength.end();) { TAU_PROFILE_START(timer5); bool keep=true; for(vector::const_iterator group=mvRigidGroup.begin(); group!=mvRigidGroup.end();++group) { unsigned long ct=0; for(set::const_iterator at=(*group)->begin();at!=(*group)->end();++at) ct += pos->mvTranslatedAtomList.count(*at); if((ct>0)&&(ct!=(*group)->size())) { keep=false; #ifdef __DEBUG__ cout<<" Breaks Rigid Group:"; for(set::const_iterator at=(*group)->begin();at!=(*group)->end();++at) cout<<(*at)->GetName()<<" "; cout<SaveParamSet(mLocalParamSet); unsigned long paramSetRandom[5]; for(unsigned long i=0;i<5;++i) { for(vector::iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos) { (*pos)->SetX(100.*rand()/(REAL) RAND_MAX); (*pos)->SetY(100.*rand()/(REAL) RAND_MAX); (*pos)->SetZ(100.*rand()/(REAL) RAND_MAX); } paramSetRandom[i]=this->CreateParamSet(); } // find bond lengths broken by each mode for(list::iterator pos=mvStretchModeBondLength.begin(); pos!=mvStretchModeBondLength.end();) { TAU_PROFILE_START(timer2); bool keep=true; pos->mvpBrokenBond.clear(); for(vector::const_iterator r=mvpBond.begin();r!=mvpBond.end();++r) { unsigned int ct=0; for(set::const_iterator at=pos->mvTranslatedAtomList.begin(); at!=pos->mvTranslatedAtomList.end();++at) { if(*at==&((*r)->GetAtom1())) ct++; if(*at==&((*r)->GetAtom2())) ct++; } // If we moved either both or non of the bond atom, the bond length is unchanged. if((ct!=0)&&(ct !=2)) pos->mvpBrokenBond.insert(make_pair(*r,0)); } if(mFlexModel.GetChoice()==2) { int nb=pos->mvpBrokenBond.size(); if(pos->mpBond!=0) nb -= 1; if(nb>0) keep=false; } if(keep) ++pos; else pos=mvStretchModeBondLength.erase(pos); TAU_PROFILE_STOP(timer2); } // find bond angles broken by each mode for(list::iterator pos=mvStretchModeBondLength.begin(); pos!=mvStretchModeBondLength.end();) { TAU_PROFILE_START(timer3); bool keep=true; pos->mvpBrokenBondAngle.clear(); for(vector::const_iterator r=mvpBondAngle.begin();r!=mvpBondAngle.end();++r) { unsigned int ct=0; for(set::const_iterator at=pos->mvTranslatedAtomList.begin(); at!=pos->mvTranslatedAtomList.end();++at) { if(*at==&((*r)->GetAtom1())) ct++; if(*at==&((*r)->GetAtom2())) ct++; if(*at==&((*r)->GetAtom3())) ct++; } bool broken=true; if((ct==0)||(ct==3)) broken=false; if(broken) {// Make sure with derivatives REAL d=0; for(unsigned long i=0;i<5;++i) { this->RestoreParamSet(paramSetRandom[i]); pos->CalcDeriv(false); (*r)->GetLogLikelihood(true,true); d += abs((*r)->GetDeriv(pos->mDerivXYZ)); if(d>0.01) break; } if(abs(d)<=0.01) broken=false; } if(broken) pos->mvpBrokenBondAngle.insert(make_pair(*r,0)); } if(mFlexModel.GetChoice()==2) { if(pos->mvpBrokenBondAngle.size()>0) keep=false; } if(keep) ++pos; else pos=mvStretchModeBondLength.erase(pos); TAU_PROFILE_STOP(timer3); } // find dihedral angles broken by each mode for(list::iterator pos=mvStretchModeBondLength.begin(); pos!=mvStretchModeBondLength.end();) { TAU_PROFILE_START(timer4); bool keep=true; pos->mvpBrokenDihedralAngle.clear(); for(vector::const_iterator r=mvpDihedralAngle.begin();r!=mvpDihedralAngle.end();++r) { unsigned int ct=0; for(set::const_iterator at=pos->mvTranslatedAtomList.begin(); at!=pos->mvTranslatedAtomList.end();++at) { if(*at==&((*r)->GetAtom1())) ct++; if(*at==&((*r)->GetAtom2())) ct++; if(*at==&((*r)->GetAtom3())) ct++; if(*at==&((*r)->GetAtom4())) ct++; } bool broken=true; if((ct==0)||(ct==4)) broken=false; if(broken) {// Make sure with derivatives REAL d=0; for(unsigned long i=0;i<5;++i) { this->RestoreParamSet(paramSetRandom[i]); pos->CalcDeriv(false); (*r)->GetLogLikelihood(true,true); d += abs((*r)->GetDeriv(pos->mDerivXYZ)); if(d>0.01) break; } if(abs(d)<=0.01) broken=false; } if(broken) pos->mvpBrokenDihedralAngle.insert(make_pair(*r,0)); } if(mFlexModel.GetChoice()==2) { if(pos->mvpBrokenDihedralAngle.size()>0) keep=false; } if(keep) ++pos; else pos=mvStretchModeBondLength.erase(pos); TAU_PROFILE_STOP(timer4); } this->RestoreParamSet(mLocalParamSet); for(unsigned long i=0;i<5;++i) this->ClearParamSet(paramSetRandom[i]); #if 1//def __DEBUG__ cout<<"List of Bond Length stretch modes"<::const_iterator pos=mvStretchModeBondLength.begin(); pos!=mvStretchModeBondLength.end();++pos) { cout<<" Bond:"<mpAtom0->GetName()<<"-"<mpAtom1->GetName()<<", Translated Atoms: "; for(set::const_iterator atom=pos->mvTranslatedAtomList.begin(); atom!=pos->mvTranslatedAtomList.end();++atom) { cout<<(*atom)->GetName()<<","; } if(pos->mpBond!=0) cout<< " ; restrained to length="<mpBond->GetLength0() <<", sigma="<mpBond->GetLengthSigma() <<", delta="<mpBond->GetLengthDelta(); if(pos->mvpBrokenBond.size()>0) { cout<::const_iterator bond=pos->mvpBrokenBond.begin(); bond!=pos->mvpBrokenBond.end();++bond) cout<first->GetName()<<", "; } if(pos->mvpBrokenBondAngle.size()>0) { cout<::const_iterator angle=pos->mvpBrokenBondAngle.begin(); angle!=pos->mvpBrokenBondAngle.end();++angle) cout<first->GetName()<<", "; } if(pos->mvpBrokenDihedralAngle.size()>0) { cout<::const_iterator angle=pos->mvpBrokenDihedralAngle.begin(); angle!=pos->mvpBrokenDihedralAngle.end();++angle) cout<first->GetName()<<", "; } cout<mClockBondList) &&(mClockStretchModeBondAngle>mClockAtomList) &&(mClockStretchModeBondAngle>mClockBondAngleList) &&(mClockStretchModeBondAngle>mClockDihedralAngleList)) return; #endif VFN_DEBUG_ENTRY("Molecule::BuildStretchModeBondAngle()",10) this->BuildConnectivityTable(); TAU_PROFILE("Molecule::BuildStretchModeBondAngle()","void ()",TAU_DEFAULT); TAU_PROFILE_TIMER(timer1,"Molecule::BuildStretchModeBondAngle 1","", TAU_FIELD); TAU_PROFILE_TIMER(timer2,"Molecule::BuildStretchModeBondAngle 2","", TAU_FIELD); TAU_PROFILE_TIMER(timer3,"Molecule::BuildStretchModeBondAngle 3","", TAU_FIELD); TAU_PROFILE_TIMER(timer4,"Molecule::BuildStretchModeBondAngle 4","", TAU_FIELD); TAU_PROFILE_TIMER(timer5,"Molecule::BuildStretchModeBondAngle 5","", TAU_FIELD); mvStretchModeBondAngle.clear(); // Build list of atoms moved when stretching a bond angle. Only keep the group // of atoms on the smaller side. TAU_PROFILE_START(timer1); for(unsigned long i=0;iIsFreeTorsion())) continue; set *pConn0=&(mConnectivityTable[mvpAtom[i]]); if(pConn0->size()<2) continue; for(set::const_iterator pos1=pConn0->begin();pos1!=pConn0->end();++pos1) { set::const_iterator pos2=pos1; pos2++; for(;pos2!=pConn0->end();++pos2) { VFN_DEBUG_MESSAGE("Molecule::BuildStretchModeBondAngle():"<::const_iterator pos=mvpBondAngle.begin();pos!=mvpBondAngle.end();++pos) { if(&((*pos)->GetAtom2())==mvpAtom[i]) { if( ((&((*pos)->GetAtom1())==*pos1)&&(&((*pos)->GetAtom3())==*pos2)) ||((&((*pos)->GetAtom1())==*pos2)&&(&((*pos)->GetAtom3())==*pos1))) { pMolBondAngle=*pos; break; } } } for(unsigned int j=1;j<=2;++j) { const set *pConn; if(j==1) { pConn=&(mConnectivityTable[*pos1]); mvStretchModeBondAngle.push_back(StretchModeBondAngle(**pos2, *mvpAtom[i], **pos1, pMolBondAngle)); mvStretchModeBondAngle.back().mvRotatedAtomList.insert(*pos1); } else { pConn=&(mConnectivityTable[*pos2]); mvStretchModeBondAngle.push_back(StretchModeBondAngle(**pos1, *mvpAtom[i], **pos2, pMolBondAngle)); mvStretchModeBondAngle.back().mvRotatedAtomList.insert(*pos2); } mvStretchModeBondAngle.back().mvRotatedAtomList.insert(mvpAtom[i]); for(set::const_iterator pos=pConn->begin();pos!=pConn->end();++pos) { if(*pos==mvpAtom[i]) continue; ExpandAtomGroupRecursive(*pos,mConnectivityTable, mvStretchModeBondAngle.back().mvRotatedAtomList); } //if(j==1)mvStretchModeBondAngle.back().mvRotatedAtomList.erase(*pos2); //if(j==2)mvStretchModeBondAngle.back().mvRotatedAtomList.erase(*pos1); mvStretchModeBondAngle.back().mvRotatedAtomList.erase(mvpAtom[i]); if( (mvStretchModeBondAngle.back().mvRotatedAtomList.size()>=((mvpAtom.size()+1)/2)) ||(mvStretchModeBondAngle.back().mvRotatedAtomList.size()==0)) { #ifdef __DEBUG__ cout<<"Rejecting StretchModeBondAngle ";mvStretchModeBondAngle.back().Print(cout);cout<::iterator pos=mvStretchModeBondAngle.begin(); pos!=mvStretchModeBondAngle.end();) { TAU_PROFILE_START(timer5); bool keep=true; for(vector::const_iterator group=mvRigidGroup.begin(); group!=mvRigidGroup.end();++group) { unsigned long ct=0; for(set::const_iterator at=(*group)->begin();at!=(*group)->end();++at) ct += pos->mvRotatedAtomList.count(*at); if(ct>0) { // Add the origin atom, which does not move relatively to the rotated atoms ct += (*group)->count(pos->mpAtom1); if(ct!=(*group)->size()) { keep=false; #ifdef __DEBUG__ pos->Print(cout); cout<<" Breaks Rigid Group:"; for(set::const_iterator at=(*group)->begin();at!=(*group)->end();++at) cout<<(*at)->GetName()<<" "; cout<SaveParamSet(mLocalParamSet); unsigned long paramSetRandom[5]; for(unsigned long i=0;i<5;++i) { for(vector::iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos) { (*pos)->SetX(100.*rand()/(REAL) RAND_MAX); (*pos)->SetY(100.*rand()/(REAL) RAND_MAX); (*pos)->SetZ(100.*rand()/(REAL) RAND_MAX); } paramSetRandom[i]=this->CreateParamSet(); } // find bond lengths broken by each mode for(list::iterator pos=mvStretchModeBondAngle.begin(); pos!=mvStretchModeBondAngle.end();) { TAU_PROFILE_START(timer2); bool keep=true; pos->mvpBrokenBond.clear(); for(vector::const_iterator r=mvpBond.begin();r!=mvpBond.end();++r) { unsigned int ct=0; for(set::const_iterator at=pos->mvRotatedAtomList.begin(); at!=pos->mvRotatedAtomList.end();++at) { if(*at==&((*r)->GetAtom1())) ct++; if(*at==&((*r)->GetAtom2())) ct++; } bool broken=true; // If we moved either both or non of the bond atom, the bond length is unchanged. if((ct==0)||(ct==2)) broken=false; if(broken) {// Make sure with derivatives REAL d=0; for(unsigned long i=0;i<5;++i) { this->RestoreParamSet(paramSetRandom[i]); pos->CalcDeriv(false); (*r)->GetLogLikelihood(true,true); d += abs((*r)->GetDeriv(pos->mDerivXYZ)); if(d>0.01) break; } if(abs(d)<=0.01) broken=false; } if(broken) pos->mvpBrokenBond.insert(make_pair(*r,0)); } if(mFlexModel.GetChoice()==2) { if(pos->mvpBrokenBond.size()>0) keep=false; } if(keep) ++pos; else pos=mvStretchModeBondAngle.erase(pos); TAU_PROFILE_STOP(timer2); } // find bond angles broken by each mode for(list::iterator pos=mvStretchModeBondAngle.begin(); pos!=mvStretchModeBondAngle.end();) { TAU_PROFILE_START(timer3); bool keep=true; pos->mvpBrokenBondAngle.clear(); for(vector::const_iterator r=mvpBondAngle.begin();r!=mvpBondAngle.end();++r) { unsigned int ct=0; for(set::const_iterator at=pos->mvRotatedAtomList.begin(); at!=pos->mvRotatedAtomList.end();++at) { if(*at==&((*r)->GetAtom1())) ct++; if(*at==&((*r)->GetAtom2())) ct++; if(*at==&((*r)->GetAtom3())) ct++; } bool broken=true; if(ct==0) broken=false; if(ct==3) broken=false; if(broken) {// Make sure with derivatives REAL d=0; for(unsigned long i=0;i<5;++i) { this->RestoreParamSet(paramSetRandom[i]); pos->CalcDeriv(false); (*r)->GetLogLikelihood(true,true); d += abs((*r)->GetDeriv(pos->mDerivXYZ)); if(d>0.01) break; } if(abs(d)<=0.01) broken=false; } if(broken) pos->mvpBrokenBondAngle.insert(make_pair(*r,0)); } if(mFlexModel.GetChoice()==2) { int nb=pos->mvpBrokenBond.size(); if(pos->mpBondAngle!=0) nb -= 1; if(nb>0) keep=false; } if(keep) ++pos; else pos=mvStretchModeBondAngle.erase(pos); TAU_PROFILE_STOP(timer3); } // find dihedral angles broken by each mode for(list::iterator pos=mvStretchModeBondAngle.begin(); pos!=mvStretchModeBondAngle.end();) { TAU_PROFILE_START(timer4); bool keep=true; pos->mvpBrokenDihedralAngle.clear(); for(vector::const_iterator r=mvpDihedralAngle.begin();r!=mvpDihedralAngle.end();++r) { unsigned int ct=0; for(set::const_iterator at=pos->mvRotatedAtomList.begin(); at!=pos->mvRotatedAtomList.end();++at) { if(*at==&((*r)->GetAtom1())) ct++; if(*at==&((*r)->GetAtom2())) ct++; if(*at==&((*r)->GetAtom3())) ct++; if(*at==&((*r)->GetAtom4())) ct++; } bool broken=true; if(ct==0) broken=false; if(ct==4) broken=false; if(broken) {// Make sure with derivatives REAL d=0; for(unsigned long i=0;i<5;++i) { this->RestoreParamSet(paramSetRandom[i]); pos->CalcDeriv(false); (*r)->GetLogLikelihood(true,true); d += abs((*r)->GetDeriv(pos->mDerivXYZ)); if(d>0.01) break; } if(abs(d)<=0.01) broken=false; } if(broken) pos->mvpBrokenDihedralAngle.insert(make_pair(*r,0)); } if(mFlexModel.GetChoice()==2) { if(pos->mvpBrokenDihedralAngle.size()>0) keep=false; } if(keep) ++pos; else pos=mvStretchModeBondAngle.erase(pos); TAU_PROFILE_STOP(timer4); } this->RestoreParamSet(mLocalParamSet); for(unsigned long i=0;i<5;++i) this->ClearParamSet(paramSetRandom[i]); #ifdef __DEBUG__ cout<<"List of Bond Angle stretch modes"<::const_iterator pos=mvStretchModeBondAngle.begin(); pos!=mvStretchModeBondAngle.end();++pos) { cout<<" Angle:"<mpAtom0->GetName()<<"-" <mpAtom1->GetName()<<"-" <mpAtom2->GetName()<<", Rotated Atoms: "; for(set::const_iterator atom=pos->mvRotatedAtomList.begin(); atom!=pos->mvRotatedAtomList.end();++atom) { cout<<(*atom)->GetName()<<","; } if(pos->mpBondAngle!=0) cout<< " ; restrained to angle="<mpBondAngle->GetAngle0()*RAD2DEG <<"�, sigma="<mpBondAngle->GetAngleSigma()*RAD2DEG <<"�, delta="<mpBondAngle->GetAngleDelta()*RAD2DEG<<"�"; if(pos->mvpBrokenBond.size()>0) { cout<::const_iterator bond=pos->mvpBrokenBond.begin(); bond!=pos->mvpBrokenBond.end();++bond) cout<first->GetName()<<", "; } if(pos->mvpBrokenBondAngle.size()>0) { cout<::const_iterator angle=pos->mvpBrokenBondAngle.begin(); angle!=pos->mvpBrokenBondAngle.end();++angle) cout<first->GetName()<<", "; } if(pos->mvpBrokenDihedralAngle.size()>0) { cout<::const_iterator angle=pos->mvpBrokenDihedralAngle.begin(); angle!=pos->mvpBrokenDihedralAngle.end();++angle) cout<first->GetName()<<", "; } cout<mClockBondList) &&(mClockStretchModeTorsion>mClockAtomList) &&(mClockStretchModeTorsion>mClockBondAngleList) &&(mClockStretchModeTorsion>mClockDihedralAngleList)) return; #endif VFN_DEBUG_ENTRY("Molecule::BuildStretchModeTorsion()",7) TAU_PROFILE("Molecule::BuildStretchModeTorsion()","void ()",TAU_DEFAULT); TAU_PROFILE_TIMER(timer1,"Molecule::BuildStretchModeTorsion 1","", TAU_FIELD); TAU_PROFILE_TIMER(timer2,"Molecule::BuildStretchModeTorsion 2","", TAU_FIELD); TAU_PROFILE_TIMER(timer3,"Molecule::BuildStretchModeTorsion 3","", TAU_FIELD); TAU_PROFILE_TIMER(timer4,"Molecule::BuildStretchModeTorsion 4","", TAU_FIELD); TAU_PROFILE_TIMER(timer5,"Molecule::BuildStretchModeTorsion 5","", TAU_FIELD); this->BuildConnectivityTable(); mvStretchModeTorsion.clear(); // Build list of atoms moved when changing the angle. Only keep the group // of atoms on the smaller side. for(unsigned long i=0;iIsFreeTorsion())) continue; MolAtom* const atom1=&(mvpBond[i]->GetAtom1()); MolAtom* const atom2=&(mvpBond[i]->GetAtom2()); for(unsigned int j=1;j<=2;++j) { const set *pConn; if(j==1) pConn=&(mConnectivityTable[atom1]); else pConn=&(mConnectivityTable[atom2]); mvStretchModeTorsion.push_back(StretchModeTorsion(*atom1,*atom2,0)); mvStretchModeTorsion.back().mvRotatedAtomList.insert(atom1); mvStretchModeTorsion.back().mvRotatedAtomList.insert(atom2); for(set::const_iterator pos=pConn->begin();pos!=pConn->end();++pos) { if((*pos==atom2)||(*pos==atom1)) continue; ExpandAtomGroupRecursive(*pos,mConnectivityTable, mvStretchModeTorsion.back().mvRotatedAtomList); } mvStretchModeTorsion.back().mvRotatedAtomList.erase(atom1); mvStretchModeTorsion.back().mvRotatedAtomList.erase(atom2); for(vector::const_iterator dih=mvpDihedralAngle.begin();dih!=mvpDihedralAngle.end();++dih) { // :TODO: There are some other weird cases to take into account, // for restraints with atoms *not* connected to another // More generally, should check the list of atoms rotated. if( ((&((*dih)->GetAtom2())==atom1) && (&((*dih)->GetAtom3())==atom2)) ||((&((*dih)->GetAtom3())==atom1) && (&((*dih)->GetAtom2())==atom2))) { const unsigned long ct1=mvStretchModeTorsion.back().mvRotatedAtomList.count(&((*dih)->GetAtom1())); const unsigned long ct4=mvStretchModeTorsion.back().mvRotatedAtomList.count(&((*dih)->GetAtom4())); if((ct1+ct4)==1)// One of the atom is rotated, not the other { mvStretchModeTorsion.back().mpDihedralAngle=*dih; //:TODO: Check sense of rotation ! if(ct4==1) { mvStretchModeTorsion.back().mpAtom1=&((*dih)->GetAtom2()); mvStretchModeTorsion.back().mpAtom2=&((*dih)->GetAtom3()); } else { mvStretchModeTorsion.back().mpAtom1=&((*dih)->GetAtom3()); mvStretchModeTorsion.back().mpAtom2=&((*dih)->GetAtom2()); } } } } if(mvStretchModeTorsion.size()>1) {//Duplicate ? // Does not work with a const_reverse_iterator ? // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11729 list::reverse_iterator mode=mvStretchModeTorsion.rbegin(); ++mode; for(;mode!=mvStretchModeTorsion.rend();++mode) { if( ( ((mode->mpAtom1==atom1)&&(mode->mpAtom2==atom2)) ||((mode->mpAtom1==atom2)&&(mode->mpAtom2==atom1))) &&(mode->mvRotatedAtomList==mvStretchModeTorsion.back().mvRotatedAtomList)) { #ifdef __DEBUG__ cout<<"Duplicate StretchModeTorsion ";mvStretchModeTorsion.back().Print(cout);cout<((mvpAtom.size()+1)/2)) ||(mvStretchModeTorsion.back().mvRotatedAtomList.size()==0)) { #ifdef __DEBUG__ cout<<"Rejecting StretchModeTorsion ";mvStretchModeTorsion.back().Print(cout);cout<IsFreeTorsion())) continue; MolAtom* const atom1=&(mvpBond[i]->GetAtom1()); MolAtom* const atom2=&(mvpBond[i]->GetAtom2()); for(unsigned int j=1;j<=2;++j) { const set *pConn; if(j==1) pConn=&(mConnectivityTable[atom1]); else pConn=&(mConnectivityTable[atom2]); for(set::const_iterator pos=pConn->begin();pos!=pConn->end();++pos) { if((*pos==atom2)||(*pos==atom1)) continue; mvStretchModeTorsion.push_back(StretchModeTorsion(*atom1,*atom2,0)); mvStretchModeTorsion.back().mvRotatedAtomList.insert(atom1); mvStretchModeTorsion.back().mvRotatedAtomList.insert(atom2); ExpandAtomGroupRecursive(*pos,mConnectivityTable, mvStretchModeTorsion.back().mvRotatedAtomList); mvStretchModeTorsion.back().mvRotatedAtomList.erase(atom1); mvStretchModeTorsion.back().mvRotatedAtomList.erase(atom2); for(vector::const_iterator dih=mvpDihedralAngle.begin();dih!=mvpDihedralAngle.end();++dih) { // :TODO: There are some other weird cases to take into account, // for restraints with atoms *not* connected to another // More generally, should check the list of atoms rotated. if( ((&((*dih)->GetAtom2())==atom1) && (&((*dih)->GetAtom3())==atom2)) ||((&((*dih)->GetAtom3())==atom1) && (&((*dih)->GetAtom2())==atom2))) { const unsigned long ct1=mvStretchModeTorsion.back().mvRotatedAtomList.count(&((*dih)->GetAtom1())); const unsigned long ct4=mvStretchModeTorsion.back().mvRotatedAtomList.count(&((*dih)->GetAtom4())); if((ct1+ct4)==1)// One of the atom is rotated, not the other { mvStretchModeTorsion.back().mpDihedralAngle=*dih; //:TODO: Check sense of rotation ! if(ct4==1) { mvStretchModeTorsion.back().mpAtom1=&((*dih)->GetAtom2()); mvStretchModeTorsion.back().mpAtom2=&((*dih)->GetAtom3()); } else { mvStretchModeTorsion.back().mpAtom1=&((*dih)->GetAtom3()); mvStretchModeTorsion.back().mpAtom2=&((*dih)->GetAtom2()); } } } } if(mvStretchModeTorsion.size()>1) {//Duplicate ? // Does not work with a const_reverse_iterator ? // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11729 list::reverse_iterator mode=mvStretchModeTorsion.rbegin(); ++mode; for(;mode!=mvStretchModeTorsion.rend();++mode) { if( ( ((mode->mpAtom1==atom1)&&(mode->mpAtom2==atom2)) ||((mode->mpAtom1==atom2)&&(mode->mpAtom2==atom1))) &&(mode->mvRotatedAtomList==mvStretchModeTorsion.back().mvRotatedAtomList)) { #ifdef __DEBUG__ cout<<"Duplicate StretchModeTorsion ";mvStretchModeTorsion.back().Print(cout);cout<((mvpAtom.size()+1)/2)) ||(mvStretchModeTorsion.back().mvRotatedAtomList.size()==0)) { #ifdef __DEBUG__ cout<<"Rejecting StretchModeTorsion ";mvStretchModeTorsion.back().Print(cout);cout<::iterator pos=mvStretchModeTorsion.begin(); pos!=mvStretchModeTorsion.end();) { TAU_PROFILE_START(timer5); bool keep=true; for(vector::const_iterator group=mvRigidGroup.begin(); group!=mvRigidGroup.end();++group) { unsigned long ct=0; for(set::const_iterator at=(*group)->begin();at!=(*group)->end();++at) ct += pos->mvRotatedAtomList.count(*at); if(ct>0) { // Add the axis atoms, which do not move relatively to the rotated atoms ct += (*group)->count(pos->mpAtom1); ct += (*group)->count(pos->mpAtom2); if(ct!=(*group)->size()) { keep=false; #ifdef __DEBUG__ pos->Print(cout); cout<<" Breaks Rigid Group:"; for(set::const_iterator at=(*group)->begin();at!=(*group)->end();++at) cout<<(*at)->GetName()<<" "; cout<SaveParamSet(mLocalParamSet); unsigned long paramSetRandom[5]; for(unsigned long i=0;i<5;++i) { for(vector::iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos) { (*pos)->SetX(100.*rand()/(REAL) RAND_MAX); (*pos)->SetY(100.*rand()/(REAL) RAND_MAX); (*pos)->SetZ(100.*rand()/(REAL) RAND_MAX); } paramSetRandom[i]=this->CreateParamSet(); } // find bond lengths broken by each mode for(list::iterator pos=mvStretchModeTorsion.begin(); pos!=mvStretchModeTorsion.end();) { TAU_PROFILE_START(timer2); bool keep=true; pos->mvpBrokenBond.clear(); for(vector::const_iterator r=mvpBond.begin();r!=mvpBond.end();++r) { unsigned int ct=0; for(set::const_iterator at=pos->mvRotatedAtomList.begin(); at!=pos->mvRotatedAtomList.end();++at) { if(*at==&((*r)->GetAtom1())) ct++; if(*at==&((*r)->GetAtom2())) ct++; } bool broken=true; // If we moved either both or non of the bond atom, the bond length is unchanged. if((ct==0)||(ct==2)) broken=false; if(broken) {// Make sure with derivatives REAL d=0; for(unsigned long i=0;i<5;++i) { this->RestoreParamSet(paramSetRandom[i]); pos->CalcDeriv(false); (*r)->GetLogLikelihood(true,true); d += abs((*r)->GetDeriv(pos->mDerivXYZ)); if(d>0.01) break; } if(abs(d)<=0.01) broken=false; } if(broken) pos->mvpBrokenBond.insert(make_pair(*r,0)); } if(mFlexModel.GetChoice()==2) { if(pos->mvpBrokenBond.size()>0) keep=false; } if(keep) ++pos; else pos=mvStretchModeTorsion.erase(pos); TAU_PROFILE_STOP(timer2); } // find bond angles broken by each mode for(list::iterator pos=mvStretchModeTorsion.begin(); pos!=mvStretchModeTorsion.end();) { TAU_PROFILE_START(timer3); bool keep=true; pos->mvpBrokenBondAngle.clear(); for(vector::const_iterator r=mvpBondAngle.begin();r!=mvpBondAngle.end();++r) { unsigned int ct=0; for(set::const_iterator at=pos->mvRotatedAtomList.begin(); at!=pos->mvRotatedAtomList.end();++at) { if(*at==&((*r)->GetAtom1())) ct++; if(*at==&((*r)->GetAtom2())) ct++; if(*at==&((*r)->GetAtom3())) ct++; } bool broken=true; if((ct==0)||(ct==3)) broken=false; if(broken) {// Make sure with derivatives REAL d=0; for(unsigned long i=0;i<5;++i) { this->RestoreParamSet(paramSetRandom[i]); pos->CalcDeriv(false); (*r)->GetLogLikelihood(true,true); d += abs((*r)->GetDeriv(pos->mDerivXYZ)); if(d>0.01) break; } if(abs(d)<=0.01) broken=false; } if(broken) pos->mvpBrokenBondAngle.insert(make_pair(*r,0)); } if(mFlexModel.GetChoice()==2) { if(pos->mvpBrokenBond.size()>0) keep=false; } if(keep) ++pos; else pos=mvStretchModeTorsion.erase(pos); TAU_PROFILE_STOP(timer3); } // find dihedral angles broken by each mode for(list::iterator pos=mvStretchModeTorsion.begin(); pos!=mvStretchModeTorsion.end();) { TAU_PROFILE_START(timer4); bool keep=true; pos->mvpBrokenDihedralAngle.clear(); for(vector::const_iterator r=mvpDihedralAngle.begin();r!=mvpDihedralAngle.end();++r) { unsigned int ct=0; for(set::const_iterator at=pos->mvRotatedAtomList.begin(); at!=pos->mvRotatedAtomList.end();++at) { if(*at==&((*r)->GetAtom1())) ct++; if(*at==&((*r)->GetAtom2())) ct++; if(*at==&((*r)->GetAtom3())) ct++; if(*at==&((*r)->GetAtom4())) ct++; } bool broken=true; if((ct==0)||(ct==4)) broken=false; if(broken) {// Make sure with derivatives REAL d=0; for(unsigned long i=0;i<5;++i) { this->RestoreParamSet(paramSetRandom[i]); pos->CalcDeriv(false); (*r)->GetLogLikelihood(true,true); d += abs((*r)->GetDeriv(pos->mDerivXYZ)); if(d>0.01) break; } if(abs(d)<=0.01) broken=false; } if(broken) pos->mvpBrokenDihedralAngle.insert(make_pair(*r,0)); } if(mFlexModel.GetChoice()==2) { int nb=pos->mvpBrokenDihedralAngle.size(); if(pos->mpDihedralAngle!=0) nb -= 1; if(nb>0) keep=false; } if(keep) ++pos; else pos=mvStretchModeTorsion.erase(pos); TAU_PROFILE_STOP(timer4); } for(unsigned long i=0;i<5;++i) this->ClearParamSet(paramSetRandom[i]); this->RestoreParamSet(mLocalParamSet); #ifdef __DEBUG__ cout<<"List of Dihedral Angle stretch modes("<::const_iterator pos=mvStretchModeTorsion.begin(); pos!=mvStretchModeTorsion.end();++pos) { cout<<" Dihedral Angle:" <mpAtom1->GetName()<<"-" <mpAtom2->GetName()<<", Rotated Atoms: "; for(set::const_iterator atom=pos->mvRotatedAtomList.begin(); atom!=pos->mvRotatedAtomList.end();++atom) { cout<<(*atom)->GetName()<<","; } if(pos->mpDihedralAngle!=0) cout<restrained by dihedral angle "<mpDihedralAngle->GetName() <<"to :"<mpDihedralAngle->GetAngle0()*RAD2DEG <<"�, sigma="<mpDihedralAngle->GetAngleSigma()*RAD2DEG <<"�, delta="<mpDihedralAngle->GetAngleDelta()*RAD2DEG<<"�"; if(pos->mvpBrokenBond.size()>0) { cout<::const_iterator bond=pos->mvpBrokenBond.begin(); bond!=pos->mvpBrokenBond.end();++bond) cout<first->GetName()<<", "; } if(pos->mvpBrokenBondAngle.size()>0) { cout<::const_iterator angle=pos->mvpBrokenBondAngle.begin(); angle!=pos->mvpBrokenBondAngle.end();++angle) cout<first->GetName()<<", "; } if(pos->mvpBrokenDihedralAngle.size()>0) { cout<::const_iterator angle=pos->mvpBrokenDihedralAngle.begin(); angle!=pos->mvpBrokenDihedralAngle.end();++angle) cout<first->GetName()<<", "; } cout<mClockBondList) &&(mClockStretchModeTwist>mClockAtomList) &&(mClockStretchModeTwist>mClockBondAngleList) &&(mClockStretchModeTwist>mClockDihedralAngleList)) return; #endif VFN_DEBUG_ENTRY("Molecule::BuildStretchModeTwist()",7) this->BuildConnectivityTable(); mvStretchModeTwist.clear(); // For each pair of atoms, build an internal chain to twist. for(vector::const_iterator atom1=this->GetAtomList().begin(); atom1!=this->GetAtomList().end();++atom1) { const set *pConn=&(mConnectivityTable[*atom1]); vector::const_iterator atom2=atom1; atom2++; for(;atom2!=this->GetAtomList().end();++atom2) { for(set::const_iterator pos=pConn->begin();pos!=pConn->end();++pos) {// Start from one atom connected to atom1 if(*pos==*atom2) continue; mvStretchModeTwist.push_back(StretchModeTwist(**atom1,**atom2)); mvStretchModeTwist.back().mvRotatedAtomList.insert(*atom1); ExpandAtomGroupRecursive(*pos,mConnectivityTable, mvStretchModeTwist.back().mvRotatedAtomList, *atom2); //Check if this chains actually leads to atom2 set::const_iterator check =find(mvStretchModeTwist.back().mvRotatedAtomList.begin(), mvStretchModeTwist.back().mvRotatedAtomList.end(),*atom2); bool keep =true; if( (check==mvStretchModeTwist.back().mvRotatedAtomList.end()) ||(mvStretchModeTwist.back().mvRotatedAtomList.size()<3) ||(mvStretchModeTwist.back().mvRotatedAtomList.size()>=((mvpAtom.size()+1)/2))) { keep=false; } if(keep) { mvStretchModeTwist.back().mvRotatedAtomList.erase(*atom1); mvStretchModeTwist.back().mvRotatedAtomList.erase(*atom2); if( (mvStretchModeTwist.back().mvRotatedAtomList.size()>=(mvpAtom.size()/2)) ||(mvStretchModeTwist.back().mvRotatedAtomList.size()==0)) { #ifdef __DEBUG__ cout<<"Rejecting StretchModeTwist ";mvStretchModeTwist.back().Print(cout);cout<1) {//Duplicate ? // Does not work with a const_reverse_iterator ? // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11729 list::reverse_iterator mode=mvStretchModeTwist.rbegin(); ++mode; for(;mode!=mvStretchModeTwist.rend();++mode) { if( ( ((mode->mpAtom1==*atom1)&&(mode->mpAtom2==*atom2)) ||((mode->mpAtom1==*atom2)&&(mode->mpAtom2==*atom1))) &&(mode->mvRotatedAtomList==mvStretchModeTwist.back().mvRotatedAtomList)) { #ifdef __DEBUG__ cout<<"Duplicate StretchModeTwist ";mvStretchModeTwist.back().Print(cout);cout<0) // Torsion and twist modes can be identical for cycles. {//Duplicate ? // Does not work with a const_reverse_iterator ? // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11729 list::reverse_iterator mode; for(mode=mvStretchModeTorsion.rbegin();mode!=mvStretchModeTorsion.rend();++mode) { if( ( ((mode->mpAtom1==*atom1)&&(mode->mpAtom2==*atom2)) ||((mode->mpAtom1==*atom2)&&(mode->mpAtom2==*atom1))) &&(mode->mvRotatedAtomList==mvStretchModeTwist.back().mvRotatedAtomList)) { #ifdef __DEBUG__ cout<<"Duplicate StretchModeTwist (with Torsion) ";mvStretchModeTwist.back().Print(cout);cout<SaveParamSet(mLocalParamSet); unsigned long paramSetRandom[5]; for(unsigned long i=0;i<5;++i) { for(vector::iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos) { (*pos)->SetX(100.*rand()/(REAL) RAND_MAX); (*pos)->SetY(100.*rand()/(REAL) RAND_MAX); (*pos)->SetZ(100.*rand()/(REAL) RAND_MAX); } paramSetRandom[i]=this->CreateParamSet(); } // find bond, bond angles and dihedral angles broken by each mode for(list::iterator pos=mvStretchModeTwist.begin(); pos!=mvStretchModeTwist.end();) { pos->mvpBrokenBond.clear(); pos->mvpBrokenBondAngle.clear(); pos->mvpBrokenDihedralAngle.clear(); pos->CalcDeriv(); #ifdef __DEBUG__ cout<<" DerivLLK for Twist mode around:" <mpAtom1->GetName()<<"-" <mpAtom2->GetName()<<": Moving atoms:"; for(set::const_iterator atom=pos->mvRotatedAtomList.begin(); atom!=pos->mvRotatedAtomList.end();++atom) cout<<(*atom)->GetName()<<","; cout<::const_iterator r=mvpBond.begin();r!=mvpBond.end();++r) { (*r)->GetLogLikelihood(true,true); REAL d=0; for(unsigned long i=0;i<5;++i) { this->RestoreParamSet(paramSetRandom[i]); d += abs((*r)->GetDeriv(pos->mDerivXYZ)); } if(abs(d)>0.1) { #ifdef __DEBUG__ cout<<" Bond "<<(*r)->GetName() <<": dLength/da="<mvpBrokenBond.insert(make_pair(*r,0.0)); } } for(vector::const_iterator r=mvpBondAngle.begin();r!=mvpBondAngle.end();++r) { (*r)->GetLogLikelihood(true,true); REAL d=0; for(unsigned long i=0;i<5;++i) { this->RestoreParamSet(paramSetRandom[i]); d += abs((*r)->GetDeriv(pos->mDerivXYZ)); } if(abs(d)>0.01) { #ifdef __DEBUG__ cout<<" BondAngle:"<<(*r)->GetName()<<": dAngle/da="<mvpBrokenBondAngle.insert(make_pair(*r,0.0)); } } for(vector::const_iterator r=mvpDihedralAngle.begin(); r!=mvpDihedralAngle.end();++r) { //if(*r==pos->mpDihedralAngle) continue; (*r)->GetLogLikelihood(true,true); REAL d=0; for(unsigned long i=0;i<5;++i) { this->RestoreParamSet(paramSetRandom[i]); d += abs((*r)->GetDeriv(pos->mDerivXYZ)); } if(abs(d)>0.01) { #ifdef __DEBUG__ cout<<" DihedralAngle:"<<(*r)->GetName()<<": dAngle/da="<mvpBrokenDihedralAngle.insert(make_pair(*r,0.0)); } } //Get rid of stretch modes that break rigid groups bool keep=true; for(vector::const_iterator group=mvRigidGroup.begin(); group!=mvRigidGroup.end();++group) { unsigned long ct=0; for(set::const_iterator at=(*group)->begin();at!=(*group)->end();++at) ct += pos->mvRotatedAtomList.count(*at); if(ct>0) { // Add atom1 and atom2 to the count only if they are in the group // They do not move in absolute or relatively to the group. ct += (*group)->count(pos->mpAtom1); ct += (*group)->count(pos->mpAtom2); if(ct!=(*group)->size()) { keep=false; #ifdef __DEBUG__ cout<<" Breaks Rigid Group:"<size()<<":"; for(set::const_iterator at=(*group)->begin();at!=(*group)->end();++at) cout<<(*at)->GetName()<<" "; cout<mvpBrokenBond.size()+pos->mvpBrokenBondAngle.size()+pos->mvpBrokenDihedralAngle.size()) keep=false; } if(keep) ++pos; else pos=mvStretchModeTwist.erase(pos); } for(unsigned long i=0;i<5;++i) this->ClearParamSet(paramSetRandom[i]); this->RestoreParamSet(mLocalParamSet); #ifdef __DEBUG__ cout<<"List of Twist stretch modes("<::const_iterator pos=mvStretchModeTwist.begin(); pos!=mvStretchModeTwist.end();++pos) { cout<<" Twist mode:" <mpAtom1->GetName()<<"-" <mpAtom2->GetName()<<", Rotated Atoms: "; for(set::const_iterator atom=pos->mvRotatedAtomList.begin(); atom!=pos->mvRotatedAtomList.end();++atom) { cout<<(*atom)->GetName()<<","; } if(pos->mvpBrokenBond.size()>0) { cout<::const_iterator bond=pos->mvpBrokenBond.begin(); bond!=pos->mvpBrokenBond.end();++bond) cout<first->GetName()<<", "; } if(pos->mvpBrokenBondAngle.size()>0) { cout<::const_iterator angle=pos->mvpBrokenBondAngle.begin(); angle!=pos->mvpBrokenBondAngle.end();++angle) cout<first->GetName()<<", "; } if(pos->mvpBrokenDihedralAngle.size()>0) { cout<::const_iterator angle=pos->mvpBrokenDihedralAngle.begin(); angle!=pos->mvpBrokenDihedralAngle.end();++angle) cout<first->GetName()<<", "; } cout<CreateParamSet("Initial Configuration"); const unsigned int nbTest=100; // First we store in mBaseRotationAmplitude the cumulated atomic displacement // for nbTest rotations of 0.01 rad for(list::iterator pos=mvStretchModeBondAngle.begin(); pos!=mvStretchModeBondAngle.end();++pos) pos->mBaseAmplitude=0; for(list::iterator pos=mvStretchModeTorsion.begin(); pos!=mvStretchModeTorsion.end();++pos) pos->mBaseAmplitude=0; REAL displacement=0;//For the global Molecule rotation for(unsigned int j=0;jRandomizeConfiguration(); // Atomic positions, orthonormal coordinates vector x0(this->GetNbComponent()); vector y0(this->GetNbComponent()); vector z0(this->GetNbComponent()); // Center of molecule coords REAL xc=0.,yc=0.,zc=0.; for(long i=0;iGetNbComponent();++i) { x0[i]=mvpAtom[i]->GetX(); xc += x0[i]; y0[i]=mvpAtom[i]->GetY(); yc += y0[i]; z0[i]=mvpAtom[i]->GetZ(); zc += z0[i]; } xc /= (REAL)(this->GetNbComponent()); yc /= (REAL)(this->GetNbComponent()); zc /= (REAL)(this->GetNbComponent()); // Record displacement amplitude for torsion angles REAL dx,dy,dz; for(list::iterator pos=mvStretchModeBondAngle.begin(); pos!=mvStretchModeBondAngle.end();++pos) { const REAL dx10=pos->mpAtom0->GetX()-pos->mpAtom1->GetX(); const REAL dy10=pos->mpAtom0->GetY()-pos->mpAtom1->GetY(); const REAL dz10=pos->mpAtom0->GetZ()-pos->mpAtom1->GetZ(); const REAL dx12=pos->mpAtom2->GetX()-pos->mpAtom1->GetX(); const REAL dy12=pos->mpAtom2->GetY()-pos->mpAtom1->GetY(); const REAL dz12=pos->mpAtom2->GetZ()-pos->mpAtom1->GetZ(); const REAL vx=dy10*dz12-dz10*dy12; const REAL vy=dz10*dx12-dx10*dz12; const REAL vz=dx10*dy12-dy10*dx12; this->RotateAtomGroup(*(pos->mpAtom1),vx,vy,vz,pos->mvRotatedAtomList,0.01,false); for(long i=0;iGetNbComponent();++i) { dx=x0[i]-mvpAtom[i]->GetX(); dy=y0[i]-mvpAtom[i]->GetY(); dz=z0[i]-mvpAtom[i]->GetZ(); pos->mBaseAmplitude+=sqrt(abs(dx*dx+dy*dy+dz*dz)); } this->RotateAtomGroup(*(pos->mpAtom1),vx,vy,vz,pos->mvRotatedAtomList,-0.01,false); } for(list::iterator pos=mvStretchModeTorsion.begin(); pos!=mvStretchModeTorsion.end();++pos) { this->RotateAtomGroup(*(pos->mpAtom1),*(pos->mpAtom2),pos->mvRotatedAtomList,0.01,false); for(long i=0;iGetNbComponent();++i) { dx=x0[i]-mvpAtom[i]->GetX(); dy=y0[i]-mvpAtom[i]->GetY(); dz=z0[i]-mvpAtom[i]->GetZ(); pos->mBaseAmplitude+=sqrt(abs(dx*dx+dy*dy+dz*dz)); } this->RotateAtomGroup(*(pos->mpAtom1),*(pos->mpAtom2),pos->mvRotatedAtomList,-0.01,false); } // Record displacement amplitude for global rotation, for 10 random rot axis for(unsigned int k=0;k<10;++k) { Quaternion quat=Quaternion::RotationQuaternion (mBaseRotationAmplitude,(REAL)rand(),(REAL)rand(),(REAL)rand()); for(long i=0;iGetNbComponent();++i) { REAL x=x0[i]-xc; REAL y=y0[i]-yc; REAL z=z0[i]-zc; quat.RotateVector(x,y,z); dx=(x0[i]-xc)-x; dy=(y0[i]-yc)-y; dz=(z0[i]-zc)-z; displacement+=sqrt(abs(dx*dx+dy*dy+dz*dz)); } } } // Modify base rotation amplitudes, for an average 0.02 Angstroem displacement for(list::iterator pos=mvStretchModeBondAngle.begin(); pos!=mvStretchModeBondAngle.end();++pos) { pos->mBaseAmplitude/=(REAL)(nbTest*this->GetNbComponent());//(REAL)(nbTest*(0.5*pos->mvRotatedAtomList.size()+0.5*this->GetNbComponent())); pos->mBaseAmplitude=0.1*0.01/pos->mBaseAmplitude; if(pos->mBaseAmplitude>.17) pos->mBaseAmplitude=.17; bool free=true; if((pos->mvpBrokenBond.size()+pos->mvpBrokenBondAngle.size()+pos->mvpBrokenDihedralAngle.size())>0) { pos->mBaseAmplitude/=10; free=false; } #if 1// def __DEBUG__ cout<<"ANGLE :" <mpAtom0->GetName()<<"-" <mpAtom1->GetName()<<"-" <mpAtom2->GetName()<<":"; for(set::const_iterator atom=pos->mvRotatedAtomList.begin(); atom!=pos->mvRotatedAtomList.end();++atom) cout<<(*atom)->GetName()<<","; cout <<": base rotation="<mBaseAmplitude*RAD2DEG<<" free="<::iterator pos=mvStretchModeTorsion.begin(); pos!=mvStretchModeTorsion.end();++pos) { pos->mBaseAmplitude/=(REAL)(nbTest*this->GetNbComponent());//(REAL)(nbTest*(0.5*pos->mvRotatedAtomList.size()+0.5*this->GetNbComponent())); pos->mBaseAmplitude=0.1*0.01/pos->mBaseAmplitude; if(pos->mBaseAmplitude>.17) pos->mBaseAmplitude=.17; bool free=true; if((pos->mvpBrokenBond.size()+pos->mvpBrokenBondAngle.size()+pos->mvpBrokenDihedralAngle.size())>0) { pos->mBaseAmplitude/=10; free=false; } #if 1// def __DEBUG__ cout<<"TORSION :" <mpAtom1->GetName()<<"-" <mpAtom2->GetName()<<":"; for(set::const_iterator atom=pos->mvRotatedAtomList.begin(); atom!=pos->mvRotatedAtomList.end();++atom) cout<<(*atom)->GetName()<<","; cout <<": base rotation="<mBaseAmplitude*RAD2DEG<<" free="<::iterator pos=mvStretchModeTwist.begin(); pos!=mvStretchModeTwist.end();++pos) { pos->mBaseAmplitude/=(REAL)(nbTest*this->GetNbComponent());//(REAL)(nbTest*(0.5*pos->mvRotatedAtomList.size()+0.5*this->GetNbComponent())); pos->mBaseAmplitude=0.1*0.01/pos->mBaseAmplitude; if(pos->mBaseAmplitude>.17) pos->mBaseAmplitude=.17; bool free=true; if((pos->mvpBrokenBond.size()+pos->mvpBrokenBondAngle.size()+pos->mvpBrokenDihedralAngle.size())>0) { pos->mBaseAmplitude/=10; free=false; } #if 1// def __DEBUG__ cout<<"TWIST :" <mpAtom1->GetName()<<"-" <mpAtom2->GetName()<<":"; for(set::const_iterator atom=pos->mvRotatedAtomList.begin(); atom!=pos->mvRotatedAtomList.end();++atom) cout<<(*atom)->GetName()<<","; cout <<": base rotation="<mBaseAmplitude*RAD2DEG<<" free="<GetNbComponent()); //cout<<"Overall Atomic Displacement for Global Rotation:="<0) mBaseRotationAmplitude*=0.1/displacement; if(mBaseRotationAmplitude<(0.02*M_PI/20.)) { mBaseRotationAmplitude=0.02*M_PI/20.; //cout <<"WARNING - too low Global BaseRotationAmplitude - setting to: " // << mBaseAmplitude*RAD2DEG<< " �"<(0.02*M_PI*20.)) { mBaseRotationAmplitude=0.02*M_PI*20.; //cout <<"WARNING - too high Global BaseRotationAmplitude - setting to: " // << mBaseAmplitude*RAD2DEG<< " �"< Base rotation="<RestoreParamSet(initialConfig); VFN_DEBUG_EXIT("Molecule::TuneGlobalOptimRotationAmplitude()",5) } void Molecule::BuildFlipGroup() { this->BuildConnectivityTable(); if( (mClockFlipGroup>mClockConnectivityTable) &&(mClockFlipGroup>mClockRigidGroup)) return; VFN_DEBUG_ENTRY("Molecule::BuildFlipGroup()",5) TAU_PROFILE("Molecule::BuildFlipGroup()","void ()",TAU_DEFAULT); mvFlipGroup.clear(); for(vector::const_iterator atom0=this->GetAtomList().begin(); atom0!=this->GetAtomList().end();++atom0) { const set *pConn=&(mConnectivityTable[*atom0]); if(pConn->size()<3) continue; // Build all chains for(set::const_iterator pos1=pConn->begin();pos1!=pConn->end();++pos1) { for(set::const_iterator pos2=pos1;pos2!=pConn->end();++pos2) { if(*pos2==*pos1) continue; if(mFlexModel.GetChoice()==0) { mvFlipGroup.push_back(FlipGroup(**atom0,**pos1,**pos2)); bool foundRing=false; for(set::const_iterator pos=pConn->begin();pos!=pConn->end();++pos) { if((pos==pos1)||(pos==pos2)) continue; mvFlipGroup.back().mvRotatedChainList.push_back( make_pair(*pos,set())); mvFlipGroup.back().mvRotatedChainList.back().second.insert(*atom0); ExpandAtomGroupRecursive(*pos,mConnectivityTable, mvFlipGroup.back().mvRotatedChainList.back().second); mvFlipGroup.back().mvRotatedChainList.back().second.erase(*atom0); set::const_iterator ringdetect1,ringdetect2; ringdetect1=find(mvFlipGroup.back().mvRotatedChainList.back().second.begin(), mvFlipGroup.back().mvRotatedChainList.back().second.end(), *pos1); ringdetect2=find(mvFlipGroup.back().mvRotatedChainList.back().second.begin(), mvFlipGroup.back().mvRotatedChainList.back().second.end(), *pos2); if( (ringdetect1!=mvFlipGroup.back().mvRotatedChainList.back().second.end()) ||(ringdetect2!=mvFlipGroup.back().mvRotatedChainList.back().second.end())) foundRing=true; } unsigned long flipSize=0; for(list > >::const_iterator chain=mvFlipGroup.back().mvRotatedChainList.begin(); chain!=mvFlipGroup.back().mvRotatedChainList.end();++chain) flipSize+=chain->second.size(); if(((flipSize*2)>mvpAtom.size())||foundRing) mvFlipGroup.pop_back(); } // Add the entry which will exchange atom1 and atom2 (this entry can be a ring) mvFlipGroup.push_back(FlipGroup(**atom0,**pos1,**pos2)); mvFlipGroup.back().mvRotatedChainList.push_back( make_pair(*atom0,set())); mvFlipGroup.back().mvRotatedChainList.back().second.insert(*atom0); ExpandAtomGroupRecursive(*pos1,mConnectivityTable, mvFlipGroup.back().mvRotatedChainList.back().second); ExpandAtomGroupRecursive(*pos2,mConnectivityTable, mvFlipGroup.back().mvRotatedChainList.back().second); mvFlipGroup.back().mvRotatedChainList.back().second.erase(*atom0); if((mvFlipGroup.back().mvRotatedChainList.back().second.size()*2)>mvpAtom.size()) mvFlipGroup.pop_back(); } } } // Exclude flip groups that include only a part of any rigid group for(list::iterator pos=mvFlipGroup.begin(); pos!=mvFlipGroup.end();) { // This should not be necessary ? Why keep one list for each chain, and not one big ? set fullset; for(list > >::iterator chain=pos->mvRotatedChainList.begin(); chain!=pos->mvRotatedChainList.end();++chain) for(set::const_iterator at=chain->second.begin();at!=chain->second.end();++at) fullset.insert(*at); bool keep=true; for(vector::const_iterator group=mvRigidGroup.begin(); group!=mvRigidGroup.end();++group) { unsigned long ct=0; for(set::const_iterator at=fullset.begin();at!=fullset.end();++at) ct+=(*group)->count(*at); if((ct>0)&&(ct<(*group)->size())) {keep=false; break;} } if(!keep) { cout <<"EXCLUDING flip group (breaking a rigid group): " <mpAtom0->GetName()<<",exchanging bonds with " <mpAtom1->GetName()<<" and " <mpAtom2->GetName()<<", resulting in a 180deg rotation of atoms : "; for(set::iterator pos1=pos->mvRotatedChainList.begin()->second.begin(); pos1!=pos->mvRotatedChainList.begin()->second.end();++pos1) cout<<(*pos1)->GetName()<<" "; cout<::iterator pos=mvFlipGroup.begin(); pos!=mvFlipGroup.end();) { if(pos->mpAtom0->IsNonFlipAtom()) { cout <<"EXCLUDING flip group (central atom is in the non-flip list): " <mpAtom0->GetName()<<",exchanging bonds with " <mpAtom1->GetName()<<" and " <mpAtom2->GetName()<<", resulting in a 180deg rotation of atoms : "; for(set::iterator pos1=pos->mvRotatedChainList.begin()->second.begin(); pos1!=pos->mvRotatedChainList.begin()->second.end();++pos1) cout<<(*pos1)->GetName()<<" "; cout<SaveParamSet(mLocalParamSet); #if 1//def __DEBUG__ // const REAL llk0=this->GetLogLikelihood(); for(list::iterator pos=mvFlipGroup.begin(); pos!=mvFlipGroup.end();++pos) { if(pos->mvRotatedChainList.begin()->first==pos->mpAtom0) { cout <<"Flip group from atom " <mpAtom0->GetName()<<",exchanging bonds with " <mpAtom1->GetName()<<" and " <mpAtom2->GetName()<<", resulting in a 180� rotation of atoms : "; for(set::iterator pos1=pos->mvRotatedChainList.begin()->second.begin(); pos1!=pos->mvRotatedChainList.begin()->second.end();++pos1) cout<<(*pos1)->GetName()<<" "; } else { cout <<"Flip group with respect to: " <mpAtom1->GetName()<<"-" <mpAtom0->GetName()<<"-" <mpAtom2->GetName()<<" : "; for(list > >::const_iterator chain=pos->mvRotatedChainList.begin(); chain!=pos->mvRotatedChainList.end();++chain) { cout<<" -"<first->GetName()<<":"; for(set::const_iterator pos1=chain->second.begin(); pos1!=chain->second.end();++pos1) cout<<(*pos1)->GetName()<<" "; } } #if 0 // test if they do not break something (dihedral angle restraint) ? // We seldom try flippping, so don't test - test is done during optimization this->FlipAtomGroup(*pos); const REAL dllk=this->GetLogLikelihood()-llk0; if(dllk>1000.) { pos = mvFlipGroup.erase(pos); --pos; cout <<" -> NOT a free flip, d(llk)="<RestraintStatus(cout); } else cout <<" -> free flip, d(llk)="<RestoreParamSet(mLocalParamSet); #endif cout< > vpBond; for(list::const_iterator mode=mvStretchModeBondLength.begin(); mode!=mvStretchModeBondLength.end();++mode) { if(mode->mpBond!=0) vpBond[mode->mpBond].insert(&(*mode)); for(map::const_iterator pos=mode->mvpBrokenBond.begin(); pos!=mode->mvpBrokenBond.end();++pos) vpBond[pos->first].insert(&(*mode)); } for(list::const_iterator mode=mvStretchModeBondAngle.begin(); mode!=mvStretchModeBondAngle.end();++mode) for(map::const_iterator pos=mode->mvpBrokenBond.begin(); pos!=mode->mvpBrokenBond.end();++pos) vpBond[pos->first].insert(&(*mode)); for(list::const_iterator mode=mvStretchModeTorsion.begin(); mode!=mvStretchModeTorsion.end();++mode) for(map::const_iterator pos=mode->mvpBrokenBond.begin(); pos!=mode->mvpBrokenBond.end();++pos) vpBond[pos->first].insert(&(*mode)); for(list::const_iterator mode=mvStretchModeTwist.begin(); mode!=mvStretchModeTwist.end();++mode) for(map::const_iterator pos=mode->mvpBrokenBond.begin(); pos!=mode->mvpBrokenBond.end();++pos) vpBond[pos->first].insert(&(*mode)); map > vpAngle; for(list::const_iterator mode=mvStretchModeBondLength.begin(); mode!=mvStretchModeBondLength.end();++mode) for(map::const_iterator pos=mode->mvpBrokenBondAngle.begin(); pos!=mode->mvpBrokenBondAngle.end();++pos) vpAngle[pos->first].insert(&(*mode)); for(list::const_iterator mode=mvStretchModeBondAngle.begin(); mode!=mvStretchModeBondAngle.end();++mode) { if(mode->mpBondAngle!=0) vpAngle[mode->mpBondAngle].insert(&(*mode)); for(map::const_iterator pos=mode->mvpBrokenBondAngle.begin(); pos!=mode->mvpBrokenBondAngle.end();++pos) vpAngle[pos->first].insert(&(*mode)); } for(list::const_iterator mode=mvStretchModeTorsion.begin(); mode!=mvStretchModeTorsion.end();++mode) for(map::const_iterator pos=mode->mvpBrokenBondAngle.begin(); pos!=mode->mvpBrokenBondAngle.end();++pos) vpAngle[pos->first].insert(&(*mode)); for(list::const_iterator mode=mvStretchModeTwist.begin(); mode!=mvStretchModeTwist.end();++mode) for(map::const_iterator pos=mode->mvpBrokenBondAngle.begin(); pos!=mode->mvpBrokenBondAngle.end();++pos) vpAngle[pos->first].insert(&(*mode)); map > vpDihed; for(list::const_iterator mode=mvStretchModeBondLength.begin(); mode!=mvStretchModeBondLength.end();++mode) for(map::const_iterator pos=mode->mvpBrokenDihedralAngle.begin(); pos!=mode->mvpBrokenDihedralAngle.end();++pos) vpDihed[pos->first].insert(&(*mode)); for(list::const_iterator mode=mvStretchModeBondAngle.begin(); mode!=mvStretchModeBondAngle.end();++mode) for(map::const_iterator pos=mode->mvpBrokenDihedralAngle.begin(); pos!=mode->mvpBrokenDihedralAngle.end();++pos) vpDihed[pos->first].insert(&(*mode)); for(list::const_iterator mode=mvStretchModeTorsion.begin(); mode!=mvStretchModeTorsion.end();++mode) { if(mode->mpDihedralAngle!=0) vpDihed[mode->mpDihedralAngle].insert(&(*mode)); for(map::const_iterator pos=mode->mvpBrokenDihedralAngle.begin(); pos!=mode->mvpBrokenDihedralAngle.end();++pos) vpDihed[pos->first].insert(&(*mode)); } for(list::const_iterator mode=mvStretchModeTwist.begin(); mode!=mvStretchModeTwist.end();++mode) for(map::const_iterator pos=mode->mvpBrokenDihedralAngle.begin(); pos!=mode->mvpBrokenDihedralAngle.end();++pos) vpDihed[pos->first].insert(&(*mode)); #if 0 for(map >::const_iterator pos=vpBond.begin();pos!=vpBond.end();++pos) { cout<<"Bond "<first->GetName()<<" is modified by the stretch modes:"<::const_iterator mode=pos->second.begin();mode!=pos->second.end();++mode) { cout<<" "; (*mode)->Print(cout); cout< >::const_iterator pos=vpAngle.begin();pos!=vpAngle.end();++pos) { cout<<"Bond Angle "<first->GetName()<<" is modified by the stretch modes:"<::const_iterator mode=pos->second.begin();mode!=pos->second.end();++mode) { cout<<" "; (*mode)->Print(cout); cout< >::const_iterator pos=vpDihed.begin();pos!=vpDihed.end();++pos) { cout<<"Dihedral Angle "<first->GetName()<<" is modified by the stretch modes:"<::const_iterator mode=pos->second.begin();mode!=pos->second.end();++mode) { cout<<" "; (*mode)->Print(cout); cout<::iterator mode=mvStretchModeBondLength.begin(); mode!=mvStretchModeBondLength.end();++mode) { int nb=mode->mvpBrokenDihedralAngle.size()+mode->mvpBrokenBondAngle.size()+mode->mvpBrokenBond.size(); if(mode->mpBond!=0) nb -= 1; if(nb==0) mvpStretchModeFree.push_back(&(*mode)); else mvpStretchModeNotFree.push_back(&(*mode)); } for(list::iterator mode=mvStretchModeBondAngle.begin(); mode!=mvStretchModeBondAngle.end();++mode) { int nb=mode->mvpBrokenDihedralAngle.size()+mode->mvpBrokenBondAngle.size()+mode->mvpBrokenBond.size(); if(mode->mpBondAngle!=0) nb -= 1; if(nb==0) mvpStretchModeFree.push_back(&(*mode)); else mvpStretchModeNotFree.push_back(&(*mode)); } for(list::iterator mode=mvStretchModeTorsion.begin(); mode!=mvStretchModeTorsion.end();++mode) { int nb=mode->mvpBrokenDihedralAngle.size()+mode->mvpBrokenBondAngle.size()+mode->mvpBrokenBond.size(); if(mode->mpDihedralAngle!=0) nb -= 1; if(nb==0) mvpStretchModeFree.push_back(&(*mode)); else mvpStretchModeNotFree.push_back(&(*mode)); } #if 1 for(list::iterator mode=mvStretchModeTwist.begin(); mode!=mvStretchModeTwist.end();++mode) if(mode->mvpBrokenDihedralAngle.size()+mode->mvpBrokenBondAngle.size()+mode->mvpBrokenBond.size()==0) mvpStretchModeFree.push_back(&(*mode)); else mvpStretchModeNotFree.push_back(&(*mode)); #endif } void Molecule::BuildMDAtomGroups() { // For each atom, list all atoms that are never moved relatively to it. // (not moved == distance cannot change) map > vBoundAtoms; set set0; for(vector::iterator pos=this->GetAtomList().begin();pos!=this->GetAtomList().end();++pos) set0.insert(*pos); for(vector::iterator pat1=this->GetAtomList().begin();pat1!=this->GetAtomList().end();++pat1) { vBoundAtoms[*pat1]=set0; for(vector::iterator pat2=this->GetAtomList().begin();pat2!=this->GetAtomList().end();++pat2) { bool cont=false; for(list::iterator pstretch=this->GetStretchModeBondLengthList().begin(); pstretch!=this->GetStretchModeBondLengthList().end();++pstretch) { set::iterator pos1=pstretch->mvTranslatedAtomList.find(*pat1), pos2=pstretch->mvTranslatedAtomList.find(*pat2); if( ((pos1==pstretch->mvTranslatedAtomList.end())&&(pos2!=pstretch->mvTranslatedAtomList.end())) ||((pos1!=pstretch->mvTranslatedAtomList.end())&&(pos2==pstretch->mvTranslatedAtomList.end()))) { vBoundAtoms[*pat1].erase(*pat2); //cout<<(*pat1)->GetName()<<" moves (b) relatively to "<<(*pat2)->GetName()<<" /"; //pstretch->Print(cout);cout<::iterator pstretch=this->GetStretchModeBondAngleList().begin(); pstretch!=this->GetStretchModeBondAngleList().end();++pstretch) { //pstretch->mpAtom1 does not move relatively to any atom if((*pat1==pstretch->mpAtom1)||(*pat2==pstretch->mpAtom1)) continue; set::iterator pos1=pstretch->mvRotatedAtomList.find(*pat1), pos2=pstretch->mvRotatedAtomList.find(*pat2); //:TODO: Take into account the special case of the atoms defining the bond angle if( ((pos1==pstretch->mvRotatedAtomList.end())&&(pos2!=pstretch->mvRotatedAtomList.end())) ||((pos1!=pstretch->mvRotatedAtomList.end())&&(pos2==pstretch->mvRotatedAtomList.end()))) { vBoundAtoms[*pat1].erase(*pat2); //cout<<(*pat1)->GetName()<<" moves (a) relatively to "<<(*pat2)->GetName()<<" /"; //pstretch->Print(cout);cout<::iterator pstretch=this->GetStretchModeTorsionList().begin(); pstretch!=this->GetStretchModeTorsionList().end();++pstretch) { set::iterator pos1=pstretch->mvRotatedAtomList.find(*pat1), pos2=pstretch->mvRotatedAtomList.find(*pat2); if( (pos1!=pstretch->mvRotatedAtomList.end())&&(pos2==pstretch->mvRotatedAtomList.end()) &&(*pat2!=pstretch->mpAtom1) &&(*pat2!=pstretch->mpAtom2) ) { vBoundAtoms[*pat1].erase(*pat2); //cout<<(*pat1)->GetName()<<" moves (d1) relatively to "<<(*pat2)->GetName()<<" /"; //pstretch->Print(cout);cout<mvRotatedAtomList.end())&&(pos2!=pstretch->mvRotatedAtomList.end()) &&(*pat1!=pstretch->mpAtom1) && (*pat1!=pstretch->mpAtom2) ) { vBoundAtoms[*pat1].erase(*pat2); //cout<<(*pat1)->GetName()<<" moves (d2) relatively to "<<(*pat2)->GetName()<<" /"; //pstretch->Print(cout);cout< > vBoundGroups; for(map >::iterator pos=vBoundAtoms.begin();pos!=vBoundAtoms.end();++pos) { #if 0 cout<<"Non-flexible group from "<first->GetName()<<": "; for(set::const_iterator atom=pos->second.begin();atom!=pos->second.end();++atom) cout<<(*atom)->GetName()<<","; cout<::iterator pr=this->GetRigidGroupList().begin();pr!=this->GetRigidGroupList().end();++pr) for(set::iterator at=(*pr)->begin();at!=(*pr)->end();++at) pos->second.erase(*at); if(pos->second.size()>1) vBoundGroups.insert(pos->second); } #if 0 for(set >::iterator pos=vBoundGroups.begin();pos!=vBoundGroups.end();++pos) { cout<<"Non-flexible group:"; for(set::const_iterator atom=pos->begin();atom!=pos->end();++atom) cout<<(*atom)->GetName()<<","; cout< >::iterator pos=vBoundGroups.begin();pos!=vBoundGroups.end();++pos) { set vb; for(vector::iterator pr=this->GetBondList().begin();pr!=this->GetBondList().end();++pr) if( (pos->find(&(*pr)->GetAtom1())!=pos->end()) ||(pos->find(&(*pr)->GetAtom2())!=pos->end())) vb.insert(*pr); set va; for(vector::iterator pr=this->GetBondAngleList().begin();pr!=this->GetBondAngleList().end();++pr) if( (pos->find(&(*pr)->GetAtom1())!=pos->end()) ||(pos->find(&(*pr)->GetAtom2())!=pos->end()) ||(pos->find(&(*pr)->GetAtom3())!=pos->end())) va.insert(*pr); set vd; for(vector::iterator pr=this->GetDihedralAngleList().begin();pr!=this->GetDihedralAngleList().end();++pr) if( (pos->find(&(*pr)->GetAtom1())!=pos->end()) ||(pos->find(&(*pr)->GetAtom2())!=pos->end()) ||(pos->find(&(*pr)->GetAtom3())!=pos->end()) ||(pos->find(&(*pr)->GetAtom4())!=pos->end())) vd.insert(*pr); set tmp= *pos;// Cannot pass *pos directly ? gcc bug evaluating const-ness? mvMDAtomGroup.push_back(MDAtomGroup(tmp,vb,va,vd)); mvMDAtomGroup.back().Print(cout); } // Create mvMDFullAtomGroup mvMDFullAtomGroup.clear(); #if 1 // All atoms except those in rigid groups for(vector::iterator at=this->GetAtomList().begin();at!=this->GetAtomList().end();++at) mvMDFullAtomGroup.insert(*at); for(vector::iterator pr=this->GetRigidGroupList().begin();pr!=this->GetRigidGroupList().end();++pr) for(set::iterator at=(*pr)->begin();at!=(*pr)->end();++at) mvMDFullAtomGroup.erase(*at); cout<<"Full MD atom group:"<::const_iterator pos=mvMDFullAtomGroup.begin();pos!=mvMDFullAtomGroup.end();++pos) cout<<(*pos)->GetName()<<" "; cout<::const_iterator pos= mvMDAtomGroup.begin();pos!= mvMDAtomGroup.end();++pos) for(set::const_iterator at=pos->mvpAtom.begin();at!=pos->mvpAtom.end();++at) mvMDFullAtomGroup.insert(*at); cout<<"Full MD atom group:"<::const_iterator pos=mvMDFullAtomGroup.begin();pos!=mvMDFullAtomGroup.end();++pos) cout<<(*pos)->GetName()<<" "; cout<GetCrystal().GetClockLatticePar()GetNbComponent(); // Get internal coords for(long i=0;iIsDummy()) mScattCompList(i).mpScattPow=0; else mScattCompList(i).mpScattPow=&(mvpAtom[i]->GetScatteringPower()); mScattCompList(i).mX=mvpAtom[i]->GetX(); mScattCompList(i).mY=mvpAtom[i]->GetY(); mScattCompList(i).mZ=mvpAtom[i]->GetZ(); mScattCompList(i).mOccupancy=mvpAtom[i]->GetOccupancy()*mOccupancy; } #ifdef RIGID_BODY_STRICT_EXPERIMENTAL // During an optimization, apply the translations & rotations of the rigid group parameters if(true)//this->IsBeingRefined()) { for(vector::const_iterator pos=this->GetRigidGroupList().begin();pos!=this->GetRigidGroupList().end();++pos) { (*pos)->mQuat.Normalize(); // Center of the atom group REAL x0=0,y0=0,z0=0; for(set::iterator at=(*pos)->mvIdx.begin();at!=(*pos)->mvIdx.end();++at) { x0+=mvpAtom[*at]->GetX(); y0+=mvpAtom[*at]->GetY(); z0+=mvpAtom[*at]->GetZ(); } x0/=(*pos)->size(); y0/=(*pos)->size(); z0/=(*pos)->size(); // Apply rotation & translation to all atoms for(set::iterator at=(*pos)->mvIdx.begin();at!=(*pos)->mvIdx.end();++at) { REAL x=mvpAtom[*at]->GetX()-x0, y=mvpAtom[*at]->GetY()-y0, z=mvpAtom[*at]->GetZ()-z0; (*pos)->mQuat.RotateVector(x,y,z); mScattCompList(*at).mX=x+x0+(*pos)->mX; mScattCompList(*at).mY=y+y0+(*pos)->mY; mScattCompList(*at).mZ=z+z0+(*pos)->mZ; } } } #endif // translate center to (0,0,0) REAL x0=0,y0=0,z0=0; if((mMoleculeCenter.GetChoice()==0) || (mpCenterAtom==0)) { for(long i=0;iGetX(); y0=mpCenterAtom->GetY(); z0=mpCenterAtom->GetZ(); } for(long i=0;iGetCrystal().OrthonormalToFractionalCoords(mScattCompList(i).mX, mScattCompList(i).mY, mScattCompList(i).mZ); } // translate center to position in unit cell for(long i=0;i::reverse_iterator Molecule::FindAtom(const string &name) { VFN_DEBUG_ENTRY("Molecule::FindAtom():"<::reverse_iterator rpos; for(rpos=mvpAtom.rbegin();rpos!=mvpAtom.rend();++rpos) if(name==(*rpos)->GetName()) { VFN_DEBUG_EXIT("Molecule::FindAtom():"<::const_reverse_iterator Molecule::FindAtom(const string &name)const { vector::const_reverse_iterator rpos; rpos=mvpAtom.rbegin(); for(rpos=mvpAtom.rbegin();rpos!=mvpAtom.rend();++rpos) if(name==(*rpos)->GetName()) return rpos; return rpos; } void Molecule::InitOptions() { VFN_DEBUG_ENTRY("Molecule::InitOptions",7) static string Flexname; static string Flexchoices[3]; static string FlipName; static string FlipChoice[2]; static string autoOptimizeConformationName; static string autoOptimizeConformationChoices[2]; static string optimizeOrientationName; static string optimizeOrientationChoices[2]; static string moleculeCenterName; static string moleculeCenterChoices[2]; static bool needInitNames=true; if(true==needInitNames) { Flexname="Flexibility Model"; Flexchoices[0]="Automatic from Restraints, relaxed - RECOMMENDED"; Flexchoices[1]="Rigid Body"; Flexchoices[2]="Automatic from Restraints, strict"; //Flexchoices[3]="Molecular Dynamics"; FlipName="Enable Flipping"; FlipChoice[0]="Yes"; FlipChoice[1]="No"; autoOptimizeConformationName="Auto Optimize Starting Conformation"; autoOptimizeConformationChoices[0]="Yes"; autoOptimizeConformationChoices[1]="No"; optimizeOrientationName="Optimize Orientation"; optimizeOrientationChoices[0]="Yes"; optimizeOrientationChoices[1]="No"; moleculeCenterName="Rotation Center"; moleculeCenterChoices[0]="Geometrical center (recommended)"; moleculeCenterChoices[1]="User-chosen Atom"; needInitNames=false; } mFlexModel.Init(3,&Flexname,Flexchoices); mFlexModel.SetChoice(0); this->AddOption(&mFlexModel); mFlipModel.Init(2, &FlipName, FlipChoice); mFlipModel.SetChoice(0); this->AddOption(&mFlipModel); mAutoOptimizeConformation.Init(2,&autoOptimizeConformationName, autoOptimizeConformationChoices); this->AddOption(&mAutoOptimizeConformation); mOptimizeOrientation.Init(2,&optimizeOrientationName,optimizeOrientationChoices); this->AddOption(&mOptimizeOrientation); mMoleculeCenter.Init(2,&moleculeCenterName,moleculeCenterChoices); this->AddOption(&mMoleculeCenter); VFN_DEBUG_EXIT("Molecule::InitOptions",7) } Molecule::FlipGroup::FlipGroup(const MolAtom &at0,const MolAtom &at1,const MolAtom &at2): mpAtom0(&at0),mpAtom1(&at1),mpAtom2(&at2),mNbTest(0),mNbAccept(0) { } void Molecule::FlipAtomGroup(const FlipGroup& group, const bool keepCenter) { TAU_PROFILE("Molecule::FlipAtomGroup(FlipGroup&)","void (...)",TAU_DEFAULT); if(group.mpAtom0==group.mvRotatedChainList.back().first) {// We are doing a 180� rotation exchanging two bonds const REAL vx=group.mpAtom0->X()-(group.mpAtom1->X()+group.mpAtom2->X())/2.; const REAL vy=group.mpAtom0->Y()-(group.mpAtom1->Y()+group.mpAtom2->Y())/2.; const REAL vz=group.mpAtom0->Z()-(group.mpAtom1->Z()+group.mpAtom2->Z())/2.; this->RotateAtomGroup(*(group.mpAtom0),vx,vy,vz, group.mvRotatedChainList.back().second,M_PI,keepCenter); } else {// we are flipping bonds with respect to a plane defined by other bonds REAL v01x=group.mpAtom1->X()-group.mpAtom0->X(); REAL v01y=group.mpAtom1->Y()-group.mpAtom0->Y(); REAL v01z=group.mpAtom1->Z()-group.mpAtom0->Z(); const REAL norm01=sqrt(v01x*v01x+v01y*v01y+v01z*v01z+1e-7); v01x /= norm01;v01y /= norm01;v01z /= norm01; REAL v02x=group.mpAtom2->X()-group.mpAtom0->X(); REAL v02y=group.mpAtom2->Y()-group.mpAtom0->Y(); REAL v02z=group.mpAtom2->Z()-group.mpAtom0->Z(); const REAL norm02=sqrt(v02x*v02x+v02y*v02y+v02z*v02z+1e-7); v02x /= norm02;v02y /= norm02;v02z /= norm02; REAL v12x=group.mpAtom2->X()-group.mpAtom1->X(); REAL v12y=group.mpAtom2->Y()-group.mpAtom1->Y(); REAL v12z=group.mpAtom2->Z()-group.mpAtom1->Z(); const REAL norm12=sqrt(v12x*v12x+v12y*v12y+v12z*v12z+1e-7); v12x /= norm12;v12y /= norm12;v12z /= norm12; REAL v0mx=group.mpAtom0->X()-(group.mpAtom1->X()+group.mpAtom2->X())/2.; REAL v0my=group.mpAtom0->Y()-(group.mpAtom1->Y()+group.mpAtom2->Y())/2.; REAL v0mz=group.mpAtom0->Z()-(group.mpAtom1->Z()+group.mpAtom2->Z())/2.; const REAL norm0m=sqrt(v0mx*v0mx+v0my*v0my+v0mz*v0mz+1e-7); v0mx /= norm0m;v0my /= norm0m;v0mz /= norm0m; if(fabs(v01x*v02x+v01y*v02y+v01z*v02z) >0.05*sqrt(abs( (v01x*v01x+v01y*v01y+v01z*v01z) *(v02x*v02x+v02y*v02y+v02z*v02z)))) { REAL v012x=v01y*v02z-v01z*v02y; REAL v012y=v01z*v02x-v01x*v02z; REAL v012z=v01x*v02y-v01y*v02x; const REAL norm012=sqrt(v012x*v012x+v012y*v012y+v012z*v012z+1e-7); v012x /= norm012;v012y /= norm012;v012z /= norm012; for(list > >::const_iterator chain=group.mvRotatedChainList.begin(); chain!=group.mvRotatedChainList.end();++chain) { REAL v03x=chain->first->X()-group.mpAtom0->X(); REAL v03y=chain->first->Y()-group.mpAtom0->Y(); REAL v03z=chain->first->Z()-group.mpAtom0->Z(); const REAL norm03=sqrt( v03x*v03x + v03y*v03y + v03z*v03z +1e-7); v03x /= norm03;v03y /= norm03;v03z /= norm03; const REAL a1=v012x*v03x+v012y*v03y+v012z*v03z; const REAL a2= v0mx*v03x+ v0my*v03y+ v0mz*v03z; const REAL a3= v12x*v03x+ v12y*v03y+ v12z*v03z; REAL angle = -a1/sqrt(1-a3*a3+1e-7); if(angle>=1.) angle = M_PI/2.; else { if(angle<=-1.) { angle = -M_PI/2.; } else angle = asin(angle); } if(a2<0) angle=M_PI-angle; this->RotateAtomGroup(*(group.mpAtom0),v12x,v12y,v12z, chain->second,2*angle,keepCenter); } } } } void Molecule::SetDeleteSubObjInDestructor(const bool b) { mDeleteSubObjInDestructor=b; } void Molecule::ResetRigidGroupsPar()const { #ifdef RIGID_BODY_STRICT_EXPERIMENTAL // Apply the translations & rotations of all rigid group parameters, and // use this as the newly stored atomic coordinates. for(vector::const_iterator pos=this->GetRigidGroupList().begin();pos!=this->GetRigidGroupList().end();++pos) { (*pos)->mQuat.Normalize(); // Center of atom group REAL x0=0,y0=0,z0=0; for(set::iterator at=(*pos)->begin();at!=(*pos)->end();++at) { x0+=(*at)->GetX(); y0+=(*at)->GetY(); z0+=(*at)->GetZ(); } x0/=(*pos)->size(); y0/=(*pos)->size(); z0/=(*pos)->size(); // Apply rotation & translation to all atoms for(set::iterator at=(*pos)->begin();at!=(*pos)->end();++at) { REAL x=(*at)->GetX()-x0, y=(*at)->GetY()-y0, z=(*at)->GetZ()-z0; (*pos)->mQuat.RotateVector(x,y,z); (*at)->SetX(x+x0+(*pos)->mX); (*at)->SetY(y+y0+(*pos)->mY); (*at)->SetZ(z+z0+(*pos)->mZ); } // Reset the translation & rotation parameters, only useful during an optimization (*pos)->mX=0; (*pos)->mY=0; (*pos)->mZ=0; (*pos)->mQuat.Q0()=1; (*pos)->mQuat.Q1()=0; (*pos)->mQuat.Q2()=0; (*pos)->mQuat.Q3()=0; } #endif } #ifdef __WX__CRYST__ WXCrystObjBasic* Molecule::WXCreate(wxWindow* parent) { VFN_DEBUG_ENTRY("Molecule::WXCreate()",5) mpWXCrystObj=new WXMolecule(parent,this); VFN_DEBUG_EXIT("Molecule::WXCreate()",5) return mpWXCrystObj; } #endif Molecule *ZScatterer2Molecule(ZScatterer *scatt) { VFN_DEBUG_ENTRY("ZScatterer2Molecule()",6) Molecule *mol=new Molecule(scatt->GetCrystal(),scatt->GetName()); const unsigned long nb=scatt->GetZAtomRegistry().GetNb(); REAL x0=0,y0=0,z0=0; for(unsigned int i=0;iGetZAtomX(i); const REAL y=scatt->GetZAtomY(i); const REAL z=scatt->GetZAtomZ(i); x0+=x; y0+=y; z0+=z; mol->AddAtom(x,y,z,scatt->GetZAtomRegistry().GetObj(i).GetScatteringPower(), scatt->GetZAtomRegistry().GetObj(i).GetName()); #if 0 if(i>0) { const RefinablePar* pLength=&(scatt->GetPar(&(scatt->GetZAtomRegistry() .GetObj(i).GetZBondLength()))); if(pLength->IsFixed()) mol->AddBond(mol->GetAtom(i),mol->GetAtom(scatt->GetZBondAtom(i)), pLength->GetValue(),.01,.02,false); else if(pLength->IsLimited()) mol->AddBond(mol->GetAtom(i),mol->GetAtom(scatt->GetZBondAtom(i)), (pLength->GetMin()+pLength->GetMax())/2.,.01,.02,false); } if(i>1) { const RefinablePar* pAngle=&(scatt->GetPar(&(scatt->GetZAtomRegistry() .GetObj(i).GetZAngle()))); if(pAngle->IsFixed()) mol->AddBondAngle(mol->GetAtom(i),mol->GetAtom(scatt->GetZBondAtom(i)), mol->GetAtom(scatt->GetZAngleAtom(i)), pAngle->GetValue(),.01,.02,false); else if(pAngle->IsLimited()) mol->AddBondAngle(mol->GetAtom(i),mol->GetAtom(scatt->GetZBondAtom(i)), mol->GetAtom(scatt->GetZAngleAtom(i)), (pAngle->GetMin()+pAngle->GetMax())/2.,.01,.02,false); } if(i>2) { const RefinablePar* pDihed=&(scatt->GetPar(&(scatt->GetZAtomRegistry() .GetObj(i).GetZDihedralAngle()))); MolAtom *p1=&(mol->GetAtom(i)); MolAtom *p2=&(mol->GetAtom(scatt->GetZBondAtom(i))); MolAtom *p3=&(mol->GetAtom(scatt->GetZAngleAtom(i))); MolAtom *p4=&(mol->GetAtom(scatt->GetZDihedralAngleAtom(i))); if( (fabs(GetBondAngle(*p1,*p2,*p3)-M_PI)>0.3) &&(fabs(GetBondAngle(*p1,*p2,*p4)-M_PI)>0.3) &&(fabs(GetBondAngle(*p1,*p3,*p4)-M_PI)>0.3) &&(fabs(GetBondAngle(*p2,*p3,*p4)-M_PI)>0.3)) { if(pDihed->IsFixed()) mol->AddDihedralAngle(*p1,*p2,*p3,*p4,pDihed->GetValue(),.01,.02,false); else if(((pDihed->GetMax()-pDihed->GetMax())<0.3)&&(i>2)&&(pDihed->IsLimited())) mol->AddDihedralAngle(*p1,*p2,*p3,*p4, (pDihed->GetMin()+pDihed->GetMax())/2.,.01,.02,false); } } #endif mol->GetAtom(i).SetOccupancy(scatt->GetZAtomRegistry().GetObj(i).GetOccupancy()); } CrystVector_REAL x(nb),y(nb),z(nb),radius(nb); vector > scattpow(nb); for(unsigned int i=0;iGetAtom(i).GetX(); y(i)=mol->GetAtom(i).GetY(); z(i)=mol->GetAtom(i).GetZ(); if(mol->GetAtom(i).IsDummy()) { radius(i)=-1; scattpow[i].first=0; } else { radius(i)=mol->GetAtom(i).GetScatteringPower().GetRadius(); scattpow[i].first=dynamic_cast (&(mol->GetAtom(i).GetScatteringPower())); scattpow[i].second=scattpow[i].first->GetAtomicNumber(); } } for(unsigned int i=0;i d="<AddBond(mol->GetAtom(i),mol->GetAtom(j),dist,.01,.02,false); } } } x += x1; y += y1; z += z1; } mol->BuildConnectivityTable(); for(map >::const_iterator pos=mol->GetConnectivityTable().begin(); pos!=mol->GetConnectivityTable().end();++pos) { for(set::const_iterator pos1=pos->second.begin(); pos1!=pos->second.end();++pos1) { for(set::const_iterator pos2=pos1; pos2!=pos->second.end();++pos2) { if(pos2==pos1) continue; if(mol->FindBondAngle(**pos1,*(pos->first),**pos2)== mol->GetBondAngleList().end()) mol->AddBondAngle(**pos1,*(pos->first),**pos2, GetBondAngle(**pos1,*(pos->first),**pos2),0.01,0.02,false); } } } x0 /= nb; y0 /= nb; z0 /= nb; mol->GetCrystal().OrthonormalToFractionalCoords(x0,y0,z0); mol->SetX(x0); mol->SetY(y0); mol->SetZ(z0); mol->UpdateDisplay(); VFN_DEBUG_EXIT("ZScatterer2Molecule()",6) return mol; } }//namespace objcryst-2022.1/ObjCryst/ObjCryst/Molecule.h000066400000000000000000001731071430515525000206640ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Molecule.h * header file for the Molecule scatterer * */ #ifndef _OBJCRYST_MOLECULE_H_ #define _OBJCRYST_MOLECULE_H_ #include #include #include #include #include #include "ObjCryst/ObjCryst/General.h" #include "ObjCryst/ObjCryst/ScatteringPower.h" #include "ObjCryst/ObjCryst/Scatterer.h" namespace ObjCryst { class MolAtom; class MolBond; class Molecule; /// Structure holding 3 coordinates, or deriviatives with respect to each of these coordinates struct XYZ { XYZ(REAL x=0,REAL y=0,REAL z=0); REAL x,y,z; }; /** MolAtom : atom inside a Molecule * * This keeps coordinates, recorded in a cartesian frame (in Angstroem), * the associated scattering power * and it also keeps in a list of all bonds in which this atom is involved. * * \note maybe it's not a great idea to keep a reference of bonds for this * atom in here */ class MolAtom { public: /** Constructor for a MolAtom * */ MolAtom(const REAL x, const REAL y, const REAL z, const ScatteringPower *pPow, const string &name, Molecule &parent); /** Destructor * * Tells the parent Molecule and all Bond that it is being destroyed. */ virtual ~MolAtom(); void SetName(const string &name); const string& GetName()const; string& GetName(); const Molecule& GetMolecule()const; Molecule& GetMolecule(); const REAL& X()const; const REAL& Y()const; const REAL& Z()const; REAL& X(); REAL& Y(); REAL& Z(); REAL GetX()const; REAL GetY()const; REAL GetZ()const; REAL GetOccupancy()const; //@{ /// Set the X,Y,Z coordinate - this is const because sometimes their /// coordinate must be changed even though the atom does not move, /// if the atom is part of a rigid group (its position is then described /// by a combination of atomic cooordinates, plus a global /// translation and rotation... void SetX(const REAL)const; void SetY(const REAL)const; void SetZ(const REAL)const; //@} void SetOccupancy(const REAL); /** Returns true if this is a dummy atom, i.e. without an associated scattering power. * * Dummy atoms can be used to mark positions, or for restraints. */ bool IsDummy()const; const ScatteringPower& GetScatteringPower()const; void SetScatteringPower(const ScatteringPower&); virtual void XMLOutput(ostream &os,int indent=0)const; virtual void XMLInput(istream &is,const XMLCrystTag &tag); /// Flag this atom as being in a ring (or not). This is a const method /// because the existence of a ring is only a consequence of the connectivity /// of the Molecule. void SetIsInRing(const bool r)const; bool IsInRing()const; /** Set a flag to prevent the atom's absolute configuration to be changed. * \param nonflip: if true, the atom. * * \internal This should only be changed by Molecule::AddNonFlipAtom() and Molecule::RemoveNonFlipAtom() */ void SetNonFlipAtom(const bool nonflip); /// Can this atom be flipped (return=false) or should its absolute configuration be kept (return=true) bool IsNonFlipAtom() const; /// Access to the integer address of this object, for unique identification from python size_t int_ptr() const; private: /// Name for this atom string mName; /* Get the atom at the other end of bond #i MolAtom & GetBondedAtom(unsigned int i); */ /** Cartesian oordinates in the Molecule reference frame. * * mutable because they may need to be changed when in a rigid group, * even though the end position of the atom remains the same. */ mutable REAL mX,mY,mZ; /// Occupancy REAL mOccupancy; /// ScatteringPower const ScatteringPower* mpScattPow; /// Parent Molecule Molecule *mpMol; /// Is the atom in a ring ? mutable bool mIsInRing; /// Can the atom be flipped (this is used for optically active atom which should keep their absolute configuration bool mIsNonFlipAtom; #ifdef __WX__CRYST__ public: WXCrystObjBasic *mpWXCrystObj; virtual WXCrystObjBasic* WXCreate(wxWindow*); WXCrystObjBasic* WXGet(); void WXDelete(); void WXNotifyDelete(); #endif }; /// Get The Bond Length between two atoms REAL GetBondLength(const MolAtom&,const MolAtom&); /// Get The Bond Angle of 3 atoms REAL GetBondAngle(const MolAtom&,const MolAtom&,const MolAtom&); /// Get The dihedral angle defined by 4 atoms REAL GetDihedralAngle(const MolAtom&,const MolAtom&,const MolAtom&,const MolAtom&); /** Bond between two atoms, also a restraint on the associated bond length. * */ class MolBond:public Restraint { public: /** Constructor * * Both atoms of the bond are told of the creation of the bond, so that * they can keep a list of bonds they are involved in. * * \param atom1, atom2: the atoms of the bond * \param length: the expected bond length * \param sigma,delta: depending on the calculated length, the log(likelihood) is equal to: * - within \f$[length_{0}-\delta;length_{0}+\delta]\f$: * \f$ -\log(likelihood)= \log\left(2\delta+\sqrt{2\pi\sigma^2}\right)\f$ * - if \f$length > length_{0}+\delta\f$: * \f$ -\log(likelihood)= \log\left(2\delta+\sqrt{2\pi\sigma^2}\right) * + \left(\frac{(length-\delta)-length_{0}}{\sigma} \right)^2\f$ * - if \f$length < length_{0}-\delta\f$: * \f$ -\log(likelihood)= \log\left(2\delta+\sqrt{2\pi\sigma^2}\right) * + \left(\frac{(length+\delta)-length_{0}}{\sigma} \right)^2\f$ * */ MolBond(MolAtom &atom1, MolAtom &atom2, const REAL length, const REAL sigma, const REAL delta, Molecule &parent,const REAL bondOrder=1.); /** Destructor * * Notifies the atoms that the bond has disappeared. */ virtual ~MolBond(); const Molecule& GetMolecule()const; Molecule& GetMolecule(); /// Name of the bond, e.g. "C3-O4" string GetName()const; virtual void XMLOutput(ostream &os,int indent=0)const; virtual void XMLInput(istream &is,const XMLCrystTag &tag); virtual REAL GetLogLikelihood()const; REAL GetLogLikelihood(const bool calcDeriv, const bool recalc)const; /// Get the derivative of the bond length, given the derivatives of the atom positions /// This requires that GetLogLikelihood(calcDeriv=true) be called first. /// If llk=true, this will return the derivative of the llk rather than the derivative of the length or angle REAL GetDeriv(const std::map &m, const bool llk=false)const; /** Calc log(likelihood) gradient - versus all atomic coordinates * * \param m: this map should have been initialized by adding all possible atom * pointers as keys, with all XYZ values equal to zeros. On return, the derivative * of the log(likelihood) vs each atomic coordinates will \b added * to each coordinate of the corresponding atoms. */ void CalcGradient(std::map &m)const; const MolAtom& GetAtom1()const; const MolAtom& GetAtom2()const; MolAtom& GetAtom1(); MolAtom& GetAtom2(); void SetAtom1(MolAtom &at1); void SetAtom2(MolAtom &at2); REAL GetLength()const; REAL GetLength0()const; REAL GetLengthDelta()const; REAL GetLengthSigma()const; REAL GetBondOrder()const; REAL& Length0(); REAL& LengthDelta(); REAL& LengthSigma(); REAL& BondOrder(); void SetLength0(const REAL length); void SetLengthDelta(const REAL length); void SetLengthSigma(const REAL length); void SetBondOrder(const REAL length); bool IsFreeTorsion()const; void SetFreeTorsion(const bool isInRing); /// Access to the integer address of this object, for unique identification from python size_t int_ptr() const; private: pair mAtomPair; REAL mLength0,mDelta,mSigma; REAL mBondOrder; bool mIsFreeTorsion; /// Parent Molecule Molecule *mpMol; /// Stored log(likelihood) mutable REAL mLLK; /** Derivatives of the bond length with respect to the coordinates of the atoms * * The derivatives are calculated in MolBond::GetLogLikelihood(true) */ mutable XYZ mDerivAtom1,mDerivAtom2; /** The factor used to change the derivative of the length/angle, to the derivative * of the log(likelihood). e.g. (for mDelta=0) \f$ mDerivLLKCoeff = \frac{L-L_0}{\sigma^2} \f$ */ mutable REAL mDerivLLKCoeff; #ifdef __WX__CRYST__ public: WXCrystObjBasic *mpWXCrystObj; virtual WXCrystObjBasic* WXCreate(wxWindow*); WXCrystObjBasic* WXGet(); void WXDelete(); void WXNotifyDelete(); #endif }; /** Bond angle restraint between 3 atoms. * * The atoms involved need not be bonded. * * */ class MolBondAngle:public Restraint { public: /** Constructor * */ MolBondAngle(MolAtom &atom1,MolAtom &atom2,MolAtom &atom3, const REAL angle, const REAL sigma, const REAL delta, Molecule &parent); /** Destructor * */ virtual ~MolBondAngle(); const Molecule& GetMolecule()const; Molecule& GetMolecule(); string GetName()const; virtual void XMLOutput(ostream &os,int indent=0)const; virtual void XMLInput(istream &is,const XMLCrystTag &tag); virtual REAL GetLogLikelihood()const; REAL GetLogLikelihood(const bool calcDeriv, const bool recalc)const; /// Get the derivative of the angle, given the derivatives of the atom positions /// This requires that GetLogLikelihood(calcDeriv=true) be called first /// If llk=true, this will return the derivative of the llk rather than the derivative of the length or angle REAL GetDeriv(const std::map &m, const bool llk=false)const; /** Calc log(likelihood) gradient - versus all atomic coordinates * * \param m: this map should have been initialized by adding all possible atom * pointers as keys, with all XYZ values equal to zeros. On return, the derivative * of the log(likelihood) vs each atomic coordinates will \b added * to each coordinate of the corresponding atoms. */ void CalcGradient(std::map &m)const; REAL GetAngle()const; REAL& Angle0(); REAL& AngleDelta(); REAL& AngleSigma(); REAL GetAngle0()const; REAL GetAngleDelta()const; REAL GetAngleSigma()const; void SetAngle0(const REAL angle); void SetAngleDelta(const REAL delta); void SetAngleSigma(const REAL sigma); const MolAtom& GetAtom1()const; const MolAtom& GetAtom2()const; const MolAtom& GetAtom3()const; void SetAtom1(MolAtom &at); void SetAtom2(MolAtom &at); void SetAtom3(MolAtom &at); MolAtom& GetAtom1(); MolAtom& GetAtom2(); MolAtom& GetAtom3(); bool IsFlexible()const; void SetFlexible(const bool isInRing); std::size_t size() const; vector::const_iterator begin() const; vector::const_iterator end() const; /// Access to the integer address of this object, for unique identification from python size_t int_ptr() const; private: /// The vector of the 3 atoms involved in the bond angle. vector mvpAtom; REAL mAngle0,mDelta,mSigma; /// Parent Molecule Molecule *mpMol; /// When using the user-chosen flexibility model, this allows /// some flexibility for this bond angle, i.e. the bond angle /// does not remain strictly rigid, and is still restrained. bool mIsFlexible; /// Stored log(likelihood) mutable REAL mLLK; /** Partial derivatives of the angle with respect to the coordinates of the atoms * * The derivatives are calculated in MolBondAngle::GetLogLikelihood(true) */ mutable XYZ mDerivAtom1,mDerivAtom2,mDerivAtom3; /** The factor used to change the derivative of the length/angle, to the derivative * of the log(likelihood). e.g. (for mDelta=0) \f$ mDerivLLKCoeff = \frac{L-L_0}{\sigma^2} \f$ */ mutable REAL mDerivLLKCoeff; #ifdef __WX__CRYST__ public: WXCrystObjBasic *mpWXCrystObj; virtual WXCrystObjBasic* WXCreate(wxWindow*); WXCrystObjBasic* WXGet(); void WXDelete(); void WXNotifyDelete(); #endif }; /** Dihedral angle restraint between 4 atoms. * * The atoms involved need not be bonded. * * */ class MolDihedralAngle:public Restraint { public: /** Constructor * */ MolDihedralAngle(MolAtom &atom1, MolAtom &atom2, MolAtom &atom3, MolAtom &atom4, const REAL angle, const REAL sigma, const REAL delta, Molecule &parent); /** Destructor * */ virtual ~MolDihedralAngle(); const Molecule& GetMolecule()const; Molecule& GetMolecule(); string GetName()const; virtual void XMLOutput(ostream &os,int indent=0)const; virtual void XMLInput(istream &is,const XMLCrystTag &tag); virtual REAL GetLogLikelihood()const; REAL GetLogLikelihood(const bool calcDeriv, const bool recalc)const; /// Get the derivative of the Angle, given the derivatives of the atom positions /// This requires that GetLogLikelihood(calcDeriv=true) be called first /// If llk=true, this will return the derivative of the llk rather than the derivative of the length or angle REAL GetDeriv(const std::map &m, const bool llk=false)const; /** Calc log(likelihood) gradient - versus all atomic coordinates * * \param m: this map should have been initialized by adding all possible atom * pointers as keys, with all XYZ values equal to zeros. On return, the derivative * of the log(likelihood) vs each atomic coordinates will \b added * to each coordinate of the corresponding atoms. */ void CalcGradient(std::map &m)const; REAL GetAngle()const; REAL& Angle0(); REAL& AngleDelta(); REAL& AngleSigma(); REAL GetAngle0()const; REAL GetAngleDelta()const; REAL GetAngleSigma()const; void SetAngle0(const REAL angle); void SetAngleDelta(const REAL delta); void SetAngleSigma(const REAL sigma); const MolAtom& GetAtom1()const; const MolAtom& GetAtom2()const; const MolAtom& GetAtom3()const; const MolAtom& GetAtom4()const; void SetAtom1(MolAtom& at); void SetAtom2(MolAtom& at); void SetAtom3(MolAtom& at); void SetAtom4(MolAtom& at); MolAtom& GetAtom1(); MolAtom& GetAtom2(); MolAtom& GetAtom3(); MolAtom& GetAtom4(); std::size_t size() const; vector::const_iterator begin() const; vector::const_iterator end() const; /// Access to the integer address of this object, for unique identification from python size_t int_ptr() const; private: /// The vector of the 4 atoms involved in the bond angle. vector mvpAtom; REAL mAngle0, mDelta, mSigma; /// Parent Molecule Molecule *mpMol; /// Stored log(likelihood) mutable REAL mLLK; /** Partial derivatives of the angle with respect to the coordinates of the atoms * * The derivatives are calculated in MolBondAngle::GetLogLikelihood(true) */ mutable XYZ mDerivAtom1,mDerivAtom2,mDerivAtom3,mDerivAtom4; /** The factor used to change the derivative of the length/angle, to the derivative * of the log(likelihood). e.g. (for mDelta=0) \f$ mDerivLLKCoeff = \frac{L-L_0}{\sigma^2} \f$ */ mutable REAL mDerivLLKCoeff; #ifdef __WX__CRYST__ public: WXCrystObjBasic *mpWXCrystObj; virtual WXCrystObjBasic* WXCreate(wxWindow*); WXCrystObjBasic* WXGet(); void WXDelete(); void WXNotifyDelete(); #endif }; /** Ring class * * \note This class could be used to restrain atom positions for * aromatic rings (planar restriction). * \note We could also store the aromatic status of the ring. */ class MolRing { public: MolRing(); const std::list& GetAtomList()const; std::list& GetAtomList(); /// Access to the integer address of this object, for unique identification from python size_t int_ptr() const; private: std::list mvpAtom; }; /** A quaternion class, used to represent the orientation of the molecule. * It may or may not be a unit quaternion. * */ class Quaternion { public: /// Default constructor, yields q=(1,0,0,0) Quaternion(); /// Creates a unit quaternion from its components (normalized automatically) Quaternion(const REAL q0,const REAL q1,const REAL q2,const REAL q3,bool unit=true); ~Quaternion(); /// Create a rotation quaternion around a given vector for a given angle static Quaternion RotationQuaternion(const REAL ang,const REAL v1,const REAL v2,const REAL v3); /// Get the conjugate of this quaternion (== the inverse if unit quaternion) Quaternion GetConjugate()const; /// Quaternion multiplication Quaternion operator*(const Quaternion &q)const; void operator*=(const Quaternion &q); void XMLOutput(ostream &os,int indent=0)const; void XMLInput(istream &is,const XMLCrystTag &tag); /// Rotate vector v=(v1,v2,v3). The rotated components are directly written void RotateVector(REAL &v1,REAL &v2, REAL &v3)const; /// Re-normalize the quaternion to unity. This should not be useful, except /// on individual component input, or after long calculations. And even /// if wrong, the rotation is independent of the norm of the quaternion. /// /// This is markerd const because we use only unit quaternions void Normalize()const ; REAL GetNorm()const; const REAL& Q0()const; const REAL& Q1()const; const REAL& Q2()const; const REAL& Q3()const; REAL& Q0(); REAL& Q1(); REAL& Q2(); REAL& Q3(); private: /// The components of the quaternion z=(q0,v) with v=(q1,q2,q3) /// /// These are mutable so that the quaternion can be normalized in a const method. mutable REAL mQ0,mQ1,mQ2,mQ3; bool mIsUniQuaternion; }; /** Rigid groups of atoms inside a molecule. * * These atoms can be moved as a group using * one rotation and one translation. * \warning: the rotation (quaternion) and translation parameters * are not saved or displayed, so any time this must be done * Molecule::ResetRigidGroupsPar() \b must be called beforehand - * this will use the rotation and translation parameters * to generate the final atomic coordinates, and reset mQuat,mX,mY and mZ. */ class RigidGroup:public std::set { public: std::string GetName()const; /// The unit quaternion defining the orientation - this is used /// during optimizations to rotate all atoms as a group. /// The quaternion does not give an absolute position - its value /// will be resetted whenever entering or leaving an optimization. mutable Quaternion mQuat; /// The translation of all the atoms as a group /// The values will be resetted whenever entering or leaving an optimization. mutable REAL mX,mY,mZ; /// Temporary list of the atoms indices in the molecule, used during optimization /// This is created in Molecule::BeginOptimization() mutable std::set mvIdx; /// Access to the integer address of this object, for unique identification from python size_t int_ptr() const; }; /** Abstract base Stretch Mode for Molecule objects * */ struct StretchMode { virtual ~StretchMode(); /** Calculate the derivative of the Molecule's Log(likelihood) and atomic positions * versus a change of the bond length. The result is stored in mLLKDeriv and mLLKDerivXYZ, * as well as in the various lists of restraints broken by this mode. * * \param derivllk: if false, the derivative of the overall llk will not be computed, only * the derivative of the atomic positions. **/ virtual void CalcDeriv(const bool derivllk=true)const=0; /// Print one-line list of atoms moved virtual void Print(ostream &os,bool full=true)const=0; /// Move the atoms according to this mode virtual void Stretch(const REAL change, const bool keepCenter=true)=0; /// Move the atoms according to this mode, randomly virtual void RandomStretch(const REAL amplitude, const bool keepCenter=true)=0; /// List of bond restraints affected by this mode /// The key is the restraint, the value is the derivative of the LLK associated std::map mvpBrokenBond; /// List of bond angle restraints modified by this mode /// The key is the restraint, the value is the derivative of the LLK associated std::map mvpBrokenBondAngle; /// List of dihedral angle restraints modified by this mode /// The key is the restraint, the value is the derivative of the LLK associated std::map mvpBrokenDihedralAngle; /// Derivative of the Molecule's Log(likelihood) versus a change of the bond length. mutable REAL mLLKDeriv; /// Derivative of the atomic positions versus a change of the bond length. mutable std::map mDerivXYZ; /// The Molecule corresponding to this stretch mode Molecule *mpMol; /** The recommended change amplitude, for a base global optimization * displacement, to obtain an average 0.1 Angstroem displacement. * * This is learnt at the beginning of an optimization. * * This can be superseeded to respect any restraint. */ REAL mBaseAmplitude; }; /** Group of atoms for random moves changing a bond length. * * This should be merged (or have an inheritance relation) with MolBond. */ struct StretchModeBondLength:public StretchMode { /** Constructor * If pBond!=0, the bond length restraint is respected. */ StretchModeBondLength(MolAtom &at0,MolAtom &at1,const MolBond *pBond); virtual ~StretchModeBondLength(); virtual void CalcDeriv(const bool derivllk=true)const; /// Print one-line list of atoms moved virtual void Print(ostream &os,bool full=true)const; /// Move the atoms according to this mode virtual void Stretch(const REAL change, const bool keepCenter=true); /// Move the atoms according to this mode, randomly virtual void RandomStretch(const REAL amplitude, const bool keepCenter=true); /// The first atom (fixed). MolAtom * mpAtom0; /// The second atom (first atom moved) MolAtom * mpAtom1; /// The (optional) bond length which this stretch mode should respect. const MolBond *mpBond; /// The set of atoms that are to be translated, including at1. set mvTranslatedAtomList; }; /** Atoms moved when changing a bond angle. * * This should be merged (or have an inheritance relation) with MolBondAngle. */ struct StretchModeBondAngle:public StretchMode { /** Constructor * If pBondAngle!=0, the bond angle length restraint is respected. */ StretchModeBondAngle(MolAtom &at0,MolAtom &at1,MolAtom &at2, const MolBondAngle *pBondAngle); virtual ~StretchModeBondAngle(); virtual void CalcDeriv(const bool derivllk=true)const; /// Print one-line list of atoms moved virtual void Print(ostream &os,bool full=true)const; /// Move the atoms according to this mode virtual void Stretch(const REAL change, const bool keepCenter=true); /// Move the atoms according to this mode, randomly virtual void RandomStretch(const REAL amplitude, const bool keepCenter=true); /// The first atom MolAtom * mpAtom0; /// The second atom MolAtom * mpAtom1; /// The third atom MolAtom * mpAtom2; /// The (optional) bond angle restraint which this stretch mode should respect. const MolBondAngle *mpBondAngle; /// The set of atoms that are to be rotated around the direction going /// through at1 and perpendicular to the at0-at1-at2 plane. set mvRotatedAtomList; }; /** Atoms moved when rotated around a bond at0-at1-at2-at3 * * This should be merged (or have an inheritance relation) with MolDihedralAngle */ struct StretchModeTorsion:public StretchMode { /** Constructor * If pDihedralAngle!=0, the dihedral angle length restraint is respected. */ StretchModeTorsion(MolAtom &at1,MolAtom &at2, const MolDihedralAngle *pDihedralAngle); virtual ~StretchModeTorsion(); virtual void CalcDeriv(const bool derivllk=true)const; /// Print one-line list of atoms moved virtual void Print(ostream &os,bool full=true)const; /// Move the atoms according to this mode virtual void Stretch(const REAL change, const bool keepCenter=true); /// Move the atoms according to this mode, randomly virtual void RandomStretch(const REAL amplitude, const bool keepCenter=true); /// The first atom MolAtom * mpAtom1; /// The second atom MolAtom * mpAtom2; /// The (optional) bond angle restraint which this stretch mode should respect. /// The mpAtom1 and mpAtom2 must be the central atoms of this restraint. const MolDihedralAngle *mpDihedralAngle; /// The set of atoms that are to be rotated around at1-at2 set mvRotatedAtomList; }; /** Atoms moved *between* two other atoms, using a "twist" *of their positions - only small twists of their positions * are allowed to avoid breaking restraints too much. Also, * the atoms in the middle between the two reference atoms are more * displaced than the one closer, to help avoid breaking restraints. */ struct StretchModeTwist:public StretchMode { /** Constructor * If pDihedralAngle!=0, the dihedral angle length restraint is respected. */ StretchModeTwist(MolAtom &at1,MolAtom &at2); virtual ~StretchModeTwist(); virtual void CalcDeriv(const bool derivllk=true)const; /// Print one-line list of atoms moved virtual void Print(ostream &os,bool full=true)const; /// Move the atoms according to this mode virtual void Stretch(const REAL change, const bool keepCenter=true); /// Move the atoms according to this mode, randomly virtual void RandomStretch(const REAL amplitude, const bool keepCenter=true); /// The first atom MolAtom * mpAtom1; /// The second atom MolAtom * mpAtom2; /// The set of atoms that are to be rotated around at1-at2 set mvRotatedAtomList; }; /** Groups of atoms that can be moved using molecular dynamics * principles, taking a list of restraints as ptential. * This is used to move group of atoms for which no adequate stretch mode * can be used, such as inside flexible rings. */ struct MDAtomGroup { /// Default constructor MDAtomGroup(); /** Constructor. * \param vat: list of atoms inside the group * \param vb,va,vd: list of bond, bond angle and dihedral angle restraints */ MDAtomGroup(std::set &vat, std::set &vb, std::set &va, std::set &vd); /// Print one-line list of atoms moved void Print(ostream &os,bool full=true)const; std::set mvpAtom; std::vector mvpBond; std::vector mvpBondAngle; std::vector mvpDihedralAngle; }; /** Light-weight representation of an atom in the molecule, as a part of a Z-matrix. * This is used to export the Molecule structure to a z-matrix. * * \todo: some flags could be added to mark the fixed/limited nature of the parameters. */ struct MolZAtom { const ScatteringPower *mpPow; unsigned long mBondAtom,mBondAngleAtom,mDihedralAtom; REAL mBondLength,mBondAngle,mDihedralAngle; }; /** Molecule : class for complex scatterer descriptions using * cartesian coordinates with bond length/angle restraints, and * moves either of individual atoms or using torsion bonds. * * This can also be used for non-organic compounds (polyhedras etc...) * \note the parametrization is very different from ZScatterer: we keep * a list of x,y,z which do not use limits (they must not), but the * coordinates must be restrained or constrained from the expected * bond lengths, angles and dihedral angles. The list of parameters is * re-created in BeginOptimization() (except for the global x y z parameters * for the global position of the Molecule, in fractionnal coordinates). * * \note : all atoms must be somehow connected */ class Molecule: public Scatterer { public: /** Constructor * */ Molecule(Crystal &cryst, const string &name=""); /** Copy constructor * */ Molecule(const Molecule &old); /** Destructor * */ ~Molecule(); virtual Molecule* CreateCopy() const; virtual const string& GetClassName() const; virtual void SetName(const string &name); /// Formula with atoms in alphabetic order std::string GetFormula() const; virtual void Print()const; virtual void XMLOutput(ostream &os,int indent=0)const; virtual void XMLInput(istream &is,const XMLCrystTag &tag); virtual void UpdateDisplay()const; virtual void BeginOptimization(const bool allowApproximations=false,const bool enableRestraints=false); virtual void EndOptimization(); virtual void RandomizeConfiguration(); virtual void GlobalOptRandomMove(const REAL mutationAmplitude, const RefParType *type); virtual REAL GetLogLikelihood()const; virtual unsigned int GetNbLSQFunction()const; virtual const CrystVector_REAL& GetLSQCalc(const unsigned int) const; virtual const CrystVector_REAL& GetLSQObs(const unsigned int) const; virtual const CrystVector_REAL& GetLSQWeight(const unsigned int) const; virtual const CrystVector_REAL& GetLSQDeriv(const unsigned int n, RefinablePar&par); virtual void TagNewBestConfig()const; virtual int GetNbComponent() const; virtual const ScatteringComponentList& GetScatteringComponentList() const; virtual string GetComponentName(const int i) const; virtual ostream& POVRayDescription(ostream &os, const CrystalPOVRayOptions &options)const; #ifdef OBJCRYST_GL virtual void GLInitDisplayList(const bool onlyIndependentAtoms=false, const REAL xMin=-.1,const REAL xMax=1.1, const REAL yMin=-.1,const REAL yMax=1.1, const REAL zMin=-.1,const REAL zMax=1.1, const bool displayEnantiomer=false, const bool displayNames=false, const bool hideHydrogens=false, const REAL fadeDistance=0, const bool fullMoleculeInLimits=false)const; #endif // OBJCRYST_GL /** Add an atom * * */ void AddAtom(const REAL x, const REAL y, const REAL z, const ScatteringPower *pPow,const string &name, const bool updateDisplay=true); /** Remove an atom. Returns the iterator to the next atom in the list. * * This also removes all corresponding bonds, bond angles, etc... * If del is true (default), then the MolAtom object is deleted. The del * flag gets sent to the RemoveXXX functions for the corresponding * objects. */ vector::iterator RemoveAtom(MolAtom&, const bool del = true); /** Add a bond * * */ void AddBond(MolAtom &atom1, MolAtom &atom2, const REAL length, const REAL sigma, const REAL delta, const REAL bondOrder=1., const bool updateDisplay=true); /** Remove a bond. Returns the iterator to the next bond in the list. * * If del is true (default), then the MolBond object is deleted. * */ vector::iterator RemoveBond(const MolBond&, const bool del = true); /** Searches whether a bond between two atoms already exists. * * If no bond is found, returns Molecule::mvpAtom.end(). */ vector::const_iterator FindBond(const MolAtom&,const MolAtom&)const; /** Searches whether a bond between two atoms already exists. * * If no bond is found, returns Molecule::mvpAtom.end(). */ vector::iterator FindBond(const MolAtom&,const MolAtom&); /** Add a bond angle restraint * * */ void AddBondAngle(MolAtom &atom1, MolAtom &atom2, MolAtom &atom3, const REAL angle, const REAL sigma, const REAL delta, const bool updateDisplay=true); /** Remove a BondAngle * * If del is true (default), then the MolBondAngle object is deleted. */ vector::iterator RemoveBondAngle(const MolBondAngle&, const bool del = true); /** Searches whether a bond between three atoms already exists, * searching for either (at1,at2,at3) and (at3,at2,at1), as these are equivalent. * * If no bond angle is found, returns Molecule::mvpBondAngle.end(). */ vector::const_iterator FindBondAngle(const MolAtom& at1,const MolAtom&at0,const MolAtom&at2)const; /** Add a dihedral angle restraint * * */ void AddDihedralAngle(MolAtom &atom1, MolAtom &atom2, MolAtom &atom3, MolAtom &atom4, const REAL angle, const REAL sigma, const REAL delta, const bool updateDisplay=true); /** Remove a dihedral angle * * If del is true (default), then the MolDihedralAngle object is deleted. */ vector::iterator RemoveDihedralAngle(const MolDihedralAngle&, const bool del = true); /** Searches whether a dihedral between four atoms already exists, * searching for either (at1,at2,at3,at4) and (at4,at3,at2,at1), as these are equivalent. * * If no dihedral angle is found, returns Molecule::mvpDihedralAngle.end(). */ vector::const_iterator FindDihedralAngle(const MolAtom &at1, const MolAtom &at2, const MolAtom &at3, const MolAtom &at4)const; /** Add a rigid group of atoms. See Molecule::mvRigidGroup */ void AddRigidGroup(const RigidGroup&,const bool updateDisplay=true); /** Remove a rigid group of atoms. See Molecule::mvRigidGroup * * If del is true (default), then the RigidGroup object is deleted. */ std::vector::iterator RemoveRigidGroup(const RigidGroup &group,const bool updateDisplay=true, const bool del = true); MolAtom &GetAtom(unsigned int i); const MolAtom &GetAtom(unsigned int i)const; MolAtom &GetAtom(const string &name); const MolAtom &GetAtom(const string &name)const; /// Search a MolAtom from its name. Search begins at the end, and the /// first match is returned. returns mvAtom.rend() if no atom matches vector::reverse_iterator FindAtom(const string &name); /// Search a MolAtom from its name. Search begins at the end, and the /// first match is returned. returns mvAtom.rend() if no atom matches vector::const_reverse_iterator FindAtom(const string &name)const; /** Minimize configuration from internal restraints (bond lengths, angles * and dihedral angles). Useful when adding manually atoms to get an initial * reasonable configuration. */ void OptimizeConformation(const long nbTrial=10000,const REAL stopCost=0.); /** Optimize the conformation from internal restraints (bond lengths, angles * and dihedral angles), using a steepest descent algorithm. * *\param maxStep: maximum displacement allowed along any coordinate for all atoms. *\param nbStep: number of steps - the gradient is re-calculated after each step. */ void OptimizeConformationSteepestDescent(const REAL maxStep=0.1,const unsigned nbStep=1); /** Change the conformation of the molecule using molecular dynamics principles. * Optionnally, move only a subgroup of atoms and only take into account some restraints. * * The atoms actually moved are those included as keys in v0, and those part of the * rigid bodies in vr. * * \param v0: initial speed of all atoms. On return, includes the new speed coordinates. * Only the atoms used as keys in v0 will be moved, so this should be used to work * only on a subgroup of atoms. * \param nbStep: number of steps to perform. * \param dt: time step. Recommended value are such that v0[].xyz * dt = 0.001 * \param vb,va,vd: vector of bond, bond angle and dihedral angle restraints to * be taken into account. If these are empty, the full list of restraints of the Molecule * are taken into account, including rigid groups. If they are not empty, then * it is assumed that no atom moved belongs to a rigid group. * \param vr: initial speed for the angular and translation parameters of rigid groups * included in the evolution. For each entry of the map the first XYZ coordinates are the speed * for RigidGroup::mX,mY,mZ, and the second are the speed for the angular coordinates * of the quaternion Q1,Q2,Q3 * \param nrj0: the total energy the system should try to maintain. If equal to 0, * the initial energy will be used. The speed will be de/increased to compensate * any energy change. */ void MolecularDynamicsEvolve(std::map &v0,const unsigned nbStep,const REAL dt, const std::vector &vb,const std::vector &va, const std::vector &vd, std::map > &vr, REAL nrj0=0); const std::vector& GetAtomList()const; const std::vector& GetBondList()const; const std::vector& GetBondAngleList()const; const std::vector& GetDihedralAngleList()const; std::vector& GetAtomList(); std::vector& GetBondList(); std::vector& GetBondAngleList(); std::vector& GetDihedralAngleList(); std::list& GetStretchModeBondLengthList(); std::list& GetStretchModeBondAngleList(); std::list& GetStretchModeTorsionList(); const std::list& GetStretchModeBondLengthList()const; const std::list& GetStretchModeBondAngleList()const; const std::list& GetStretchModeTorsionList()const; /** List of rigid group of atoms. See Molecule::mvRigidGroup */ const std::vector& GetRigidGroupList()const; /** List of rigid group of atoms. See Molecule::mvRigidGroup */ std::vector& GetRigidGroupList(); /** Rotate a group of atoms around an axis defined by two atoms * * \param keepCenter: if true, the coordinates of the molecule are modified * so that only the rotated atoms are moved. */ void RotateAtomGroup(const MolAtom &at1,const MolAtom &at2, const set &atoms, const REAL angle, const bool keepCenter=true); /** Rotate a group of atoms around an axis defined by one atom and a vector * * \param keepCenter: if true, the coordinates of the molecule are modified * so that only the rotated atoms are moved. */ void RotateAtomGroup(const MolAtom &at,const REAL vx,const REAL vy,const REAL vz, const set &atoms, const REAL angle, const bool keepCenter=true); /** Translate a group of atoms in a given direction * * \param keepCenter: if true, the coordinates of the molecule are modified * so that only the translated atoms are moved. */ void TranslateAtomGroup(const set &atoms, const REAL dx,const REAL dy,const REAL dz, const bool keepCenter=true); /// Print the status of all restraints (bond length, angles...) void RestraintStatus(ostream &os)const; /// Print the restraints (bond length, angles...) as whole labels and number in column text format which accessible to other programs void RestraintExport(ostream &os)const; /// Get the connectivity table const map > & GetConnectivityTable(); /// get the clock associated to the list of bonds RefinableObjClock& GetBondListClock(); /// get the clock associated to the list of bonds const RefinableObjClock& GetBondListClock()const; /// Get the clock associated to the atomic positions RefinableObjClock& GetAtomPositionClock(); /// Get the clock associated to the atomic positions const RefinableObjClock& GetAtomPositionClock()const; /// Get the clock associated to the scattering powers const RefinableObjClock& GetAtomScattPowClock()const; /// Get the clock associated to the scattering powers RefinableObjClock& GetAtomScattPowClock(); /// Get the clock associated to the list of rigid groups ///(clicked also whenever a rigid group is modified) RefinableObjClock& GetRigidGroupClock(); /// Get the clock associated to the list of rigid groups ///(clicked also whenever a rigid group is modified) const RefinableObjClock& GetRigidGroupClock()const; /** Add dihedral angles so as to rigidify the Molecule. * * In practice, for every sequence of atoms A-B-C-D, add the dihedral angle * defined by these 4 atoms, unless either ABC or BCD are aligned (angle below 10�). * * No duplicate dihedral angle is generated. */ void RigidifyWithDihedralAngles(); /** Stretch a bond, while respecting the Restraint (if any). * *\return the \e actual change in bond length. *\param: the desired change in bond length. This will be the actual change \e if * there is no restraint \e or if the restraint is constant in this range. */ REAL BondLengthRandomChange(const StretchModeBondLength& mode, const REAL amplitude, const bool respectRestraint=true); /** change a bond angle, while respecting the Restraint (if any). * *\return the \e actual change in bond angle. *\param: the desired angular change. This will be the actual change \e if * there is no restraint \e or if the restraint is constant in this range. */ REAL BondAngleRandomChange(const StretchModeBondAngle& mode, const REAL amplitude, const bool respectRestraint=true); /** Change a dihedral angle, while respecting the Restraint (if any). * *\return the \e actual change in bond angle. *\param: the desired angular change. This will be the actual change \e if * there is no restraint \e or if the restraint is constant in this range. */ REAL DihedralAngleRandomChange(const StretchModeTorsion& mode, const REAL amplitude, const bool respectRestraint=true); /// Get the atom defining the origin of the Molecule /// Equal to 0 if no atom as been set. const MolAtom* GetCenterAtom()const; /// Get the atom defining the origin of the Molecule /// Equal to 0 if no atom as been set. void SetCenterAtom(const MolAtom &at); /** Molecule as Z-matrix * * \param keeporder: if true, the order of the atoms is exactly the same as in * the Molecule. */ const std::vector& AsZMatrix(const bool keeporder)const; /** Set whether to delete the MolAtoms, MolBonds, MolBondAngles and * MolDihedralAngles in the destructor. By default these sub-objects are * deleted. */ void SetDeleteSubObjInDestructor(const bool b); public: virtual void InitRefParList(); /** Build the list of rings in the molecule. * * The list is \e only rebuilt if the bond or atom list has changed,so * it should be safe to call again this function. * * \note So far this is a const method as the ring list just reflects the bond list * and therefore is mutable (see Molecule::mvRing)... but maybe this could * change... */ void BuildRingList(); /** Build the Connectivity table * */ void BuildConnectivityTable()const; /** Build the groups of atoms that will be rotated during global optimization. * * This is not const because we temporarily modify the molecule conformation * to test which RotorGroups are forbidden by restraints (but it should be const). */ void BuildRotorGroup(); /** Tune the rotation amplitude for free torsions and for the overall Molecule * Rotation. * * This should be done after Molecule::BuildRotorGroup(); */ void TuneGlobalOptimRotationAmplitude(); /** Build the groups of atoms that can be flipped. * * This is not const because we temporarily modify the molecule conformation * to test which FlipGroups are forbidden by restraints (but it should be const). */ void BuildFlipGroup(); /** Build the groups of atoms moved when stretching a bond length, while * respecting the Molecule restraints. */ void BuildStretchModeBondLength(); /** Build the groups of atoms moved when changing a bond angle, while * respecting the Molecule restraints. */ void BuildStretchModeBondAngle(); /** Build the groups of atoms moved when changing a dihedral angle, while * respecting the Molecule restraints. */ void BuildStretchModeTorsion(); /** Build the groups of atoms used to twist internally the Molecule, e.g. by * rotating one chain of atoms between 2 given atoms. */ void BuildStretchModeTwist(); /** Separate StretchMode that break more than their assigned restraint from others. * See Molecule::mvpStretchModeFree and Molecule::mvpStretchModeNotFree */ void BuildStretchModeGroups(); /** Find groups of atoms that cannot be moved relatively to each other * using the free or non-free stretch modes. Usually these will correspond * to atoms inside a flexible ring. * * These atoms (if they are not in a rigid group) are stored in a MDAtomGroup * so that they can still move using molecular dynamics. * *\b this should be called after BuildStretchModeGroups(), to make sure the * list of free/non-free stretch mode has been built. */ void BuildMDAtomGroups(); /** Update the Molecule::mScattCompList from the cartesian coordinates * of all atoms, and the orientation parameters. */ void UpdateScattCompList()const; /// Build options for this object void InitOptions(); /** Set the orientation & translation parameters of all rigid * groups to 0, after correcting the atomic positions. * This is \b required before saving the structure, as these * parameters are not saved. */ void ResetRigidGroupsPar()const; /** The list of scattering components * * this is mutable since it only reflects the list of atoms. */ mutable ScatteringComponentList mScattCompList; /** The list of atoms * */ vector mvpAtom; /** The list of bonds * */ vector mvpBond; /** The list of bond angles * */ vector mvpBondAngle; /** The list of dihedral angles * */ vector mvpDihedralAngle; /** List of Bonds for each atom. * * This duplicates the information in Molecule::mvBond */ map > mvAtomBond; /** Rigid groups of atoms. This group will be kept \e strictly rigid, * preventing the use of any stretch mode altering their relative position. * The entire group of atoms can however be rotated or translated. */ std::vector mvRigidGroup; /** The list of rings * * \note this only reflects the bond list, so it is mutable. */ mutable list mvRing; /** The unit quaternion defining the orientation * */ Quaternion mQuat; /** Base Rotation amplitude (in radians) for the Molecule, so that * the average atomic displacement is equal to 0.1 A * * Default=0.02*pi */ // Flag indicating whether to destroy MolAtoms, MolBonds, MolBondAngles, // and MolDihedralAngles in the destructor (default true). Mofified by // SetDeleteSubObjInDestructor. bool mDeleteSubObjInDestructor; REAL mBaseRotationAmplitude; // Clocks RefinableObjClock mClockAtomList; RefinableObjClock mClockBondList; RefinableObjClock mClockBondAngleList; RefinableObjClock mClockDihedralAngleList; RefinableObjClock mClockRigidGroup; /// This clock is the parent of mClockAtomList, mClockBondList, mClockBondAngleList, /// mClockDihedralAngleList and mClockRigidGroup. It can be used to determine if /// either the list of atoms or restraints have changed. RefinableObjClock mClockRestraint; RefinableObjClock mClockAtomPosition; RefinableObjClock mClockAtomScattPow; RefinableObjClock mClockOrientation; mutable RefinableObjClock mClockLogLikelihood; mutable RefinableObjClock mClockConnectivityTable; mutable RefinableObjClock mClockRingList; mutable RefinableObjClock mClockRotorGroup; mutable RefinableObjClock mClockFlipGroup; mutable RefinableObjClock mClockStretchModeBondLength; mutable RefinableObjClock mClockStretchModeBondAngle; mutable RefinableObjClock mClockStretchModeTorsion; mutable RefinableObjClock mClockStretchModeTwist; mutable RefinableObjClock mClockMDAtomGroup; // For local minimization (EXPERIMENTAL) unsigned long mLocalParamSet; mutable unsigned long mRandomConformChangeNbTest; mutable unsigned long mRandomConformChangeNbAccept; mutable REAL mRandomConformChangeTemp; REAL mLastLogLike; bool mIsSelfOptimizing; /// OPtion for the different types of flexibility possible for this /// molecule: rigid body, free atoms + restraints, torsion angles... /// \warning still EXPERIMENTAL ! RefObjOpt mFlexModel; RefObjOpt mFlipModel; /** Option to automatically optimize the starting conformation, if the * total restraint cost is too high. This is done in BeginOptimization(). * * This is enabled by default, and should be disabled by people who already * supply a good starting conformation for their molecule. */ RefObjOpt mAutoOptimizeConformation; /** Option to optimize the Molecule's orientation. Useful to completely * fix the Molecule. */ RefObjOpt mOptimizeOrientation; /** Option to choose the center of rotation of the Molecule for the global orientation * either as the geometrical center, or as a given atom. */ RefObjOpt mMoleculeCenter; /** Atom chosen as center of rotation, if mRotationCenter is set to use * an atom rather than the geometrical center. */ const MolAtom* mpCenterAtom; /// Connectivity table: for each atom, keep the list of atoms /// bonded to it. All atoms are referenced from their index. mutable map > mConnectivityTable; /** Defines a group of atoms which can be rotated around an axis defined * by two other atoms. */ struct RotorGroup { /** Constructor, with the two atoms around which the rotation * shall be made. The list of atoms to be rotated is initially empty. */ RotorGroup(const MolAtom &at1,const MolAtom &at2); /// The first atom defining the rotation axis const MolAtom * mpAtom1; /// The second atom defining the rotation axis const MolAtom * mpAtom2; /// The set of atoms that are to be rotated set mvRotatedAtomList; /** The recommended rotation amplitude, for a base global optimization * displacement, to obtain an average 0.1 Angstroem displacement * per atom (pi*0.04 by default) * * This is learnt at the beginning of an optimization, i.e. in * Molecule::BuildRotorGroup() */ REAL mBaseRotationAmplitude; }; /** List of RotorGroups corresponding to free torsion bonds. * * In this list are list of atoms on one side of a bond, that can be rotated * freely around this bond. Each bond is listed only once, with * the side which has the smallest number of atoms. */ mutable list mvRotorGroupTorsion; /** List of RotorGroups corresponding to free torsion bonds, but with only * one chain of atoms listed. * * The difference with Molecule::mRotorGroupTorsion is that if the bond is * A-B, with atom A linked with atoms A1,A2,A3, in this list only one chain * (starting either from A1, A2 or A3) will be rotated, instead of the 3 chains. * This is useful when searching for the absolute configuration of atoms. */ mutable list mvRotorGroupTorsionSingleChain; /** List of RotorGroups for internal rotations. This lists groups of atoms * that can be rotated \e between two given atoms. This is useful to alter * the conformation of large rings, where no free torsion bonds exists, and * also for long flexible chains. */ mutable list mvRotorGroupInternal; /** When 3(A1..1n) or more atoms are connected to a same atom A, it defines * a 'flip' group, where it is possible to rotate bonds to their symmetric * with respect to one plane defined by atoms Ai-A-Aj. This is useful to * flip the absolute configuration for asymmetric centers. Note that the bond * is only rotated, so that the entire group is not mirrored (no absolute configuration * is broken in the group). * * Also, a FlipGroup can correspond to a 180� rotation exchanging Ai and Aj * (rotating the two chains around the bissecting angle of bonds A-Ai and A-Aj) */ struct FlipGroup { /** Constructor, with the central atom. */ FlipGroup(const MolAtom &at0,const MolAtom &at1,const MolAtom &at2); /// The atom which is an asymmetric center const MolAtom * mpAtom0; /// The first atom defining the rotation axis const MolAtom * mpAtom1; /// The second atom defining the rotation axis const MolAtom * mpAtom2; /// The set of atoms that are to be rotated during the flip. The first /// atom is the one bonded to the central atom, whose bond will be flipped /// with respect to the plane defined by (at1,at0,at2). /// /// However, if this atom is identical to mpAtom0, then this indicates that /// a 180� rotation exchanging atom1 and atom2 is to be performed. list > > mvRotatedChainList; /// Number of times this flip has been tried, and the number of times /// it has been accepted. Used in Molecule::GlobalOptRandomMove, /// to avoid flips that break some restraint (and deciding which flips /// break some restraint is difficult before having a real conformation). mutable unsigned long mNbTest,mNbAccept; }; /// Flip a group of atom. See Molecule::FlipGroup. void FlipAtomGroup(const FlipGroup&, const bool keepCenter=true); /** The list of FlipGroups. * */ mutable list mvFlipGroup; // Group of atoms for random moves naturally respecting restraints /// List of StretchModeBondLength mutable list mvStretchModeBondLength; /// List of StretchModeBondLength mutable list mvStretchModeBondAngle; /// List of StretchModeBondLength mutable list mvStretchModeTorsion; /// List of StretchModeTwist mutable list mvStretchModeTwist; /// Groups of StretchMode not breaking any restraint (unless the one they are associated to) mutable std::list mvpStretchModeFree; /// Groups of StretchMode breaking restraints (beyond the one they are associated to) mutable std::list mvpStretchModeNotFree; /// Group of concurrent StretchModes (affecting common restraints) /// A given stretch mode can only belong to one group. struct StretchModeGroup { std::set mvpStretchMode; std::set mvpBrokenBond; std::set mvpBrokenBondAngle; std::set mvpBrokenDihedralAngle; }; /** Groups of atoms that should be moved according to molecular dynamics * principles. */ mutable list mvMDAtomGroup; /// Full list of atoms that can be moved using molecular dynamics /// This excludes any atom part of a rigid group mutable std::set mvMDFullAtomGroup; /// Frequency of using molecular dynamics move during GlobalOptRandomMove() REAL mMDMoveFreq; /// Relative energy of molecule during molecular dynamics move /// Default: 40, 10 (slow conformation change), 200 (large changes) REAL mMDMoveEnergy; /// The Molecule, as a lightweight ZMatrix, for export purposes. mutable std::vector mAsZMatrix; /// The current log(likelihood) mutable REAL mLogLikelihood; /** Scale (multiplier) for the log(likelihood) * * Changing this scale is equivalent to changing the sigma values of all bonds, * bond angles and dihedral angles - but it allows a simple global scaling for the * user. */ REAL mLogLikelihoodScale; /// Current LSQ Calc - one value for each restraint (bond distance, angle or dihedral angle) mutable CrystVector_REAL mLSQCalc; /// Current LSQ Calc - one value for each restraint (bond distance, angle or dihedral angle ideal values) mutable CrystVector_REAL mLSQObs; /// Current LSQ Calc - one value for each restraint(bond distance, angle or dihedral angle sigmas) mutable CrystVector_REAL mLSQWeight; #ifdef __WX__CRYST__ public: virtual WXCrystObjBasic* WXCreate(wxWindow*); #endif }; /** Build recursively a list of atoms, starting from a one atom, and given * a connectivity table. * * \param atom: the starting atom * \param connect: the connectivity table * \param atomlist: the list of atoms to which will be appended the atoms newly found. * \param finalAtom: if specified, the list buildin will stop after finding this atom. * This can be used to build the list of atoms between two given atoms. Otherwise, * the list is expanded until the end of the chain(s), or until an atom already * in the list is encountered (i.e. a ring has been found). */ void ExpandAtomGroupRecursive(MolAtom* atom, const map > &connect, set &atomlist,const MolAtom* finalAtom=0); /** Build recursively a list of atoms, starting from a one atom, and given * a connectivity table, until a certain depth (number of bonds) is reached. * * \param atom: the starting atom * \param connect: the connectivity table * \param atomlist: the list of atoms to which will be appended the atoms newly found. * \param finalAtom: if specified, the list buildin will stop after finding this atom. * This can be used to build the list of atoms between two given atoms. Otherwise, * the list is expanded until the end of the chain(s), or until an atom already * in the list is encountered (i.e. a ring has been found). */ void ExpandAtomGroupRecursive(MolAtom* atom, const map > &connect, map &atomlist,const unsigned long maxdepth, unsigned long depth=0); // Forward declaration class ZScatterer; /// Converter from ZScatterer to a Molecule object Molecule *ZScatterer2Molecule(ZScatterer *scatt); }//namespace #endif objcryst-2022.1/ObjCryst/ObjCryst/PDF.cpp000066400000000000000000000270161430515525000200600ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2007-2008 Vincent Favre-Nicolin vincefn@users.sourceforge.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* PDF.cpp - Pair Distribution calculations * */ #include "ObjCryst/ObjCryst/PDF.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" #ifdef __WX__CRYST__ #include "ObjCryst/wxCryst/wxPDF.h" #endif #include namespace ObjCryst { const RefParType *gpRefParTypePDF=0; PDF::PDF(): mRadiationType(RAD_XRAY) { } PDF::PDF(const PDF &old): mRadiationType(old.mRadiationType), mPDFR(old.mPDFR),mPDFCalc(old.mPDFCalc),mPDFObs(old.mPDFObs), mvPDFPhase(old.mvPDFPhase) {} PDF::~PDF(){} const string& PDF::GetClassName() const { static const string className = "PDF"; return className; } void PDF::SetPDFObs(const CrystVector_REAL &r,const CrystVector_REAL &obs) { mPDFR=r; mPDFObs=obs, mPDFCalc.resize(r.numElements()); mPDFCalc=0; } RadiationType PDF::GetRadiationType()const{return mRadiationType;} void PDF::SetRadiationType(RadiationType type){mRadiationType=type;} REAL PDF::GetRMax()const { const unsigned long nb=mPDFR.numElements(); if(nb>0) return mPDFR(nb-1); return 0; } const CrystVector_REAL &PDF::GetPDFCalc()const { //:TODO: re-calculate only when needed ! mPDFCalc.resize(mPDFR.numElements()); mPDFCalc=0; CrystVector_REAL tmp; for(list >::const_iterator pos=mvPDFPhase.begin();pos!=mvPDFPhase.end();++pos) { tmp=pos->first->GetPDFCalc(); tmp*=pos->second; mPDFCalc+=tmp; } return mPDFCalc; } const CrystVector_REAL &PDF::GetPDFObs()const { return mPDFObs; } const CrystVector_REAL &PDF::GetPDFR()const { return mPDFR; } void PDF::AddPDFPhase(PDFPhase &phase) { mvPDFPhase.push_back(make_pair(&phase,1.0)); } #ifdef __WX__CRYST__ WXCrystObjBasic* PDF::WXCreate(wxWindow* parent) { if(mpWXCrystObj==0) mpWXCrystObj=new WXPDF(parent,this); return mpWXCrystObj; } #endif ////////////////////////// PDFPhase ///////////////////////////// PDFPhase::PDFPhase(const PDF &pdf): mpPDF(&pdf) { } const CrystVector_REAL &PDFPhase::GetPDFCalc()const { this->CalcPDF(); return mPDFCalc; } ////////////////////////// PDFCrystal ///////////////////////////// PDFCrystal::PDFCrystal(const PDF &pdf, const Crystal &cryst): PDFPhase(pdf),mpCrystal(&cryst),mDelta1(0.0),mDelta2(0.0),mQbroad(0.0),mQdamp(0.0) { } PDFCrystal::pdfAtom::pdfAtom(): fx0(0),fy0(0),fz0(0),x0(0),y0(0),z0(0),occupBi(1),hasChanged(true) {} void PDFCrystal::Init(const PDF &pdf, const Crystal &cryst) { mpCrystal=&cryst; mpPDF=&pdf; this->ResetParList(); { RefinablePar tmp("Delta1",&mDelta1,0,1.0,gpRefParTypePDF, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,1); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-3); this->AddPar(tmp); } { RefinablePar tmp("Delta2",&mDelta2,0,1.0,gpRefParTypePDF, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,1); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-3); this->AddPar(tmp); } { RefinablePar tmp("Qbroad",&mQbroad,0,1.0,gpRefParTypePDF, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,1); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-3); this->AddPar(tmp); } { RefinablePar tmp("Qdamp",&mQdamp,0,1.0,gpRefParTypePDF, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,1); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-3); this->AddPar(tmp); } } void PDFCrystal::CalcPDF()const { const unsigned long nbr=mpPDF->GetPDFR().numElements(); mPDFCalc.resize(nbr); if(mpCrystal==0) { mPDFCalc=0; return; } // Get current fractionnal coordinates from Crystal, check if any has changed const ScatteringComponentList *pScatt=&(mpCrystal->GetScatteringComponentList()); unsigned long nb=pScatt->GetNbComponent(); pScatt->Print(); // Calc and rho0 REAL rho0=0,b_av=0; // Note: We cannot use the dynamical occupancy as computed in a Crystal Object, //as we need the real occupancy for each *unique* poisition. // :TODO: So we need to compute a new dynamical occupancy that only corrects the overlap //between one unique atom and different atoms, excluding symetrics of the unique atom. if(nb!=mvPDFAtom.size()) { mvPDFAtom.resize(nb); unsigned int i=0; for(vector::iterator pos=mvPDFAtom.begin();pos!=mvPDFAtom.end();++pos) { pos->fx0=(*pScatt)(i).mX; pos->fy0=(*pScatt)(i).mY; pos->fz0=(*pScatt)(i).mZ; if((*pScatt)(i).mpScattPow==0) pos->occupBi=0; else { const REAL occ=(*pScatt)(i).mOccupancy; const REAL b=(*pScatt)(i).mpScattPow->GetForwardScatteringFactor(mpPDF->GetRadiationType()); rho0+=occ; b_av+=occ*b; pos->occupBi= occ*b; pos->pScattPow=(*pScatt)(i).mpScattPow; pos->hasChanged=true; } ++i; } } else { unsigned int i=0; for(vector::iterator pos=mvPDFAtom.begin();pos!=mvPDFAtom.end();++pos) { if(pos->fx0!=(*pScatt)(i).mX){pos->fx0=(*pScatt)(i).mX;pos->hasChanged=true;} if(pos->fy0!=(*pScatt)(i).mY){pos->fy0=(*pScatt)(i).mY;pos->hasChanged=true;} if(pos->fz0!=(*pScatt)(i).mZ){pos->fz0=(*pScatt)(i).mZ;pos->hasChanged=true;} if(pos->pScattPow!=(*pScatt)(i).mpScattPow){pos->pScattPow=(*pScatt)(i).mpScattPow;pos->hasChanged=true;} REAL occupBi; if((*pScatt)(i).mpScattPow==0) occupBi=0; else { const REAL occ=(*pScatt)(i).mOccupancy; const REAL b=(*pScatt)(i).mpScattPow->GetForwardScatteringFactor(mpPDF->GetRadiationType()); rho0+=occ; b_av+=occ*b; occupBi= occ*b; //:TODO: check if B-factor has changed } if(pos->occupBi!=occupBi){pos->occupBi=occupBi;pos->hasChanged=true;} } } // Determine number of translations needed //to get all interatomic distances up to Rmax // :TODO: faster by smarter limits on translations ? const int nx=int(ceil(mpPDF->GetRMax()/mpCrystal->GetLatticePar(0))+.001); const int ny=int(ceil(mpPDF->GetRMax()/mpCrystal->GetLatticePar(1))+.001); const int nz=int(ceil(mpPDF->GetRMax()/mpCrystal->GetLatticePar(2))+.001); const unsigned int nbSymmetrics=mpCrystal->GetSpaceGroup().GetNbSymmetrics(); const unsigned int neq=(2*nx+1)*(2*ny+1)*(2*nz+1)*nbSymmetrics; b_av/=rho0; cout<<"rho0="<GetVolume()<<"="<GetVolume()<GetVolume(); // Calc all equivalent positions & translations // TODO: Use knowledge of special positions, rather than use dynamical occupancy ? { const CrystMatrix_REAL *pOrth=&(mpCrystal->GetOrthMatrix()); const REAL m00=(*pOrth)(0,0); const REAL m01=(*pOrth)(0,1); const REAL m02=(*pOrth)(0,2); const REAL m11=(*pOrth)(1,1); const REAL m12=(*pOrth)(1,2); const REAL m22=(*pOrth)(2,2); cout<::iterator pos=mvPDFAtom.begin();pos!=mvPDFAtom.end();++pos) { if(pos->hasChanged) { symmetricsCoords=mpCrystal->GetSpaceGroup().GetAllSymmetrics(pos->fx0,pos->fy0,pos->fz0); pos->x.resize(neq); pos->y.resize(neq); pos->z.resize(neq); REAL *px=pos->x.data(); REAL *py=pos->y.data(); REAL *pz=pos->z.data(); for(unsigned int j=0;jFractionalToOrthonormalCoords(x,y,z); if(pos==mvPDFAtom.begin()) cout<x0=x;pos->y0=y;pos->z0=z;} for(int ix=-nx;ix<=nx;++ix) for(int iy=-ny;iy<=ny;++iy) for(int iz=-nz;iz<=nz;++iz) { //cout<GetRMax()+0.2)*(mpPDF->GetRMax()+0.2); const REAL nsigcut=5;// Cut gaussian at abs(r_ij-r)<3*sigma const REAL norm=1/sqrt(2*M_PI); for(vector::iterator pos=mvPDFAtom.begin();pos!=mvPDFAtom.end();++pos) { if(pos->occupBi==0) continue; const REAL x0=pos->x0; const REAL y0=pos->y0; const REAL z0=pos->z0; for(vector::iterator pos1=pos;pos1!=mvPDFAtom.end();++pos1) { if(pos1->occupBi==0) continue; REAL normij=norm*pos->occupBi*pos1->occupBi/(b_av*b_av)/nb; if(pos!=pos1)normij*=2;// i!j should be counted twice in the loop const REAL *px=pos1->x.data(); const REAL *py=pos1->y.data(); const REAL *pz=pos1->z.data(); const REAL sigma2=(pos->pScattPow->GetBiso()+pos1->pScattPow->GetBiso())/(8*M_PI*M_PI); for(unsigned long i=0;i1)) { const REAL rij=sqrt(d2); REAL s2=sigma2*(1-mDelta1/rij-mDelta2/d2+mQbroad*d2); if(s2<.01) s2=0.01; const REAL sig=sqrt(s2); REAL *p=mPDFCalc.data(); const REAL *pr=mpPDF->GetPDFR().data(); const REAL rmin=rij-nsigcut*sig,rmax=rij+nsigcut*sig; //cout<<" "<"<rmax) break; const REAL dr=rij-*pr; *p += n*exp(-dr*dr/(2*s2)); p++;pr++; } } } } } cout<GetPDFR(); CrystVector_REAL tmp; tmp=mpPDF->GetPDFR(); tmp*=4*M_PI*rho0; mPDFCalc-=tmp; } #ifdef __WX__CRYST__ WXCrystObjBasic* PDFCrystal::WXCreate(wxWindow* parent) { if(mpWXCrystObj==0) mpWXCrystObj=new WXPDFCrystal(parent,this); return mpWXCrystObj; } #endif }//namespace objcryst-2022.1/ObjCryst/ObjCryst/PDF.h000066400000000000000000000113521430515525000175210ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2007-2008 Vincent Favre-Nicolin vincefn@users.sourceforge.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* PDF.h header file for Pair Distribution calculations * */ #ifndef _OBJCRYST_PDF_H_ #define _OBJCRYST_PDF_H_ #include "ObjCryst/CrystVector/CrystVector.h" #include "ObjCryst/ObjCryst/Crystal.h" #ifdef __WX__CRYST__ #include "ObjCryst/wxCryst/wxCryst.h" #endif #include #include #include namespace ObjCryst { extern const RefParType *gpRefParTypePDF; // Forward declaration class PDFPhase; /** Main class for Pair distribution function calculations and comparison to observed one * */ class PDF:public RefinableObj { public: PDF(); /// Copy constructor PDF(const PDF &old); /// Crystal destructor ~PDF(); virtual const string& GetClassName() const; /// Experimental data void SetPDFObs(const CrystVector_REAL &r,const CrystVector_REAL &obs); /// GetRadiationType RadiationType GetRadiationType()const; /// SetRadiationType void SetRadiationType(RadiationType type); /// Cutoff r value REAL GetRMax()const; /// Get the calculated PDF const CrystVector_REAL &GetPDFCalc()const; /// Get the observed PDF const CrystVector_REAL &GetPDFObs()const; /// Get the r coordinates (in Angstroem) for the PDF const CrystVector_REAL &GetPDFR()const; /// Add PDF phase void AddPDFPhase(PDFPhase &phase); private: /// Radiation type RadiationType mRadiationType; /// r coordinates (in Angstroem) of the PDF CrystVector_REAL mPDFR; /// The PDF itself,calculated mutable CrystVector_REAL mPDFCalc; /// The PDF itself,observed CrystVector_REAL mPDFObs; /// Contributions to the PDF, with their scale factor std::list > mvPDFPhase; #ifdef __WX__CRYST__ public: virtual WXCrystObjBasic* WXCreate(wxWindow*); #endif }; /// Global registry for all PDF objects extern ObjRegistry gPDFRegistry; /** Contribution to a PDF * * Right now this can only be a PDFCrystal. */ class PDFPhase:public RefinableObj { public: /// Constructor PDFPhase(const PDF &pdf); /// Get the calculated PDF const CrystVector_REAL &GetPDFCalc()const; protected: /// Calculate the pdf virtual void CalcPDF()const=0; /// Parent PDF const PDF *mpPDF; /// The calculated PDF mutable CrystVector_REAL mPDFCalc; #ifdef __WX__CRYST__ public: virtual WXCrystObjBasic* WXCreate(wxWindow*)=0; #endif }; /** Class for Pair Distribution Function calculations for a single Crystal object * */ class PDFCrystal:public PDFPhase { public: /// Constructor PDFCrystal(const PDF &pdf, const Crystal &cryst); private: /// Initialize all parameters void Init(const PDF &pdf, const Crystal &cryst); /// Calculate the pdf virtual void CalcPDF()const; /// The Crystal const Crystal *mpCrystal; // Parameters to describe the PDF /// Parameters affecting the width & intensity of peaks REAL mDelta1,mDelta2,mQbroad,mQdamp; // Cached data to speed up computations /// Container of temp data for each atom struct pdfAtom { /// default constructor pdfAtom(); /// Fractionnal & cartesian unique coordinates REAL fx0,fy0,fz0,x0,y0,z0; /// The scattering power const ScatteringPower *pScattPow; /// Scattering amplitudes, multiplied by occupancy REAL occupBi; /// Has this atom changed since last time ? bool hasChanged; /// List of all equivalent & translated positions, /// in cartesian coordinates CrystVector_REAL x,y,z; }; /// List of all temp data mutable std::vector mvPDFAtom; #ifdef __WX__CRYST__ public: virtual WXCrystObjBasic* WXCreate(wxWindow*); #endif }; }//namespace #endif objcryst-2022.1/ObjCryst/ObjCryst/Polyhedron.cpp000066400000000000000000000452351430515525000215750ustar00rootroot00000000000000#include "ObjCryst/ObjCryst/Polyhedron.h" namespace ObjCryst { Molecule* MakeTetrahedron(Crystal &cryst,const string &name, const ScatteringPower *centralAtom, const ScatteringPower *peripheralAtom, const REAL dist) { Molecule *mol=new Molecule(cryst,name); mol->AddAtom(0.,0.,0.,centralAtom,centralAtom->GetName()); mol->AddAtom(0.,0.,dist,peripheralAtom,peripheralAtom->GetName()+"1"); mol->AddAtom(0.,dist*0.943,-dist*0.333,peripheralAtom,peripheralAtom->GetName()+"2"); mol->AddAtom(dist*0.817,-dist*0.472,-dist*0.333,peripheralAtom,peripheralAtom->GetName()+"3"); mol->AddAtom(-dist*0.817,-dist*0.472,-dist*0.333,peripheralAtom,peripheralAtom->GetName()+"4"); mol->AddBond(mol->GetAtom(0),mol->GetAtom(1),dist,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(2),dist,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(3),dist,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(4),dist,0.01,0.05); mol->AddBondAngle(mol->GetAtom(1),mol->GetAtom(0),mol->GetAtom(2),109.5*DEG2RAD,0.01,0.05); mol->AddBondAngle(mol->GetAtom(1),mol->GetAtom(0),mol->GetAtom(3),109.5*DEG2RAD,0.01,0.05); mol->AddBondAngle(mol->GetAtom(1),mol->GetAtom(0),mol->GetAtom(4),109.5*DEG2RAD,0.01,0.05); mol->AddBondAngle(mol->GetAtom(2),mol->GetAtom(0),mol->GetAtom(3),109.5*DEG2RAD,0.01,0.05); mol->AddBondAngle(mol->GetAtom(2),mol->GetAtom(0),mol->GetAtom(4),109.5*DEG2RAD,0.01,0.05); mol->AddBondAngle(mol->GetAtom(3),mol->GetAtom(0),mol->GetAtom(4),109.5*DEG2RAD,0.01,0.05); return mol; } Molecule* MakeOctahedron(Crystal &cryst,const string &name, const ScatteringPower *centralAtom, const ScatteringPower *peripheralAtom, const REAL dist) { Molecule *mol=new Molecule(cryst,name); mol->AddAtom(0.,0.,0.,centralAtom,centralAtom->GetName()); mol->AddAtom(0.,0.,dist,peripheralAtom,peripheralAtom->GetName()+"1"); mol->AddAtom(dist,0.,0.,peripheralAtom,peripheralAtom->GetName()+"2"); mol->AddAtom(0.,dist,0.,peripheralAtom,peripheralAtom->GetName()+"3"); mol->AddAtom(-dist,0.,0.,peripheralAtom,peripheralAtom->GetName()+"4"); mol->AddAtom(0.,-dist,0.,peripheralAtom,peripheralAtom->GetName()+"5"); mol->AddAtom(0.,0.,-dist,peripheralAtom,peripheralAtom->GetName()+"6"); mol->AddBond(mol->GetAtom(0),mol->GetAtom(1),dist,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(2),dist,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(3),dist,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(4),dist,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(5),dist,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(6),dist,0.01,0.05); mol->AddBondAngle(mol->GetAtom(1),mol->GetAtom(0),mol->GetAtom(2),M_PI/2.,0.01,0.05); mol->AddBondAngle(mol->GetAtom(1),mol->GetAtom(0),mol->GetAtom(3),M_PI/2.,0.01,0.05); mol->AddBondAngle(mol->GetAtom(1),mol->GetAtom(0),mol->GetAtom(4),M_PI/2.,0.01,0.05); mol->AddBondAngle(mol->GetAtom(1),mol->GetAtom(0),mol->GetAtom(5),M_PI/2.,0.01,0.05); mol->AddBondAngle(mol->GetAtom(6),mol->GetAtom(0),mol->GetAtom(2),M_PI/2.,0.01,0.05); mol->AddBondAngle(mol->GetAtom(6),mol->GetAtom(0),mol->GetAtom(3),M_PI/2.,0.01,0.05); mol->AddBondAngle(mol->GetAtom(6),mol->GetAtom(0),mol->GetAtom(4),M_PI/2.,0.01,0.05); mol->AddBondAngle(mol->GetAtom(6),mol->GetAtom(0),mol->GetAtom(5),M_PI/2.,0.01,0.05); mol->AddBondAngle(mol->GetAtom(2),mol->GetAtom(0),mol->GetAtom(3),M_PI/2.,0.01,0.05); mol->AddBondAngle(mol->GetAtom(3),mol->GetAtom(0),mol->GetAtom(4),M_PI/2.,0.01,0.05); mol->AddBondAngle(mol->GetAtom(4),mol->GetAtom(0),mol->GetAtom(5),M_PI/2.,0.01,0.05); mol->AddBondAngle(mol->GetAtom(5),mol->GetAtom(0),mol->GetAtom(2),M_PI/2.,0.01,0.05); return mol; } Molecule* MakeSquarePlane(Crystal &cryst,const string &name, const ScatteringPower *centralAtom, const ScatteringPower *peripheralAtom, const REAL d) { Molecule *mol=new Molecule(cryst,name); mol->AddAtom(0.,0.,0.,centralAtom,centralAtom->GetName()); mol->AddAtom( d,0.,0.,peripheralAtom,peripheralAtom->GetName()+"1"); mol->AddAtom(0., d,0.,peripheralAtom,peripheralAtom->GetName()+"2"); mol->AddAtom(-d,0.,0.,peripheralAtom,peripheralAtom->GetName()+"3"); mol->AddAtom(0.,-d,0.,peripheralAtom,peripheralAtom->GetName()+"4"); mol->AddBond(mol->GetAtom(0),mol->GetAtom(1),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(2),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(3),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(4),d,0.01,0.05); mol->AddBondAngle(mol->GetAtom(1),mol->GetAtom(0),mol->GetAtom(2),M_PI/2.,0.01,0.05); mol->AddBondAngle(mol->GetAtom(2),mol->GetAtom(0),mol->GetAtom(3),M_PI/2.,0.01,0.05); mol->AddBondAngle(mol->GetAtom(3),mol->GetAtom(0),mol->GetAtom(4),M_PI/2.,0.01,0.05); mol->AddBondAngle(mol->GetAtom(4),mol->GetAtom(0),mol->GetAtom(1),M_PI/2.,0.01,0.05); return mol; } Molecule* MakeCube(Crystal &cryst,const string &name, const ScatteringPower *centralAtom, const ScatteringPower *peripheralAtom, const REAL d) { Molecule *mol=new Molecule(cryst,name); const REAL d0=d/sqrt(3.); mol->AddAtom(0.,0.,0.,centralAtom,centralAtom->GetName()); mol->AddAtom( d0,-d0, d0,peripheralAtom,peripheralAtom->GetName()+"1"); mol->AddAtom( d0, d0, d0,peripheralAtom,peripheralAtom->GetName()+"2"); mol->AddAtom(-d0, d0, d0,peripheralAtom,peripheralAtom->GetName()+"3"); mol->AddAtom(-d0,-d0, d0,peripheralAtom,peripheralAtom->GetName()+"4"); mol->AddAtom( d0,-d0,-d0,peripheralAtom,peripheralAtom->GetName()+"5"); mol->AddAtom( d0, d0,-d0,peripheralAtom,peripheralAtom->GetName()+"6"); mol->AddAtom(-d0, d0,-d0,peripheralAtom,peripheralAtom->GetName()+"7"); mol->AddAtom(-d0,-d0,-d0,peripheralAtom,peripheralAtom->GetName()+"8"); mol->AddBond(mol->GetAtom(0),mol->GetAtom(1),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(2),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(3),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(4),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(5),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(6),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(7),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(8),d,0.01,0.05); mol->AddBond(mol->GetAtom(1),mol->GetAtom(2),2*d0,0.01,0.05); mol->AddBond(mol->GetAtom(2),mol->GetAtom(3),2*d0,0.01,0.05); mol->AddBond(mol->GetAtom(3),mol->GetAtom(4),2*d0,0.01,0.05); mol->AddBond(mol->GetAtom(4),mol->GetAtom(1),2*d0,0.01,0.05); mol->AddBond(mol->GetAtom(5),mol->GetAtom(6),2*d0,0.01,0.05); mol->AddBond(mol->GetAtom(6),mol->GetAtom(7),2*d0,0.01,0.05); mol->AddBond(mol->GetAtom(7),mol->GetAtom(8),2*d0,0.01,0.05); mol->AddBond(mol->GetAtom(8),mol->GetAtom(5),2*d0,0.01,0.05); mol->AddBond(mol->GetAtom(1),mol->GetAtom(5),2*d0,0.01,0.05); mol->AddBond(mol->GetAtom(2),mol->GetAtom(6),2*d0,0.01,0.05); mol->AddBond(mol->GetAtom(3),mol->GetAtom(7),2*d0,0.01,0.05); mol->AddBond(mol->GetAtom(4),mol->GetAtom(8),2*d0,0.01,0.05); #if 0 const REAL a=2*atan(1/sqrt(2.)); mol->AddBondAngle(mol->GetAtom(1),mol->GetAtom(0),mol->GetAtom(2),a,0.01,0.05); mol->AddBondAngle(mol->GetAtom(2),mol->GetAtom(0),mol->GetAtom(3),a,0.01,0.05); mol->AddBondAngle(mol->GetAtom(3),mol->GetAtom(0),mol->GetAtom(4),a,0.01,0.05); mol->AddBondAngle(mol->GetAtom(4),mol->GetAtom(0),mol->GetAtom(1),a,0.01,0.05); mol->AddBondAngle(mol->GetAtom(5),mol->GetAtom(0),mol->GetAtom(6),a,0.01,0.05); mol->AddBondAngle(mol->GetAtom(6),mol->GetAtom(0),mol->GetAtom(7),a,0.01,0.05); mol->AddBondAngle(mol->GetAtom(7),mol->GetAtom(0),mol->GetAtom(8),a,0.01,0.05); mol->AddBondAngle(mol->GetAtom(8),mol->GetAtom(0),mol->GetAtom(1),a,0.01,0.05); mol->AddBondAngle(mol->GetAtom(1),mol->GetAtom(0),mol->GetAtom(5),a,0.01,0.05); mol->AddBondAngle(mol->GetAtom(2),mol->GetAtom(0),mol->GetAtom(6),a,0.01,0.05); mol->AddBondAngle(mol->GetAtom(3),mol->GetAtom(0),mol->GetAtom(7),a,0.01,0.05); mol->AddBondAngle(mol->GetAtom(4),mol->GetAtom(0),mol->GetAtom(8),a,0.01,0.05); #endif return mol; } Molecule* MakeAntiPrismTetragonal(Crystal &cryst,const string &name, const ScatteringPower *centralAtom, const ScatteringPower *peripheralAtom, const REAL d) { Molecule *mol=new Molecule(cryst,name); const REAL d0=d/sqrt(3.); mol->AddAtom(0.,0.,0.,centralAtom,centralAtom->GetName()); mol->AddAtom( d0,-d0, d0,peripheralAtom,peripheralAtom->GetName()+"1"); mol->AddAtom( d0, d0, d0,peripheralAtom,peripheralAtom->GetName()+"2"); mol->AddAtom(-d0, d0, d0,peripheralAtom,peripheralAtom->GetName()+"3"); mol->AddAtom(-d0,-d0, d0,peripheralAtom,peripheralAtom->GetName()+"4"); mol->AddAtom( d0*sqrt(2.),0.,-d0,peripheralAtom,peripheralAtom->GetName()+"5"); mol->AddAtom(0., d0*sqrt(2.),-d0,peripheralAtom,peripheralAtom->GetName()+"6"); mol->AddAtom(-d0*sqrt(2.),0.,-d0,peripheralAtom,peripheralAtom->GetName()+"7"); mol->AddAtom(0.,-d0*sqrt(2.),-d0,peripheralAtom,peripheralAtom->GetName()+"8"); mol->AddBond(mol->GetAtom(0),mol->GetAtom(1),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(2),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(3),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(4),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(5),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(6),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(7),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(8),d,0.01,0.05); mol->AddBond(mol->GetAtom(1),mol->GetAtom(2),2*d0,0.01,0.05); mol->AddBond(mol->GetAtom(2),mol->GetAtom(3),2*d0,0.01,0.05); mol->AddBond(mol->GetAtom(3),mol->GetAtom(4),2*d0,0.01,0.05); mol->AddBond(mol->GetAtom(4),mol->GetAtom(1),2*d0,0.01,0.05); mol->AddBond(mol->GetAtom(5),mol->GetAtom(6),2*d0,0.01,0.05); mol->AddBond(mol->GetAtom(6),mol->GetAtom(7),2*d0,0.01,0.05); mol->AddBond(mol->GetAtom(7),mol->GetAtom(8),2*d0,0.01,0.05); mol->AddBond(mol->GetAtom(8),mol->GetAtom(5),2*d0,0.01,0.05); mol->AddBond(mol->GetAtom(5),mol->GetAtom(1),d0*sqrt(5.),0.01,0.05); mol->AddBond(mol->GetAtom(5),mol->GetAtom(2),d0*sqrt(5.),0.01,0.05); mol->AddBond(mol->GetAtom(6),mol->GetAtom(2),d0*sqrt(5.),0.01,0.05); mol->AddBond(mol->GetAtom(6),mol->GetAtom(3),d0*sqrt(5.),0.01,0.05); mol->AddBond(mol->GetAtom(7),mol->GetAtom(3),d0*sqrt(5.),0.01,0.05); mol->AddBond(mol->GetAtom(7),mol->GetAtom(4),d0*sqrt(5.),0.01,0.05); mol->AddBond(mol->GetAtom(8),mol->GetAtom(4),d0*sqrt(5.),0.01,0.05); mol->AddBond(mol->GetAtom(8),mol->GetAtom(1),d0*sqrt(5.),0.01,0.05); #if 0 const REAL a=2*atan(1/sqrt(2.)); mol->AddBondAngle(mol->GetAtom(1),mol->GetAtom(0),mol->GetAtom(2),a,0.01,0.05); mol->AddBondAngle(mol->GetAtom(2),mol->GetAtom(0),mol->GetAtom(3),a,0.01,0.05); mol->AddBondAngle(mol->GetAtom(3),mol->GetAtom(0),mol->GetAtom(4),a,0.01,0.05); mol->AddBondAngle(mol->GetAtom(4),mol->GetAtom(0),mol->GetAtom(1),a,0.01,0.05); mol->AddBondAngle(mol->GetAtom(5),mol->GetAtom(0),mol->GetAtom(6),a,0.01,0.05); mol->AddBondAngle(mol->GetAtom(6),mol->GetAtom(0),mol->GetAtom(7),a,0.01,0.05); mol->AddBondAngle(mol->GetAtom(7),mol->GetAtom(0),mol->GetAtom(8),a,0.01,0.05); mol->AddBondAngle(mol->GetAtom(8),mol->GetAtom(0),mol->GetAtom(1),a,0.01,0.05); mol->AddBondAngle(mol->GetAtom(1),mol->GetAtom(0),mol->GetAtom(5),a,0.01,0.05); mol->AddBondAngle(mol->GetAtom(2),mol->GetAtom(0),mol->GetAtom(6),a,0.01,0.05); mol->AddBondAngle(mol->GetAtom(3),mol->GetAtom(0),mol->GetAtom(7),a,0.01,0.05); mol->AddBondAngle(mol->GetAtom(4),mol->GetAtom(0),mol->GetAtom(8),a,0.01,0.05); #endif return mol; } Molecule* MakePrismTrigonal(Crystal &cryst,const string &name, const ScatteringPower *centralAtom, const ScatteringPower *peripheralAtom, const REAL d) { const REAL a=sqrt(3./7.)*d; const REAL a1=a*2./sqrt(3.); Molecule *mol=new Molecule(cryst,name); mol->AddAtom(0.,0.,0.,centralAtom,centralAtom->GetName()); mol->AddAtom( a1 ,0. , a,peripheralAtom,peripheralAtom->GetName()+"1"); mol->AddAtom(-a1/2., a1*sqrt(3.)/2., a,peripheralAtom,peripheralAtom->GetName()+"2"); mol->AddAtom(-a1/2.,-a1*sqrt(3.)/2., a,peripheralAtom,peripheralAtom->GetName()+"3"); mol->AddAtom( a1 ,0. ,-a,peripheralAtom,peripheralAtom->GetName()+"4"); mol->AddAtom(-a1/2., a1*sqrt(3.)/2.,-a,peripheralAtom,peripheralAtom->GetName()+"5"); mol->AddAtom(-a1/2.,-a1*sqrt(3.)/2.,-a,peripheralAtom,peripheralAtom->GetName()+"6"); mol->AddBond(mol->GetAtom(0),mol->GetAtom(1),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(2),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(3),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(4),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(5),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(6),d,0.01,0.05); mol->AddBond(mol->GetAtom(1),mol->GetAtom(2),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(1),mol->GetAtom(3),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(2),mol->GetAtom(3),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(4),mol->GetAtom(5),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(4),mol->GetAtom(6),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(5),mol->GetAtom(6),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(1),mol->GetAtom(4),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(2),mol->GetAtom(5),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(3),mol->GetAtom(6),2*a,0.01,0.05); return mol; } Molecule* MakeIcosahedron(Crystal &cryst,const string &name, const ScatteringPower *centralAtom, const ScatteringPower *peripheralAtom, const REAL d) { Molecule *mol=new Molecule(cryst,name); const REAL g0=(1.+sqrt(5.))/2.; const REAL a=d/sqrt(1.+g0*g0); const REAL g=g0*a; mol->AddAtom(0.,0.,0.,centralAtom,centralAtom->GetName()); mol->AddAtom(0., g, a,peripheralAtom,peripheralAtom->GetName()+"1"); mol->AddAtom(0., g,-a,peripheralAtom,peripheralAtom->GetName()+"2"); mol->AddAtom(0.,-g, a,peripheralAtom,peripheralAtom->GetName()+"3"); mol->AddAtom(0.,-g,-a,peripheralAtom,peripheralAtom->GetName()+"4"); mol->AddAtom( a,0., g,peripheralAtom,peripheralAtom->GetName()+"5"); mol->AddAtom(-a,0., g,peripheralAtom,peripheralAtom->GetName()+"6"); mol->AddAtom( a,0.,-g,peripheralAtom,peripheralAtom->GetName()+"7"); mol->AddAtom(-a,0.,-g,peripheralAtom,peripheralAtom->GetName()+"8"); mol->AddAtom( g, a,0.,peripheralAtom,peripheralAtom->GetName()+"9"); mol->AddAtom( g,-a,0.,peripheralAtom,peripheralAtom->GetName()+"10"); mol->AddAtom(-g, a,0.,peripheralAtom,peripheralAtom->GetName()+"11"); mol->AddAtom(-g,-a,0.,peripheralAtom,peripheralAtom->GetName()+"12"); mol->AddBond(mol->GetAtom(0),mol->GetAtom(1),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(2),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(3),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(4),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(5),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(6),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(7),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(8),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(9),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(10),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(11),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(12),d,0.01,0.05); mol->AddBond(mol->GetAtom(1),mol->GetAtom(2),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(1),mol->GetAtom(11),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(1),mol->GetAtom(6),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(1),mol->GetAtom(5),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(1),mol->GetAtom(9),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(2),mol->GetAtom(11),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(11),mol->GetAtom(6),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(6),mol->GetAtom(5),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(5),mol->GetAtom(9),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(9),mol->GetAtom(2),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(4),mol->GetAtom(3),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(4),mol->GetAtom(12),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(4),mol->GetAtom(8),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(4),mol->GetAtom(7),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(4),mol->GetAtom(10),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(3),mol->GetAtom(12),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(12),mol->GetAtom(8),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(8),mol->GetAtom(7),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(7),mol->GetAtom(10),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(10),mol->GetAtom(3),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(3),mol->GetAtom(5),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(3),mol->GetAtom(6),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(12),mol->GetAtom(6),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(12),mol->GetAtom(11),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(8),mol->GetAtom(11),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(8),mol->GetAtom(2),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(7),mol->GetAtom(2),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(7),mol->GetAtom(9),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(10),mol->GetAtom(9),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(10),mol->GetAtom(5),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(3),mol->GetAtom(5),2*a,0.01,0.05); mol->AddBond(mol->GetAtom(3),mol->GetAtom(6),2*a,0.01,0.05); return mol; } Molecule* MakeTriangle(Crystal &cryst,const string &name, const ScatteringPower *centralAtom, const ScatteringPower *peripheralAtom, const REAL d) { Molecule *mol=new Molecule(cryst,name); mol->AddAtom(0.,0.,0.,centralAtom,centralAtom->GetName()); mol->AddAtom(d,0.,0.,peripheralAtom,peripheralAtom->GetName()+"1"); mol->AddAtom(-d/2., d*sqrt(3.)/2,0.,peripheralAtom,peripheralAtom->GetName()+"2"); mol->AddAtom(-d/2.,-d*sqrt(3.)/2,0.,peripheralAtom,peripheralAtom->GetName()+"3"); mol->AddBond(mol->GetAtom(0),mol->GetAtom(1),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(2),d,0.01,0.05); mol->AddBond(mol->GetAtom(0),mol->GetAtom(3),d,0.01,0.05); mol->AddBondAngle(mol->GetAtom(1),mol->GetAtom(0),mol->GetAtom(2),M_PI/3.*2.,0.01,0.05); mol->AddBondAngle(mol->GetAtom(1),mol->GetAtom(0),mol->GetAtom(3),M_PI/3.*2.,0.01,0.05); mol->AddBondAngle(mol->GetAtom(2),mol->GetAtom(0),mol->GetAtom(3),M_PI/3.*2.,0.01,0.05); return mol; } }//namespace objcryst-2022.1/ObjCryst/ObjCryst/Polyhedron.h000066400000000000000000000054111430515525000212320ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Polyhedron.h * header file for the Polyhdron creation * */ #include "ObjCryst/ObjCryst/ScatteringPower.h" #include "ObjCryst/ObjCryst/Crystal.h" #include "ObjCryst/ObjCryst/Molecule.h" namespace ObjCryst { Molecule* MakeTetrahedron(Crystal &cryst,const string &name, const ScatteringPower *centralAtom, const ScatteringPower *peripheralAtom, const REAL dist); Molecule* MakeOctahedron(Crystal &cryst,const string &name, const ScatteringPower *centralAtom, const ScatteringPower *peripheralAtom, const REAL dist); Molecule* MakeSquarePlane(Crystal &cryst,const string &name, const ScatteringPower *centralAtom, const ScatteringPower *peripheralAtom, const REAL dist); Molecule* MakeCube(Crystal &cryst,const string &name, const ScatteringPower *centralAtom, const ScatteringPower *peripheralAtom, const REAL dist); Molecule* MakeAntiPrismTetragonal(Crystal &cryst,const string &name, const ScatteringPower *centralAtom, const ScatteringPower *peripheralAtom, const REAL dist); Molecule* MakePrismTrigonal(Crystal &cryst,const string &name, const ScatteringPower *centralAtom, const ScatteringPower *peripheralAtom, const REAL dist); Molecule* MakeIcosahedron(Crystal &cryst,const string &name, const ScatteringPower *centralAtom, const ScatteringPower *peripheralAtom, const REAL dist); Molecule* MakeTriangle(Crystal &cryst,const string &name, const ScatteringPower *centralAtom, const ScatteringPower *peripheralAtom, const REAL dist); }//namespace objcryst-2022.1/ObjCryst/ObjCryst/PowderPattern.cpp000066400000000000000000010311271430515525000222440ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * source file for LibCryst++ PowderPattern class * */ #include #include #include //for sprintf() #include #include "cctbx/sgtbx/space_group.h" // For fullprof export #include "ObjCryst/ObjCryst/PowderPattern.h" #include "ObjCryst/ObjCryst/Molecule.h" // For fullprof export #include "ObjCryst/ObjCryst/PowderPatternBackgroundBayesianMinimiser.h" #include "ObjCryst/RefinableObj/Simplex.h" #include "ObjCryst/Quirks/VFNDebug.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" #include "ObjCryst/ObjCryst/CIF.h" #include "ObjCryst/Quirks/Chronometer.h" #ifdef __WX__CRYST__ #include "ObjCryst/wxCryst/wxPowderPattern.h" #endif #include #include #include #ifdef _MSC_VER // MS VC++ predefined macros.... #undef min #undef max #endif //#define USE_BACKGROUND_MAXLIKE_ERROR #define POSSIBLY_UNUSED(expr) (void)(expr) namespace ObjCryst { //////////////////////////////////////////////////////////////////////// // // Cylinder absorption correction // //////////////////////////////////////////////////////////////////////// CylinderAbsCorr::CylinderAbsCorr(const PowderPatternDiffraction & data): ScatteringCorr(data), mpPowderPatternDiff(&data) {} CylinderAbsCorr::~CylinderAbsCorr() {} const string & CylinderAbsCorr::GetName() const { //So far, we do not need a personalized name... const static string mName="CylinderAbsCorr"; return mName; } const string & CylinderAbsCorr::GetClassName() const { const static string className="CylinderAbsCorr"; return className; } void CylinderAbsCorr::CalcCorr() const { mpData->GetTheta(); // Make sure theta is up-to-date if((mpPowderPatternDiff->GetParentPowderPattern().GetClockPowderPatternAbsCorr() < mClockCorrCalc) && (mpData->GetClockTheta()GetNbRefl()); const REAL muR = mpPowderPatternDiff->GetParentPowderPattern().GetMuR(); if(muR == 0) { mCorr = 1; return; } for(long i=0;iGetNbRefl();i++) { const REAL s2 = pow(sin(mpData->GetTheta()(i)),2); if(muR<=3) { const REAL t0 = 16.0/(3.*M_PI); const REAL t1 = (25.99978-0.01911*pow(s2,0.25))*exp(-0.024551*s2)+ 0.109561*sqrt(s2)-26.04556; const REAL t2 = -0.02489-0.39499*s2+1.219077*pow(s2,1.5)- 1.31268*pow(s2,2)+0.871081*pow(s2,2.5)-0.2327*pow(s2,3); const REAL t3 = 0.003045+0.018167*s2-0.03305*pow(s2,2); const REAL t = -t0*muR-t1*pow(muR,2)-t2*pow(muR,3)-t3*pow(muR,4); mCorr(i) = exp(t); } else { const REAL t1 = 1.433902+11.07504*s2-8.77629*s2*s2+ 10.02088*s2*s2*s2-3.36778*s2*s2*s2*s2; const REAL t2 = (0.013869-0.01249*s2)*exp(3.27094*s2)+ (0.337894+13.77317*s2)/pow(1.0+11.53544*s2, 1.555039); const REAL t3 = 1.933433/pow(1.0+23.12967*s2, 1.686715) -0.13576*sqrt(s2)+1.163198; const REAL t4 = 0.044365-0.04259/pow(1.0+0.41051*s2, 148.4202); const REAL t = (t1-t4)/pow(1+t2*(muR-3),t3)+t4; mCorr(i) = t/100; } } mClockCorrCalc.Click(); } //////////////////////////////////////////////////////////////////////// // // PowderPatternComponent // //////////////////////////////////////////////////////////////////////// ObjRegistry gPowderPatternComponentRegistry("List of all PowderPattern Components"); PowderPatternComponent::PowderPatternComponent(): mIsScalable(false),mpParentPowderPattern(0) { gPowderPatternComponentRegistry.Register(*this); mClockMaster.AddChild(mClockBraggLimits); } PowderPatternComponent::PowderPatternComponent(const PowderPatternComponent &old): mIsScalable(old.mIsScalable), mpParentPowderPattern(old.mpParentPowderPattern) { mClockMaster.AddChild(mClockBraggLimits); if(mpParentPowderPattern!=0) { mClockMaster.AddChild(mpParentPowderPattern->GetClockPowderPatternPar()); mClockMaster.AddChild(mpParentPowderPattern->GetClockPowderPatternXCorr()); mClockMaster.AddChild(mpParentPowderPattern->GetClockPowderPatternRadiation()); } } PowderPatternComponent::~PowderPatternComponent() { gPowderPatternComponentRegistry.DeRegister(*this); } const string& PowderPatternComponent::GetClassName() const { const static string className="PowderPatternComponent"; return className; } const PowderPattern& PowderPatternComponent::GetParentPowderPattern()const { return *mpParentPowderPattern; } std::map& PowderPatternComponent::GetPowderPattern_FullDeriv(std::set &vPar) { this->CalcPowderPattern_FullDeriv(vPar); return mPowderPattern_FullDeriv; } std::map& PowderPatternComponent::GetPowderPatternIntegrated_FullDeriv(std::set &vPar) { this->CalcPowderPatternIntegrated_FullDeriv(vPar); return mPowderPatternIntegrated_FullDeriv; } PowderPattern& PowderPatternComponent::GetParentPowderPattern() { return *mpParentPowderPattern; } bool PowderPatternComponent::IsScalable()const {return mIsScalable;} const RefinableObjClock& PowderPatternComponent::GetClockPowderPatternCalc()const { return mClockPowderPatternCalc; } const RefinableObjClock& PowderPatternComponent::GetClockBraggLimits()const { return mClockBraggLimits; } const list >& PowderPatternComponent::GetPatternLabelList()const { return mvLabel; } void PowderPatternComponent::CalcPowderPattern_FullDeriv(std::set &vPar) { TAU_PROFILE("PowderPatternComponent::CalcPowderPattern_FullDeriv()","void ()",TAU_DEFAULT); mPowderPattern_FullDeriv.clear(); for(std::set::iterator par=vPar.begin();par!=vPar.end();par++) { if(*par==0) { mPowderPattern_FullDeriv[*par]=this->GetPowderPatternCalc(); continue; } const REAL step=(*par)->GetDerivStep(); (*par)->Mutate(step); mPowderPattern_FullDeriv[*par] =this->GetPowderPatternCalc(); (*par)->Mutate(-2*step); mPowderPattern_FullDeriv[*par]-=this->GetPowderPatternCalc(); (*par)->Mutate(step); mPowderPattern_FullDeriv[*par]/= step*2; if(MaxAbs(mPowderPattern_FullDeriv[*par])==0) mPowderPattern_FullDeriv[*par].resize(0); } } void PowderPatternComponent::CalcPowderPatternIntegrated_FullDeriv(std::set &vPar) { TAU_PROFILE("PowderPatternComponent::CalcPowderPatternIntegrated_FullDeriv()","void ()",TAU_DEFAULT); mPowderPatternIntegrated_FullDeriv.clear(); for(std::set::iterator par=vPar.begin();par!=vPar.end();par++) { if(*par==0) { mPowderPatternIntegrated_FullDeriv[*par]=*(this->GetPowderPatternIntegratedCalc().first); continue; } const REAL step=(*par)->GetDerivStep(); (*par)->Mutate(step); mPowderPatternIntegrated_FullDeriv[*par] =*(this->GetPowderPatternIntegratedCalc().first); (*par)->Mutate(-2*step); mPowderPatternIntegrated_FullDeriv[*par]-=*(this->GetPowderPatternIntegratedCalc().first); (*par)->Mutate(step); mPowderPatternIntegrated_FullDeriv[*par]/= step*2; if(MaxAbs(mPowderPatternIntegrated_FullDeriv[*par])==0) mPowderPatternIntegrated_FullDeriv[*par].resize(0); } } //////////////////////////////////////////////////////////////////////// // // PowderPatternBackground // //////////////////////////////////////////////////////////////////////// PowderPatternBackground::PowderPatternBackground(): mBackgroundNbPoint(0), mMaxSinThetaOvLambda(10),mModelVariance(0) { mClockMaster.AddChild(mClockBackgroundPoint); this->InitOptions(); } PowderPatternBackground::PowderPatternBackground(const PowderPatternBackground &old): mBackgroundNbPoint(old.mBackgroundNbPoint), mBackgroundInterpPointX(old.mBackgroundInterpPointX), mBackgroundInterpPointIntensity(old.mBackgroundInterpPointIntensity), mMaxSinThetaOvLambda(10),mModelVariance(0) { mClockMaster.AddChild(mClockBackgroundPoint); this->InitOptions(); mInterpolationModel.SetChoice(old.mInterpolationModel.GetChoice()); } PowderPatternBackground::~PowderPatternBackground(){} const string& PowderPatternBackground::GetClassName() const { const static string className="PowderPatternBackground"; return className; } void PowderPatternBackground::SetParentPowderPattern(PowderPattern &s) { if(mpParentPowderPattern!=0) mClockMaster.RemoveChild(mpParentPowderPattern->GetIntegratedProfileLimitsClock()); mpParentPowderPattern = &s; mClockMaster.AddChild(mpParentPowderPattern->GetIntegratedProfileLimitsClock()); mClockMaster.AddChild(mpParentPowderPattern->GetClockPowderPatternPar()); mClockMaster.AddChild(mpParentPowderPattern->GetClockPowderPatternXCorr()); mClockMaster.AddChild(mpParentPowderPattern->GetClockPowderPatternRadiation()); } const CrystVector_REAL& PowderPatternBackground::GetPowderPatternCalc()const { this->CalcPowderPattern(); return mPowderPatternCalc; } pair PowderPatternBackground::GetPowderPatternIntegratedCalc()const { VFN_DEBUG_MESSAGE("PowderPatternBackground::GetPowderPatternIntegratedCalc()",3) this->CalcPowderPatternIntegrated(); return make_pair(&mPowderPatternIntegratedCalc,&mClockPowderPatternIntegratedCalc); } void PowderPatternBackground::ImportUserBackground(const string &filename) { VFN_DEBUG_MESSAGE("PowderPatternBackground::ImportUserBackground():"<> bckgd2Theta(nbPoints); fin >> bckgd(nbPoints); if(!fin) break; VFN_DEBUG_MESSAGE("Background=" << bckgd(nbPoints)\ <<" at 2theta="<GetParentPowderPattern().GetRadiation().GetWavelengthType()==WAVELENGTH_MONOCHROMATIC) ||(this->GetParentPowderPattern().GetRadiation().GetWavelengthType()==WAVELENGTH_ALPHA12)) bckgd2Theta*= DEG2RAD; } else bckgd2Theta*= DEG2RAD; this->SetInterpPoints(bckgd2Theta,bckgd); this->InitRefParList(); mClockBackgroundPoint.Click(); { char buf [200]; sprintf(buf,"Imported %d background points",(int)nbPoints); (*fpObjCrystInformUser)((string)buf); } this->UpdateDisplay(); VFN_DEBUG_MESSAGE("PowderPatternBackground::ImportUserBackground():finished",5) } void PowderPatternBackground::SetInterpPoints(const CrystVector_REAL tth, const CrystVector_REAL backgd) { VFN_DEBUG_ENTRY("PowderPatternBackground::SetInterpPoints():",5) if( (tth.numElements()!=backgd.numElements()) ||(tth.numElements()<2)) { throw ObjCrystException("PowderPatternBackground::SetInterpPoints() : \ number of points differ or less than 2 points !"); } mBackgroundNbPoint=tth.numElements(); mBackgroundInterpPointX.resize(mBackgroundNbPoint); mBackgroundInterpPointIntensity.resize(mBackgroundNbPoint); // Sort in ascending order, disregarding radiation type. CrystVector subs; subs=SortSubs(tth); for(long i=0;iInitRefParList(); mClockBackgroundPoint.Click(); VFN_DEBUG_EXIT("PowderPatternBackground::SetInterpPoints()",5) } const pair PowderPatternBackground::GetInterpPoints()const { return make_pair(&mBackgroundInterpPointX,&mBackgroundInterpPointIntensity); } void PowderPatternBackground::GetGeneGroup(const RefinableObj &obj, CrystVector_uint & groupIndex, unsigned int &first) const { // One group for all background points unsigned int index=0; VFN_DEBUG_MESSAGE("PowderPatternBackground::GetGeneGroup()",4) for(long i=0;iGetNbPar();j++) if(&(obj.GetPar(i)) == &(this->GetPar(j))) { if(index==0) index=first++; groupIndex(i)=index; } } void PowderPatternBackground::BeginOptimization(const bool allowApproximations, const bool enableRestraints) { this->RefinableObj::BeginOptimization(allowApproximations,enableRestraints); } const CrystVector_REAL& PowderPatternBackground::GetPowderPatternCalcVariance()const { this->CalcPowderPattern(); return mPowderPatternCalcVariance; } pair PowderPatternBackground::GetPowderPatternIntegratedCalcVariance()const { this->CalcPowderPatternIntegrated(); return make_pair(&mPowderPatternIntegratedCalcVariance, &mClockPowderPatternIntegratedVarianceCalc); } bool PowderPatternBackground::HasPowderPatternCalcVariance()const { #ifdef USE_BACKGROUND_MAXLIKE_ERROR return true; #else return false; #endif } void PowderPatternBackground::TagNewBestConfig()const { } void PowderPatternBackground::OptimizeBayesianBackground() { VFN_DEBUG_ENTRY("PowderPatternBackground::OptimizeBayesianBackground()",5); TAU_PROFILE("PowderPatternBackground::OptimizeBayesianBackground()","void ()",TAU_DEFAULT); PowderPatternBackgroundBayesianMinimiser min(*this); SimplexObj simplex("Simplex Test"); simplex.AddRefinableObj(min); long nbcycle; REAL llk=simplex.GetLogLikelihood(); long ct=0; cout<<"Initial Chi^2(BayesianBackground)="<SetGlobalOptimStep(gpRefParTypeScattDataBackground, mBackgroundInterpPointIntensity.max()/1000.0); { char buf [200]; sprintf(buf,"Optimizing Background, Cycle %d, Chi^2(Background)=%f", (int)ct,(float)llk); (*fpObjCrystInformUser)((string)buf); } nbcycle=500*mBackgroundNbPoint; simplex.Optimize(nbcycle,false); llk=simplex.GetLogLikelihood(); cout<GetParentPowderPattern().UpdateDisplay(); VFN_DEBUG_EXIT("PowderPatternBackground::OptimizeBayesianBackground()",5); } void PowderPatternBackground::FixParametersBeyondMaxresolution(RefinableObj &obj) { //Auto-fix points beyond used range unsigned long nbpoint=this->GetParentPowderPattern().GetNbPointUsed(); for(long j=0;jGetParentPowderPattern().X2Pixel(mBackgroundInterpPointX(j))>nbpoint) { // obj.GetPar(&mBackgroundInterpPointIntensity(j)).Print(); obj.GetPar(&mBackgroundInterpPointIntensity(j)).SetIsFixed(true); } } void PowderPatternBackground::CalcPowderPattern() const { if(mClockPowderPatternCalc>mClockMaster) return; //:TODO: This needs serious optimization ! if( (mClockPowderPatternCalc>mClockBackgroundPoint) &&(mClockPowderPatternCalc>mpParentPowderPattern->GetClockPowderPatternPar()) &&(mClockPowderPatternCalc>mInterpolationModel.GetClock())) return; TAU_PROFILE("PowderPatternBackground::CalcPowderPattern()","void ()",TAU_DEFAULT); VFN_DEBUG_MESSAGE("PowderPatternBackground::CalcPowderPattern()",3); const unsigned long nb=mpParentPowderPattern->GetNbPoint(); mPowderPatternCalc.resize(nb); if(nb!=0) switch(mInterpolationModel.GetChoice()) { case POWDER_BACKGROUND_LINEAR: { VFN_DEBUG_MESSAGE("PowderPatternBackground::CalcPowderPattern()..Linear",2) REAL p1,p2; REAL b1,b2; if(mBackgroundNbPoint==0) { mPowderPatternCalc=0; break; } VFN_DEBUG_MESSAGE("PowderPatternBackground::CalcPowderPattern()"<InitSpline(); REAL *b=mPowderPatternCalc.data(); p1=this->GetParentPowderPattern().X2Pixel(mBackgroundInterpPointX(mPointOrder(0))); p2=this->GetParentPowderPattern().X2Pixel(mBackgroundInterpPointX(mPointOrder(1))); b1=mBackgroundInterpPointIntensity(mPointOrder(0)); b2=mBackgroundInterpPointIntensity(mPointOrder(1)); long point=1; for(unsigned long i=0;i= p2) { if(point < mBackgroundNbPoint-1) { b1=b2; p1=p2; b2=mBackgroundInterpPointIntensity(mPointOrder(point+1)); p2=this->GetParentPowderPattern().X2Pixel(mBackgroundInterpPointX(mPointOrder(point+1))); point++ ; } } *b = (b1*(p2-i)+b2*(i-p1))/(p2-p1) ; b++; } break; } case POWDER_BACKGROUND_CUBIC_SPLINE: { if(mBackgroundNbPoint==0) mPowderPatternCalc=0; else { this->InitSpline(); mPowderPatternCalc=mvSpline((REAL)0,(REAL)1,nb); } break; } } VFN_DEBUG_MESSAGE("PowderPatternBackground::CalcPowderPattern()",3); #ifdef USE_BACKGROUND_MAXLIKE_ERROR { mPowderPatternCalcVariance.resize(nb); const REAL step=mModelVariance*mModelVariance/(REAL)nbPoint; REAL var=0; REAL *p=mPowderPatternCalcVariance.data(); for(long i=0;i &vPar) { TAU_PROFILE("PowderPatternBackground::CalcPowderPattern_FullDeriv()","void ()",TAU_DEFAULT); const unsigned long nb=mpParentPowderPattern->GetNbPoint(); mPowderPattern_FullDeriv.clear(); if((nb==0)||(mBackgroundNbPoint==0)) return; for(std::set::iterator par=vPar.begin();par!=vPar.end();++par) { if((*par)==0) mPowderPattern_FullDeriv[*par]=this->GetPowderPatternCalc(); else for(int j = 0; j < mBackgroundNbPoint; j++) { if((*par)->GetPointer()!=mBackgroundInterpPointIntensity.data()+j) continue; const REAL step=(*par)->GetDerivStep(); (*par)->Mutate(step); mPowderPattern_FullDeriv[*par] =this->GetPowderPatternCalc(); (*par)->Mutate(-2*step); mPowderPattern_FullDeriv[*par]-=this->GetPowderPatternCalc(); (*par)->Mutate(step); mPowderPattern_FullDeriv[*par]/= step*2; if(MaxAbs(mPowderPattern_FullDeriv[*par])==0) mPowderPattern_FullDeriv[*par].resize(0); } } } void PowderPatternBackground::CalcPowderPatternIntegrated() const { if(mClockPowderPatternCalc>mClockMaster) return; this->CalcPowderPattern();// :TODO: Optimize if( (mClockPowderPatternIntegratedCalc>mClockPowderPatternCalc) &&(mClockPowderPatternIntegratedCalc>mpParentPowderPattern->GetIntegratedProfileLimitsClock())) return; VFN_DEBUG_ENTRY("PowderPatternBackground::CalcPowderPatternIntegrated()",3) TAU_PROFILE("PowderPatternBackground::CalcPowderPatternIntegrated()","void ()",TAU_DEFAULT); const CrystVector_long *pMin=&(mpParentPowderPattern->GetIntegratedProfileMin()); const CrystVector_long *pMax=&(mpParentPowderPattern->GetIntegratedProfileMax()); const long numInterval=pMin->numElements(); mPowderPatternIntegratedCalc.resize(numInterval); REAL * RESTRICT p2=mPowderPatternIntegratedCalc.data(); for(int j=0;j &vPar) { TAU_PROFILE("PowderPatternBackground::CalcPowderPatternIntegrated_FullDeriv()","void ()",TAU_DEFAULT); //cout<<"PowderPatternBackground::CalcPowderPatternIntegrated_FullDeriv"<GetNbPoint(); mPowderPatternIntegrated_FullDeriv.clear(); if((nb==0)||(mBackgroundNbPoint==0)) return; for(std::set::iterator par=vPar.begin();par!=vPar.end();++par) { if((*par)==0) mPowderPattern_FullDeriv[*par]=this->GetPowderPatternCalc(); else for(int j = 0; j < mBackgroundNbPoint; j++) { if((*par)->GetPointer()!=mBackgroundInterpPointIntensity.data()+j) continue; const REAL step=(*par)->GetDerivStep(); (*par)->Mutate(step); mPowderPatternIntegrated_FullDeriv[*par] =*(this->GetPowderPatternIntegratedCalc().first); (*par)->Mutate(-2*step); mPowderPatternIntegrated_FullDeriv[*par]-=*(this->GetPowderPatternIntegratedCalc().first); (*par)->Mutate(step); mPowderPatternIntegrated_FullDeriv[*par]/= step*2; if(MaxAbs(mPowderPatternIntegrated_FullDeriv[*par])==0) mPowderPatternIntegrated_FullDeriv[*par].resize(0); } } #if 0 std::map newDeriv=mPowderPatternIntegrated_FullDeriv; this->PowderPatternComponent::CalcPowderPatternIntegrated_FullDeriv(vPar); std::vector v; int n=0; for(std::map::reverse_iterator pos=mPowderPatternIntegrated_FullDeriv.rbegin();pos!=mPowderPatternIntegrated_FullDeriv.rend();++pos) { cout<first->GetName()<<":"<second.size()<<","<first].size()<second.size()==0) continue; v.push_back(&(pos->second)); v.push_back(&(newDeriv[pos->first])); if(++n>8) break; } if(v.size()>0) cout<<"PowderPatternBackground::CalcPowderPatternIntegrated_FullDeriv():"<(v,12,1,20)<ResetParList(); REAL *p=mBackgroundInterpPointIntensity.data(); char buf [10]; string str="Background_Point_"; //for(int i=0;i<3;i++) for(int i=0;iAddPar(tmp); } #ifdef USE_BACKGROUND_MAXLIKE_ERROR { RefinablePar tmp("ML Model Error",&mModelVariance, 0.,100000.,gpRefParTypeObjCryst,REFPAR_DERIV_STEP_RELATIVE, true,true,true,false,1.); tmp.AssignClock(mClockBackgroundPoint); tmp.SetDerivStep(1e-3); //tmp.SetGlobalOptimStep(10.); tmp.SetGlobalOptimStep(sqrt(mBackgroundInterpPointIntensity.sum() /mBackgroundInterpPointIntensity.numElements())); this->AddPar(tmp); } #endif } void PowderPatternBackground::InitOptions() { VFN_DEBUG_MESSAGE("PowderPatternBackground::InitOptions()",5) static string InterpolationModelName; static string InterpolationModelChoices[2]; static bool needInitNames=true; if(true==needInitNames) { InterpolationModelName="Interpolation Model"; InterpolationModelChoices[0]="Linear"; InterpolationModelChoices[1]="Spline"; //InterpolationModelChoices[2]="Chebyshev"; needInitNames=false;//Only once for the class } mInterpolationModel.Init(2,&InterpolationModelName,InterpolationModelChoices); this->AddOption(&mInterpolationModel); mClockMaster.AddChild(mInterpolationModel.GetClock()); mInterpolationModel.SetChoice(1); } void PowderPatternBackground::InitSpline()const { if( (mClockSpline>mClockBackgroundPoint) &&(mClockSpline>mpParentPowderPattern->GetClockPowderPatternPar()) &&(mClockSpline>this->GetParentPowderPattern().GetRadiation().GetClockWavelength())) return; mvSplinePixel.resize(mBackgroundNbPoint); // The points must be in ascending order // Take care later of neutron TOF, as the powder apttern data may not have been initialized yet. CrystVector subs; subs=SortSubs(mBackgroundInterpPointX); if(this->GetParentPowderPattern().GetRadiation().GetWavelengthType()==WAVELENGTH_TOF) { mPointOrder.resize(mBackgroundNbPoint); for(long i=0;iGetParentPowderPattern().X2Pixel(mBackgroundInterpPointX(mPointOrder(i))); ipixel(i)=mBackgroundInterpPointIntensity(mPointOrder(i)); } mvSpline.Init(mvSplinePixel,ipixel); mClockSpline.Click(); } #ifdef __WX__CRYST__ WXCrystObjBasic* PowderPatternBackground::WXCreate(wxWindow* parent) { //:TODO: Check mpWXCrystObj==0 mpWXCrystObj=new WXPowderPatternBackground(parent,this); return mpWXCrystObj; } #endif //////////////////////////////////////////////////////////////////////// // // PowderPatternDiffraction // //////////////////////////////////////////////////////////////////////// PowderPatternDiffraction::PowderPatternDiffraction(): mpReflectionProfile(0), mCorrLorentz(*this),mCorrPolar(*this),mCorrSlitAperture(*this), mCorrTextureMarchDollase(*this),mCorrTextureEllipsoid(*this),mCorrTOF(*this),mCorrCylAbs(*this),mExtractionMode(false), mpLeBailData(0),mFrozenLatticePar(6),mFreezeLatticePar(false),mFrozenBMatrix(3,3) { VFN_DEBUG_MESSAGE("PowderPatternDiffraction::PowderPatternDiffraction()",10) mIsScalable=true; this->InitOptions(); this->SetProfile(new ReflectionProfilePseudoVoigt); this->SetIsIgnoringImagScattFact(true); this->AddSubRefObj(mCorrTextureMarchDollase); this->AddSubRefObj(mCorrTextureEllipsoid); mClockMaster.AddChild(mClockProfilePar); mClockMaster.AddChild(mClockLorentzPolarSlitCorrPar); mClockMaster.AddChild(mpReflectionProfile->GetClockMaster()); for(unsigned int i=0;i<3;++i) mFrozenLatticePar(i)=5; for(unsigned int i=3;i<6;++i) mFrozenLatticePar(i)=M_PI/2; } PowderPatternDiffraction::PowderPatternDiffraction(const PowderPatternDiffraction &old): mpReflectionProfile(0), mCorrLorentz(*this),mCorrPolar(*this),mCorrSlitAperture(*this), mCorrTextureMarchDollase(*this),mCorrTextureEllipsoid(*this),mCorrTOF(*this),mCorrCylAbs(*this),mExtractionMode(false), mpLeBailData(0),mFrozenLatticePar(6),mFreezeLatticePar(old.FreezeLatticePar()),mFrozenBMatrix(3,3) { this->AddSubRefObj(mCorrTextureMarchDollase); this->AddSubRefObj(mCorrTextureEllipsoid); this->SetIsIgnoringImagScattFact(true); this->SetProfile(old.mpReflectionProfile->CreateCopy()); #if 0 //:TODO: if(old.mpLeBailData!=0) { mpLeBailData=new DiffractionDataSingleCrystal(false); *mpLeBailData = *(old.mpLeBailData); } #endif mClockMaster.AddChild(mClockProfilePar); mClockMaster.AddChild(mClockLorentzPolarSlitCorrPar); mClockMaster.AddChild(mpReflectionProfile->GetClockMaster()); for(unsigned int i=0;i<6;++i) mFrozenLatticePar(i)=old.GetFrozenLatticePar(i); mFrozenBMatrix=old.GetBMatrix(); } PowderPatternDiffraction::~PowderPatternDiffraction() { if(mpReflectionProfile!=0) { this->RemoveSubRefObj(*mpReflectionProfile); delete mpReflectionProfile; } } const string& PowderPatternDiffraction::GetClassName() const { const static string className="PowderPatternDiffraction"; return className; } PowderPatternDiffraction* PowderPatternDiffraction::CreateCopy()const { return new PowderPatternDiffraction(*this); } void PowderPatternDiffraction::SetParentPowderPattern(PowderPattern &s) { if(mpParentPowderPattern!=0) mClockMaster.RemoveChild(mpParentPowderPattern->GetIntegratedProfileLimitsClock()); mpParentPowderPattern = &s; mClockMaster.AddChild(mpParentPowderPattern->GetIntegratedProfileLimitsClock()); mClockMaster.AddChild(mpParentPowderPattern->GetClockPowderPatternPar()); mClockMaster.AddChild(mpParentPowderPattern->GetClockPowderPatternXCorr()); mClockMaster.AddChild(mpParentPowderPattern->GetClockPowderPatternRadiation()); mClockMaster.AddChild(mpParentPowderPattern->GetClockPowderPatternAbsCorr()); } const CrystVector_REAL& PowderPatternDiffraction::GetPowderPatternCalc()const { this->CalcPowderPattern(); return mPowderPatternCalc; } pair PowderPatternDiffraction::GetPowderPatternIntegratedCalc()const { this->CalcPowderPatternIntegrated(); return make_pair(&mPowderPatternIntegratedCalc,&mClockPowderPatternIntegratedCalc); } void PowderPatternDiffraction::SetReflectionProfilePar(const ReflectionProfileType prof, const REAL w, const REAL u, const REAL v, const REAL eta0, const REAL eta1) { VFN_DEBUG_MESSAGE("PowderPatternDiffraction::SetReflectionProfilePar()",5) ReflectionProfilePseudoVoigt* p=new ReflectionProfilePseudoVoigt(); p->SetProfilePar(w,u,v,eta0,eta1); this->SetProfile(p); } void PowderPatternDiffraction::SetProfile(ReflectionProfile *p) { if(p==mpReflectionProfile) return; if(mpReflectionProfile!=0) { this->RemoveSubRefObj(*mpReflectionProfile); delete mpReflectionProfile; } mpReflectionProfile= p; this->AddSubRefObj(*mpReflectionProfile); mClockMaster.AddChild(mpReflectionProfile->GetClockMaster()); } const ReflectionProfile& PowderPatternDiffraction::GetProfile()const { return *mpReflectionProfile; } ReflectionProfile& PowderPatternDiffraction::GetProfile() { return *mpReflectionProfile; } // Disable the base-class function. void PowderPatternDiffraction::GenHKLFullSpace( const REAL maxTheta, const bool useMultiplicity) { // This should be never called. abort(); } void PowderPatternDiffraction::GenHKLFullSpace() { VFN_DEBUG_ENTRY("PowderPatternDiffraction::GenHKLFullSpace():",5) float stol; if(this->GetRadiation().GetWavelengthType()==WAVELENGTH_TOF) stol=mpParentPowderPattern->X2STOL(mpParentPowderPattern->GetPowderPatternXMin()); else stol=mpParentPowderPattern->X2STOL(mpParentPowderPattern->GetPowderPatternXMax()); if(stol>1) stol=1; // Do not go beyond 0.5 A resolution (mostly for TOF data) this->ScatteringData::GenHKLFullSpace2(stol,true); if((mExtractionMode) && (mFhklObsSq.numElements()!=this->GetNbRefl())) {// Reflections changed, so ScatteringData::PrepareHKLarrays() probably reseted mFhklObsSq VFN_DEBUG_ENTRY("PowderPatternDiffraction::GenHKLFullSpace(): need to reset observed intensities",7) mFhklObsSq.resize(this->GetNbRefl()); mFhklObsSq=100; } mCorrTextureEllipsoid.InitRefParList();// #TODO: SHould this be here ? VFN_DEBUG_EXIT("PowderPatternDiffraction::GenHKLFullSpace():"<GetNbRefl(),5) } void PowderPatternDiffraction::BeginOptimization(const bool allowApproximations, const bool enableRestraints) { if(mUseFastLessPreciseFunc!=allowApproximations) { mClockProfileCalc.Reset(); mClockGeomStructFact.Reset(); mClockStructFactor.Reset(); mClockMaster.Click(); } mUseFastLessPreciseFunc=allowApproximations; this->GetNbReflBelowMaxSinThetaOvLambda(); this->RefinableObj::BeginOptimization(allowApproximations,enableRestraints); } void PowderPatternDiffraction::EndOptimization() { if(mOptimizationDepth==1) { if(mUseFastLessPreciseFunc==true) { mClockProfileCalc.Reset(); mClockGeomStructFact.Reset(); mClockStructFactor.Reset(); mClockMaster.Click(); } mUseFastLessPreciseFunc=false; this->GetNbReflBelowMaxSinThetaOvLambda(); } this->RefinableObj::EndOptimization(); } void PowderPatternDiffraction::SetApproximationFlag(const bool allow) { if(mUseFastLessPreciseFunc!=allow) { mClockProfileCalc.Reset(); mClockGeomStructFact.Reset(); mClockStructFactor.Reset(); mClockMaster.Click(); } mUseFastLessPreciseFunc=allow; this->GetNbReflBelowMaxSinThetaOvLambda(); this->RefinableObj::SetApproximationFlag(allow); } void PowderPatternDiffraction::GetGeneGroup(const RefinableObj &obj, CrystVector_uint & groupIndex, unsigned int &first) const { // One group for all profile parameters unsigned int index=0; VFN_DEBUG_MESSAGE("PowderPatternDiffraction::GetGeneGroup()",4) for(long i=0;iGetNbPar();j++) if(&(obj.GetPar(i)) == &(this->GetPar(j))) { //if(this->GetPar(j).GetType()->IsDescendantFromOrSameAs()) //{ if(index==0) index=first++; groupIndex(i)=index; //} //else //no parameters other than unit cell } } const CrystVector_REAL& PowderPatternDiffraction::GetPowderPatternCalcVariance()const { return mPowderPatternCalcVariance; } pair PowderPatternDiffraction::GetPowderPatternIntegratedCalcVariance()const { this->CalcPowderPatternIntegrated(); return make_pair(&mPowderPatternIntegratedCalcVariance, &mClockPowderPatternIntegratedVarianceCalc); } bool PowderPatternDiffraction::HasPowderPatternCalcVariance()const { return true; } void PowderPatternDiffraction::SetCrystal(Crystal &crystal) { bool reprep=(mpCrystal!=0); this->ScatteringData::SetCrystal(crystal); // Check if we use DE-PV if(mpReflectionProfile!=0) if(mpReflectionProfile->GetClassName()=="ReflectionProfileDoubleExponentialPseudoVoigt") { ReflectionProfileDoubleExponentialPseudoVoigt *p =dynamic_cast(mpReflectionProfile); p->SetUnitCell((UnitCell)crystal); } mClockHKL.Reset(); if(reprep) this->Prepare(); } const Radiation& PowderPatternDiffraction::GetRadiation()const { return mpParentPowderPattern->GetRadiation();} void PowderPatternDiffraction::SetExtractionMode(const bool extract,const bool init) { VFN_DEBUG_ENTRY("PowderPatternDiffraction::SetExtractionMode(),ExtractionMode="<0)) {// Leaving extraction mode, so update extracted single crystal data VFN_DEBUG_ENTRY("PowderPatternDiffraction::SetExtractionMode(),LEAVING Le Bail Mode",7) if(mpLeBailData==0) mpLeBailData=new DiffractionDataSingleCrystal(this->GetCrystal(),false); // Update wavelength & name mpLeBailData->SetWavelength(this->GetRadiation().GetWavelength()(0)); mpLeBailData->SetRadiationType(this->GetRadiation().GetRadiationType()); char buf[200]; sprintf(buf,"LeBail (d=%4.2fA):",1/(2*abs(mMaxSinThetaOvLambda)+1e-6)); mpLeBailData->SetName(string(buf)+this->GetCrystal().GetName()); const unsigned long nbrefl=this->GetNbReflBelowMaxSinThetaOvLambda(); CrystVector_REAL iobs(nbrefl),sigma(nbrefl); CrystVector_long h(nbrefl),k(nbrefl),l(nbrefl); sigma=1; for(unsigned long i=0;iSetHklIobs(h,k,l,iobs,sigma); // Erase mFhklObsSq - only used during extraction mode. mFhklObsSq.resize(0); } mClockIhklCalc.Reset();mClockMaster.Reset(); mClockFhklObsSq.Click(); VFN_DEBUG_EXIT("PowderPatternDiffraction::SetExtractionMode(),ExtractionMode="<SetExtractionMode(true,true);// Should not have to do this here ! if(mFhklObsSq.numElements()!=this->GetNbRefl()) {//Something went wrong ! VFN_DEBUG_ENTRY("PowderPatternDiffraction::ExtractLeBail() mFhklObsSq.size() != NbRefl !!!!!!",7) mFhklObsSq.resize(this->GetNbRefl()); mFhklObsSq=100; } // First get the observed powder pattern, minus the contribution of all other phases. CrystVector_REAL obs,iextract,calc; iextract=mFhklObsSq; mFhklObsSq=0; mClockFhklObsSq.Click(); // Get the observed and calculated powder pattern (excluding this diffraction phase) obs=mpParentPowderPattern->GetPowderPatternObs(); obs-=mpParentPowderPattern->GetPowderPatternCalc(); mFhklObsSq=iextract; mClockFhklObsSq.Click(); // We take here the reflections which are centered below the max(sin(theta)/lambda) // actually more reflections are calculated, but the pattern is only calculated up to // max(sin(theta)/lambda). const unsigned long nbrefl=this->ScatteringData::GetNbReflBelowMaxSinThetaOvLambda(); iextract=0; for(;nbcycle>0;nbcycle--) { //cout<<"PowderPatternDiffraction::ExtractLeBail(): cycle #"<GetPowderPatternCalc(); for(unsigned int k0=0;k0=(long)(mpParentPowderPattern->GetNbPointUsed())) last=mpParentPowderPattern->GetNbPointUsed(); if(mvReflProfile[k0].first<0)first=0; else first=(mvReflProfile[k0].first); const REAL *p1=mvReflProfile[k0].profile.data()+(first-mvReflProfile[k0].first); const REAL *p2=calc.data()+first; const REAL *pobs=obs.data()+first; for(long i=first;i<=last;++i) { const REAL s2=*p2++; const REAL tmp=*pobs++ * *p1++; if( (s2<1e-8) ) // || (tmp<=0) {// Avoid <0 intensities (should not happen, it means profile is <0) //cout<<"S2? "<< int(mH(k0))<<" "<1e-8)&&(!ISNAN_OR_INF(s1))) iextract(k0)=s1*mFhklObsSq(k0); else iextract(k0)=1e-8;//:KLUDGE: should <0 intensities be allowed ? //if(nbcycle==1) cout<<" Le Bail "<(mH,mK,mL,this->GetFhklCalcSq(),mFhklObsSq,10,4,nbrefl)<SetHklIobs(h,k,l,iobs,sigma); } VFN_DEBUG_EXIT("PowderPatternDiffraction::ExtractLeBail()mFhklObsSq.size()=="<IsBeingRefined()) return mNbReflUsed; VFN_DEBUG_MESSAGE("PowderPatternDiffraction::GetNbReflBelowMaxSinThetaOvLambda(): "<CalcPowderReflProfile(); const long nbpoint=mpParentPowderPattern->GetNbPointUsed(); if((mNbReflUsed>0)&&(mNbReflUsednbpoint) &&(mvReflProfile[mNbReflUsed-1].first<=nbpoint)) return mNbReflUsed; } if((mNbReflUsed==mNbRefl) && (mvReflProfile[mNbReflUsed-1].profile.numElements()>0)) if(mvReflProfile[mNbReflUsed-1].first<=nbpoint)return mNbReflUsed; long i; for(i=0;inbpoint) break; } if(i!=mNbReflUsed) { mNbReflUsed=i; mClockNbReflUsed.Click(); VFN_DEBUG_MESSAGE("->Changed Max sin(theta)/lambda="<CalcFrozenBMatrix(); } REAL PowderPatternDiffraction::GetFrozenLatticePar(const unsigned int i) const {return mFrozenLatticePar(i);} void PowderPatternDiffraction::FreezeLatticePar(const bool use) { VFN_DEBUG_MESSAGE("PowderPatternDiffraction::FreezeLatticePar("<GetCrystal().GetLatticePar(); if(use) this->CalcFrozenBMatrix(); mClockTheta.Reset(); this->UpdateDisplay(); } bool PowderPatternDiffraction::FreezeLatticePar() const {return mFreezeLatticePar;} unsigned int PowderPatternDiffraction::GetProfileFitNetNbObs()const { unsigned int nb=0; unsigned int irefl=0; unsigned int ilast=0; while(this->GetParentPowderPattern().STOL2Pixel(mSinThetaLambda(irefl))<0) { irefl++; if(irefl>=this->GetNbReflBelowMaxSinThetaOvLambda()) break; } while(ireflGetNbReflBelowMaxSinThetaOvLambda()) { const REAL stol = mSinThetaLambda(irefl); while(mSinThetaLambda(irefl)==stol) { //cout<=this->GetNbReflBelowMaxSinThetaOvLambda()) break; } const int nbnew =this->GetParentPowderPattern().STOL2Pixel(stol)-ilast; if(nbnew>1) nb += nbnew-1; //cout<<" => Added "<< nbnew-1<< "net observed points ("<GetParentPowderPattern().STOL2Pixel(stol)<<"-"<GetParentPowderPattern().STOL2Pixel(stol); } //cout<<"Final number of net observed points: "<GetFhklObsSq().size() > 0; } const CrystVector_REAL& PowderPatternDiffraction::GetFhklObsSq() const { if(mpLeBailData==NULL) throw ObjCrystException("PowderPatternDiffraction::GetFhklObsSq(): no extracted intensities available"); return mpLeBailData->GetFhklObsSq(); } void PowderPatternDiffraction::CalcPowderPattern() const { this->GetNbReflBelowMaxSinThetaOvLambda(); if(mClockPowderPatternCalc>mClockMaster) return; TAU_PROFILE("PowderPatternDiffraction::CalcPowderPattern()-Apply profiles","void (bool)",TAU_DEFAULT); VFN_DEBUG_ENTRY("PowderPatternDiffraction::CalcPowderPattern():",3) // :TODO: Can't do this as this is non-const //if(this->GetCrystal().GetSpaceGroup().GetClockSpaceGroup()>mClockHKL) // this->GenHKLFullSpace(); // // The workaround is to call Prepare() (non-const) before every calculation // when a modifictaion may have occured. this->CalcIhkl(); this->CalcPowderReflProfile(); if( (mClockPowderPatternCalc>mClockIhklCalc) &&(mClockPowderPatternCalc>mClockProfileCalc)) return; if(true) //:TODO: false == mUseFastLessPreciseFunc { const long nbRefl=this->GetNbRefl(); VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcPowderPattern\ Applying profiles for "<GetNbPoint(); mPowderPatternCalc.resize(specNbPoints); mPowderPatternCalc=0; const bool useML= (mIhklCalcVariance.numElements() != 0); if(useML) { mPowderPatternCalcVariance.resize(specNbPoints); mPowderPatternCalcVariance=0; } else mPowderPatternCalcVariance.resize(0); VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcPowderPattern() Has variance:"<=mNbReflUsed) break;// After sin(theta)/lambda limit else continue; // before beginning of pattern ? } VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcPowderPattern()#"<IsAnisotropic()) break;// Anisotropic profiles if( (i+step) >= nbRefl) break; if(mSinThetaLambda(i+step) > (mSinThetaLambda(i)+1e-5) ) break; } VFN_DEBUG_MESSAGE("Apply profile(Monochromatic)Refl("<"< &vPar) { TAU_PROFILE("PowderPatternDiffraction::CalcPowderPattern_FullDeriv()","void ()",TAU_DEFAULT); //cout<<"PowderPatternDiffraction::CalcPowderPattern_FullDeriv"<CalcPowderPattern(); bool notYetDerivProfiles=true; mIhkl_FullDeriv.clear(); mvReflProfile_FullDeriv.clear(); mPowderPattern_FullDeriv.clear(); for(std::set::iterator par=vPar.begin();par!=vPar.end();++par) { if(*par==0) continue; if((*par)->IsFixed()) continue; if((*par)->IsUsed()==false) continue; if( (*par)->GetType()->IsDescendantFromOrSameAs(gpRefParTypeScatt) ||(*par)->GetType()->IsDescendantFromOrSameAs(gpRefParTypeScattPow)) { this->CalcIhkl_FullDeriv(vPar); } if(notYetDerivProfiles) { if( (*par)->GetType()->IsDescendantFromOrSameAs(gpRefParTypeRadiation) ||(*par)->GetType()->IsDescendantFromOrSameAs(gpRefParTypeUnitCell) ||(*par)->GetType()->IsDescendantFromOrSameAs(gpRefParTypeScattDataCorrPos) ||(*par)->GetType()->IsDescendantFromOrSameAs(gpRefParTypeScattDataProfile)) { this->CalcPowderReflProfile_FullDeriv(vPar); notYetDerivProfiles=false; } } } //this->CalcPowderReflProfile(); for(std::set::iterator par=vPar.begin();par!=vPar.end();++par) { if(*par==0) mPowderPattern_FullDeriv[*par]=this->GetPowderPatternCalc(); else { if((*par)->IsFixed()) continue; if((*par)->IsUsed()==false) continue; if(mIhkl_FullDeriv[*par].size()!=0) { const long nbRefl=this->GetNbRefl(); long step; // number of reflections at the same place and with the same (assumed) profile const long specNbPoints=mpParentPowderPattern->GetNbPoint(); mPowderPattern_FullDeriv[*par].resize(specNbPoints); mPowderPattern_FullDeriv[*par]=0; for(long i=0;i=mNbReflUsed) break; else continue; } REAL intensity=0.; //check if the next reflection is at the same theta. If this is true, //Then assume that the profile is exactly the same, unless it is anisotropic for(step=0; ;) { intensity += mIhkl_FullDeriv[*par](i + step); step++; if(mpReflectionProfile->IsAnisotropic()) break;// Anisotropic profiles if( (i+step) >= nbRefl) break; if(mSinThetaLambda(i+step) > (mSinThetaLambda(i)+1e-5) ) break; } { const long first=mvReflProfile[i].first,last=mvReflProfile[i].last; const REAL *p2 = mvReflProfile[i].profile.data(); REAL *p3 = mPowderPattern_FullDeriv[*par].data()+first; for(long j=first;j<=last;j++) *p3++ += *p2++ * intensity; } } } if(mvReflProfile_FullDeriv[*par].size()!=0) { const long nbRefl=this->GetNbRefl(); long step; // number of reflections at the same place and with the same (assumed) profile const long specNbPoints=mpParentPowderPattern->GetNbPoint(); mPowderPattern_FullDeriv[*par].resize(specNbPoints); mPowderPattern_FullDeriv[*par]=0;// :TODO: use only the number of points actually used cout<<__FILE__<<":"<<__LINE__<<":PowderPatternDiffraction::CalcPowderPattern_FullDeriv():par="<<(*par)->GetName()<=mNbReflUsed) break; else continue; } REAL intensity=0.; //check if the next reflection is at the same theta. If this is true, //Then assume that the profile is exactly the same, unless it is anisotropic for(step=0; ;) { intensity += mIhklCalc(i + step); step++; if(mpReflectionProfile->IsAnisotropic()) break;// Anisotropic profiles if( (i+step) >= nbRefl) break; if(mSinThetaLambda(i+step) > (mSinThetaLambda(i)+1e-5) ) break; } if(mvReflProfile_FullDeriv[*par][i].size()>0)// Some profiles may be unaffected by a given parameter { const long first=mvReflProfile[i].first,last=mvReflProfile[i].last; const REAL *p2 = mvReflProfile_FullDeriv[*par][i].data(); REAL *p3 = mPowderPattern_FullDeriv[*par].data()+first; for(long j=first;j<=last;j++) *p3++ += *p2++ * intensity; } } } } } #if 0 std::map newDeriv=mPowderPattern_FullDeriv; this->PowderPatternComponent::CalcPowderPattern_FullDeriv(vPar); std::vector v; int n=0; for(std::map::reverse_iterator pos=mPowderPattern_FullDeriv.rbegin();pos!=mPowderPattern_FullDeriv.rend();++pos) { if(pos->first==0) continue; if(pos->second.size()==0) continue; v.push_back(&(newDeriv[pos->first])); v.push_back(&(pos->second)); cout<first->GetName()<<":"<second.size()<<","<first].size()<8) break; } cout<(v,16,4,1000)<GetNbReflBelowMaxSinThetaOvLambda(); if(mClockPowderPatternIntegratedCalc>mClockMaster) return; TAU_PROFILE("PowderPatternDiffraction::CalcPowderPatternIntegrated()","void (bool)",TAU_DEFAULT); TAU_PROFILE_TIMER(timer1,"PowderPatternDiffraction::CalcPowderPatternIntegrated()1","", TAU_FIELD); TAU_PROFILE_TIMER(timer2,"PowderPatternDiffraction::CalcPowderPatternIntegrated()2","", TAU_FIELD); this->CalcIhkl(); TAU_PROFILE_START(timer1); this->PrepareIntegratedProfile(); TAU_PROFILE_STOP(timer1); if( (mClockPowderPatternIntegratedCalc>mClockIhklCalc) &&(mClockPowderPatternIntegratedCalc>mClockIntegratedProfileFactor) &&(mClockPowderPatternIntegratedCalc>mpParentPowderPattern->GetIntegratedProfileLimitsClock())) return; VFN_DEBUG_ENTRY("PowderPatternDiffraction::CalcPowderPatternIntegrated()",3) const long nbRefl=this->GetNbRefl(); const long nb=mpParentPowderPattern->GetIntegratedProfileMin().numElements(); mPowderPatternIntegratedCalc.resize(nb); mPowderPatternIntegratedCalc=0; const bool useML= (mIhklCalcVariance.numElements() != 0); if(useML) { mPowderPatternIntegratedCalcVariance.resize(nb); mPowderPatternIntegratedCalcVariance=0; } else mPowderPatternIntegratedCalcVariance.resize(0); const REAL * RESTRICT psith=mSinThetaLambda.data(); const REAL * RESTRICT pI=mIhklCalc.data(); const REAL * RESTRICT pIvar=mIhklCalcVariance.data(); vector< pair >::const_iterator pos; pos=mIntegratedProfileFactor.begin(); TAU_PROFILE_START(timer2); for(long i=0;i= nbRefl) break; if( *(++psith) > thmax ) break; if(mpReflectionProfile->IsAnisotropic()) break;// Anisotropic profile ++pos; } VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcPowderPatternIntegrated():"<first; const REAL * RESTRICT pFact=pos->second.data(); const unsigned long nb=pos->second.numElements(); //cout <0;j--) { //cout <first+j<<"("<<*pFact<<","<<*pData<<") "; *pData++ += intensity * *pFact++ ; } //cout<second.data(); REAL * RESTRICT pVar=mPowderPatternIntegratedCalcVariance.data()+pos->first; for(unsigned long j=nb;j>0;j--) *pVar++ += var * *pFact++ ; } ++pos; } TAU_PROFILE_STOP(timer2); #ifdef __DEBUG__ if(gVFNDebugMessageLevel<3) { this->CalcPowderPattern(); CrystVector_REAL integr(nb),min(nb),max(nb),diff(nb),index(nb); integr=0; for(long i=0;iGetIntegratedProfileMin()(i); max(i)=mpParentPowderPattern->GetIntegratedProfileMax()(i); integr(i)=0; for(long j=mpParentPowderPattern->GetIntegratedProfileMin()(i); j<=mpParentPowderPattern->GetIntegratedProfileMax()(i);j++) { integr(i) += mPowderPatternCalc(j); } diff(i)=1.-mPowderPatternIntegratedCalc(i)/integr(i); } cout << "Integrated intensities, Component"< (index,min,max,integr,mPowderPatternIntegratedCalc,diff,20,6)< &vPar) { TAU_PROFILE("PowderPatternDiffraction::CalcPowderPatternIntegrated_FullDeriv()","void ()",TAU_DEFAULT); //cout<<"PowderPatternDiffraction::CalcPowderPatternIntegrated_FullDeriv"<PowderPatternComponent::CalcPowderPatternIntegrated_FullDeriv(vPar); //return; this->CalcPowderPatternIntegrated(); this->CalcIhkl_FullDeriv(vPar); const long nbRefl=this->GetNbRefl(); //#define PowderPatternDiffraction_CalcPowderPatternIntegrated_FullDerivDEBUG #ifdef PowderPatternDiffraction_CalcPowderPatternIntegrated_FullDerivDEBUG this->PowderPatternComponent::CalcPowderPatternIntegrated_FullDeriv(vPar); std::map oldDeriv=mPowderPatternIntegrated_FullDeriv; #endif const long nbprof=mpParentPowderPattern->GetIntegratedProfileMin().size(); long ctpar=0; mPowderPatternIntegrated_FullDeriv.clear(); for(std::set::iterator par=vPar.begin();par!=vPar.end();++par) { if(*par==0) mPowderPatternIntegrated_FullDeriv[*par]=mPowderPatternIntegratedCalc; else { if(mIhkl_FullDeriv[*par].size()==0) continue; if(mPowderPatternIntegrated_FullDeriv[*par].size()==0) { mPowderPatternIntegrated_FullDeriv[*par].resize(nbprof); mPowderPatternIntegrated_FullDeriv[*par]=0; } const REAL * RESTRICT psith=mSinThetaLambda.data(); const REAL * RESTRICT pI=mIhkl_FullDeriv[*par].data(); // :TODO: also handle derivatives of profile parameters ? Though one should not // refine profiles using integrated profiles ! vector< pair >::const_iterator pos=mIntegratedProfileFactor.begin(); for(long i=0;i= nbRefl) break; if( *(++psith) > thmax ) break; if(mpReflectionProfile->IsAnisotropic()) break;// Anisotropic profile ++pos; } REAL * RESTRICT pData=mPowderPatternIntegrated_FullDeriv[*par].data()+pos->first; const REAL * RESTRICT pFact=pos->second.data(); const unsigned long nb=pos->second.numElements(); #ifdef PowderPatternDiffraction_CalcPowderPatternIntegrated_FullDerivDEBUG if((i<5)&&(ctpar<8)) cout<<__FILE__<<":"<<__LINE__<<":"<<(*par)->GetName()<<"i="<0;j--) { #ifdef PowderPatternDiffraction_CalcPowderPatternIntegrated_FullDerivDEBUG *pData += intensity * *pFact ; if((i<5)&&((*par)->GetName()=="Cimetidine_C11_x")&&(pos->first==0)&&(nb==j)) cout<::iterator par=vPar.begin();par!=vPar.end();++par) { if(mPowderPatternIntegrated_FullDeriv[*par].size()==0) continue; v.push_back(&(mPowderPatternIntegrated_FullDeriv[*par])); v.push_back(&(oldDeriv[*par])); cout<<(*par)->GetName()<<":"<6) break; } cout<<"PowderPatternDiffraction::CalcPowderPatternIntegrated_FullDeriv():"<(v,12,1,20)<CalcSinThetaLambda(); mpParentPowderPattern->GetNbPointUsed();// if( (mClockProfileCalc>mClockProfilePar) &&(mClockProfileCalc>mpReflectionProfile->GetClockMaster()) &&(mClockProfileCalc>mClockTheta) &&(mClockProfileCalc>this->GetRadiation().GetClockWavelength()) &&(mClockProfileCalc>mpParentPowderPattern->GetClockPowderPatternXCorr()) &&(mClockProfileCalc>mClockHKL) &&(mClockProfileCalc>mpParentPowderPattern->GetClockNbPointUsed())) return; TAU_PROFILE("PowderPatternDiffraction::CalcPowderReflProfile()","void (bool)",TAU_DEFAULT); VFN_DEBUG_ENTRY("PowderPatternDiffraction::CalcPowderReflProfile()",5) //Calc all profiles mvLabel.clear(); stringstream label; unsigned int nbLine=1; CrystVector_REAL spectrumDeltaLambdaOvLambda; CrystVector_REAL spectrumFactor;//relative weigths of different lines of X-Ray tube switch(this->GetRadiation().GetWavelengthType()) { case WAVELENGTH_MONOCHROMATIC: { spectrumDeltaLambdaOvLambda.resize(1);spectrumDeltaLambdaOvLambda=0.0; spectrumFactor.resize(1);spectrumFactor=1.0; break; } case WAVELENGTH_ALPHA12: { nbLine=2; spectrumDeltaLambdaOvLambda.resize(2); spectrumDeltaLambdaOvLambda(0) =-this->GetRadiation().GetXRayTubeDeltaLambda() *this->GetRadiation().GetXRayTubeAlpha2Alpha1Ratio() /(1+this->GetRadiation().GetXRayTubeAlpha2Alpha1Ratio()) /this->GetRadiation().GetWavelength()(0); spectrumDeltaLambdaOvLambda(1) = this->GetRadiation().GetXRayTubeDeltaLambda() /(1+this->GetRadiation().GetXRayTubeAlpha2Alpha1Ratio()) /this->GetRadiation().GetWavelength()(0); spectrumFactor.resize(2); spectrumFactor(0)=1./(1.+this->GetRadiation().GetXRayTubeAlpha2Alpha1Ratio()); spectrumFactor(1)=this->GetRadiation().GetXRayTubeAlpha2Alpha1Ratio() /(1.+this->GetRadiation().GetXRayTubeAlpha2Alpha1Ratio()); break; } case WAVELENGTH_TOF: { spectrumDeltaLambdaOvLambda.resize(1);spectrumDeltaLambdaOvLambda=0.0; spectrumFactor.resize(1);spectrumFactor=1.0; break; } default: throw ObjCrystException("PowderPatternDiffraction::PrepareIntegratedProfile():\ Radiation must be either monochromatic, from an X-Ray Tube, or neutron TOF !!"); } VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcPowderReflProfile():\ Computing all Profiles",5) REAL center,// center of current reflection (depends on line if several) x0; // theoretical (uncorrected for zero's, etc..) position of center of line long first,last;// first & last point of the stored profile CrystVector_REAL vx,reflProfile,tmpV; mvReflProfile.resize(this->GetNbRefl()); for(unsigned int i=0;iGetNbRefl();i++) { mvReflProfile[i].first=0; mvReflProfile[i].last=0; mvReflProfile[i].profile.resize(0); } VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcPowderReflProfile()",5) for(unsigned int line=0;lineGetNbRefl();i++) {// Only the reflections contributing below the max(sin(theta)/lambda) will be computed VFN_DEBUG_ENTRY("PowderPatternDiffraction::CalcPowderReflProfile()#"<STOL2X(mSinThetaLambda(i)); VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcPowderReflProfile()#"<1) {// we have several lines, not centered on the profile range center = mpParentPowderPattern->X2XCorr( x0+2*tan(x0/2.0)*spectrumDeltaLambdaOvLambda(line)); } else center=mpParentPowderPattern->X2XCorr(x0); REAL fact=1.0; if(!mUseFastLessPreciseFunc) fact=5.0; const REAL halfwidth=mpReflectionProfile->GetFullProfileWidth(0.04,center,mH(i),mK(i),mL(i))*fact; if(line==0) { // For an X-Ray tube, label on first (strongest) of reflections lines (Kalpha1) label.str(""); label<GetRadiation().GetWavelengthType()==WAVELENGTH_ALPHA12) {// We need to shift the last point to include 2 lines in the profile spectrumwidth=2*this->GetRadiation().GetXRayTubeDeltaLambda() /this->GetRadiation().GetWavelength()(0)*tan(x0/2.0); } first=(long)(mpParentPowderPattern->X2Pixel(center-halfwidth)); last =(long)(mpParentPowderPattern->X2Pixel(center+halfwidth+spectrumwidth)); if(this->GetRadiation().GetWavelengthType()==WAVELENGTH_TOF) { const long f=first; first=last; last=f; } if(first>last) { // Whoops - should not happen !! Unless there is a strange (dis)order for the x coordinates... cout<<"PowderPatternDiffraction::CalcPowderReflProfile(), line"<<__LINE__<<"first>last !! :"<last) { cout<<__FILE__<<__LINE__<=0)&&(first<(long)(mpParentPowderPattern->GetNbPoint()))) { if(first<0) first=0; if(last>=(long)(mpParentPowderPattern->GetNbPoint())) last=mpParentPowderPattern->GetNbPoint()-1; vx.resize(last-first+1); } else vx.resize(0); // store no profile if reflection out of pattern mvReflProfile[i].first=first; mvReflProfile[i].last=last; } else { first=mvReflProfile[i].first; last=mvReflProfile[i].last; if((last>=0)&&(first<(long)(mpParentPowderPattern->GetNbPoint()))) vx.resize(last-first+1); else vx.resize(0); vx.resize(last-first+1); } if((last>=0)&&(first<(long)(mpParentPowderPattern->GetNbPoint()))) { { const REAL *p0=mpParentPowderPattern->GetPowderPatternX().data()+first; REAL *p1=vx.data(); for(long i=first;i<=last;i++) *p1++ = *p0++; } VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcPowderReflProfile():"<GetProfile(vx,center,mH(i),mK(i),mL(i)); VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcPowderReflProfile()",2) if(nbLine>1) reflProfile *=spectrumFactor(line); if(line==0) mvReflProfile[i].profile = reflProfile; else mvReflProfile[i].profile += reflProfile; } else { // reflection is out of pattern, so store no profile mvReflProfile[i].profile.resize(0); } VFN_DEBUG_EXIT("PowderPatternDiffraction::CalcPowderReflProfile():\ Computing all Profiles: Reflection #"<(long)(mpParentPowderPattern->GetNbPointUsed())) break; } } mClockProfileCalc.Click(); VFN_DEBUG_EXIT("PowderPatternDiffraction::CalcPowderReflProfile()",5) } void PowderPatternDiffraction::CalcPowderReflProfile_FullDeriv(std::set &vPar) { TAU_PROFILE("PowderPatternDiffraction::CalcPowderReflProfile_FullDeriv()","void (bool)",TAU_DEFAULT); cout<<__FILE__<<":"<<__LINE__<<":PowderPatternDiffraction::CalcPowderReflProfile_FullDeriv()"<CalcPowderReflProfile(); unsigned int nbLine=1; CrystVector_REAL spectrumDeltaLambdaOvLambda; CrystVector_REAL spectrumFactor;//relative weigths of different lines of X-Ray tube switch(this->GetRadiation().GetWavelengthType()) { case WAVELENGTH_MONOCHROMATIC: { spectrumDeltaLambdaOvLambda.resize(1);spectrumDeltaLambdaOvLambda=0.0; spectrumFactor.resize(1);spectrumFactor=1.0; break; } case WAVELENGTH_ALPHA12: { nbLine=2; spectrumDeltaLambdaOvLambda.resize(2); spectrumDeltaLambdaOvLambda(0) =-this->GetRadiation().GetXRayTubeDeltaLambda() *this->GetRadiation().GetXRayTubeAlpha2Alpha1Ratio() /(1+this->GetRadiation().GetXRayTubeAlpha2Alpha1Ratio()) /this->GetRadiation().GetWavelength()(0); spectrumDeltaLambdaOvLambda(1) = this->GetRadiation().GetXRayTubeDeltaLambda() /(1+this->GetRadiation().GetXRayTubeAlpha2Alpha1Ratio()) /this->GetRadiation().GetWavelength()(0); spectrumFactor.resize(2); spectrumFactor(0)=1./(1.+this->GetRadiation().GetXRayTubeAlpha2Alpha1Ratio()); spectrumFactor(1)=this->GetRadiation().GetXRayTubeAlpha2Alpha1Ratio() /(1.+this->GetRadiation().GetXRayTubeAlpha2Alpha1Ratio()); break; } case WAVELENGTH_TOF: { spectrumDeltaLambdaOvLambda.resize(1);spectrumDeltaLambdaOvLambda=0.0; spectrumFactor.resize(1);spectrumFactor=1.0; break; } default: throw ObjCrystException("PowderPatternDiffraction::CalcPowderReflProfile_FullDeriv():\ Radiation must be either monochromatic, from an X-Ray Tube, or neutron TOF !!"); } REAL center,// center of current reflection (depends on line if several) x0; // theoretical (uncorrected for zero's, etc..) position of center of line long first,last;// first & last point of the stored profile CrystVector_REAL vx,reflProfile,tmpV; // Derivative vs the shift of the reflection center vector vReflProfile_DerivCenter(mNbReflUsed); mvReflProfile_FullDeriv.clear(); for(std::set::iterator par=vPar.begin();par!=vPar.end();++par) { if(*par==0) continue; if( (*par)->GetType()->IsDescendantFromOrSameAs(gpRefParTypeRadiation) ||(*par)->GetType()->IsDescendantFromOrSameAs(gpRefParTypeUnitCell) ||(*par)->GetType()->IsDescendantFromOrSameAs(gpRefParTypeScattDataCorrPos) ||(*par)->GetType()->IsDescendantFromOrSameAs(gpRefParTypeScattDataProfile)) { mvReflProfile_FullDeriv[*par].resize(mNbReflUsed); for(unsigned int line=0;lineSTOL2X(mSinThetaLambda(i)); if(nbLine>1) {// we have several lines, not centered on the profile range center = mpParentPowderPattern->X2XCorr( x0+2*tan(x0/2.0)*spectrumDeltaLambdaOvLambda(line)); } else center=mpParentPowderPattern->X2XCorr(x0); first=mvReflProfile[i].first; last=mvReflProfile[i].last; if((last>=0)&&(first<(long)(mpParentPowderPattern->GetNbPoint()))) vx.resize(last-first+1); else vx.resize(0); vx.resize(last-first+1); if((last>=0)&&(first<(long)(mpParentPowderPattern->GetNbPoint()))) { { const REAL *p0=mpParentPowderPattern->GetPowderPatternX().data()+first; REAL *p1=vx.data(); for(long i=first;i<=last;i++) *p1++ = *p0++; } if((*par)->GetType()->IsDescendantFromOrSameAs(gpRefParTypeScattDataProfile)) {// Parameter only affects profile //if(i==0) cout<<"PowderPatternDiffraction::CalcPowderReflProfile_FullDeriv()par="<<(*par)->GetName()<<":refl #"<GetDerivStep(); (*par)->Mutate(step); reflProfile=mpReflectionProfile->GetProfile(vx,center,mH(i),mK(i),mL(i)); (*par)->Mutate(-2*step); reflProfile-=mpReflectionProfile->GetProfile(vx,center,mH(i),mK(i),mL(i)); (*par)->Mutate(step); reflProfile/=2*step; } else {// Parameter affects reflection center REAL dcenter=0; { //:TODO: analytical derivatives const REAL step=(*par)->GetDerivStep(); (*par)->Mutate(step); REAL x1=mpParentPowderPattern->STOL2X(this->CalcSinThetaLambda(mH(i),mK(i),mL(i))); if(nbLine>1) dcenter = mpParentPowderPattern->X2XCorr(x1+2*tan(x1/2.0)*spectrumDeltaLambdaOvLambda(line)); else dcenter = mpParentPowderPattern->X2XCorr(x1); (*par)->Mutate(-2*step); x1=mpParentPowderPattern->STOL2X(this->CalcSinThetaLambda(mH(i),mK(i),mL(i))); if(nbLine>1) dcenter-= mpParentPowderPattern->X2XCorr(x1+2*tan(x1/2.0)*spectrumDeltaLambdaOvLambda(line)); else dcenter-= mpParentPowderPattern->X2XCorr(x1); (*par)->Mutate(step); dcenter/=2*step; } if(dcenter!=0) { //if(i==0) cout<<"PowderPatternDiffraction::CalcPowderReflProfile_FullDeriv()par="<<(*par)->GetName()<<":refl #"< Parameter affects nothing ?"<0) { if(nbLine>1) reflProfile *=spectrumFactor(line); if(line==0) mvReflProfile_FullDeriv[*par][i] = reflProfile; else mvReflProfile_FullDeriv[*par][i] += reflProfile; } } } } } } } void PowderPatternDiffraction::CalcIntensityCorr()const { bool needRecalc=false; this->CalcSinThetaLambda(); if((mClockIntensityCorrGetClockNbReflBelowMaxSinThetaOvLambda())) needRecalc=true; const CrystVector_REAL *mpCorr[6] = {0, 0, 0, 0, 0, 0}; if(this->GetRadiation().GetWavelengthType()==WAVELENGTH_TOF) { mpCorr[0]=&(mCorrTOF.GetCorr()); if(mClockIntensityCorrGetRadiation().GetRadiationType()==RAD_XRAY) { mpCorr[1]=&(mCorrPolar.GetCorr()); if(mClockIntensityCorr0) { mpCorr[3]=&(mCorrTextureMarchDollase.GetCorr()); if(mClockIntensityCorrdata(); for(long i=mNbReflUsed;i>0;i--) *pCorr++ = *p++; if(this->GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) { if(this->GetRadiation().GetRadiationType()==RAD_XRAY) { pCorr=mIntensityCorr.data(); p=mpCorr[1]->data(); const REAL* p2=mpCorr[2]->data(); for(long i=mNbReflUsed;i>0;i--) *pCorr++ *= *p++ * *p2++; } else { pCorr=mIntensityCorr.data(); p=mpCorr[2]->data(); for(long i=mNbReflUsed;i>0;i--) *pCorr++ *= *p++; } } if(mCorrTextureMarchDollase.GetNbPhase()>0) { pCorr=mIntensityCorr.data(); p=mpCorr[3]->data(); for(long i=mNbReflUsed;i>0;i--) *pCorr++ *= *p++; } if(mpCorr[4]->numElements()>0) { pCorr=mIntensityCorr.data(); p=mpCorr[4]->data(); for(long i=mNbReflUsed;i>0;i--) *pCorr++ *= *p++; } if(mpCorr[5] != NULL) if(mpCorr[5]->numElements()>0) { pCorr=mIntensityCorr.data(); p=mpCorr[5]->data(); for(long i=mNbReflUsed;i>0;i--) *pCorr++ *= *p++; } mClockIntensityCorr.Click(); VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcIntensityCorr():finished",2) } void PowderPatternDiffraction::CalcIhkl() const { this->CalcIntensityCorr(); if(mExtractionMode==true) { VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcIhkl():"<CalcStructFactor(); if( (mClockIhklCalc>mClockIntensityCorr) &&(mClockIhklCalc>mClockStructFactor) &&(mClockIhklCalc>mClockNbReflUsed)) return; VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcIhkl()",3) TAU_PROFILE("PowderPatternDiffraction::CalcIhkl()","void ()",TAU_DEFAULT); const REAL * RESTRICT pr,* RESTRICT pi,* RESTRICT pcorr; const int * RESTRICT mult; REAL * RESTRICT p; pr=mFhklCalcReal.data(); pi=mFhklCalcImag.data(); pcorr=mIntensityCorr.data(); mult=mMultiplicity.data(); mIhklCalc.resize(mNbRefl); p=mIhklCalc.data(); if(mFhklCalcVariance.numElements()>0) { const REAL * RESTRICT pv=mFhklCalcVariance.data(); for(long i=mNbReflUsed;i>0;i--) { *p++ = *mult++ * (*pr * *pr + *pi * *pi + 2 * *pv++) * *pcorr++; pr++; pi++; } } else { for(long i=mNbReflUsed;i>0;i--) { *p++ = *mult++ * (*pr * *pr + *pi * *pi) * *pcorr++; pr++; pi++; } } if(mFhklCalcVariance.numElements()==0) { VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcIhkl(): No Calc Variance",2) mIhklCalcVariance.resize(0); VFN_DEBUG_MESSAGE(endl<< FormatVertVectorHKLFloats(mH,mK,mL,mSinThetaLambda, mFhklCalcReal, mFhklCalcImag, mIhklCalc, mIntensityCorr ),2) } else { VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcIhkl(): Calc Variance",2) mIhklCalcVariance.resize(mNbRefl); REAL * RESTRICT pVar2=mIhklCalcVariance.data(); const REAL * RESTRICT pInt=mIhklCalc.data(); const REAL * RESTRICT pVar=mFhklCalcVariance.data(); pcorr=mIntensityCorr.data(); mult=mMultiplicity.data(); for(long j=mNbReflUsed;j>0;j--) { *pVar2++ = (4* *mult) * *pcorr * *pVar *(*pInt++ - (*mult * *pcorr) * *pVar); pVar++;mult++;pcorr++; } VFN_DEBUG_MESSAGE(endl<< FormatVertVectorHKLFloats(mH,mK,mL,mSinThetaLambda, mFhklCalcReal, mIhklCalc, mExpectedIntensityFactor, mIntensityCorr, mMultiplicity, mvLuzzatiFactor[&(mpCrystal->GetScatteringPowerRegistry().GetObj(0))], mFhklCalcVariance, mIhklCalcVariance),2); VFN_DEBUG_MESSAGE(mNbRefl<<" "<(mTheta,mIhklCalc,mMultiplicity, // mFhklCalcReal,mFhklCalcImag,mIntensityCorr); mClockIhklCalc.Click(); VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcIhkl():End",3) } void PowderPatternDiffraction::CalcIhkl_FullDeriv(std::set &vPar) { TAU_PROFILE("PowderPatternDiffraction::CalcIhkl_FullDeriv()","void ()",TAU_DEFAULT); //cout<<"PowderPatternDiffraction::CalcIhkl_FullDeriv()"<CalcIntensityCorr();//:TODO: derivatives of intensity corrections (Texture, displacement parameters,...) mIhkl_FullDeriv.clear(); if(mExtractionMode==true) { //:TODO: handle Pawley refinements of I(hkl) return; } this->CalcStructFactor_FullDeriv(vPar); for(std::set::iterator par=vPar.begin();par!=vPar.end();++par) { if(*par==0) mIhkl_FullDeriv[*par]=mIhklCalc; else { if(mFhklCalcReal_FullDeriv[*par].size()==0) continue; const REAL * RESTRICT pr,* RESTRICT pi,* RESTRICT prd,* RESTRICT pid,* RESTRICT pcorr; const int * RESTRICT mult; REAL * RESTRICT p; pr=mFhklCalcReal.data(); pi=mFhklCalcImag.data(); prd=mFhklCalcReal_FullDeriv[*par].data(); pid=mFhklCalcImag_FullDeriv[*par].data(); pcorr=mIntensityCorr.data();//:TODO: derivatives of intensity corrections (Texture, displacement parameters,...) mult=mMultiplicity.data(); mIhkl_FullDeriv[*par].resize(mNbRefl); p=mIhkl_FullDeriv[*par].data(); if(mFhklCalcImag_FullDeriv[*par].size()==0) for(long i=mNbReflUsed;i>0;i--) *p++ = *mult++ * 2 * *pr++ * *prd++ * *pcorr++; else for(long i=mNbReflUsed;i>0;i--) *p++ = *mult++ * 2 *(*pr++ * *prd++ + *pi++ * *pid++) * *pcorr++; } } #if 0 std::map oldDeriv; std::vector v; v.push_back(&mH); v.push_back(&mK); v.push_back(&mL); CrystVector_REAL m; m=mMultiplicity; v.push_back(&m); v.push_back(&mIntensityCorr); int n=0; for(std::set::iterator par=vPar.begin();par!=vPar.end();++par) { if((*par)==0) continue; if(mIhkl_FullDeriv[*par].size()==0) continue; const REAL step=(*par)->GetDerivStep(); (*par)->Mutate(step); this->CalcIhkl(); oldDeriv[*par]=mIhklCalc; (*par)->Mutate(-2*step); this->CalcIhkl(); oldDeriv[*par]-=mIhklCalc; oldDeriv[*par]/=2*step; (*par)->Mutate(step); v.push_back(&(mIhkl_FullDeriv[*par])); v.push_back(&(oldDeriv[*par])); cout<<(*par)->GetName()<<":"<(v,12,1,20)<GetCrystal().GetSpaceGroup().GetClockSpaceGroup()>mClockHKL) ||(this->GetCrystal().GetClockLatticePar()>mClockHKL) ||(this->GetRadiation().GetClockWavelength()>mClockHKL) ||(mpParentPowderPattern->GetClockPowderPatternPar()>mClockHKL)) this->GenHKLFullSpace(); //if(0==this->GetNbRefl()) this->GenHKLFullSpace(); } void PowderPatternDiffraction::InitOptions() { VFN_DEBUG_MESSAGE("PowderPatternDiffraction::InitOptions()",5) #if 0 static string ReflectionProfileTypeName; static string ReflectionProfileTypeChoices[3]; static bool needInitNames=true; if(true==needInitNames) { ReflectionProfileTypeName="Profile Type"; ReflectionProfileTypeChoices[0]="Gaussian"; ReflectionProfileTypeChoices[1]="Lorentzian"; ReflectionProfileTypeChoices[2]="Pseudo-Voigt"; needInitNames=false;//Only once for the class } mReflectionProfileType.Init(3,&ReflectionProfileTypeName,ReflectionProfileTypeChoices); this->AddOption(&mReflectionProfileType); #endif } const CrystVector_long& PowderPatternDiffraction::GetBraggLimits()const { this->CalcPowderReflProfile(); if((mClockProfileCalc>mClockBraggLimits)&&(this->GetNbReflBelowMaxSinThetaOvLambda()>0)) { VFN_DEBUG_ENTRY("PowderPatternDiffraction::GetBraggLimits(*min,*max)",3) TAU_PROFILE("PowderPatternDiffraction::GetBraggLimits()","void ()",TAU_DEFAULT); mIntegratedReflLimits.resize(this->GetNbReflBelowMaxSinThetaOvLambda()); long i = 0; mIntegratedReflLimits(i)=mvReflProfile[0].first; for(;i<(this->GetNbReflBelowMaxSinThetaOvLambda()-1);++i) mIntegratedReflLimits(i+1)=(mvReflProfile[i].first+mvReflProfile[i].last+mvReflProfile[i+1].first+mvReflProfile[i+1].last)/4; mIntegratedReflLimits(i)=mvReflProfile[i].last; mClockBraggLimits.Click(); VFN_DEBUG_EXIT("PowderPatternDiffraction::GetBraggLimits(*min,*max)",3) } return mIntegratedReflLimits; } void PowderPatternDiffraction::SetMaxSinThetaOvLambda(const REAL max) {this->ScatteringData::SetMaxSinThetaOvLambda(max);} const CrystMatrix_REAL& PowderPatternDiffraction::GetBMatrix()const { if(mFreezeLatticePar) return mFrozenBMatrix; return this->ScatteringData::GetBMatrix(); } void PowderPatternDiffraction::CalcFrozenBMatrix()const { VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcFrozenBMatrix()", 10) REAL a,b,c,alpha,beta,gamma;//direct space parameters REAL aa,bb,cc,alphaa,betaa,gammaa;//reciprocal space parameters POSSIBLY_UNUSED(alphaa); REAL v;//volume of the unit cell a=mFrozenLatticePar(0); b=mFrozenLatticePar(1); c=mFrozenLatticePar(2); alpha=mFrozenLatticePar(3); beta=mFrozenLatticePar(4); gamma=mFrozenLatticePar(5); v=sqrt(1-cos(alpha)*cos(alpha)-cos(beta)*cos(beta)-cos(gamma)*cos(gamma) +2*cos(alpha)*cos(beta)*cos(gamma)); aa=sin(alpha)/a/v; bb=sin(beta )/b/v; cc=sin(gamma)/c/v; alphaa=acos( (cos(beta )*cos(gamma)-cos(alpha))/sin(beta )/sin(gamma) ); betaa =acos( (cos(alpha)*cos(gamma)-cos(beta ))/sin(alpha)/sin(gamma) ); gammaa=acos( (cos(alpha)*cos(beta )-cos(gamma))/sin(alpha)/sin(beta ) ); mFrozenBMatrix = aa , bb*cos(gammaa) , cc*cos(betaa) , 0 , bb*sin(gammaa) ,-cc*sin(betaa)*cos(alpha), 0 , 0 ,1/c; } void PowderPatternDiffraction::PrepareIntegratedProfile()const { this->CalcPowderReflProfile(); this->GetNbReflBelowMaxSinThetaOvLambda(); if( (mClockIntegratedProfileFactor>mClockProfileCalc) &&(mClockIntegratedProfileFactor>mpParentPowderPattern->GetIntegratedProfileLimitsClock()) &&(mClockIntegratedProfileFactor>mClockNbReflUsed)) return; VFN_DEBUG_ENTRY("PowderPatternDiffraction::PrepareIntegratedProfile()",7) TAU_PROFILE("PowderPatternDiffraction::PrepareIntegratedProfile()","void ()",TAU_DEFAULT); const CrystVector_long *pMin=&(mpParentPowderPattern->GetIntegratedProfileMin()); const CrystVector_long *pMax=&(mpParentPowderPattern->GetIntegratedProfileMax()); const long numInterval=pMin->numElements(); vector< map > vIntegratedProfileFactor; vIntegratedProfileFactor.resize(mNbReflUsed); vector< map >::iterator pos1; pos1=vIntegratedProfileFactor.begin(); mIntegratedProfileFactor.resize(mNbReflUsed); vector< pair >::iterator pos2; pos2=mIntegratedProfileFactor.begin(); for(long i=0;iclear(); long firstInterval=numInterval; for(long j=0;j(*pMin)(j) ? first0:(*pMin)(j); const long last = last0 <(*pMax)(j) ? last0 :(*pMax)(j); if((first<=last) && (mvReflProfile[i].profile.size()>0)) { if(firstInterval>j) firstInterval=j; if(pos1->find(j) == pos1->end()) (*pos1)[j]=0.; REAL *fact = &((*pos1)[j]);//this creates the 'j' entry if necessary const REAL *p2 = mvReflProfile[i].profile.data()+(first-first0); //cout << i<<","<first=firstInterval; pos2->second.resize(pos1->size()); REAL *pFact=pos2->second.data(); for(map::const_iterator pos=pos1->begin();pos!=pos1->end();++pos) *pFact++ = pos->second; pos1++; pos2++; } mClockIntegratedProfileFactor.Click(); #ifdef __DEBUG__ if(gVFNDebugMessageLevel<3) { unsigned long i=0; for(vector< pair >::const_iterator pos=mIntegratedProfileFactor.begin(); pos!=mIntegratedProfileFactor.end();++pos) { cout <<"Integrated profile factors for reflection #"<second.numElements();++j) cout << j+pos->first<<"("<second(j)<<") "; cout< gPowderPatternRegistry("List of all PowderPattern objects"); PowderPattern::PowderPattern(): mIsXAscending(true),mNbPoint(0), mXZero(0.),m2ThetaDisplacement(0.),m2ThetaTransparency(0.), mDIFC(48277.14),mDIFA(-6.7), mScaleFactor(20),mMuR(0), mUseFastLessPreciseFunc(false), mStatisticsExcludeBackground(false),mMaxSinThetaOvLambda(10),mNbPointUsed(0) { mScaleFactor=1; mSubObjRegistry.SetName("SubObjRegistry for a PowderPattern object"); mPowderPatternComponentRegistry.SetName("Powder Pattern Components"); this->AddSubRefObj(mRadiation); this->Init(); gPowderPatternRegistry.Register(*this); gTopRefinableObjRegistry.Register(*this); mClockMaster.AddChild(mClockPowderPatternPar); mClockMaster.AddChild(mClockNbPointUsed); mClockMaster.AddChild(mClockPowderPatternXCorr); mClockMaster.AddChild(mClockScaleFactor); mClockMaster.AddChild(mClockPowderPatternRadiation); mClockMaster.AddChild(mClockCorrAbs); } PowderPattern::PowderPattern(const PowderPattern &old): mIsXAscending(old.mIsXAscending),mNbPoint(old.mNbPoint), mRadiation(old.mRadiation), mXZero(old.mXZero),m2ThetaDisplacement(old.m2ThetaDisplacement), m2ThetaTransparency(old.m2ThetaTransparency), mDIFC(old.mDIFC),mDIFA(old.mDIFA), mPowderPatternComponentRegistry(old.mPowderPatternComponentRegistry), mScaleFactor(old.mScaleFactor),mMuR(old.mMuR), mUseFastLessPreciseFunc(old.mUseFastLessPreciseFunc), mStatisticsExcludeBackground(old.mStatisticsExcludeBackground), mMaxSinThetaOvLambda(old.mMaxSinThetaOvLambda),mNbPointUsed(old.mNbPointUsed) { mX=old.mX; this->Init(); mSubObjRegistry.SetName("SubObjRegistry for a PowderPattern :"+mName); gPowderPatternRegistry.Register(*this); gTopRefinableObjRegistry.Register(*this); this->AddSubRefObj(mRadiation); mClockMaster.AddChild(mClockPowderPatternPar); mClockMaster.AddChild(mClockNbPointUsed); mClockMaster.AddChild(mClockPowderPatternXCorr); mClockMaster.AddChild(mClockScaleFactor); mClockMaster.AddChild(mClockPowderPatternRadiation); } PowderPattern::~PowderPattern() { gPowderPatternRegistry.DeRegister(*this); for(int i=0;iRemoveSubRefObj(mPowderPatternComponentRegistry.GetObj(i)); delete &(mPowderPatternComponentRegistry.GetObj(i)); } gTopRefinableObjRegistry.DeRegister(*this); } const string& PowderPattern::GetClassName() const { const static string className="PowderPattern"; return className; } void PowderPattern::AddPowderPatternComponent(PowderPatternComponent &comp) { VFN_DEBUG_ENTRY("PowderPattern::AddPowderPatternComponent():"<AddSubRefObj(comp); comp.RegisterClient(*this); mClockPowderPatternCalc.Reset(); mClockIntegratedFactorsPrep.Reset(); mPowderPatternComponentRegistry.Register(comp); //:TODO: check if there are enough scale factors //mScaleFactor.resizeAndPreserve(mPowderPatternComponentRegistry.GetNb()); mScaleFactor(mPowderPatternComponentRegistry.GetNb()-1)=1.; mClockScaleFactor.Click(); if(comp.IsScalable()) {//Init refinable parameter RefinablePar tmp("Scale_"+comp.GetName(),mScaleFactor.data()+mPowderPatternComponentRegistry.GetNb()-1, 1e-10,1e10,gpRefParTypeScattDataScale,REFPAR_DERIV_STEP_RELATIVE, false,true,true,false,1.); tmp.SetGlobalOptimStep(0.); tmp.AssignClock(mClockScaleFactor); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } //this->UpdateDisplay(); VFN_DEBUG_EXIT("PowderPattern::AddPowderPatternComponent():"< mX(0)) mIsXAscending=true; else mIsXAscending=false; VFN_DEBUG_MESSAGE("PowderPattern::SetPowderPatternX() is ascending="<IsBeingRefined()) this->CalcNbPointUsed(); return mNbPointUsed; } const RefinableObjClock& PowderPattern::GetClockNbPointUsed()const{return mClockNbPointUsed;} void PowderPattern::SetRadiation(const Radiation &radiation) { mRadiation=radiation; mClockPowderPatternRadiation.Click(); } const Radiation& PowderPattern::GetRadiation()const {return mRadiation;} Radiation& PowderPattern::GetRadiation() {return mRadiation;} void PowderPattern::SetRadiationType(const RadiationType rad) { mRadiation.SetRadiationType(rad); } RadiationType PowderPattern::GetRadiationType()const {return mRadiation.GetRadiationType();} void PowderPattern::SetWavelength(const REAL lambda) { VFN_DEBUG_MESSAGE("PowderPattern::SetWavelength(lambda)",3) mRadiation.SetWavelength(lambda); } void PowderPattern::SetWavelength(const string &XRayTubeElementName,const REAL alpha12ratio) { VFN_DEBUG_MESSAGE("PowderPattern::SetWavelength(wavelength)",3) mRadiation.SetWavelength(XRayTubeElementName,alpha12ratio); } REAL PowderPattern::GetWavelength()const{return mRadiation.GetWavelength()(0);} const CrystVector_REAL& PowderPattern::GetPowderPatternCalc()const { this->CalcPowderPattern(); return mPowderPatternCalc; } std::map& PowderPattern::GetPowderPattern_FullDeriv(std::set &vPar) { this->CalcPowderPattern_FullDeriv(vPar); return mPowderPattern_FullDeriv; } const CrystVector_REAL& PowderPattern::GetPowderPatternObs()const { return mPowderPatternObs; } const CrystVector_REAL& PowderPattern::GetPowderPatternObsSigma()const { return mPowderPatternObsSigma; } const CrystVector_REAL& PowderPattern::GetPowderPatternVariance()const { return mPowderPatternVariance; } const CrystVector_REAL& PowderPattern::GetPowderPatternWeight()const { return mPowderPatternWeight; } REAL PowderPattern::GetPowderPatternXMin()const { if(mNbPoint==0) return 0;//:KLUDGE: ? if(true==mIsXAscending) return mX(0); return mX(mNbPoint-1); } REAL PowderPattern::GetPowderPatternXStep()const { if(mNbPoint==0) return 0;//:KLUDGE: ? return abs((-mX(0)+mX(mNbPoint-1))/(mNbPoint-1)); } REAL PowderPattern::GetPowderPatternXMax()const { if(mNbPoint==0) return 0;//:KLUDGE: ? if(true==mIsXAscending) return mX(mNbPoint-1); return mX(0); } const CrystVector_REAL& PowderPattern::GetPowderPatternX()const { return mX; } const CrystVector_REAL& PowderPattern::GetChi2Cumul(const int m)const { VFN_DEBUG_ENTRY("PowderPattern::GetChi2Cumul()",3) mChi2Cumul.resize(mNbPoint); int mode = m; if((mode!=0) && (mode!=1)) mode = mOptProfileIntegration.GetChoice(); if(0 == mode) { this->CalcPowderPatternIntegrated(); if(mNbIntegrationUsed==0) mChi2Cumul=0; else { const REAL *pObs=mIntegratedObs.data(); const REAL *pCalc=mPowderPatternIntegratedCalc.data(); const REAL *pWeight; if(mIntegratedWeight.numElements()==0) pWeight=mIntegratedWeightObs.data(); else pWeight=mIntegratedWeight.data(); REAL *pC2Cu=mChi2Cumul.data(); for(int i=0;i(int)mNbPointUsed) { for(unsigned int i=mIntegratedPatternMin(j);iCalcPowderPattern(); const REAL *pObs=mPowderPatternObs.data(); const REAL *pCalc=mPowderPatternCalc.data(); const REAL *pWeight=mPowderPatternWeight.data(); REAL *pC2Cu=mChi2Cumul.data(); REAL chi2cumul=0,tmp; for(unsigned int i=0;iX2Pixel(this->X2XCorr(x0)); } REAL PowderPattern::X2Pixel(const REAL x)const { //:TODO: faster if the step is actually constant. // Step may not be constant, so we guess twice before step-search REAL pixx; if(mIsXAscending==false) { VFN_DEBUG_MESSAGE("PowderPattern::X2Pixel()",1) long pix=(long)(mNbPoint-1-(x-this->GetPowderPatternXMin())/this->GetPowderPatternXStep()); if((pix>0)&&(pix<((long)mNbPoint-1))) { // Why floor() and ceil() don't return a bloody integer is beyond me const REAL localStep=mX(pix)-mX(pix+1); if(localStep>0) pix -= (long)((x-mX(pix))/localStep); } VFN_DEBUG_MESSAGE("PowderPattern::X2Pixel():"<((long)mNbPoint-2))pix=(long)mNbPoint-2; VFN_DEBUG_MESSAGE("PowderPattern::X2Pixel():"<=x) break; if(pix==0) break; } } else { for(;;pix++) { if(mX(pix)<=x) {pix--;break;} if(pix==((long)mNbPoint-2)) break; } } // This assumes step is at least localy constant... VFN_DEBUG_MESSAGE("PowderPattern::X2Pixel():"<GetPowderPatternXMin()<<","<GetPowderPatternXMax(),1) long pix=(long)((x-this->GetPowderPatternXMin())/this->GetPowderPatternXStep()); if((pix>0)&&(pix<((long)mNbPoint-1))) { // Why floor() and ceil() don't return a bloody integer is beyond me const REAL localStep=mX(pix+1)-mX(pix); if(localStep>0) pix += (long)((x-mX(pix))/localStep); } VFN_DEBUG_MESSAGE("PowderPattern::X2Pixel():"<((long)mNbPoint-2))pix=(long)mNbPoint-2; VFN_DEBUG_MESSAGE("PowderPattern::X2Pixel():"<=x) {pix-- ;break;} if(pix==((long)mNbPoint-2)) break; } } VFN_DEBUG_MESSAGE("PowderPattern::X2Pixel():"<((long)mNbPoint-2))pix=(long)mNbPoint-2; // This assumes step is at least localy constant... const REAL localStep=mX(pix+1)-mX(pix); VFN_DEBUG_MESSAGE("PowderPattern::X2Pixel():"<> min >> step >> max; min *= DEG2RAD; max *= DEG2RAD; step *= DEG2RAD; this->SetPowderPatternPar(min,step,(long)((max-min)/step+1.001)); VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternFullprof() :"\ << " 2Theta min=" << min*RAD2DEG << " 2Theta max=" << max*RAD2DEG \ << " NbPoints=" << mNbPoint,5) mPowderPatternObs.resize (mNbPoint); mPowderPatternObsSigma.resize (mNbPoint); mPowderPatternWeight.resize(mNbPoint); char tmpComment[200]; fin.getline(tmpComment,100); //if(""==mName) mName.append(tmpComment); for(unsigned long i=0;i> mPowderPatternObs(i); fin.close(); this->SetSigmaToSqrtIobs(); this->SetWeightToInvSigmaSq(); mClockPowderPatternPar.Click(); this->UpdateDisplay(); { char buf [200]; sprintf(buf,"Imported powder pattern: %d points, 2theta=%7.3f -> %7.3f, step=%6.3f", (int)mNbPoint,min*RAD2DEG,max*RAD2DEG,step*RAD2DEG); (*fpObjCrystInformUser)((string)buf); } VFN_DEBUG_MESSAGE("PowderPattern::ImportFullProfPattern():finished:"<> min >> step >> max; min *= DEG2RAD; max *= DEG2RAD; step *= DEG2RAD; this->SetPowderPatternPar(min,step,(unsigned long)((max-min)/step+1.001)); VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternPSI_DMC() :"\ << " 2Theta min=" << min*RAD2DEG << " 2Theta max=" << max*RAD2DEG \ << " NbPoints=" << mNbPoint,5) mPowderPatternObs.resize (mNbPoint); mPowderPatternObsSigma.resize (mNbPoint); mPowderPatternWeight.resize(mNbPoint); fin.getline(tmpComment,100); //if(""==mName) mName.append(tmpComment); for(unsigned long i=0;i> mPowderPatternObs(i); for(unsigned long i=0;i> mPowderPatternObsSigma(i); fin.close(); this->SetWeightToInvSigmaSq(); mClockPowderPatternPar.Click(); this->UpdateDisplay(); { char buf [200]; sprintf(buf,"Imported powder pattern: %d points, 2theta=%7.3f -> %7.3f, step=%6.3f", (int)mNbPoint,min*RAD2DEG,max*RAD2DEG,step*RAD2DEG); (*fpObjCrystInformUser)((string)buf); } VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternPSI_DMC():finished",5) } void PowderPattern::ImportPowderPatternILL_D1A5(const string &filename) { VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternILL_D1AD2B() : \ from file : "+filename,5) ifstream fin(filename.c_str()); if(!fin) { throw ObjCrystException("PowderPattern::ImportPowderPatternILL_D1AD2B() : \ Error opening file for input:"+filename); } //Skip the first three lines char tmpComment[200]; fin.getline(tmpComment,190); fin.getline(tmpComment,190); fin.getline(tmpComment,190); fin >> mNbPoint; fin.getline(tmpComment,190); REAL min,step; fin >> min >> step; min *= DEG2RAD; step *= DEG2RAD; this->SetPowderPatternPar(min,step,mNbPoint); VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternILL_D1AD2B() :"\ << " 2Theta min=" << min*RAD2DEG << " 2Theta max=" << min*RAD2DEG+mNbPoint*step*RAD2DEG \ << " NbPoints=" << mNbPoint,5) mPowderPatternObs.resize (mNbPoint); mPowderPatternObsSigma.resize (mNbPoint); mPowderPatternWeight.resize(mNbPoint); //if(""==mName) mName.append(tmpComment); for(unsigned long i=0;i> mPowderPatternObs(i); for(unsigned long i=0;i> mPowderPatternObsSigma(i); fin.close(); this->SetWeightToInvSigmaSq(); mClockPowderPatternPar.Click(); this->UpdateDisplay(); { char buf [200]; sprintf(buf,"Imported powder pattern: %d points, 2theta=%7.3f -> %7.3f, step=%6.3f", (int)mNbPoint,min*RAD2DEG,(min+step*(mNbPoint-1))*RAD2DEG, step*RAD2DEG); (*fpObjCrystInformUser)((string)buf); } VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternILL_D1AD2B():finished",5) } void PowderPattern::ImportPowderPatternXdd(const string &filename) { VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternXdd():from file :" \ +filename,5) ifstream fin (filename.c_str()); if(!fin) { throw ObjCrystException("PowderPattern::ImportPowderPatternXdd() : \ Error opening file for input:"+filename); } char tmpComment[200]; fin.getline(tmpComment,100); //if(""==mName) mName.append(tmpComment); REAL min,max,step,tmp; fin >> min >> step >> max; min *= DEG2RAD; max *= DEG2RAD; step *= DEG2RAD; this->SetPowderPatternPar(min,step,(long)((max-min)/step+1.001)); mPowderPatternObs.resize (mNbPoint); mPowderPatternObsSigma.resize(mNbPoint); mPowderPatternCalc.resize(mNbPoint); mPowderPatternWeight.resize(mNbPoint); mPowderPatternWeight=1.; fin >> tmp; //Count time fin >> tmp; //unused fin >> tmp; //unused (wavelength?) for(unsigned long i=0;i> mPowderPatternObs(i); fin.close(); this->SetSigmaToSqrtIobs(); this->SetWeightToInvSigmaSq(); this->UpdateDisplay(); { char buf [200]; sprintf(buf,"Imported powder pattern: %d points, 2theta=%7.3f -> %7.3f, step=%6.3f", (int)mNbPoint,min*RAD2DEG,max*RAD2DEG,step*RAD2DEG); (*fpObjCrystInformUser)((string)buf); } VFN_DEBUG_MESSAGE("DiffractionDataPowder::ImportXddPattern() :finished",5) } void PowderPattern::ImportPowderPatternSietronicsCPI(const string &filename) { VFN_DEBUG_ENTRY("PowderPattern::ImportPowderPatternSietronicsCPI():from file :" \ +filename,5) ifstream fin (filename.c_str()); if(!fin) { throw ObjCrystException("PowderPattern::ImportPowderPatternSietronicsCPI() : \ Error opening file for input:"+filename); } char tmpComment[300]; fin.getline(tmpComment,100); VFN_DEBUG_MESSAGE(" ->Discarded comment :"<> min >> max >> step; min *= DEG2RAD; max *= DEG2RAD; step *= DEG2RAD; this->SetPowderPatternPar(min,step,(long)((max-min)/step+1.001)); mPowderPatternObs.resize (mNbPoint); mPowderPatternObsSigma.resize(mNbPoint); mPowderPatternCalc.resize(mNbPoint); mPowderPatternWeight.resize(mNbPoint); mPowderPatternWeight=1.; //Following lines are ignored (no fixed format ?) string str; do { fin>>str; VFN_DEBUG_MESSAGE(" ->Read :"<> mPowderPatternObs(i); fin.close(); this->SetSigmaToSqrtIobs(); this->SetWeightToInvSigmaSq(); mClockPowderPatternPar.Click(); this->UpdateDisplay(); { char buf [200]; sprintf(buf,"Imported powder pattern: %d points, 2theta=%7.3f -> %7.3f, step=%6.3f", (int)mNbPoint,min*RAD2DEG,max*RAD2DEG,step*RAD2DEG); (*fpObjCrystInformUser)((string)buf); } VFN_DEBUG_EXIT("DiffractionDataPowder::ImportPowderPatternSietronicsCPI()",5) } void PowderPattern::ImportPowderPattern2ThetaObsSigma(const string &filename,const int nbSkip) { VFN_DEBUG_MESSAGE("DiffractionDataPowder::ImportPowderPattern2ThetaObsSigma():from:" \ +filename,5) ifstream fin (filename.c_str()); if(!fin) { throw ObjCrystException("PowderPattern::ImportPowderPattern2ThetaObsSigma():\ Error opening file for input:"+filename); } {//Get rid of first lines char tmpComment[200]; for(int i=0;i> mX (mNbPoint); fin >> mPowderPatternObs (mNbPoint); fin >> mPowderPatternObsSigma(mNbPoint); //cout << mX (mNbPoint)<<" " // << mPowderPatternObs (mNbPoint)<<" " // << mPowderPatternObsSigma(mNbPoint)<SetWeightToInvSigmaSq(); mClockPowderPatternPar.Click(); this->UpdateDisplay(); { char buf [200]; sprintf(buf,"Imported powder pattern: %d points, 2theta=%7.3f -> %7.3f, step=%6.3f", (int)mNbPoint,this->GetPowderPatternXMin()*RAD2DEG, this->GetPowderPatternXMax()*RAD2DEG, this->GetPowderPatternXStep()*RAD2DEG); (*fpObjCrystInformUser)((string)buf); } VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPattern2ThetaObsSigma()\ :finished: "<> mX(mNbPoint); fin >> mPowderPatternObs (mNbPoint); mPowderPatternObsSigma(mNbPoint) =sqrt(mPowderPatternObs(mNbPoint)); if(!fin) break; mNbPoint++; if( (mNbPoint%500)==0) { mX.resizeAndPreserve(mNbPoint+500); mPowderPatternObs.resizeAndPreserve(mNbPoint+500); mPowderPatternObsSigma.resizeAndPreserve(mNbPoint+500); } } while(fin.eof() == false); fin.close(); mX.resizeAndPreserve (mNbPoint); mPowderPatternObs.resizeAndPreserve (mNbPoint); mPowderPatternObsSigma.resizeAndPreserve(mNbPoint); mPowderPatternWeight.resize(mNbPoint); mX *= DEG2RAD; this->SetSigmaToSqrtIobs(); this->SetWeightToInvSigmaSq(); mClockPowderPatternPar.Click(); this->UpdateDisplay(); { char buf [200]; sprintf(buf,"Imported powder pattern: %d points, 2theta=%7.3f -> %7.3f, step=%6.3f", (int)mNbPoint,this->GetPowderPatternXMin()*RAD2DEG, this->GetPowderPatternXMax()*RAD2DEG, this->GetPowderPatternXStep()*RAD2DEG); (*fpObjCrystInformUser)((string)buf); } VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPattern2ThetaObs():finished",5) } void PowderPattern::ImportPowderPatternMultiDetectorLLBG42(const string &filename) { //Sample 4: NaY + CF2=CCL2 T=20K, Lambda: 2.343 A. // 100 0 0.100 70 0 0 // 3.000 // 500000. 12000. 0.00 0.00 //70 570369 569668 562868 532769 527469 495669 481969 452767 429468 4132 //68 393269 372067 353769 337068 328268 310270 299469 296470 294668 2780 //... //14 255814 282714 274014 281314 300314 302714 301114 298014 313214 3097 //14 286914 295714 305214 300714 288311 295511 288511 3024 8 2937 7 2883 // 7 2905 7 2895 7 2767 7 2777 7 2758 7 2495 7 2507 7 2496 7 2382 7 2329 // 7 2542 7 2415 7 2049 7 2389 7 2270 7 2157 6 2227 6 2084 3 1875 2 2094 // 1 1867 // -1000 // -10000 VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternMultiDetectorLLBG42() : \ from file : "+filename,5) ifstream fin(filename.c_str()); if(!fin) { throw ObjCrystException("PowderPattern::ImportPowderPatternMultiDetectorLLBG42() : \ Error opening file for input:"+filename); } string str; getline(fin,str); float junk; REAL min,step; fin >>junk>>junk>>step>>junk>>junk>>junk>>min>>junk>>junk>>junk>>junk; min *= DEG2RAD; step *= DEG2RAD; VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternMultiDetectorLLBG42() :"\ << " 2Theta min=" << min*RAD2DEG << " 2Theta step=" << step*RAD2DEG,5) mPowderPatternObs.resize (500); mPowderPatternObsSigma.resize (500); getline(fin,str);//finish reading line float tmp; string sub; float ct,iobs; mNbPoint=0; for(;;) { getline(fin,str); sscanf(str.c_str(),"%f",&tmp); if(tmp<0) break; const unsigned int nb=str.length()/8; for(unsigned int i=0;iSetPowderPatternPar(min,step,mNbPoint); //exit(1); mPowderPatternObs.resizeAndPreserve (mNbPoint); mPowderPatternObsSigma.resizeAndPreserve (mNbPoint); mPowderPatternWeight.resizeAndPreserve(mNbPoint); fin.close(); this->SetWeightToInvSigmaSq(); mClockPowderPatternPar.Click(); this->UpdateDisplay(); { char buf [200]; sprintf(buf,"Imported powder pattern: %d points, 2theta=%7.3f -> %7.3f, step=%6.3f", (int)mNbPoint,min*RAD2DEG,mX(mNbPoint-1)*RAD2DEG,step*RAD2DEG); (*fpObjCrystInformUser)((string)buf); } VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternMultiDetectorLLBG42():finished:"<> min >> step >> max; min *= DEG2RAD; max *= DEG2RAD; step *= DEG2RAD; this->SetPowderPatternPar(min,step,(long)((max-min)/step+1.001)); VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternFullprof4() :"\ << " 2Theta min=" << min*RAD2DEG << " 2Theta max=" << max*RAD2DEG \ << " NbPoints=" << mNbPoint,5) mPowderPatternObs.resize (mNbPoint); mPowderPatternObsSigma.resize (mNbPoint); mPowderPatternWeight.resize(mNbPoint); string str; getline(fin,str);//read end of first line unsigned ct=0; unsigned ctSig=0; float line[10]; for(;ctSetWeightToInvSigmaSq(); mClockPowderPatternPar.Click(); this->UpdateDisplay(); { char buf [200]; sprintf(buf,"Imported powder pattern: %d points, 2theta=%7.3f -> %7.3f, step=%6.3f", (int)mNbPoint,min*RAD2DEG,max*RAD2DEG, step*RAD2DEG); (*fpObjCrystInformUser)((string)buf); } VFN_DEBUG_MESSAGE("PowderPattern::ImportFullProfPattern4():finished:"<> mX (mNbPoint); fin >> mPowderPatternObs (mNbPoint); fin >> mPowderPatternObsSigma(mNbPoint); //cout << mX (mNbPoint)<<" " // << mPowderPatternObs (mNbPoint)<<" " // << mPowderPatternObsSigma(mNbPoint)<SetPowderPatternX(mX); this->SetWeightToInvSigmaSq(); this->SetRadiationType(RAD_NEUTRON); this->GetRadiation().SetWavelengthType(WAVELENGTH_TOF); mClockPowderPatternPar.Click(); this->UpdateDisplay(); { char buf [200]; sprintf(buf,"Imported TOF powder pattern: %d points, TOF=%7.3f -> %7.3f", (int)mNbPoint,this->GetPowderPatternXMin(), this->GetPowderPatternXMax()); (*fpObjCrystInformUser)((string)buf); } VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternTOF_ISIS_XYSigma()\ :finished: "<GetName()=="Change Me!") this->SetName(title); } //BANK 1 38101 7620 CONST 200.00 0.10 0 0 ESD int numBank,nbRecords; string binType, type; float bcoeff[4]; //string line; char line[81]; char bank[5]; do { fin.getline(line,80); while(isprint(fin.peek())==false) { if(fin.eof()) break; fin.get(); } sscanf(line,"%4s",bank); if(fin.eof()) throw ObjCrystException("PowderPattern::ImportPowderPatternGSAS():\ Could not find BANK statement !! In file: "+filename); } while(string(bank)!=string("BANK")); { line[80]='\0'; char binTypeC[20],typeC[20]; sscanf(line,"%4s%d %ld %d %s %f %f %f %f %s",bank,&numBank,&mNbPoint,&nbRecords, binTypeC,&bcoeff[0],&bcoeff[1],&bcoeff[2],&bcoeff[3],typeC); binType=binTypeC; type=typeC; } if(binType=="CONST") binType="CONS"; if((type!="ALT")&&(type!="ESD")) type="STD"; cout<<"BANK #"<SetPowderPatternPar(bcoeff[0]*DEG2RAD/100,bcoeff[1]*DEG2RAD/100,mNbPoint); string sub; unsigned long point=0; REAL iobs,isig; string substr; for(long i=0;i> iobs; substr=string(line).substr(j*16+8 ,8); istringstream(substr) >> isig; mPowderPatternObs(point)=iobs; mPowderPatternObsSigma(point++)=isig; if(point==mNbPoint) break; } if(point==mNbPoint) break; } importOK=true; } if((binType=="CONS") && (type=="STD")) { this->SetPowderPatternPar(bcoeff[0]*DEG2RAD/100,bcoeff[1]*DEG2RAD/100,mNbPoint); unsigned long point=0; REAL iobs; int nc; string substr; for(long i=0;i> iobs; mPowderPatternObs(point)=iobs; mPowderPatternObsSigma(point++)=sqrt(iobs)/sqrt((REAL)nc); if(point==mNbPoint) break; } if(point==mNbPoint) break; } importOK=true; } if((binType=="RALF") && (type=="ALT")) { this->SetRadiationType(RAD_NEUTRON); this->GetRadiation().SetWavelengthType(WAVELENGTH_TOF); mClockPowderPatternPar.Click(); unsigned long point=0; REAL x,iobs,iobssigma; string substr; for(long i=0;i> x; substr=string(line).substr(j*20+8 ,7); istringstream(substr) >> iobs; substr=string(line).substr(j*20+15,5); istringstream(substr) >> iobssigma; mPowderPatternObs(point)=iobs; mPowderPatternObsSigma(point)=iobssigma; mX(point)=x/32; if(++point==mNbPoint) break; } if(point==mNbPoint) break; } // Reverse order of arrays, so that we are in ascending order of sin(theta)/lambda REAL tmp; for(unsigned long i=0;i<(mNbPoint/2);i++) { tmp=mX(i); mX(i)=mX(mNbPoint-1-i); mX(mNbPoint-1-i)=tmp; tmp=mPowderPatternObs(i); mPowderPatternObs(i)=mPowderPatternObs(mNbPoint-1-i); mPowderPatternObs(mNbPoint-1-i)=tmp; tmp=mPowderPatternObsSigma(i); mPowderPatternObsSigma(i)=mPowderPatternObsSigma(mNbPoint-1-i); mPowderPatternObsSigma(mNbPoint-1-i)=tmp; } importOK=true; } fin.close(); if(!importOK) { mNbPoint=0; mPowderPatternObs.resize (mNbPoint); mPowderPatternObsSigma.resize(mNbPoint); mX.resize(mNbPoint); throw ObjCrystException("PowderPattern::ImportPowderPatternGSAS(): Sorry, \ this type of format is not handled yet (send an example file to the Fox author)!:"+filename); } mPowderPatternWeight.resize(mNbPoint); this->SetPowderPatternX(mX); this->SetWeightToInvSigmaSq(); this->UpdateDisplay(); if(this->GetRadiation().GetWavelengthType()==WAVELENGTH_TOF) { char buf [200]; sprintf(buf,"Imported powder pattern: %d points, tof=%7.3f us-> %7.3f us", (int)mNbPoint,this->GetPowderPatternXMin(), this->GetPowderPatternXMax()); (*fpObjCrystInformUser)((string)buf); } else { char buf [200]; sprintf(buf,"Imported powder pattern: %d points, 2theta=%7.3f -> %7.3f, step=%6.3f", (int)mNbPoint,this->GetPowderPatternXMin()*RAD2DEG, this->GetPowderPatternXMax()*RAD2DEG, this->GetPowderPatternXStep()*RAD2DEG); (*fpObjCrystInformUser)((string)buf); } VFN_DEBUG_EXIT("PowderPattern::ImportPowderPatternGSAS():file:"<::const_iterator pos=cif.mvData.begin();pos!=cif.mvData.end();++pos) if(pos->second.mPowderPatternObs.size()>10) { mNbPoint=pos->second.mPowderPatternObs.size(); mX.resize(mNbPoint); mPowderPatternObs.resize(mNbPoint); mPowderPatternObsSigma.resize(mNbPoint); mPowderPatternWeight.resize(mNbPoint); if(pos->second.mDataType==WAVELENGTH_TOF) { this->SetRadiationType(RAD_NEUTRON); this->GetRadiation().SetWavelengthType(WAVELENGTH_TOF); mClockPowderPatternPar.Click(); } else this->GetRadiation().SetWavelength(pos->second.mWavelength); for(unsigned long i=0;isecond.mPowderPatternObs[i]; mX(i)=pos->second.mPowderPatternX[i]; mPowderPatternObsSigma(i)=pos->second.mPowderPatternSigma[i]; } this->SetWeightToInvSigmaSq(); this->SetPowderPatternX(mX); } VFN_DEBUG_EXIT("PowderPattern::ImportPowderPatternCIF():file:",5) } void PowderPattern::SetPowderPatternObs(const CrystVector_REAL& obs) { VFN_DEBUG_MESSAGE("PowderPattern::SetPowderPatternObs()",5) if((unsigned long)obs.numElements() != mNbPoint) { throw(ObjCrystException("PowderPattern::SetPowderPatternObs(vect): The \ supplied vector of observed intensities does not have the expected number of points!")); } mPowderPatternObs=obs; mPowderPatternObsSigma.resize(mPowderPatternObs.numElements()); mPowderPatternWeight.resize(mNbPoint); this->SetSigmaToSqrtIobs(); this->SetWeightToInvSigmaSq(); mClockIntegratedFactorsPrep.Reset(); { char buf [200]; sprintf(buf,"Changed powder pattern: %d points, 2theta=%7.3f -> %7.3f, step=%6.3f", (int)mNbPoint,mX(0)*RAD2DEG,mX(mNbPoint-1)*RAD2DEG, (mX(mNbPoint-1)-mX(0))/(mNbPoint-1)*RAD2DEG); (*fpObjCrystInformUser)((string)buf); } } void PowderPattern::SavePowderPattern(const string &filename) const { VFN_DEBUG_MESSAGE("PowderPattern::SavePowderPattern",5) this->CalcPowderPattern(); ofstream out(filename.c_str()); CrystVector_REAL ttheta; ttheta=mX; if(this->GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) ttheta *= RAD2DEG; CrystVector_REAL diff; diff=mPowderPatternObs; diff-=mPowderPatternCalc; out << "# 2Theta/TOF Iobs ICalc Iobs-Icalc Weight Comp0" << endl; out << FormatVertVector(ttheta, mPowderPatternObs, mPowderPatternCalc, diff,mPowderPatternWeight, mPowderPatternComponentRegistry.GetObj(0).mPowderPatternCalc,16,8); out.close(); VFN_DEBUG_MESSAGE("DiffractionDataPowder::SavePowderPattern:End",3) } void PowderPattern::PrintObsCalcData(ostream&os)const { VFN_DEBUG_MESSAGE("DiffractionDataPowder::PrintObsCalcData()",5); CrystVector_REAL ttheta; ttheta=mX; if(this->GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) ttheta *= RAD2DEG; os << "PowderPattern : " << mName <(ttheta,mPowderPatternObs,mPowderPatternObsSigma, mPowderPatternCalc,mPowderPatternWeight,16,8); // mPowderPatternComponentRegistry.GetObj(0).mPowderPatternCalc,12,4); } REAL PowderPattern::GetR()const { if( (0==this->GetPowderPatternObs().numElements()) ||(0==GetNbPowderPatternComponent())) { return 0; } this->CalcPowderPattern(); TAU_PROFILE("PowderPattern::GetR()","void ()",TAU_DEFAULT); REAL tmp1=0.; REAL tmp2=0.; unsigned long maxPoints=mNbPointUsed; if( (true==mStatisticsExcludeBackground) &&(mPowderPatternBackgroundCalc.numElements()>0)) { const REAL *p1, *p2, *p3; p1=mPowderPatternCalc.data(); p2=mPowderPatternObs.data(); p3=mPowderPatternBackgroundCalc.data(); const long nbExclude=mExcludedRegionMinX.numElements(); if(0==nbExclude) { VFN_DEBUG_MESSAGE("PowderPattern::GetR():Exclude Backgd",4); for(unsigned long i=0;iX2Pixel(mExcludedRegionMinX(j))); max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(j))); if(min>maxPoints) break; if(max>maxPoints)max=maxPoints; for(;iX2Pixel(mExcludedRegionMinX(j))); max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(j))); if(min>maxPoints) break; if(max>maxPoints)max=maxPoints; for(;iGetPowderPatternObs().numElements()) ||(0==GetNbPowderPatternComponent())) { return 0; } this->CalcPowderPattern(); this->PrepareIntegratedRfactor(); VFN_DEBUG_ENTRY("PowderPattern::GetIntegratedR()",4); TAU_PROFILE("PowderPattern::GetIntegratedR()","void ()",TAU_DEFAULT); REAL tmp1=0.; REAL tmp2=0.; const long numInterval=mIntegratedPatternMin.numElements(); if( (true==mStatisticsExcludeBackground) &&(mPowderPatternBackgroundCalc.numElements()>0)) { const REAL *p1, *p2, *p3; CrystVector_REAL integratedCalc(numInterval); integratedCalc=0; CrystVector_REAL backgdCalc(numInterval); backgdCalc=0; REAL *pp1=integratedCalc.data(); REAL *pp2=backgdCalc.data(); for(int i=0;i(mPowderPatternObs, // mPowderPatternCalc, // mPowderPatternWeight); REAL tmp1=0.; REAL tmp2=0.; unsigned long maxPoints=mNbPointUsed; if( (true==mStatisticsExcludeBackground) &&(mPowderPatternBackgroundCalc.numElements()>0)) { VFN_DEBUG_MESSAGE("PowderPattern::GetRw():Exclude Backgd",3); const REAL *p1, *p2, *p3, *p4; p1=mPowderPatternCalc.data(); p2=mPowderPatternObs.data(); p3=mPowderPatternBackgroundCalc.data(); p4=mPowderPatternWeight.data(); const long nbExclude=mExcludedRegionMinX.numElements(); if(0==nbExclude) { for(unsigned long i=0;iX2Pixel(mExcludedRegionMinX(j))); max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(j))); if(min>maxPoints) break; if(max>maxPoints)max=maxPoints; for(;iX2Pixel(mExcludedRegionMinX(j))); max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(j))); if(min>maxPoints) break; if(max>maxPoints)max=maxPoints; for(;i0)) { const REAL *p1, *p2, *p3, *p4; CrystVector_REAL integratedCalc(numInterval); integratedCalc=0; CrystVector_REAL backgdCalc(numInterval); backgdCalc=0; REAL *pp1=integratedCalc.data(); REAL *pp2=backgdCalc.data(); for(int i=0;i"<GetPowderPatternObs().numElements()) ||(0==GetNbPowderPatternComponent())) { mChi2=0.; return mChi2; } this->CalcNbPointUsed(); if(mClockChi2>mClockMaster) return mChi2; this->CalcPowderPattern(); if( (mClockChi2>mClockPowderPatternPar) &&(mClockChi2>mClockScaleFactor) &&(mClockChi2>mClockPowderPatternCalc)) return mChi2; // We want the best scale factor this->FitScaleFactorForRw(); TAU_PROFILE("PowderPattern::GetChi2()","void ()",TAU_DEFAULT); VFN_DEBUG_ENTRY("PowderPattern::GetChi2()",3); const unsigned long maxPoints=mNbPointUsed; mChi2=0.; mChi2LikeNorm=0.; VFN_DEBUG_MESSAGE("PowderPattern::GetChi2()Integrated profiles",3); const REAL * RESTRICT p1, * RESTRICT p2, * RESTRICT p3; p1=mPowderPatternCalc.data(); p2=mPowderPatternObs.data(); p3=mPowderPatternWeight.data(); const long nbExclude=mExcludedRegionMinX.numElements(); if(0==nbExclude) { for(unsigned long i=0;iX2Pixel(mExcludedRegionMinX(j))); max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(j))); if(min>maxPoints) break; if(max>maxPoints)max=maxPoints; for(;i0) weightProd *= *p3; p1++;p2++;p3++; if(++i == mNbIntegrationUsed) break; } mIntegratedChi2LikeNorm -= log(weightProd); weightProd=1.; } mIntegratedChi2LikeNorm/=2; VFN_DEBUG_MESSAGE("Chi^2="< Number of Scale Factors:"<X2Pixel(mExcludedRegionMinX(j))); max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(j))); if(min>mNbPointUsed) break; if(max>mNbPointUsed)max=mNbPointUsed; //! min is the *beginning* of the excluded region for(;lX2Pixel(mExcludedRegionMinX(k))); max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(k))); if(min>mNbPointUsed) break; if(max>mNbPointUsed)max=mNbPointUsed; //! min is the *beginning* of the excluded region for(;lX2Pixel(mExcludedRegionMinX(k))); max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(k))); if(min>mNbPointUsed) break; if(max>mNbPointUsed)max=mNbPointUsed; //! min is the *beginning* of the excluded region for(;l Old:"<GetPowderPatternObs().numElements()) ||(0==GetNbPowderPatternComponent())) { return ; } this->CalcPowderPattern(); this->PrepareIntegratedRfactor(); VFN_DEBUG_ENTRY("PowderPattern::FitScaleFactorForIntegratedR()",3); TAU_PROFILE("PowderPattern::FitScaleFactorForIntegratedR()","void ()",TAU_DEFAULT); // Which components are scalable ? mScalableComponentIndex.resize(mPowderPatternComponentRegistry.GetNb()); int nbScale=0; for(int i=0;i Number of Scale Factors:"<1) { const REAL *p1; REAL *p2=backdIntegrated.data(); for(int j=0;j(integratedCalc[0],mIntegratedObs,mIntegratedWeight,backdIntegrated)<(integratedCalc[0],mIntegratedObs,mIntegratedWeight)< Old:"<GetPowderPatternObs().numElements()) ||(0==GetNbPowderPatternComponent())) { return ; } TAU_PROFILE("PowderPattern::FitScaleFactorForRw()","void ()",TAU_DEFAULT); VFN_DEBUG_ENTRY("PowderPattern::FitScaleFactorForRw()",3); this->CalcPowderPattern(); //:TODO: take into account excluded regions... // Which components are scalable ? mScalableComponentIndex.resize(mPowderPatternComponentRegistry.GetNb()); int nbScale=0; for(int i=0;i Number of Scale Factors:"<X2Pixel(mExcludedRegionMinX(j))); max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(j))); if(min>mNbPointUsed) break; if(max>mNbPointUsed)max=mNbPointUsed; //! min is the *beginning* of the excluded region for(;lX2Pixel(mExcludedRegionMinX(k))); max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(k))); if(min>mNbPointUsed) break; if(max>mNbPointUsed)max=mNbPointUsed; //! min is the *beginning* of the excluded region for(;lX2Pixel(mExcludedRegionMinX(k))); max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(k))); if(min>mNbPointUsed) break; if(max>mNbPointUsed)max=mNbPointUsed; //! min is the *beginning* of the excluded region for(;l Old:"<GetPowderPatternObs().numElements()) ||(0==GetNbPowderPatternComponent())) { return ; } this->CalcPowderPatternIntegrated(); if(mClockScaleFactor>mClockPowderPatternIntegratedCalc)return; VFN_DEBUG_ENTRY("PowderPattern::FitScaleFactorForIntegratedRw()",3); TAU_PROFILE("PowderPattern::FitScaleFactorForIntegratedRw()","void ()",TAU_DEFAULT); // Which components are scalable ? Which scalable calculated components have a non-null variance ? mScalableComponentIndex.resize(mPowderPatternComponentRegistry.GetNb()); CrystVector_REAL vScalableVarianceIndex(mPowderPatternComponentRegistry.GetNb()); int nbScale=0; int nbVarCalc=0; for(int i=0;inumElements()) vScalableVarianceIndex(nbVarCalc++)=i; } } VFN_DEBUG_MESSAGE("-> Number of Scale Factors:"<data(); const REAL * RESTRICT p1v=mIntegratedVarianceObs.data(); const REAL * RESTRICT p2v=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(0)) .GetPowderPatternIntegratedCalcVariance().first->data(); if(mPowderPatternBackgroundIntegratedCalc.numElements()<=1) { for(unsigned long k=mNbIntegrationUsed;k>0;k--) { a += *p2v * *p1 * *p2; b += *p2 * *p2 * *p1v - *p1 * *p1 * *p2v; c -= *p1 * *p2 * *p1v; p1++;p2++;p1v++;p2v++; } } else { const REAL * RESTRICT p3=mPowderPatternBackgroundIntegratedCalc.data(); for(unsigned long k=mNbIntegrationUsed;k>0;k--) { a += *p2v * (*p1 - *p3) * *p2; b += *p2 * *p2 * *p1v - (*p1 - *p3) * (*p1 - *p3) * *p2v; c -= (*p1 - *p3) * *p2 * *p1v; p1++;p2++;p1v++;p2v++;p3++; } } // Only one >0 solution to the 2nd degree equation newscale=(REAL)((-b+sqrt(b*b-4*a*c))/(2*a)); } {// Store new scale, and correct old calculated pattern const REAL s = newscale-mScaleFactor(mScalableComponentIndex(0)); const REAL s2 = newscale*newscale -mScaleFactor(mScalableComponentIndex(0)) *mScaleFactor(mScalableComponentIndex(0)); REAL * RESTRICT p0 = mPowderPatternIntegratedCalc.data(); const REAL * RESTRICT p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(0)) .GetPowderPatternIntegratedCalc().first->data(); REAL * RESTRICT p0v = mPowderPatternVarianceIntegrated.data(); const REAL * RESTRICT p1v=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(0)) .GetPowderPatternIntegratedCalcVariance().first->data(); REAL * RESTRICT p0w = mIntegratedWeight.data(); for(unsigned long j=mNbIntegrationUsed;j>0;j--) { *p0++ += s * *p1++; *p0v += s2 * *p1v++; if(*p0v <=0) {*p0w++ =0;p0v++;}else *p0w++ = 1. / *p0v++; } } mScaleFactor(mScalableComponentIndex(0)) = newscale; mClockScaleFactor.Click(); mClockPowderPatternIntegratedCalc.Click();//we *did* correct the spectrum } else { again=false; mScalableComponentIndex.resizeAndPreserve(nbScale); // prepare matrices mFitScaleFactorM.resize(nbScale,nbScale); mFitScaleFactorB.resize(nbScale,1); mFitScaleFactorX.resize(nbScale,1); // Build Matrix & Vector for LSQ VFN_DEBUG_MESSAGE("PowderPattern::FitScaleFactorForIntegratedRw():1",2); vector integratedCalc; for(int i=0;idata(); const REAL * RESTRICT p2=integratedCalc[j]->data(); const REAL * RESTRICT p3; if(mIntegratedWeight.numElements()==0) { p3=mIntegratedWeightObs.data(); if(ctagain>5) VFN_DEBUG_MESSAGE("ctagain="<5) VFN_DEBUG_MESSAGE("ctagain="<0;k--) {m += *p1 * *p1 * *p3++; p1++;} else for(unsigned long k=mNbIntegrationUsed;k>0;k--) m += *p1++ * *p2++ * *p3++; mFitScaleFactorM(i,j)=m; mFitScaleFactorM(j,i)=m; } } VFN_DEBUG_MESSAGE("PowderPattern::FitScaleFactorForIntegratedRw():4",2); for(int i=0;idata(); const REAL * RESTRICT p4; if(mIntegratedWeight.numElements()==0) p4=mIntegratedWeightObs.data(); else p4=mIntegratedWeight.data(); REAL b=0.; if(mPowderPatternBackgroundIntegratedCalc.numElements()<=1) { for(unsigned long k=mNbIntegrationUsed;k>0;k--) { b += *p1++ * *p2++ * *p4++; //cout<<"B:"<0;k--) { //cout<<"B(minus backgd):"<0) { //if(ctagain>0) cout <<"ctgain, sumvar="<numElements()) { const REAL * RESTRICT p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i)) .GetPowderPatternIntegratedCalcVariance().first->data(); //cout <<",sumvar(i)="<sum()); REAL * RESTRICT p0 = mPowderPatternVarianceIntegrated.data(); const REAL s2 = mFitScaleFactorX(i)*mFitScaleFactorX(i) -mScaleFactor(mScalableComponentIndex(i)) *mScaleFactor(mScalableComponentIndex(i)); for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ += s2 * *p1++; } } } //if(ctagain>0) cout <<" ->"<0) { if(abs(s/mFitScaleFactorX(i))>0.001) { again=true; //cout<<"log(scale) :"<"<"<log(scale) Old :"<5) { VFN_DEBUG_MESSAGE("PowderPattern::FitScaleFactorForIntegratedRw(), scaling again #"<Prepare(); if(0 == mOptProfileIntegration.GetChoice()) this->FitScaleFactorForIntegratedRw(); else this->FitScaleFactorForRw(); this->RefinableObj::BeginOptimization(allowApproximations,enableRestraints); } //void PowderPattern::SetApproximationFlag(const bool allow) //{// Do we need this ? // this->Prepare(); // if(0 == mOptProfileIntegration.GetChoice()) this->FitScaleFactorForIntegratedRw(); // else this->FitScaleFactorForRw(); // this->RefinableObj::SetApproximationFlag(allow); //} void PowderPattern::GlobalOptRandomMove(const REAL mutationAmplitude, const RefParType *type) { if(mRandomMoveIsDone) return; this->RefinableObj::GlobalOptRandomMove(mutationAmplitude,type); } void PowderPattern::AddExcludedRegion(const REAL min,const REAL max) { VFN_DEBUG_MESSAGE("PowderPattern::AddExcludedRegion()",5) const int num=mExcludedRegionMinX.numElements(); if(num>0) { mExcludedRegionMinX.resizeAndPreserve(num+1); mExcludedRegionMaxX.resizeAndPreserve(num+1); } else { mExcludedRegionMinX.resize(1); mExcludedRegionMaxX.resize(1); } mExcludedRegionMinX(num)=min; mExcludedRegionMaxX(num)=max; //ensure regions are sorted by ascending 2thetamin CrystVector_long subs; subs=SortSubs(mExcludedRegionMinX); CrystVector_REAL tmp1,tmp2; tmp1=mExcludedRegionMinX; tmp2=mExcludedRegionMaxX; for(int i=0;i(mExcludedRegionMinX,mExcludedRegionMaxX),5) VFN_DEBUG_MESSAGE("PowderPattern::Add2ThetaExcludedRegion():End",5) } REAL PowderPattern::GetLogLikelihood()const { REAL tmp=this->GetChi2_Option(); if(mOptProfileIntegration.GetChoice()==0) tmp+=mIntegratedChi2LikeNorm; else tmp+=mChi2LikeNorm; return tmp; } unsigned int PowderPattern::GetNbLSQFunction()const{return 2;} const CrystVector_REAL& PowderPattern::GetLSQCalc(const unsigned int idx) const { TAU_PROFILE("PowderPattern::GetLSQCalc()","void ()",TAU_DEFAULT); switch(idx) { case 1: { this->CalcPowderPatternIntegrated(); mPowderPatternUsedCalc=mPowderPatternIntegratedCalc; break; } default: { mPowderPatternUsedCalc=this->GetPowderPatternCalc(); mPowderPatternUsedCalc.resizeAndPreserve(mNbPointUsed); break; } } return mPowderPatternUsedCalc; } const CrystVector_REAL& PowderPattern::GetLSQObs(const unsigned int idx) const { TAU_PROFILE("PowderPattern::GetLSQObs()","void ()",TAU_DEFAULT); switch(idx) { case 1: { this->PrepareIntegratedRfactor(); mPowderPatternUsedObs=mIntegratedObs; break; } default: { mPowderPatternUsedObs=this->GetPowderPatternObs(); mPowderPatternUsedObs.resizeAndPreserve(mNbPointUsed); break; } } return mPowderPatternUsedObs; } const CrystVector_REAL& PowderPattern::GetLSQWeight(const unsigned int idx) const { TAU_PROFILE("PowderPattern::GetLSQWeight()","void ()",TAU_DEFAULT); switch(idx) { case 1: { this->PrepareIntegratedRfactor(); // :KLUDGE: When variance is used, mIntegratedWeight will change at each powder pattern calculation, // so this might be quite wrong... if(mIntegratedWeight.numElements()==0) mPowderPatternUsedWeight=mIntegratedWeightObs; else mPowderPatternUsedWeight=mIntegratedWeight; break; } default: { mPowderPatternUsedWeight=this->GetPowderPatternWeight(); mPowderPatternUsedWeight.resizeAndPreserve(mNbPointUsed); break; } } return mPowderPatternUsedWeight; } std::map& PowderPattern::GetLSQ_FullDeriv(const unsigned int idx,std::set &vPar) { TAU_PROFILE("PowderPattern::GetLSQ_FullDeriv()","void ()",TAU_DEFAULT); //return this->RefinableObj::GetLSQ_FullDeriv(idx,vPar); if(idx==1) { this->CalcPowderPatternIntegrated_FullDeriv(vPar); #if 0 std::map fullderiv_old; std::vector v; int n=0; //cout<<"PowderPattern::GetLSQ_FullDeriv(integrated):scales:"<::iterator par=vPar.begin();par!=vPar.end();++par) { v.push_back(&(mPowderPatternIntegrated_FullDeriv[*par])); fullderiv_old[*par]=this->GetLSQDeriv(idx,*(*par)); v.push_back(&(fullderiv_old[*par])); cout<<(*par)->GetName()<<":"<8) break; } cout<<"PowderPattern::GetLSQ_FullDeriv(integrated):"<(v,12,1,20)<GetPowderPattern_FullDeriv(vPar); return mPowderPattern_FullDeriv; } void PowderPattern::Prepare() { VFN_DEBUG_MESSAGE("PowderPattern::Prepare()",5); for(int i=0;iGetNbPar();j++) if(&(obj.GetPar(i)) == &(this->GetPar(j))) { if(this->GetPar(j).GetType()->IsDescendantFromOrSameAs(gpRefParTypeScattDataScale)) { if(scaleIndex==0) scaleIndex=first++; groupIndex(i)=scaleIndex; } else //gpRefParTypeScattDataCorrPos { if(thetaIndex==0) thetaIndex=first++; groupIndex(i)=thetaIndex; } } } void PowderPattern::SetMaxSinThetaOvLambda(const REAL max) { mMaxSinThetaOvLambda=max; for(int i=0;iPrepareIntegratedRfactor(); return mIntegratedPatternMin; } const CrystVector_long& PowderPattern::GetIntegratedProfileMax()const { this->PrepareIntegratedRfactor(); return mIntegratedPatternMax; } const RefinableObjClock& PowderPattern::GetIntegratedProfileLimitsClock()const { return mClockIntegratedFactorsPrep; } REAL PowderPattern::STOL2X(const REAL stol)const { REAL x; if(this->GetRadiation().GetWavelengthType()==WAVELENGTH_TOF) { if(stol>0) x = 1.0/(2*stol); else return 0; x = mDIFC*x+mDIFA*x*x; VFN_DEBUG_MESSAGE("PowderPattern::STOL2X("<=thres) { cout<=nb) break; } cout< "<=nb) break; obs(i)=0; } } cout<<"Width of "<=16)width_golay=16; } // get 2nd derivative CrystVector_REAL obsd2; obsd2=SavitzkyGolay(this->GetPowderPatternObs(),width_golay,2); // Zero excluded regions. for(long i= 0;iX2Pixel(mExcludedRegionMinX(i))); max=(long)ceil (this->X2Pixel(mExcludedRegionMaxX(i))); if(min<0) min = 0; if(max>=obsd2.numElements()) max = obsd2.numElements(); for(long j=min;j sub(tmp.numElements()); QuickSortSubs(tmp,sub,tmp.numElements()-1,0); min_iobs=5*(tmp(tmp.numElements()/2)-tmp(tmp.numElements()/4)); //cout<<__FILE__<<":"<<__LINE__<<" MIN_IOBS (automatic)="<=lastiobs) break; lastiobs=obsd2(i); obsd2(i)=0; iobs+=lastiobs; xmax+=mX(i)*lastiobs;nbav++; if(lastiobs<=0) break; //cout<=(nb-2)) break; if(obsd2(++i)>=lastiobs) break; lastiobs=obsd2(i); obsd2(i)=0; iobs+=lastiobs; xmax+=mX(i)*lastiobs;nbav++; if(lastiobs<=0) break; //cout<X2STOL(xmax)*2; dright=this->X2STOL(dright)*2; dleft =this->X2STOL(dleft)*2; //TODO : evaluate min intensity ratio from noise ? if(min_iobs<0) { cout<GetPowderPatternObsSigma()(imax)<<","<GetPowderPatternObs()(imax)<(&(this->GetPowderPatternComponent(i))); if(this->GetPowderPatternComponent(i).GetClassName()=="PowderPatternDiffraction") vDiff.push_back(dynamic_cast(&(this->GetPowderPatternComponent(i)))); } if((pBackground==0)||vDiff.size()==0) return; // Powder data file ofstream dat((prefix+".dat").c_str()); dat<<"XYDATA"<GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) ttheta *= RAD2DEG; dat << FormatVertVector(ttheta,mPowderPatternObs,mPowderPatternObsSigma,12,4); dat.close(); // PCR file ofstream pcr((prefix+".pcr").c_str()); // if(!pcr) :TODO: // Title pcr<<"Fox/ObjCryst exported file:"<GetName()<GetRadiation().GetRadiationType()==RAD_XRAY) job=0; if(this->GetRadiation().GetRadiationType()==RAD_NEUTRON) job=1; //:TODO: TOF: pcr<<"! Job Npr Nba Nex Nsc Nor Iwg Ilo Res Ste Uni Cor Anm"<GetInterpPoints().first->numElements() <<" 0 0 1 0 0 0 1 0 0 0"<(long)idx))idx=idx2; if(((long)idx3!=(long)string::npos)&&((long)idx3>(long)idx))idx=idx3; if(idx==string::npos) shortName=prefix; else shortName=prefix.substr(idx+1); } pcr<<"! File names of data files"<GetRadiation().GetRadiationType()==RAD_NEUTRON) wdt=10; pcr<<"!lambda1 lambda2 Ratio Bkpos Wdt Cthm muR AsyLim Rpolarz -> Patt #1"<GetRadiation().GetWavelength()(0)<<" "<GetRadiation().GetWavelength()(0) << " 0 0 "< Patt #1"<GetInterpPoints().first->numElements();i++) pcr<<(*(pBackground->GetInterpPoints().first))(i)*RAD2DEG<<" " <<(*(pBackground->GetInterpPoints().second))(i)<<" 0.0"< Patt #1"< Current R_Bragg for Pattern# 1: 0.00 "<GetCrystal().GetName()< vExportAtom; list vExportBond; list vExportAngle; { CrystMatrix_REAL minDistTable; minDistTable=vDiff[i]->GetCrystal().GetMinDistanceTable(-1.); unsigned long k=0; // list0 is the full scattering component list with all atoms except dummies, // and a correct mDynPopCorr const ScatteringComponentList list0=vDiff[i]->GetCrystal().GetScatteringComponentList(); for(int s=0;sGetCrystal().GetScattererRegistry().GetNb();s++) { const ScatteringComponentList list=vDiff[i]->GetCrystal().GetScatt(s).GetScatteringComponentList(); // If we have a Molecule, remember the names used for the atoms to describe restraints // We can't use the original atom names as they might not be unique in the crystal const Molecule *pMol=0; if(vDiff[i]->GetCrystal().GetScatt(s).GetClassName()=="Molecule") pMol=dynamic_cast(&(vDiff[i]->GetCrystal().GetScatt(s))); map vMolAtomName; for(int j=0;j::iterator pos=vExportAtom.find(l); if(pos!=vExportAtom.end()) pos->second.occMult+=1; redundant=true;//-1 means dist > 10A } if(!redundant) { //:TODO: avoid non-alphanumeric characters in name stringstream name; name<GetName()<GetBiso(), list(j).mOccupancy*list0(k).mDynPopCorr, list(j).mpScattPow))); if(pMol!=0) vMolAtomName.insert(make_pair(pMol->GetAtomList()[j],name.str())); } k++; } if(pMol!=0) { for(vector::const_iterator pos=pMol->GetBondList().begin(); pos!=pMol->GetBondList().end();++pos) { map::const_iterator p1,p2; p1=vMolAtomName.find(&((*pos)->GetAtom1())); p2=vMolAtomName.find(&((*pos)->GetAtom2())); if( (p1!=vMolAtomName.end()) && (p2!=vMolAtomName.end())) vExportBond.push_back(exportBond(p1->second, p2->second, (*pos)->GetLength0(),(*pos)->GetLengthSigma())); } for(vector::const_iterator pos=pMol->GetBondAngleList().begin(); pos!=pMol->GetBondAngleList().end();++pos) { map::const_iterator p1,p2,p3; p1=vMolAtomName.find(&((*pos)->GetAtom1())); p2=vMolAtomName.find(&((*pos)->GetAtom2())); p3=vMolAtomName.find(&((*pos)->GetAtom3())); if( (p1!=vMolAtomName.end()) && (p2!=vMolAtomName.end()) && (p3!=vMolAtomName.end())) vExportAngle.push_back(exportAngle(p1->second, p2->second,p3->second, (*pos)->GetAngle0(),(*pos)->GetAngleSigma())); } } } // :TODO: recognize special positions, and move the atoms on them. // :TODO: list atoms excluded, commented out } // Main control codes line for the phase //:TODO: extract distance (Dis) and bond angle (Ang) restraints whenever possible //const ScatteringComponentList *pSC=&(vDiff[i]->GetCrystal().GetScatteringComponentList()); pcr<<"!Nat Dis Ang Jbt Isy Str Furth ATZ Nvk More"<GetCrystal().GetSpaceGroup().GetCCTbxSpg().match_tabulated_settings().hermann_mauguin() <<" <- Space Group Symbol"<::const_iterator pos=vExportAtom.begin();pos!=vExportAtom.end();++pos) { pcr<second.name <<" "<second.mpScattPow->GetSymbol()<<" " <second.x<<" "<second.y<<" "<second.z<<" " <second.biso<<" " <second.occ*pos->second.occMult<<" 0 0 0 0"<GetProfile().GetPar("Eta0").GetHumanValue(); if(eta0<.01) eta0=.01; else if(eta0>.99) eta0=.99; pcr<<"!Scale Shape1 Bov Str1 Str2 Str3 Strain-Model"<GetProfile().GetPar("U").GetHumanValue()<<" "; pcr<GetProfile().GetPar("V").GetHumanValue()<<" "; pcr<GetProfile().GetPar("W").GetHumanValue()<<" "; pcr<< " 0.0 0.0 0.0 0.0 "<GetCrystal().GetLatticePar(0)<<" " <GetCrystal().GetLatticePar(1)<<" " <GetCrystal().GetLatticePar(2)<<" " <GetCrystal().GetLatticePar(3)*RAD2DEG<<" " <GetCrystal().GetLatticePar(4)*RAD2DEG<<" " <GetCrystal().GetLatticePar(5)*RAD2DEG<0) { pcr<<"!Soft distance constraints"<::const_iterator pos=vExportBond.begin();pos!=vExportBond.end();++pos) { pcr<at1<<" "<at2<<" 1 0 0 0 "<dist<<" "<sigma<0) { pcr<<"!Soft angle constraints"<::const_iterator pos=vExportAngle.begin();pos!=vExportAngle.end();++pos) { pcr<at1<<" "<at2<<" "<at3<<" 1 1 0 0 0 0 0 0 " <ang*RAD2DEG<<" "<sigma*RAD2DEG<CalcNbPointUsed(); if(mClockPowderPatternCalc>mClockMaster) return; TAU_PROFILE("PowderPattern::CalcPowderPattern()","void ()",TAU_DEFAULT); VFN_DEBUG_ENTRY("PowderPattern::CalcPowderPattern()",3); if(mPowderPatternComponentRegistry.GetNb()==0) { mPowderPatternCalc.resize(mNbPoint); mPowderPatternCalc=0; mPowderPatternVariance.resize(mNbPoint); mPowderPatternVariance = mPowderPatternObsSigma; mPowderPatternVariance *= mPowderPatternObsSigma; const REAL *p0 = mPowderPatternVariance.data(); REAL *p1=mPowderPatternWeight.data(); for(unsigned long j=0;jIsBeingRefined())) for(unsigned long j=mNbPointUsed;jIsBeingRefined())) for(unsigned long j=mNbPointUsed;jIsBeingRefined())) for(unsigned long j=mNbPointUsed;j &vPar) { TAU_PROFILE("PowderPattern::CalcPowderPattern_FullDeriv()","void ()",TAU_DEFAULT); this->CalcPowderPattern(); mPowderPattern_FullDeriv.clear(); if(mPowderPatternComponentRegistry.GetNb()==0) return; std::vector*> comps; for(int i=0;i::iterator par=vPar.begin();par!=vPar.end();++par) { if(*par==0) continue; for(int i=0;iGetPointer()==mScaleFactor.data()+i) { mPowderPattern_FullDeriv[*par]=mPowderPatternComponentRegistry.GetObj(i).GetPowderPatternCalc(); continue; } else { if((*(comps[i]))[*par].size()==0) continue; } if(true==mPowderPatternComponentRegistry.GetObj(i).IsScalable()) { if(mPowderPattern_FullDeriv[*par].size()==0) { mPowderPattern_FullDeriv[*par].resize(mNbPoint);// :TODO: only use mNbPointUsed const REAL * p1=(*comps[i])[*par].data(); REAL * p0 = mPowderPattern_FullDeriv[*par].data(); const REAL s = mScaleFactor(i); for(unsigned long j=0;j oldDeriv; std::vector v; int n=0; for(std::map::reverse_iterator pos=mPowderPattern_FullDeriv.rbegin();pos!=mPowderPattern_FullDeriv.rend();++pos) { if(pos->first==0) continue; if(pos->second.size()==0) continue; const REAL step=pos->first->GetDerivStep(); pos->first->Mutate(step); this->CalcPowderPattern(); oldDeriv[pos->first]=mPowderPatternCalc; pos->first->Mutate(-2*step); this->CalcPowderPattern(); oldDeriv[pos->first]-=mPowderPatternCalc; oldDeriv[pos->first]/=2*step; pos->first->Mutate(step); v.push_back(&(pos->second)); v.push_back(&(oldDeriv[pos->first])); cout<first->GetName()<<":"<second.size()<<","<first].size()<8) break; } cout<(v,16)<CalcNbPointUsed(); if(mClockPowderPatternIntegratedCalc>mClockMaster) return; this->PrepareIntegratedRfactor(); TAU_PROFILE("PowderPattern::CalcPowderPatternIntegrated()","void ()",TAU_DEFAULT); VFN_DEBUG_ENTRY("PowderPattern::CalcPowderPatternIntegrated()",4); if(mPowderPatternComponentRegistry.GetNb()==0) { mPowderPatternIntegratedCalc.resize(0); mPowderPatternVarianceIntegrated.resize(0); VFN_DEBUG_EXIT("PowderPattern::CalcPowderPatternIntegrated():no components!",4); return; } TAU_PROFILE_TIMER(timer1,"PowderPattern::CalcPowderPatternIntegrated()1:Calc components",\ "", TAU_FIELD); TAU_PROFILE_TIMER(timer2,"PowderPattern::CalcPowderPatternIntegrated()2:Add comps-scaled"\ ,"", TAU_FIELD); TAU_PROFILE_TIMER(timer3,"PowderPattern::CalcPowderPatternIntegrated()2:Add backgd1"\ ,"", TAU_FIELD); TAU_PROFILE_TIMER(timer4,"PowderPattern::CalcPowderPatternIntegrated()2:Add backgd2"\ ,"", TAU_FIELD); TAU_PROFILE_TIMER(timer5,"PowderPattern::CalcPowderPatternIntegrated()3:Variance" ,"", TAU_FIELD); TAU_PROFILE_START(timer1); vector< pair > comps; for(int i=0;i >::iterator pos=comps.begin();pos!=comps.end();++pos) if(mClockPowderPatternCalc < *(pos->second) ) { b=true; break; } if(false==b) { VFN_DEBUG_EXIT("PowderPattern::CalcPowderPatternIntegrated():no need to recalc",4); return; } VFN_DEBUG_MESSAGE("PowderPattern::CalcPowderPatternIntegrated():Recalc",3); mPowderPatternIntegratedCalc.resize(mNbIntegrationUsed); int nbBackgd=0;//count number of background phases for(int i=0;idata(); REAL * RESTRICT p0 = mPowderPatternIntegratedCalc.data(); const REAL s = mScaleFactor(i); for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ = s * *p1++; } else { const REAL * RESTRICT p1= comps[i].first->data(); REAL * RESTRICT p0 = mPowderPatternIntegratedCalc.data(); const REAL s = mScaleFactor(i); for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ += s * *p1++; } TAU_PROFILE_STOP (timer2); } else {// This is a background phase TAU_PROFILE_START(timer3); if(0==i) { const REAL * RESTRICT p1= comps[i].first->data(); REAL * RESTRICT p0 = mPowderPatternIntegratedCalc.data(); for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ = *p1++; } else { const REAL * RESTRICT p1= comps[i].first->data(); REAL * RESTRICT p0 = mPowderPatternIntegratedCalc.data(); for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ += *p1++; } TAU_PROFILE_STOP(timer3); TAU_PROFILE_START(timer4); // The following is useless if there is only one background phase... if(0==nbBackgd) { mPowderPatternBackgroundIntegratedCalc.resize(mNbIntegrationUsed); const REAL * RESTRICT p1= comps[i].first->data(); REAL * RESTRICT p0 = mPowderPatternBackgroundIntegratedCalc.data(); for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ = *p1++; } else { const REAL * RESTRICT p1= comps[i].first->data(); REAL * RESTRICT p0 = mPowderPatternBackgroundIntegratedCalc.data(); for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ += *p1++; } nbBackgd++; TAU_PROFILE_STOP(timer4); } } TAU_PROFILE_START(timer5); if(0==nbBackgd) mPowderPatternBackgroundIntegratedCalc.resize(0); // Calc variance bool useCalcVariance=false; for(int i=0;inumElements() !=0) useCalcVariance=true; if(useCalcVariance) { VFN_DEBUG_MESSAGE("PowderPattern::CalcPowderPatternIntegrated():variance",3); { mPowderPatternVarianceIntegrated.resize(mNbIntegrationUsed); mIntegratedWeight.resize(mNbIntegrationUsed); const REAL * RESTRICT p1= mIntegratedVarianceObs.data(); REAL * RESTRICT p0 = mPowderPatternVarianceIntegrated.data(); for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ = *p1++; } //cout <<"PowderPattern::CalcPowderPatternIntegrated():variance" // <<"obsvarsum="<numElements()) break; const REAL * RESTRICT p1= mPowderPatternComponentRegistry.GetObj(i) .GetPowderPatternIntegratedCalcVariance().first->data(); //cout <<",sumvar(i)="<sum()); REAL * RESTRICT p0 = mPowderPatternVarianceIntegrated.data(); if(true==mPowderPatternComponentRegistry.GetObj(i).IsScalable()) { const REAL s2 = mScaleFactor(i) * mScaleFactor(i); for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ += s2 * *p1++; } else for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ += *p1++; } } //cout <0;j--) if(*p1 <=0) {*p0++ =0;p1++;} else *p0++ = 1. / *p1++; } else mIntegratedWeight.resize(0); mClockPowderPatternIntegratedCalc.Click(); TAU_PROFILE_STOP(timer5); /* // Compare-DEBUG ONLY { VFN_DEBUG_MESSAGE("PowderPattern::CalcPowderPatternIntegrated():Check",10); this->CalcPowderPattern(); CrystVector_REAL integr(mNbIntegrationUsed); for(int k=0;k (integr,*(comps[k].first))< &vPar) { TAU_PROFILE("PowderPattern::CalcPowderPatternIntegrated_FullDeriv()","void ()",TAU_DEFAULT); this->CalcPowderPatternIntegrated(); this->CalcNbPointUsed(); this->PrepareIntegratedRfactor(); mPowderPatternUsed_FullDeriv.clear(); if(mPowderPatternComponentRegistry.GetNb()==0) return; std::vector*> comps; for(int i=0;i::iterator par=vPar.begin();par!=vPar.end();++par) { if(*par==0) continue; //:TODO: store the calculated (non-derived) pattern here ? for(int i=0;iGetPointer()==mScaleFactor.data()+i) { //scalePar=*par; mPowderPatternIntegrated_FullDeriv[*par]=*(mPowderPatternComponentRegistry.GetObj(i).GetPowderPatternIntegratedCalc().first); //cout<<"PowderPattern::CalcPowderPatternIntegrated_FullDeriv():scale #"<GetName()<<":"<<(*par)->GetPointer()<<":"<0;j--) { #if 1 *p0++ = s * *p1++; #else *p0 = s * *p1; if((j==mNbIntegrationUsed)&&((*par)->GetName()=="Cimetidine_C11_x")) cout<<__FILE__<<":"<<__LINE__<<":"<<*p0<<","<0;j--) { #if 1 *p0++ += s * *p1++; #else *p0 += s * *p1; if((j==mNbIntegrationUsed)&&((*par)->GetName()=="Cimetidine_C11_x")) cout<<__FILE__<<":"<<__LINE__<<":"<<*p0<<","<0;j--) { #if 1 *p0++ = *p1++; #else *p0 = *p1; if((j==mNbIntegrationUsed)&&((*par)->GetName()=="Cimetidine_C11_x")) cout<<__FILE__<<":"<<__LINE__<<":"<<*p0<<","<<*p1<0;j--) { #if 1 *p0++ += *p1++; #else *p0 += *p1; if((j==mNbIntegrationUsed)&&((*par)->GetName()=="Cimetidine_C11_x")) cout<<__FILE__<<":"<<__LINE__<<":"<<*p0<<","<<*p1<GetName()=="Cimetidine_C11_x") cout<<"PowderPattern::CalcPowderPatternIntegrated_FullDeriv():" <<(*par)->GetName()<<":s="<GetName()<<":"<GetPointer()<<":"<InitOptions(); { RefinablePar tmp("Zero",&mXZero,-.05,.05,gpRefParTypeScattDataCorrPos, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,RAD2DEG); tmp.AssignClock(mClockPowderPatternXCorr); tmp.SetDerivStep(1e-6); this->AddPar(tmp); } { RefinablePar tmp("2ThetaDispl",&m2ThetaDisplacement,-.05,.05,gpRefParTypeScattDataCorrPos, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,RAD2DEG); tmp.AssignClock(mClockPowderPatternXCorr); tmp.SetDerivStep(1e-6); this->AddPar(tmp); } { RefinablePar tmp("2ThetaTransp",&m2ThetaTransparency,-.05,.05,gpRefParTypeScattDataCorrPos, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,RAD2DEG); tmp.AssignClock(mClockPowderPatternXCorr); tmp.SetDerivStep(1e-6); this->AddPar(tmp); } { RefinablePar tmp("DIFC",&mDIFC,0,1e6,gpRefParTypeScattDataCorrPos, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,1.0); tmp.AssignClock(mClockPowderPatternXCorr); tmp.SetDerivStep(1e-2); this->AddPar(tmp); } { RefinablePar tmp("DIFA",&mDIFA,-1e4,1e4,gpRefParTypeScattDataCorrPos, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,1.0); tmp.AssignClock(mClockPowderPatternXCorr); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { RefinablePar tmp("MuR",&mMuR,0,1000,gpRefParTypeScattDataCorrIntAbsorp, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,1.0); tmp.AssignClock(mClockCorrAbs); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } } void PowderPattern::PrepareIntegratedRfactor()const { bool needPrep=false; for(int i=0;imClockIntegratedFactorsPrep) { needPrep=true; break; } } // If using max sin(theta)/lambda this->CalcNbPointUsed(); if(mClockIntegratedFactorsPrep vLimits; for(int i=0;i::iterator pos=vLimits.begin();pos!=vLimits.end();) { if( (*pos<0) || (*pos>=long(mNbPointUsed)) ) pos=vLimits.erase(pos); else ++pos; } // Try to avoid too small intervals list vLimits2; list::iterator pos1=vLimits.begin(); list::iterator pos2=pos1;pos2++; for(;pos2!=vLimits.end();) { const long pix1=*pos1; //cout<<__FILE__<<":"<<__LINE__<<":"<(pix1+8)) break; } } vLimits2.push_back(*pos1); // Try to avoid too small intervals (2nd pass) pos1=vLimits2.begin(); pos2=pos1;pos2++; for(;pos2!=vLimits2.end();) { //cout<<__FILE__<<":"<<__LINE__<<":"<<*pos1<<" -> "<<*pos2< "<<*pos2<<"...PLONK"; pos2=vLimits2.erase(pos2); //cout<<"->"<<*pos2< > vLimits3; pos1=vLimits2.begin(); pos2=pos1;pos2++; for(;pos2!=vLimits2.end();) { if(*pos2!=(long(mNbPointUsed)-1)) vLimits3.push_back(make_pair(*pos1++,*pos2++-1)); else vLimits3.push_back(make_pair(*pos1++,*pos2++)); //cout<<__FILE__<<":"<<__LINE__<<":"< "< >::iterator pos=vLimits3.begin();pos!=vLimits3.end();++pos) { mIntegratedPatternMin(i)=pos->first; mIntegratedPatternMax(i++)=pos->second; } } long numInterval=mIntegratedPatternMin.numElements(); CrystVector_bool keep(numInterval); keep=true; // Take care of excluded regions (change integration areas accordingly) // regions are sorted by ascending theta const long nbExclude=mExcludedRegionMinX.numElements(); if(nbExclude>0) { VFN_DEBUG_MESSAGE("PowderPattern::PrepareIntegratedRfactor():5:Excluded regions("<X2Pixel(mExcludedRegionMinX(j))); maxExcl=(long)ceil (this->X2Pixel(mExcludedRegionMaxX(j))); for(int i=0;i=numInterval) break; } if(j>=numInterval) break; while(mIntegratedPatternMin(j)minExcl) &&(mIntegratedPatternMax(j)minExcl) &&(mIntegratedPatternMax(j)>maxExcl)) mIntegratedPatternMin(j)=maxExcl; if(j==(numInterval-1)) break; j++; } minExcl=(long)(this->X2Pixel(mExcludedRegionMinX(i))); maxExcl=(long)(this->X2Pixel(mExcludedRegionMaxX(i))); //go back if one integration segment is concerned by several exclusion zones... if(j!=0) while(mIntegratedPatternMax(j)>=minExcl) { j--; if(j==0) break; } } } // Keep only the selected intervals VFN_DEBUG_MESSAGE("PowderPattern::PrepareIntegratedRfactor():6",3); long j=0; for(int i=0;i(mIntegratedPatternMin,mIntegratedPatternMax),2); // Integrate Obs and weight arrays mIntegratedObs.resize(numInterval); mIntegratedVarianceObs.resize(numInterval); mIntegratedVarianceObs=0; mIntegratedObs=0; mIntegratedWeightObs.resize(numInterval); for(int i=0;i(mIntegratedPatternMin, // mIntegratedPatternMax, // mIntegratedObs,mIntegratedWeight,12,6)<IsBeingRefined())return; unsigned long tmp; // Use the first point of the profile of the first reflection not calculated if(this->GetRadiation().GetWavelengthType()==WAVELENGTH_TOF) { tmp=(unsigned long)(this->X2PixelCorr(this->STOL2X(mMaxSinThetaOvLambda))); } else { REAL sinth=mMaxSinThetaOvLambda*this->GetWavelength(); if(1>fabs(sinth)) tmp=(unsigned long)(this->X2PixelCorr(2*asin(sinth))); else tmp=mNbPoint; } if(tmp>mNbPoint) tmp= mNbPoint; if(tmp !=mNbPointUsed) { mNbPointUsed=tmp; mClockNbPointUsed.Click(); VFN_DEBUG_MESSAGE("PowderPattern::CalcNbPointUsed():"<AddOption(&mOptProfileIntegration); } #ifdef __WX__CRYST__ WXCrystObjBasic* PowderPattern::WXCreate(wxWindow* parent) { //:TODO: Check mpWXCrystObj==0 mpWXCrystObj=new WXPowderPattern(parent,this); return mpWXCrystObj; } #endif //////////////////////////////////////////////////////////////////////// // // Spacegroup Explorer // //////////////////////////////////////////////////////////////////////// /** Structure to hold the score corresponding to a given spacegroup. * */ SPGScore::SPGScore(const string &s, const REAL r, const REAL g, const unsigned int nbextinct, const REAL ngof, const unsigned int nbrefl): hm(s),rw(r),gof(g),ngof(ngof),nbextinct446(nbextinct),nbreflused(nbrefl) {}; bool compareSPGScore(const SPGScore &s1, const SPGScore &s2) { if(s1.ngof > 0.00001 && s2.ngof >0.00001) return s1.ngof < s2.ngof; return s1.gof < s2.gof; } /// Function which determines the unique extinction fingerprint of a spacegroup, /// by calculating all present reflections between 0<=H<=4 0<=K<=4 0<=L<=6 std::vector spgExtinctionFingerprint(Crystal &c, const cctbx::sgtbx::space_group &spg) { // We don't have the extinction symbol, so do it the stupid way std::vector fingerprint(5*5*7-1+6); long i=0; fingerprint[i++]=c.GetPar("a").IsUsed(); fingerprint[i++]=c.GetPar("b").IsUsed(); fingerprint[i++]=c.GetPar("c").IsUsed(); fingerprint[i++]=c.GetPar("alpha").IsUsed(); fingerprint[i++]=c.GetPar("beta").IsUsed(); fingerprint[i++]=c.GetPar("gamma").IsUsed(); for(long h=0;h<5;++h) for(long k=0;k<5;++k) for (long l=0;l<7;++l) { if((h+k+l)==0) continue; cctbx::miller::index hkl(scitbx::vec3(h,k,l)); if(i>=fingerprint.size()) cout<<"WHOOOOOOOOOOOOOPS"<Run(sg, fitprofile, verbose, restore_orig, update_display, relative_length_tolerance, absolute_angle_tolerance_degree); } SPGScore SpaceGroupExplorer::Run(const cctbx::sgtbx::space_group &spg, const bool fitprofile, const bool verbose, const bool restore_orig, const bool update_display, const REAL relative_length_tolerance, const REAL absolute_angle_tolerance_degree) { TAU_PROFILE("SpaceGroupExplorer::Run()","void (wxCommandEvent &)",TAU_DEFAULT); TAU_PROFILE_TIMER(timer1,"SpaceGroupExplorer::Run()LSQ-P1","", TAU_FIELD); TAU_PROFILE_TIMER(timer2,"SpaceGroupExplorer::Run()LSQ1","", TAU_FIELD); TAU_PROFILE_TIMER(timer3,"SpaceGroupExplorer::Run()LSQ2","", TAU_FIELD); Crystal *pCrystal=&(mpDiff->GetCrystal()); // Keep initial lattice parameters & spg const REAL a=pCrystal->GetLatticePar(0), b=pCrystal->GetLatticePar(1), c=pCrystal->GetLatticePar(2), d=pCrystal->GetLatticePar(3), e=pCrystal->GetLatticePar(4), f=pCrystal->GetLatticePar(5); const string spghm=pCrystal->GetSpaceGroup().GetCCTbxSpg().match_tabulated_settings().hermann_mauguin(); const string name=pCrystal->GetName(); // Set up new spacegroup const cctbx::sgtbx::space_group_symbols s = spg.match_tabulated_settings(); const string hm=s.universal_hermann_mauguin(); const cctbx::uctbx::unit_cell uc(scitbx::af::double6(a,b,c,d*RAD2DEG,e*RAD2DEG,f*RAD2DEG)); if(!spg.is_compatible_unit_cell(uc,relative_length_tolerance,absolute_angle_tolerance_degree)) { throw ObjCrystException("Spacegroup is not compatible with unit cell."); } mpDiff->GetCrystal().Init(a,b,c,d,e,f,hm,name); mpDiff->SetExtractionMode(true,true); unsigned int nbcycle=1; if(update_display) mpDiff->GetParentPowderPattern().UpdateDisplay(); // Number of free parameters (not taking into account refined profile/background parameters) unsigned int nbfreepar=mpDiff->GetProfileFitNetNbObs(); if(nbfreepar<1) nbfreepar=1; // Should not happen ! // Create the LSQ obj even if the profile is not fitted, to allow restoring all parameters LSQNumObj lsq; lsq.SetRefinedObj(mpDiff->GetParentPowderPattern(),0,true,true); lsq.PrepareRefParList(true); const unsigned int saved_par = lsq.GetCompiledRefinedObj().CreateParamSet("SpaceGroupExplorer saved parameters"); lsq.GetCompiledRefinedObj().SaveParamSet(saved_par); Chronometer chrono; for(unsigned int j=0;jSetExtractionMode(true,true); const float t0=chrono.seconds(); if(verbose) cout<<"Doing Le Bail, t="<ExtractLeBail(5); if(verbose) cout<<", dt="<GetParentPowderPattern().FitScaleFactorForIntegratedRw(); if(fitprofile) {// Perform LSQ TAU_PROFILE_START(timer2); lsq.SetParIsFixed(gpRefParTypeObjCryst,true); lsq.SetParIsFixed(gpRefParTypeScattDataScale,false); std::list vnewpar; std::list vnewpartype; // Only do the full monty for P1, keep the parameters for other spacegroups if(s.number()==1) vnewpar.push_back(&lsq.GetCompiledRefinedObj().GetPar("Zero")); lsq.SetParIsFixed(gpRefParTypeUnitCell,false); lsq.SafeRefine(vnewpar, vnewpartype,1.01,2,true,true); vnewpar.clear(); TAU_PROFILE_STOP(timer2); if(s.number()==1) { TAU_PROFILE_START(timer1); vnewpar.push_back(&lsq.GetCompiledRefinedObj().GetPar("2ThetaDispl")); vnewpar.push_back(&lsq.GetCompiledRefinedObj().GetPar("2ThetaTransp")); lsq.SafeRefine(vnewpar, vnewpartype,1.01,2,true,true); vnewpar.clear(); lsq.SetParIsFixed(gpRefParTypeScattDataBackground,false); // Fix background point beyond optimized domain const unsigned int nbcomp= mpDiff->GetParentPowderPattern().GetNbPowderPatternComponent(); for(unsigned int i=0;iGetParentPowderPattern().GetPowderPatternComponent(i).GetClassName()=="PowderPatternBackground") { PowderPatternBackground *pback=dynamic_cast (&(mpDiff->GetParentPowderPattern().GetPowderPatternComponent(i))); pback->FixParametersBeyondMaxresolution(lsq.GetCompiledRefinedObj()); } for(unsigned int i=0; iSetExtractionMode(true,true); mpDiff->ExtractLeBail(5); TAU_PROFILE_START(timer3); lsq.SafeRefine(vnewpar,vnewpartype,1.01,3,true,true); TAU_PROFILE_STOP(timer3); //mpLog->AppendText(wxString::Format(_T("%5.2f%%/"),pDiff->GetParentPowderPattern().GetRw()*100)); //mpDiff->GetParentPowderPattern().FitScaleFactorForIntegratedRw(); } if(update_display) mpDiff->GetParentPowderPattern().UpdateDisplay(); const REAL rw=mpDiff->GetParentPowderPattern().GetRw()*100; const REAL gof=mpDiff->GetParentPowderPattern().GetChi2()/mpDiff->GetParentPowderPattern().GetNbPointUsed(); if(verbose) cout << boost::format(" (cycle #%u)\n Rwp=%5.2f%%\n GoF=%9.2f") % j % rw % gof <GetParentPowderPattern().GetRw()*100; const REAL gof=mpDiff->GetParentPowderPattern().GetChi2()/nbfreepar; const REAL ngof = this->GetP1IntegratedGoF(); unsigned int nbextinct446=0; std::vector fgp=spgExtinctionFingerprint(*pCrystal,spg); for(unsigned int i=6;iGetNbReflBelowMaxSinThetaOvLambda(); if(verbose>0) cout << boost::format(" Rwp= %5.2f%% GoF=%9.2f nGoF =%9.2f (%3u reflections, %3u extinct)") % rw % gof % ngof % nbrefl % nbextinct446<GetCrystal().Init(a,b,c,d,e,f,spghm,name); lsq.GetCompiledRefinedObj().RestoreParamSet(saved_par); if (update_display) { mpDiff->GetCrystal().UpdateDisplay(); this->mpDiff->GetParentPowderPattern().UpdateDisplay(); } } return SPGScore(hm.c_str(),rw,gof,nbextinct446, ngof, nbrefl); } void SpaceGroupExplorer::RunAll(const bool fitprofile_all, const bool verbose, const bool keep_best, const bool update_display, const bool fitprofile_p1, const REAL relative_length_tolerance, const REAL absolute_angle_tolerance_degree) { Crystal *pCrystal=&(mpDiff->GetCrystal()); // Initial lattice parameters & spg const REAL a=pCrystal->GetLatticePar(0), b=pCrystal->GetLatticePar(1), c=pCrystal->GetLatticePar(2), d=pCrystal->GetLatticePar(3), e=pCrystal->GetLatticePar(4), f=pCrystal->GetLatticePar(5); const cctbx::uctbx::unit_cell uc(scitbx::af::double6(a,b,c,d*RAD2DEG,e*RAD2DEG,f*RAD2DEG)); const string spghm=pCrystal->GetSpaceGroup().GetCCTbxSpg().match_tabulated_settings().hermann_mauguin(); const string name=pCrystal->GetName(); cctbx::sgtbx::space_group_symbol_iterator it=cctbx::sgtbx::space_group_symbol_iterator(); // First, count compatible spacegroups unsigned int nbspg=0; for(;;) { cctbx::sgtbx::space_group_symbols s=it.next(); if(s.number()==0) break; cctbx::sgtbx::space_group spg(s); if(spg.is_compatible_unit_cell(uc,relative_length_tolerance, absolute_angle_tolerance_degree)) nbspg++; //if(s.universal_hermann_mauguin().size()>hmlen) hmlen=s.universal_hermann_mauguin().size(); } if(verbose) cout << boost::format("Beginning spacegroup exploration... %u to go...\n") % nbspg; mvSPG.clear(); mvSPGExtinctionFingerprint.clear(); // Nb refl below max sin(theta/lambda) for p1, to compute nGoF unsigned int nb_refl_p1=1; it=cctbx::sgtbx::space_group_symbol_iterator(); Chronometer chrono; chrono.start(); for(int i=0;;) { cctbx::sgtbx::space_group_symbols s=it.next(); if(s.number()==0) break; cctbx::sgtbx::space_group spg(s); bool compat=spg.is_compatible_unit_cell(uc,relative_length_tolerance,absolute_angle_tolerance_degree); if(compat) { i++; const string hm=s.universal_hermann_mauguin(); // cout<Init(a,b,c,d,e,f,hm,name); std::vector fgp=spgExtinctionFingerprint(*pCrystal,spg); std::map,SPGScore>::iterator posfgp=mvSPGExtinctionFingerprint.find(fgp); if(posfgp!=mvSPGExtinctionFingerprint.end()) { pCrystal->Init(a,b,c,d,e,f,hm,name); mpDiff->SetExtractionMode(true,true); //:TODO: why is this needed to actually get the updated GetNbReflBelowMaxSinThetaOvLambda ? unsigned int nbrefl = mpDiff->GetNbReflBelowMaxSinThetaOvLambda(); REAL ngof = (posfgp->second.ngof * nbrefl) / posfgp->second.nbreflused; mvSPG.push_back(SPGScore(hm.c_str(),posfgp->second.rw,posfgp->second.gof,posfgp->second.nbextinct446, ngof, nbrefl)); if(verbose) cout<second.hm<<"]\n"; } else { if(((s.number()==1) && fitprofile_p1) || fitprofile_all) mvSPG.push_back(this->Run(spg, true, false, false, update_display, relative_length_tolerance, absolute_angle_tolerance_degree)); else mvSPG.push_back(this->Run(spg, false, false, true, update_display,relative_length_tolerance,absolute_angle_tolerance_degree)); if(s.number() == 1) nb_refl_p1 = mvSPG.back().nbreflused; mvSPG.back().ngof *= mpDiff->GetNbReflBelowMaxSinThetaOvLambda() / (float)nb_refl_p1; mvSPGExtinctionFingerprint.insert(make_pair(fgp, mvSPG.back())); if(verbose) cout<GetSpaceGroup().ChangeSpaceGroup(mvSPG.front().hm); } else { // Go back to original lattice and spacegroup & update display pCrystal->Init(a,b,c,d,e,f,spghm,name); } mpDiff->SetExtractionMode(true,true); mpDiff->ExtractLeBail(5); if(update_display) { pCrystal->UpdateDisplay(); this->mpDiff->GetParentPowderPattern().UpdateDisplay(); } } const list& SpaceGroupExplorer::GetScores() const { return mvSPG; } REAL SpaceGroupExplorer::GetP1IntegratedGoF() { if(mpDiff->GetCrystal().GetSpaceGroup().GetSpaceGroupNumber()==1) { mpDiff->GetPowderPatternIntegratedCalc(); mP1IntegratedProfileMin = mpDiff->GetParentPowderPattern().GetIntegratedProfileMin(); mP1IntegratedProfileMax = mpDiff->GetParentPowderPattern().GetIntegratedProfileMax(); // cout<<"Updating mP1IntegratedProfileMin/Max:"<(mP1IntegratedProfileMin, mP1IntegratedProfileMax,mP1IntegratedProfileMax)<(mpDiff->GetH(), mpDiff->GetK(), mpDiff->GetL(), mpDiff->GetFhklCalcSq()); REAL integratedChi2=0.; REAL integratedChi2LikeNorm=0.; const REAL * RESTRICT p1, * RESTRICT p2, * RESTRICT p3; CrystVector_REAL const* pcalc = &(mpDiff->GetParentPowderPattern().GetPowderPatternCalc()); CrystVector_REAL const* pobs = &(mpDiff->GetParentPowderPattern().GetPowderPatternObs()); CrystVector_REAL const* psigma = &(mpDiff->GetParentPowderPattern().GetPowderPatternObsSigma()); const unsigned int jmax = mpDiff->GetParentPowderPattern().GetNbPointUsed(); REAL chi2=0; unsigned int nbpoint = 0; for(unsigned long i=0;i jmax) break; if(mP1IntegratedProfileMax(i) < 0) continue; REAL v=0, c=0, o=0; for(unsigned long j=mP1IntegratedProfileMin(i); j<=mP1IntegratedProfileMax(i); j++) { if(j<0) continue; if(j >= jmax) break; nbpoint++; c += (*pcalc)(j); // calc o += (*pobs)(j); // obs v += (*psigma)(j)*(*psigma)(j); // variance } if(v>0) chi2 += (c-o)*(c-o)/v; } return chi2 / nbpoint; } }//namespace ObjCryst objcryst-2022.1/ObjCryst/ObjCryst/PowderPattern.h000066400000000000000000001771071430515525000217210ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _OBJCRYST_POWDERPATTERN_H_ #define _OBJCRYST_POWDERPATTERN_H_ #include #include #include #include "ObjCryst/CrystVector/CrystVector.h" #include "ObjCryst/ObjCryst/General.h" #include "ObjCryst/ObjCryst/Crystal.h" #include "ObjCryst/ObjCryst/ScatteringCorr.h" #include "ObjCryst/ObjCryst/ReflectionProfile.h" #include "ObjCryst/ObjCryst/CIF.h" #include "ObjCryst/ObjCryst/Indexing.h" #include "ObjCryst/ObjCryst/DiffractionDataSingleCrystal.h" namespace ObjCryst { class PeakList; class PowderPattern; class PowderPatternDiffraction; //###################################################################### /** \brief Cylinder absorption correction * * Correction formulas from Lobanov & Alte da Veiga, * Code re-implemented from GSAS-II (courtesy of B. von Dreele), original version: * https://subversion.xray.aps.anl.gov/trac/pyGSAS/browser/trunk/GSASIIpwd.py * */ class CylinderAbsCorr:public ScatteringCorr { public: /** Constructor * \param powp: the PowderPattern object which has the muR parameter */ CylinderAbsCorr(const PowderPatternDiffraction &data); virtual ~CylinderAbsCorr(); virtual const string & GetName() const; virtual const string & GetClassName() const; protected: virtual void CalcCorr() const; const PowderPatternDiffraction *mpPowderPatternDiff; }; //###################################################################### /** \brief Generic class to compute components (eg the contribution of * a given phase, or background) of a powder pattern. This is an abstract base class. * * Most functions are protected, only to be accessed, * internally or from the friend class PowderPattern. */ //###################################################################### class PowderPatternComponent : virtual public RefinableObj { public: PowderPatternComponent(); PowderPatternComponent(const PowderPatternComponent&); virtual ~PowderPatternComponent(); virtual const string& GetClassName() const; /// Get the PowderPattern object which uses this component. /// This allows to know the observed powder pattern to evaluate /// the background. const PowderPattern& GetParentPowderPattern()const; /// Get the PowderPattern object which uses this component. /// This allows to know the observed powder pattern to evaluate /// the background. PowderPattern& GetParentPowderPattern(); /// Set the PowderPattern object which uses this component. /// This sets all necessary pattern parameters (2theta/tof range, /// wavelength, radiation type...) accordingly. /// virtual void SetParentPowderPattern(PowderPattern&)=0; /// Get the calculated powder pattern for this component. /// Note that the pattern is \e not scaled. /// virtual const CrystVector_REAL& GetPowderPatternCalc()const=0; virtual std::map& GetPowderPattern_FullDeriv(std::set &vPar); /** Get the integrated values of the powder pattern * * \note: the integration intervals are those given by the parent * PowderPattern, so that all PowderPatternComponent's intervals * are taken into account * * This avoids explicitely calculating the full profile powder pattern. */ virtual pair GetPowderPatternIntegratedCalc()const=0; virtual std::map& GetPowderPatternIntegrated_FullDeriv(std::set &vPar); /** \brief Is this component scalable ? * * This is used by the PowderPattern class, which fits all * pattern components using scale factors. Some components may not * need to be scaled: background components, which are assumed * to be absolute. */ bool IsScalable()const; /** Get the variance associated to each point of the * calculated powder pattern, for this component. * * \warning: this is experimental, with the aim of using Maximum Likelihood * to improve structure determination. */ virtual const CrystVector_REAL& GetPowderPatternCalcVariance()const=0; /** Get the variance associated to each point of the * calculated powder pattern, for this component (integrated version). * * \warning: this is experimental, with the aim of using Maximum Likelihood * to improve structure determination. */ virtual pair GetPowderPatternIntegratedCalcVariance() const=0; /// Does this component have a variance associated with each calculated /// point ? i.e., do we use maximum likelihood to take into account /// incomplete models ? virtual bool HasPowderPatternCalcVariance()const=0; /// Last time the powder pattern was calculated. const RefinableObjClock& GetClockPowderPatternCalc()const; /// Get a list of labels for the pattern (usually reflection indexes). This /// returns the list generated during the last computation of the powder pattern. const list >& GetPatternLabelList() const; protected: /// Last time the variance on the pattern was actually calculated. const RefinableObjClock& GetClockPowderPatternCalcVariance()const; /// Calc the powder pattern. As always, recomputation is only /// done if necessary (ie if a parameter has changed since the last /// computation) virtual void CalcPowderPattern() const=0; virtual void CalcPowderPattern_FullDeriv(std::set &vPar); /// Calc the integrated powder pattern. This should be optimized so that /// the full powder pattern is not explicitely computed. virtual void CalcPowderPatternIntegrated_FullDeriv(std::set &vPar); /** Get the pixel positions separating the integration intervals around reflections. * * \returns: an array with the pixel positions, empty if this component * has no peaks. The positions should be in increasing order, but * could go beyond the pattern limits. */ virtual const CrystVector_long& GetBraggLimits()const=0; /// Get last time the Bragg Limits were changed const RefinableObjClock& GetClockBraggLimits()const; /// Set the maximum value for sin(theta)/lambda. All data above still /// exist but are ignored for all calculations. virtual void SetMaxSinThetaOvLambda(const REAL max)=0; /// The calculated component of a powder pattern. It is mutable since it is /// completely defined by other parameters (eg it is not an 'independent parameter') mutable CrystVector_REAL mPowderPatternCalc; /// The calculated powder pattern, integrated. mutable CrystVector_REAL mPowderPatternIntegratedCalc; /// The variance associated to each point of the calculated powder pattern. mutable CrystVector_REAL mPowderPatternCalcVariance; /// The variance associated to each point of the calculated powder pattern, integrated mutable CrystVector_REAL mPowderPatternIntegratedCalcVariance; /// Interval limits around each reflection, for integrated R-factors mutable CrystVector_long mIntegratedReflLimits; /// \internal /// This will be called by the parent PowderPattern object, before /// calculating the first powder pattern. Or maybe it should be called /// automatically by the object itself... virtual void Prepare()=0; /// Scalable ? (crystal phase = scalable, background= not scalable) bool mIsScalable; //Clocks /// When was the powder pattern last computed ? mutable RefinableObjClock mClockPowderPatternCalc; /// When was the 'integrated' powder pattern last computed ? mutable RefinableObjClock mClockPowderPatternIntegratedCalc; /// When was the powder pattern variance last computed ? mutable RefinableObjClock mClockPowderPatternVarianceCalc; /// When was the 'integrated' powder pattern variance last computed ? mutable RefinableObjClock mClockPowderPatternIntegratedVarianceCalc; /// The PowderPattern object in which this component is included PowderPattern *mpParentPowderPattern; /// Get last time the Bragg Limits were changed mutable RefinableObjClock mClockBraggLimits; /// The labels associated to different points of the pattern mutable list > mvLabel; mutable std::map mPowderPattern_FullDeriv; mutable std::map mPowderPatternIntegrated_FullDeriv; //Eventually this should be removed (?) friend class PowderPattern; }; /// Global registry for all PowderPatternComponent objects extern ObjRegistry gPowderPatternComponentRegistry; //###################################################################### /** \brief Phase to compute a background contribution to a powder * pattern using an interpolation. Currently only linear interpolation is * available. (in the works: cubic spline interpolation background) */ //###################################################################### class PowderPatternBackground : public PowderPatternComponent { public: PowderPatternBackground(); PowderPatternBackground(const PowderPatternBackground&); virtual ~PowderPatternBackground(); virtual const string& GetClassName() const; virtual void SetParentPowderPattern(PowderPattern&); virtual const CrystVector_REAL& GetPowderPatternCalc()const; virtual pair GetPowderPatternIntegratedCalc()const; /// Import background points from a file (with two columns 2theta (or tof), intensity) void ImportUserBackground(const string &filename); void SetInterpPoints(const CrystVector_REAL tth, const CrystVector_REAL backgd); const std::pair GetInterpPoints()const; virtual void XMLOutput(ostream &os,int indent=0)const; virtual void XMLInput(istream &is,const XMLCrystTag &tag); //virtual void XMLInputOld(istream &is,const IOCrystTag &tag); virtual void GetGeneGroup(const RefinableObj &obj, CrystVector_uint & groupIndex, unsigned int &firstGroup) const; virtual void BeginOptimization(const bool allowApproximations=false, const bool enableRestraints=false); virtual const CrystVector_REAL& GetPowderPatternCalcVariance()const; virtual pair GetPowderPatternIntegratedCalcVariance() const; virtual bool HasPowderPatternCalcVariance()const; virtual void TagNewBestConfig()const; /** Optimize the background using a Bayesian approach. The background parameters * must be un-fixed before. * * The minimization will a maximum of 50 Simplex runs (see the SimplexObj documentation), * each with 200 cycles. * * See the class documentation for PowderPatternBackgroundBayesianMinimiser. */ void OptimizeBayesianBackground(); /** Fix parameters corresponding to points of the pattern that are not actually calculated. * This is necessary for modelling using splines, to avoid divergence of interpolation * points during least squares optimization. * * \param obj: the object in which are parameters to be fixed. Normally this will be * the PowderPatternBackground object itself, but it can also be the parameter list * copied such as in a LSQNumObj. */ void FixParametersBeyondMaxresolution(RefinableObj &obj); protected: virtual void CalcPowderPattern() const; virtual void CalcPowderPattern_FullDeriv(std::set &vPar); virtual void CalcPowderPatternIntegrated() const; virtual void CalcPowderPatternIntegrated_FullDeriv(std::set &vPar); virtual void Prepare(); virtual const CrystVector_long& GetBraggLimits()const; virtual void SetMaxSinThetaOvLambda(const REAL max); void InitRefParList(); void InitOptions(); void InitSpline()const; /// Number of fitting points for background int mBackgroundNbPoint; /// Vector of 2theta values for the fitting points of the background CrystVector_REAL mBackgroundInterpPointX; /// Values of background at interpolating points CrystVector_REAL mBackgroundInterpPointIntensity; /// Subscript of the points, sorted the correct order, ///taking into account the type of radiation (monochromatic/TOF). mutable CrystVector_long mPointOrder; /// Vector of pixel values between each interval, for faster CubicSpline calculations. /// Mutable since it copies information from mBackgroundInterpPointX. mutable CrystVector_REAL mvSplinePixel; /// Spline used for interpolation. /// Mutable since it copies information from mBackgroundInterpPointX ///and mBackgroundInterpPointIntensity. mutable CubicSpline mvSpline; // Clocks /// Modification of the interpolated points RefinableObjClock mClockBackgroundPoint; /// Initialization of the spline mutable RefinableObjClock mClockSpline; /** Maximum sin(theta)/lambda for all calculations (10 by default). * * This keeps all data in memory, but only the part which is below * the max is calculated. */ REAL mMaxSinThetaOvLambda; /// Constant error (sigma) on the calculated pattern, due to an incomplete /// model REAL mModelVariance; /// Type of interpolation performed: linear or cubic spline RefObjOpt mInterpolationModel; //To be removed friend class PowderPattern; #ifdef __WX__CRYST__ public: virtual WXCrystObjBasic* WXCreate(wxWindow*); friend class WXPowderPatternBackground; #endif }; //###################################################################### /** \brief Class to compute the contribution to a powder pattern from * a crystalline phase. * */ //###################################################################### class PowderPatternDiffraction : virtual public PowderPatternComponent,public ScatteringData { public: PowderPatternDiffraction(); PowderPatternDiffraction(const PowderPatternDiffraction&); virtual ~PowderPatternDiffraction(); virtual PowderPatternDiffraction* CreateCopy()const; virtual const string& GetClassName() const; virtual void SetParentPowderPattern(PowderPattern&); virtual const CrystVector_REAL& GetPowderPatternCalc()const; virtual pair GetPowderPatternIntegratedCalc()const; /** Set reflection profile parameters * * :TODO: assymmetric profiles * \param fwhmCagliotiW,fwhmCagliotiU,fwhmCagliotiV : these are the U,V and W * parameters in the Caglioti's law : * \f$ fwhm^2= U \tan^2(\theta) + V \tan(\theta) +W \f$ * if only W is given, the width is constant * \param eta0,eta1: these are the mixing parameters in the case of a * pseudo-Voigt function. */ void SetReflectionProfilePar(const ReflectionProfileType prof, const REAL fwhmCagliotiW, const REAL fwhmCagliotiU=0, const REAL fwhmCagliotiV=0, const REAL eta0=0.5, const REAL eta1=0.); /** Assign a new profile * */ void SetProfile(ReflectionProfile *prof); /// Get reflection profile const ReflectionProfile& GetProfile()const; /// Get reflection profile ReflectionProfile& GetProfile(); virtual void GenHKLFullSpace(); virtual void XMLOutput(ostream &os,int indent=0)const; virtual void XMLInput(istream &is,const XMLCrystTag &tag); //virtual void XMLInputOld(istream &is,const IOCrystTag &tag); virtual void GetGeneGroup(const RefinableObj &obj, CrystVector_uint & groupIndex, unsigned int &firstGroup) const; virtual void BeginOptimization(const bool allowApproximations=false, const bool enableRestraints=false); virtual void EndOptimization(); virtual void SetApproximationFlag(const bool allow); virtual const Radiation& GetRadiation()const; virtual const CrystVector_REAL& GetPowderPatternCalcVariance()const; virtual pair GetPowderPatternIntegratedCalcVariance() const; virtual bool HasPowderPatternCalcVariance()const; virtual void SetCrystal(Crystal &crystal); /** Prepare intensity extraction (Le Bail or Pawley) * * *\param extract: if true, begin extraction mode, else enable structure factor calculations *\param init: if true and extract=true, intensities are set to 100. Otherwise if extract==true * and init=false, the program will try to re-use existing extracted data (in mpLeBailData), * but only if the list of HKL is unchanged. Otherwise initilization to 100 will be forced. */ void SetExtractionMode(const bool extract=true,const bool init=false); /// Return true if in extraction mode, i.e. using extracted intensities instead of computed structure factors. bool GetExtractionMode()const; /** Extract intensities using Le Bail method * *\param nbcycle: number of cycles */ void ExtractLeBail(unsigned int nbcycle=1); /// Recalc, and get the number of reflections which should be actually used, /// due to the maximuml sin(theta)/lambda value set. virtual long GetNbReflBelowMaxSinThetaOvLambda()const; /// Change one parameter in mFrozenLatticePar. This triggers a call to CalcLocalBMatrix() if the parameter has changed void SetFrozenLatticePar(const unsigned int i, REAL v); /// Access to one parameter in mFrozenLatticePar REAL GetFrozenLatticePar(const unsigned int i) const; /// Set the use local cell parameters ? (see mFrozenLatticePar) /// If this changes mUseLocalLatticePar from false to true, this triggers a copy /// of the Crystal's lattice parameters into mFrozenLatticePar void FreezeLatticePar(const bool use); /// Do we use local cell parameters ? (see mFrozenLatticePar) bool FreezeLatticePar() const; /** Get the 'net' number of observed intensities, minus the number of reflections, for a profile fit. * This calculation takes into account where each reflection appears: * - if in a low angle region there are 500 points and 2 reflections, this will contribute 498 net * - if at high angle there are 200 points and 250 reflections, this will contribute to 0 net oberved. * - reflections appearing at exactly the same angle count as one * Note that the calculation only includes the region below max(sin(theta)/lambda). * No over paremeters (profile, background) are taken into account */ unsigned int GetProfileFitNetNbObs()const; /// Return true if there are extracted (le Bail) squared structure factors, false otherwise bool HasFhklObsSq() const; /** Get the extracted structure factors modulus (squared), e.g. using the Le Bail method. * * Note that the number of reflections listed is limited to the evaluated ones, *which is usually smaller than the H,K and L arrays. * * Raises an exception if this is not available. */ const CrystVector_REAL& GetFhklObsSq() const; protected: virtual void CalcPowderPattern() const; virtual void CalcPowderPattern_FullDeriv(std::set &vPar); virtual void CalcPowderPatternIntegrated() const; virtual void CalcPowderPatternIntegrated_FullDeriv(std::set &vPar); /// \internal Calc reflection profiles for ALL reflections (powder diffraction) void CalcPowderReflProfile()const; /// \internal Calc derivatives of reflection profiles for all used reflections, /// for a given list of refinable parameters void CalcPowderReflProfile_FullDeriv(std::set &vPar); /// \internal Calc Lorentz-Polarisation-Aperture correction void CalcIntensityCorr()const; /// \internal Compute the intensity for all reflections (taking into account /// corrections, but not the multiplicity) virtual void CalcIhkl() const; virtual void CalcIhkl_FullDeriv(std::set &vPar); virtual void Prepare(); virtual void InitOptions(); virtual const CrystVector_long& GetBraggLimits()const; virtual void SetMaxSinThetaOvLambda(const REAL max); /// This can use either locally stored lattice parameters from mLocalLatticePar, /// or the Crystal's, depending on mUseLocalLatticePar. virtual const CrystMatrix_REAL& GetBMatrix()const; /// Calculate the local BMatrix, used if mFreezeLatticePar is true. void CalcFrozenBMatrix()const; void PrepareIntegratedProfile()const; //Clocks /// Last time the reflection parameters were changed RefinableObjClock mClockProfilePar; /// Last time the Lorentz-Polarization and slit parameters were changed RefinableObjClock mClockLorentzPolarSlitCorrPar; //Clocks (internal, mutable) /// Last time the Lorentz-Polar-Slit correction was computed mutable RefinableObjClock mClockIntensityCorr; /// Last time the reflection profiles were computed mutable RefinableObjClock mClockProfileCalc; /// Last time intensities were computed mutable RefinableObjClock mClockIhklCalc; /// Profile ReflectionProfile *mpReflectionProfile; // Corrections /** \brief Calculated corrections for all reflections. Calc F^2 must be multiplied *by this factor to yield intensities. * * Thus we have : \f$ I_{hkl} = L \times P \times SlitAp \times F_{hkl}^2 \f$ * *with \f$ L = \frac{1}{\sin(2\theta)} \f$ (Lorentz factor). *\f$ P = \frac{1}{1+A}\left(1+A\cos^2(2\theta)\right) \f$ (Polarization factor), with * \f$ A = \frac{1-f}{1+f} \f$, where f is the polarization rate of the incident *beam in the plane which (i) includes the incident beam, and (ii) is perpendicular to *the diffracting plane. For an X-Ray Tube without monochromator, A=1, and *if there is a monochromator : \f$ A = \cos^2(2\theta_{mono}) \f$ *The factor \f$ SlitAp = \frac{1}{\sin(\theta)} \f$ takes into account the *fraction of the diffracted cone which falls in the detector slit. * * If there is prefereed orientation, this also holds the associated correction. * * \todo: store all corrections in a registry, so that other corrections * can more easily be added (? Maybe not that useful, especially since these * correction do not need to be displayed to the user ?). */ mutable CrystVector_REAL mIntensityCorr; /// Lorentz correction LorentzCorr mCorrLorentz; /// Polarization correction PolarizationCorr mCorrPolar; /// Slit aperture correction PowderSlitApertureCorr mCorrSlitAperture; /// Preferred orientation (texture) correction following the March-Dollase model TextureMarchDollase mCorrTextureMarchDollase; /// Preferred orientation (texture) correction following the Ellipsoidal function TextureEllipsoid mCorrTextureEllipsoid; /// Time-Of-Flight intensity correction TOFCorr mCorrTOF; /// Cylinder absorption correction CylinderAbsCorr mCorrCylAbs; /// Computed intensities for all reflections mutable CrystVector_REAL mIhklCalc; mutable std::map mIhkl_FullDeriv; /// Variance on computed intensities for all reflections mutable CrystVector_REAL mIhklCalcVariance; // Saved arrays to speed-up computations /// Profile of a single reflection struct ReflProfile { /// First point of the pattern for which the profile is calculated long first; /// Last point of the pattern for which the profile is calculated long last; /// The profile CrystVector_REAL profile; }; ///Reflection profiles for ALL reflections during the last powder pattern generation mutable vector mvReflProfile; /// Derivatives of reflection profiles versus a list of parameters. This will be limited /// to the reflections actually used. First and last point of each profile /// are the same as in mvReflProfile. mutable std::map > mvReflProfile_FullDeriv; // When using integrated profiles /** For each reflection, store the integrated value of the normalized * profile over all integration intervals. * * The first field is the first integration interval to which the reflection * contributes, and the second field is a vector with all the integrated * values for the intervals, listed in ascending 2theta(tof) order. */ mutable vector< pair > mIntegratedProfileFactor; /// Last time the integrated values of normalized profiles was calculated. mutable RefinableObjClock mClockIntegratedProfileFactor; /// Extraction mode (Le Bail, Pawley) bool mExtractionMode; /// Single crystal data extracted from the powder pattern. DiffractionDataSingleCrystal *mpLeBailData; /// a,b and c in Angstroems, angles (stored) in radians /// This is used to override lattice parameter from the Crystal structure, /// e.g. for multiple datasets collected at different temperatures /// Ignored unless mFreezeLatticePar is true mutable CrystVector_REAL mFrozenLatticePar; /// If true, use local cell parameters from mFrozenLatticePar rather than the Crystal bool mFreezeLatticePar; /// Local B Matrix, used if mFreezeLatticePar is true mutable CrystMatrix_REAL mFrozenBMatrix; #ifdef __WX__CRYST__ public: virtual WXCrystObjBasic* WXCreate(wxWindow*); friend class WXPowderPatternDiffraction; #endif private: // Avoid compiler warnings. Explicitly hide the base-class method. void GenHKLFullSpace(const REAL, const bool); }; //###################################################################### /** \brief Powder pattern class, with an observed pattern and several * calculated components to modelize the pattern. * * This can also be used for simulation, using a fake Iobs. Supports * multiple phases. * */ //###################################################################### class PowderPattern : public RefinableObj { public: PowderPattern(); PowderPattern(const PowderPattern&); ~PowderPattern(); virtual const string& GetClassName() const; /** Add a component (phase, backround) to this pattern. * * It must have been allocated in the heap. The pattern parameters (2theta min, * step, nbpoints, wavelength, radiation type) of the component * are automatically changed to that of the PowderPattern object. */ void AddPowderPatternComponent(PowderPatternComponent &); /// Number of components unsigned int GetNbPowderPatternComponent()const; /// Access to a component of the powder pattern const PowderPatternComponent& GetPowderPatternComponent(const string &name)const; /// Access to a component of the powder pattern const PowderPatternComponent& GetPowderPatternComponent(const int)const; /// Access to a component of the powder pattern PowderPatternComponent& GetPowderPatternComponent(const string &name); /// Access to a component of the powder pattern PowderPatternComponent& GetPowderPatternComponent(const int); /// Access to the scale factor of components (will be 1 for background components) REAL GetScaleFactor(const int i)const; /// Access to the scale factor of components (will be 1 for background components) REAL GetScaleFactor(const PowderPatternComponent &comp)const; /// Access to the scale factor of components (will be 1 for background components) void SetScaleFactor(const int i, REAL s); /// Access to the scale factor of components (will be 1 for background components) void SetScaleFactor(const PowderPatternComponent &comp, REAL s); // Pattern parameters (2theta range, wavelength, radiation) /** \briefSet the powder pattern angular range & resolution parameter. * this will affect all components (phases) of the pattern. * * Use this with caution, as the number of points must be correct with * respect to the observed data (Iobs). * * \param min: min 2theta (in radians) or time-of-flight *(in microseconds) value, * \param step: step (assumed constant) in 2theta or time-of-flight * (in microseconds). * \param nbPoints: number of points in the pattern. * * \warning : use only this for constant-step patterns. Otherwise, use * PowderPattern::SetPowderPatternX() */ void SetPowderPatternPar(const REAL min, const REAL step, unsigned long nbPoint); /** Set the x coordinate of the powder pattern : either the * 2theta or time-of-flight values for each recorded point. The * step need not be constant, but the variation must be strictly * monotonous. * * 2theta must be in radians and time-of-flight in microseconds */ void SetPowderPatternX(const CrystVector_REAL &x); ///Number of points ? unsigned long GetNbPoint()const; ///Number of points actually calculated (below the chosen max(sin(theta)/lambda)) ? unsigned long GetNbPointUsed()const; /// Clock corresponding to the last time the number of points used was changed const RefinableObjClock& GetClockNbPointUsed()const; /// Set the radiation void SetRadiation(const Radiation &radiation); ///Neutron or x-ray experiment ? const Radiation& GetRadiation()const; ///Neutron or x-ray experiment ? Radiation& GetRadiation(); /// Set the radiation type void SetRadiationType(const RadiationType radiation); ///Neutron or x-ray experiment ? RadiationType GetRadiationType()const; /** Set the wavelength of the experiment (in Angstroems). * * \note: this is only useful for a monochromatic (X-Ray or neutron) * powder pattern. */ void SetWavelength(const REAL lambda); /** \brief Set the wavelength of the experiment to that of an X-Ray tube. * *\param XRayTubeElementName : name of the anticathode element name. Known *ones are Cr, Fe, Cu, Mo, Ag. *\param alpha2Alpha2ratio: Kalpha2/Kalpha1 ratio (0.5 by default) * *Alpha1 and alpha2 wavelength are taken *from R. Grosse-Kunstleve package, and the average wavelength is calculated *using the alpha2/alpha1 weight. All structure factors computation are made *using the average wavelength, and for powder diffraction, profiles are output *at the alpha1 and alpha2 ratio for the calculated pattern. * *NOTE : if the name of the wavelength is generic (eg"Cu"), *then the program considers that *there are both Alpha1 and Alpha2, and thus automatically changes the WavelengthType *to WAVELENGTH_ALPHA12. If instead either alpha1 or alpha2 (eg "CuA1") is asked for, *the WavelengthType is set to WAVELENGTH_MONOCHROMATIC. In both cases, * the radiation type is set to X-Ray. */ void SetWavelength(const string &XRayTubeElementName,const REAL alpha12ratio=0.5); /// Set the energy of the experiment [in keV, lambda(A)=12398/E(keV)]. void SetEnergy(const REAL energy); /// wavelength of the experiment (in Angstroems) REAL GetWavelength()const; //Access to pattern data /// Get the calculated powder pattern const CrystVector_REAL& GetPowderPatternCalc()const; std::map& GetPowderPattern_FullDeriv(std::set &vPar); /// Get the observed powder pattern const CrystVector_REAL& GetPowderPatternObs()const; /// Get the sigma for each point of the observed powder pattern const CrystVector_REAL& GetPowderPatternObsSigma()const; /// Get the variance (obs+model) for each point of the powder pattern const CrystVector_REAL& GetPowderPatternVariance()const; /// Get the weight for each point of the powder pattern const CrystVector_REAL& GetPowderPatternWeight()const; /// Get the Minimum 2theta REAL GetPowderPatternXMin()const; /** Get the average step in 2theta * * \warning : this will only return (2ThetaMax-2ThetaMin)/(nbPoints-1), * so this is the 2theta step only if the step is fixed. * * \deprecated */ REAL GetPowderPatternXStep()const; /// Get the maximum 2theta REAL GetPowderPatternXMax()const; /// Get the vector of X (2theta or time-of-flight) coordinates const CrystVector_REAL& GetPowderPatternX()const; /** Get the powder pattern cumulative Chi^2. Depending on the chosen option, *it will be calculated in an integrated manner or not. * * The vector is recomputed on every call, so this is \e slow. * \param mode: if -1 (the default), the calculation mode uses the value of mOptProfileIntegration. * if 0, the integrated mode is used. If 1, the full powder pattern mode is used. */ const CrystVector_REAL& GetChi2Cumul(const int mode=-1)const; // Clocks /// Last time the pattern was calculated const RefinableObjClock& GetClockPowderPatternCalc()const; /// When were the pattern parameters (2theta range, step) changed ? const RefinableObjClock& GetClockPowderPatternPar()const; /// When were the radiation parameter (radiation type, wavelength) changed ? const RefinableObjClock& GetClockPowderPatternRadiation()const; /// When were the parameters for 2theta/TOF correction (zero, transparency, /// displacement) last changed ? const RefinableObjClock& GetClockPowderPatternXCorr()const; /// When were the absorption correction parameters (muR) last changed ? const RefinableObjClock& GetClockPowderPatternAbsCorr() const; // Corrections to the x (2theta, tof) coordinate ///Change Zero in x (2theta,tof) void SetXZero(const REAL newZero); /// Change displacement correction /// \f$ (2\theta)_{obs} = (2\theta)_{real} + a\cos(\theta) \f$ void Set2ThetaDisplacement(const REAL displacement); ///Change transparency correction /// \f$ (2\theta)_{obs} = (2\theta)_{real} + b\sin(2\theta) \f$ void Set2ThetaTransparency(const REAL transparency); // Import & export powder pattern /** \brief Import fullprof-style diffraction data. *\param fullprofFileName: filename */ void ImportPowderPatternFullprof(const string &fullprofFileName); /** \brief Import powder pattern, format DMC from PSI */ void ImportPowderPatternPSI_DMC(const string &filename); /** \brief Import powder pattern, format from ILL D1A/D2B * (format without counter info) */ void ImportPowderPatternILL_D1A5(const string &filename); /** \brief Import *.xdd diffraction data (Topas,...). *\param fileName: filename */ void ImportPowderPatternXdd(const string &fileName); /** \brief Import *.cpi Sietronics diffraction data *\param fileName: filename */ void ImportPowderPatternSietronicsCPI(const string &fileName); /** \brief Import file with 3 columns 2Theta Iobs Sigma. *\param fileName: the filename (surprise!) *\param nbSkip: the number of lines to skip at the beginning of the file (default=0) */ void ImportPowderPattern2ThetaObsSigma(const string &fileName,const int nbSkip=0); /** \brief Import diffraction data from a file, with the first line * has 2ThetaMin, step, 2thetaMax, and the following lines alternate * 10 Iobs and 10 sigma. Ends with null entries (to fill last Iobs line * to reach last sigme line). * That's fullprof format #4. *\param fileName: filename */ void ImportPowderPatternFullprof4(const string &fileName); /** \brief diffraction data in a multi-detector format (fullprof format #6). * * First line is text. Third entry of second line is the 2theta step. Third *line has the 2thetamin, fourth line has monitors and temperatures. * Then each line has ten pairs (I2,I8)of NbCounters,intensity. Ends with * negative entries. *\param fileName: filename */ void ImportPowderPatternMultiDetectorLLBG42(const string &fileName); /** \brief Import file with 2 columns 2Theta Iobs. * *\param fileName: the filename (surprise!) *\param nbSkip: the number of lines to skip at the beginning of the file (default=0) */ void ImportPowderPattern2ThetaObs(const string &fileName,const int nbSkip=0); /** \brief Import TOF file (ISIS type, 3 columns t, Iobs, sigma(Iobs)) *\param fileName: the filename */ void ImportPowderPatternTOF_ISIS_XYSigma(const string &fileName); /** Import GSAS standard powder pattern data (see GSAS manual). * \warning : partial support (only CONST-constant wavelength- data so far) */ void ImportPowderPatternGSAS(const string &fileName); /** Import CIF powder pattern data. */ void ImportPowderPatternCIF(const CIF &cif); /** \brief Set observed powder pattern from vector array. * * Note: powder pattern parameters must have been set before calling this function, * for example by calling DiffractionDataPowder::InitPowderPatternPar(). */ void SetPowderPatternObs(const CrystVector_REAL& obs); ///Save powder pattern to one file, text format, 3 columns theta Iobs Icalc. ///If Iobs is missing, the column is omitted. /// /// \todo export in other formats (.prf,...), with a list of reflection /// position for all phases... void SavePowderPattern(const string &filename="powderPattern.out") const; /// Print to thee screen/console the observed and calculated pattern (long, /// mostly useful for debugging) void PrintObsCalcData(ostream&os=cout)const; // Statistics.. /** \brief Unweighted R-factor * * \return \f$ R= \sqrt {\frac{\sum_i \left( I_i^{obs}-I_i^{calc} \right)^2} * {\sum_i (I_i^{obs})^2} }\f$ */ REAL GetR()const ; REAL GetIntegratedR()const ; /** Get the weighted R-factor * \return \f$ R_{w}= \sqrt {\frac{\sum_i w_i\left( I_i^{obs}-I_i^{calc} \right)^2} * {\sum_i w_i (I_i^{obs})^2} }\f$ */ REAL GetRw()const; REAL GetIntegratedRw()const; /** \brief Return conventionnal Chi^2 * * \return \f$ \chi^2 = \sum_i w_i \left(I_i^{obs}-I_i^{calc} \right)^2 * \f$ */ REAL GetChi2()const; /** \brief Return integrated Chi^2 * */ REAL GetIntegratedChi2()const; /** Return the conventionnal or integrated Chi^2, depending on the option. * */ REAL GetChi2_Option()const; /// Fit the scale(s) factor of each component to minimize R void FitScaleFactorForR()const; void FitScaleFactorForIntegratedR()const; /// Fit the scale(s) factor of each component to minimize Rw void FitScaleFactorForRw()const; void FitScaleFactorForIntegratedRw()const; /// Set sigma=sqrt(Iobs) void SetSigmaToSqrtIobs(); /// Set w = 1/sigma^2. /// /// To filter too small or null intensities :If sigma< minRelatSigma* max(sigma), /// then w=1/(minRelatSigma* max(sigma))^2 void SetWeightToInvSigmaSq(const REAL minRelatSigma=1e-3); /// Set w = 1 void SetWeightToUnit(); /// Set w = 1/(a+ Iobs + b*Iobs^2+c*Iobs^3) /// /// To filter too small or null intensities: /// if Iobs < [minRelatIobs * max(Iobs)], then use Iobs=minRelatIobs * max(Iobs) /// to compute the weight. /// /// Typical values: a=2*min(Iobs) b=2/max(Iobs) c=0 void SetWeightPolynomial(const REAL a, const REAL b, const REAL c, const REAL minRelatIobs=1e-3); /// Add an Exclusion region, in 2theta, which will be ignored when computing R's /// XMLInput values must be, as always, in radians. Does not work yet with /// integrated R factors. /// Note that the pattern is still computed in these regions. They are only ignored /// by statistics functions (R, Rws). void AddExcludedRegion(const REAL min2Theta,const REAL max2theta); virtual void BeginOptimization(const bool allowApproximations=false, const bool enableRestraints=false); //virtual void SetApproximationFlag(const bool allow); virtual void GlobalOptRandomMove(const REAL mutationAmplitude, const RefParType *type=gpRefParTypeObjCryst); virtual REAL GetLogLikelihood()const; //LSQ functions virtual unsigned int GetNbLSQFunction()const; virtual const CrystVector_REAL& GetLSQCalc(const unsigned int) const; virtual const CrystVector_REAL& GetLSQObs(const unsigned int) const; virtual const CrystVector_REAL& GetLSQWeight(const unsigned int) const; virtual std::map& GetLSQ_FullDeriv(const unsigned int,std::set &vPar); // I/O virtual void XMLOutput(ostream &os,int indent=0)const; virtual void XMLInput(istream &is,const XMLCrystTag &tag); //virtual void XMLInputOld(istream &is,const IOCrystTag &tag); void Prepare(); virtual void GetGeneGroup(const RefinableObj &obj, CrystVector_uint & groupIndex, unsigned int &firstGroup) const; /// Set the maximum value for sin(theta)/lambda. All data (reflections,..) still /// exist but are ignored for all calculations. virtual void SetMaxSinThetaOvLambda(const REAL max); /// Get the maximum value for sin(theta)/lambda. REAL GetMaxSinThetaOvLambda()const; // For integrated pattern calculations /// Get the list of first pixels for the integration intervals const CrystVector_long& GetIntegratedProfileMin()const; /// Get the list of last pixels for the integration intervals const CrystVector_long& GetIntegratedProfileMax()const; /// When were the integration intervals last changed ? const RefinableObjClock& GetIntegratedProfileLimitsClock()const; /// Get the experimental x (2theta, tof) from the theoretical value, taking /// into account all corrections (zero, transparency,..). /// \internal /// \param ttheta: the theoretical x (2theta, tof) value. /// \return the x (2theta, tof) value as it appears on the pattern. REAL X2XCorr(const REAL x)const; /// Get the pixel number on the experimental pattern, from the /// theoretical (uncorrected) x coordinate, taking into account all corrections. /// (zero, transparency,..). /// \internal /// \param x: the theoretical x (2theta, tof) value. /// \return the x (2theta, tof) value as it appears on the pattern. /// /// \warning: this can be real slow, especially for non-fixed steps. /// /// \warning: this returns the exact pixel coordinate, as a floating-point /// value, and \e not the closest pixel coordinate. REAL X2PixelCorr(const REAL x)const; /// Get the pixel number on the experimental pattern, corresponding /// to a given (experimental) x coordinate /// \param x: the x (2theta, tof) value. /// \return the x (2theta, tof) value as it appears on the pattern. /// /// \warning: this can be real slow, especially for non-fixed steps. /// /// \warning: this returns the exact pixel coordinate, as a floating-point /// value, and \e not the closest pixel coordinate. REAL X2Pixel(const REAL x)const; /// Convert sin(theta)/lambda to X (i.e. either to 2theta or to TOF), /// depending on the type of radiation. /// /// This does not take into account any zero/transparency, etc... correction REAL STOL2X(const REAL stol)const; /// Convert X (either 2theta or TOF) to sin(theta)/lambda, /// depending on the type of radiation. /// /// This does not take into account any zero/transparency, etc... correction REAL X2STOL(const REAL x)const; /// Convert sin(theta)/lambda to pixel, /// depending on the type of radiation. /// /// This does not take into account any zero/transparency, etc... correction REAL STOL2Pixel(const REAL stol)const; /// Find peaks in the pattern PeakList FindPeaks(const float dmin=2.0,const float maxratio=0.01,const unsigned int maxpeak=100); /// Access the scale factors (see PowderPattern::mScaleFactor) const CrystVector_REAL &GetScaleFactor() const; /// Access the scale factors (see PowderPattern::mScaleFactor) CrystVector_REAL &GetScaleFactor(); /** Export powder pattern & crystal structure in Fullprof format. * * This will create two files - the .pcr file (including the crystal structure * and all pattern parameters), and the .dat file with the powder pattern, * written using the "Ins=10" file format. * \param prefix: the prefix used to output the two files, 'prefix'.pcr and 'prefix'.dat * * \note: in development. Only supports constant wavelength neutron & X-ray patterns. */ void ExportFullprof(const std::string &prefix)const; /// Set the $\mu R$ value for cylinder absorption correction void SetMuR(const REAL muR); /// Get the $\mu R$ value REAL GetMuR() const; protected: /// Calc the powder pattern void CalcPowderPattern() const; void CalcPowderPattern_FullDeriv(std::set &vPar); /// Calc the integrated powder pattern void CalcPowderPatternIntegrated() const; void CalcPowderPatternIntegrated_FullDeriv(std::set &vPar); /// Init parameters and options virtual void Init(); /// Prepare the calculation of the integrated R-factors void PrepareIntegratedRfactor()const; /// Calculate the number of points of the pattern actually used, from the maximum /// value of sin(theta)/lambda void CalcNbPointUsed()const; /// Initialize options virtual void InitOptions(); /// The calculated powder pattern. It is mutable since it is /// completely defined by other parameters (eg it is not an 'independent parameter') mutable CrystVector_REAL mPowderPatternCalc; mutable std::map mPowderPattern_FullDeriv; /// The calculated powder pattern, integrated mutable CrystVector_REAL mPowderPatternIntegratedCalc; mutable std::map mPowderPatternIntegrated_FullDeriv; /// The calculated powder pattern part which corresponds to 'background' /// (eg non-scalable components). It is already included in mPowderPatternCalc mutable CrystVector_REAL mPowderPatternBackgroundCalc; /// The calculated powder pattern part which corresponds to 'background' /// (eg non-scalable components), integrated mutable CrystVector_REAL mPowderPatternBackgroundIntegratedCalc; /// The observed powder pattern. CrystVector_REAL mPowderPatternObs; /// The sigma of the observed pattern. CrystVector_REAL mPowderPatternObsSigma; /// The weight for each point of the pattern. mutable CrystVector_REAL mPowderPatternWeight; /// The complete variance associated to each point of the powder pattern, /// taking into account observation and model errors. mutable CrystVector_REAL mPowderPatternVariance; /// The complete variance associated to each point of the powder pattern, /// taking into account observation and model errors. Integrated. mutable CrystVector_REAL mPowderPatternVarianceIntegrated; /// The cumulative Chi^2 (integrated or not, depending on the option) mutable CrystVector_REAL mChi2Cumul; /// The calculated powder pattern. Cropped to the maximum sin(theta)/lambda for LSQ mutable CrystVector_REAL mPowderPatternUsedCalc; mutable std::map mPowderPatternUsed_FullDeriv; /// The calculated powder pattern. Cropped to the maximum sin(theta)/lambda for LSQ mutable CrystVector_REAL mPowderPatternUsedObs; /// The weight for each point of the pattern. Cropped to the maximum sin(theta)/lambda for LSQ mutable CrystVector_REAL mPowderPatternUsedWeight; /** Vector of x coordinates (either 2theta or time-of-flight) for the pattern * * Stored in ascending order for 2theta, and descending for TOF, i.e. always * in ascending order for the corresponding sin(theta)/lambda. */ CrystVector_REAL mX; /// Is the mX vector sorted in ascending order ? (true for 2theta, false for TOF) bool mIsXAscending; /// Number of points in the pattern unsigned long mNbPoint; /// The Radiation corresponding to this experiment Radiation mRadiation; // Clocks /// When were the pattern parameters (2theta or time-of-flight range) changed ? RefinableObjClock mClockPowderPatternPar; /// When were the radiation parameter (radiation type, wavelength) changed ? RefinableObjClock mClockPowderPatternRadiation; /// When was the powder pattern last computed ? mutable RefinableObjClock mClockPowderPatternCalc; /// When was the powder pattern (integrated) last computed ? mutable RefinableObjClock mClockPowderPatternIntegratedCalc; /// Corrections to 2Theta RefinableObjClock mClockPowderPatternXCorr; /// Last modification of the scale factor mutable RefinableObjClock mClockScaleFactor; /// Last modification of absorption correction parameters mutable RefinableObjClock mClockCorrAbs; //Excluded regions in the powder pattern, for statistics. /// Min coordinate for for all excluded regions CrystVector_REAL mExcludedRegionMinX; /// Max coordinate for 2theta for all excluded regions CrystVector_REAL mExcludedRegionMaxX; //Various corrections to 2theta-to be used by the components /// Zero correction : /// \f$ (2\theta)_{obs} = (2\theta)_{real} +(2\theta)_{0}\f$ ///Thus mPowderPattern2ThetaMin=(mPowderPattern2ThetaMin-m2ThetaZero) REAL mXZero; /// Displacement correction : ///\f$ (2\theta)_{obs} = (2\theta)_{real} + \frac{a}{\cos(\theta)} \f$ REAL m2ThetaDisplacement; /// Transparency correction : ///\f$ (2\theta)_{obs} = (2\theta)_{real} + b\sin(2\theta) \f$ REAL m2ThetaTransparency; /// Time Of Flight (TOF) parameters : ///\f$ t = DIFC*\frac{\sin(\theta)}{\lambda} + DIFA*\left(\frac{\sin(\theta)}{\lambda}\right)^2 + mXZero\f$ REAL mDIFC,mDIFA; // Components of the powder pattern /// The components (crystalline phases, background,...) of the powder pattern ObjRegistry mPowderPatternComponentRegistry; /// The scale factors for each component. For unscalable phases, /// this is set to 1 (constant). /// /// This is mutable because generally we use the 'best' scale factor, but /// it should not be... mutable CrystVector_REAL mScaleFactor; /// Mu*R parameter for cylinder absorption correction REAL mMuR; /// Use faster, less precise functions ? bool mUseFastLessPreciseFunc; // For statistics /// Should Statistics (R, Rw,..) exclude the background ? bool mStatisticsExcludeBackground; /// \internal To compute scale factors, which are the components (phases) that /// can be scaled ? mutable CrystVector_int mScalableComponentIndex; /// \internal Used to fit the components' scale factors mutable CrystMatrix_REAL mFitScaleFactorM,mFitScaleFactorB,mFitScaleFactorX; /// Use Integrated profiles for Chi^2, R, Rwp... RefObjOpt mOptProfileIntegration; // Integrated R-factors mutable CrystVector_long mIntegratedPatternMin,mIntegratedPatternMax; mutable CrystVector_REAL mIntegratedObs; mutable CrystVector_REAL mIntegratedWeight; mutable CrystVector_REAL mIntegratedWeightObs; mutable CrystVector_REAL mIntegratedVarianceObs; mutable RefinableObjClock mClockIntegratedFactorsPrep; // Statistical indicators mutable REAL mChi2,mIntegratedChi2; /// This is the logarithm of the part of log(Likelihood) which corresponds /// to the normalization terms of gaussian distribution for each obs/calc /// point. In practice, this is the sum of 1/2*log(2pi*sig(i)^2), although /// we discard the 2pi terms. mutable REAL mChi2LikeNorm,mIntegratedChi2LikeNorm; mutable REAL mR; mutable REAL mRw; ///Clock the last time Chi^2 was computed mutable RefinableObjClock mClockChi2,mClockIntegratedChi2; /** Maximum sin(theta)/lambda for all calculations (10 by default). * * This keeps all data in memory, but only the part which is below * the max is calculated. */ REAL mMaxSinThetaOvLambda; /// Number of points actually used, due to the maximum value of /// sin(theta)/lambda. mutable unsigned long mNbPointUsed; /// Number of integration intervals actually used, due to the maximum value of /// sin(theta)/lambda. mutable unsigned long mNbIntegrationUsed; /// Clock recording the last time the number of points used (PowderPattern::mNbPointUsed) /// was changed. mutable RefinableObjClock mClockNbPointUsed; #ifdef __WX__CRYST__ public: virtual WXCrystObjBasic* WXCreate(wxWindow*); friend class WXPowderPattern; // This should be removed friend class WXPowderPatternGraph; #endif }; /// Global registry for all PowderPattern objects extern ObjRegistry gPowderPatternRegistry; //###################################################################### // PROFILE FUNCTIONS (for powder diffraction) //###################################################################### ///Gaussian, normalized (ie integral is equal to 1), as a function of theta /// and of the FWHM. The input is an array of the theta values. The maximum of the ///function is in theta=0. If asymmetry is used, negative tth values must be first. CrystVector_REAL PowderProfileGauss (const CrystVector_REAL theta, const REAL fwhm, const REAL asymmetryPar=1.); ///Lorentzian, normalized (ie integral is equal to 1), as a function of theta /// and of the FWHM. The input is an array of the theta values. The maximum of the ///function is in theta=0. If asymmetry is used, negative tth values must be first. CrystVector_REAL PowderProfileLorentz(const CrystVector_REAL theta, const REAL fwhm, const REAL asymmetryPar=1.); //###################################################################### // Spacegroup explorer //###################################################################### /** Structure to hold the score corresponding to a given spacegroup. * */ struct SPGScore { SPGScore(const string &s, const REAL r, const REAL g, const unsigned int nbextinct, const REAL ngof=0, const unsigned int nbrefl=0); string hm; /// Rw factor, from PowderPattern::GetRw() REAL rw; /// Goodness-of-fit, from PowderPattern::GetChi2() normalised by REAL gof; /// Normalised & integrated goodness-of-fit = iGoF * (nb_refl) / (nb_refl in P1), /// where iGoF is the integrated goodness-of-fit, computed using the integration /// intervals determined for the P1 spacegroup. This is only computed /// if the P1 spacegroup was tested first. REAL ngof; /// Number of extinct reflections for 0<=H<=4, 0<=K<=4, 0<=L<=6, which /// can be used as unique fingerprint for the spacegroup systematic extinctions. unsigned int nbextinct446; /// Number of reflections used for the fit. unsigned int nbreflused; }; bool compareSPGScore(const SPGScore &s1, const SPGScore &s2); /// Function which determines the unique extinction fingerprint of a spacegroup, /// by calculating all present reflections between 0<=H<=4 0<=K<=4 0<=L<=6 std::vector spgExtinctionFingerprint(Crystal &c, const cctbx::sgtbx::space_group &spg); /** Algorithm class to find the correct spacegroup for an indexed powder pattern. * */ class SpaceGroupExplorer { public: /** Constructor * * \param pd: the PowderPatternDiffraction for which we are trying to find the spacegroup. */ SpaceGroupExplorer(PowderPatternDiffraction *pd); /** Run test on a single spacegroup * * \param spg: the name of the spacegroup, ideally a Hall symbol, or an Hermann-Mauguin, * or a number * \param fitprofile: if true, will perform a full profile fitting instead of just Le Bail * extraction. Much slower. * \param restore_orig: if true, will go back to the original unit cell and spacegroup at the end * \param relative_length_tolerance: relative length tolerance to determine compatible unit cells * (i.e. the a/b ratio for quadratic spacegroups) * \param absolute_angle_tolerance_degree: the absolute angular tolerance in degrees * to determine compatible unit cells. * \return: the SPGScore corresponding to this spacegroup */ SPGScore Run(const string &spg, const bool fitprofile=false, const bool verbose=false, const bool restore_orig=false, const bool update_display=true, const REAL relative_length_tolerance=0.01, const REAL absolute_angle_tolerance_degree=0.5); /** Run test on a single spacegroup * * \param spg: the cctbx::sgtbx::space_group * \param fitprofile: if true, will perform a full profile fitting instead of just Le Bail * extraction. Much slower. * \param restore_orig: if true, will go back to the original unit cell and spacegroup at the end * \param update_display: if true, update the display during the search * \param relative_length_tolerance: relative length tolerance to determine compatible unit cells * (i.e. the a/b ratio for quadratic spacegroups) * \param absolute_angle_tolerance_degree: the absolute angular tolerance in degrees * to determine compatible unit cells. * \return: the SPGScore corresponding to this spacegroup */ SPGScore Run(const cctbx::sgtbx::space_group &spg, const bool fitprofile=false, const bool verbose=false, const bool restore_orig=false, const bool update_display=true, const REAL relative_length_tolerance=0.01, const REAL absolute_angle_tolerance_degree=0.5); /** Run test on all spacegroups compatible with the unit cell * Note that all scores's ngof values will be multiplied by nb_refl/nb_refl_P1 to * have a better indicator of the quality taking into account the number of reflections used. * * \param fitprofile_all: if true, will perform a full profile fitting instead of just Le Bail * extraction for all spacegroups. Much slower. By default, the profile fitting is only * performed for the first spacegroup (P1) * \param verbose: 0 (default), not verbose, 1 minimal information, 2, very verbose * \param keep_best: if true, will keep the best solution at the end (default: restore the original one) * \param update_display: if true, update the display during the search * \param fitprofile_p1: if true, fit the profile for p1 (ignored if fitprofile_all=true) * \param relative_length_tolerance: relative length tolerance to determine compatible unit cells * (i.e. the a/b ratio for quadratic spacegroups) * \param absolute_angle_tolerance_degree: the absolute angular tolerance in degrees * to determine compatible unit cells. * \return: the SPGScore corresponding to this spacegroup */ void RunAll(const bool fitprofile_all=false, const bool verbose=true, const bool keep_best=false, const bool update_display=true, const bool fitprofile_p1=true, const REAL relative_length_tolerance=0.01, const REAL absolute_angle_tolerance_degree=0.5); /// Get the list of all scores obatined after using RunAll() const list& GetScores() const; private: /// Compute the integrated goodness-of-fit using P1 integration intervals. If this is called /// and the spacegroup is P1, this initialises the P1 intervals as well. If the intervals /// have not been initialised and the spaceroup is not P1, zero is returned. REAL GetP1IntegratedGoF(); /// PwderPatternDiffraction for which we explore the spacegroups PowderPatternDiffraction *mpDiff; /// Min and max of intervals for integration domains, for the P1 specegroup. This is /// used to compute a normalised integrated goodness of fit using the same intervals CrystVector_REAL mP1IntegratedProfileMin,mP1IntegratedProfileMax; /// List of scores for the explore spacegroups list mvSPG; /// Map extinction fingerprint std::map,SPGScore> mvSPGExtinctionFingerprint; }; }//namespace ObjCryst #endif // _OBJCRYST_POWDERPATTERN_H_ objcryst-2022.1/ObjCryst/ObjCryst/PowderPatternBackgroundBayesianMinimiser.cpp000066400000000000000000000120151430515525000275670ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* PowderPatternBackgroundBayesianMinimiser.h * Bayesian estimation of powder pattern background * */ #include "ObjCryst/ObjCryst/PowderPatternBackgroundBayesianMinimiser.h" namespace ObjCryst { PowderPatternBackgroundBayesianMinimiser:: PowderPatternBackgroundBayesianMinimiser(PowderPatternBackground &backgd): mpBackground(&backgd) { this->AddSubRefObj(*mpBackground); } PowderPatternBackgroundBayesianMinimiser::~PowderPatternBackgroundBayesianMinimiser() { this->RemoveSubRefObj(*mpBackground); } const string& PowderPatternBackgroundBayesianMinimiser::GetClassName()const { static string className="PowderPatternBackgroundBayesianMinimiser"; return className; } REAL PowderPatternBackgroundBayesianMinimiser::GetLogLikelihood()const { TAU_PROFILE("PowderPatternBackgroundBayesianMinimiser::GetLogLikelihood()","void ()",TAU_DEFAULT); REAL llk=0; const long nb=mpBackground->GetPowderPatternCalc().numElements(); const long step=1; {// Calc (obs-calc)/sigma const REAL *pBackgd=mpBackground->GetPowderPatternCalc().data(); const REAL *pObs=mpBackground->GetParentPowderPattern().GetPowderPatternObs().data(); const REAL *pSigma=mpBackground->GetParentPowderPattern().GetPowderPatternObsSigma().data(); for(long i=0;i0) { llk += PowderPatternBackgroundBayesianMinimiser ::BayesianBackgroundLogLikelihood ((*pObs-*pBackgd) / (1.4142135623730951**pSigma)); } pObs+=step; pBackgd+=step; pSigma+=step; } } return llk; } unsigned int PowderPatternBackgroundBayesianMinimiser::GetNbLSQFunction () const {return 1;} const CrystVector_REAL& PowderPatternBackgroundBayesianMinimiser::GetLSQCalc (const unsigned int id) const { const long nb=mpBackground->GetPowderPatternCalc().numElements(); const long step=1; if(mBayesianCalc.numElements()!=nb) mBayesianCalc.resize(nb); const REAL *pBackgd=mpBackground->GetPowderPatternCalc().data(); const REAL *pObs=mpBackground->GetParentPowderPattern().GetPowderPatternObs().data(); const REAL *pSigma=mpBackground->GetParentPowderPattern().GetPowderPatternObsSigma().data(); REAL *pBayesCalc=mBayesianCalc.data(); for(long i=0;i0) { *pBayesCalc = 1 + PowderPatternBackgroundBayesianMinimiser::BayesianBackgroundLogLikelihood((*pObs-*pBackgd) / (1.4142135623730951**pSigma)); } else *pBayesCalc = 1; pObs+=step; pBackgd+=step; pSigma+=step; pBayesCalc+=step; } return mBayesianCalc; } const CrystVector_REAL& PowderPatternBackgroundBayesianMinimiser::GetLSQObs (const unsigned int) const { const long nb=mpBackground->GetPowderPatternCalc().numElements(); if(mBayesianObs.numElements()!=nb) { mBayesianObs.resize(nb); mBayesianObs=1; // Avoid having all observed values==0, raises issues when computing R and Rw in LSQNumObj } return mBayesianObs; } const CrystVector_REAL& PowderPatternBackgroundBayesianMinimiser::GetLSQWeight (const unsigned int) const { const long nb=mpBackground->GetPowderPatternCalc().numElements(); if(mBayesianWeight.numElements()!=nb) { mBayesianWeight.resize(nb); mBayesianWeight=1; } return mBayesianWeight; } REAL PowderPatternBackgroundBayesianMinimiser::BayesianBackgroundLogLikelihood(const REAL t) { static const REAL vllk[11]={0.00000000e+00, 1e-4, 1.77123249e-03, 1.00997634e+00, 2.89760310e+00, 3.61881096e+00, 3.93024374e+00, 4.16063018e+00, 4.34600620e+00, 4.50155649e+00, 4.63573160e+00}; static const REAL vt[11]={ 0. , 0.01, 0.1 , 1.1 , 2.1 , 3.1 , 4.1 , 5.1 , 6.1 , 7.1 , 8.1}; static const CubicSpline spline(vt,vllk,11); static const REAL s1=spline(8)-log((REAL)8); if(t<=0) return 5*t*t; if(t<8)return spline(t); return s1+log(t); } }//namespace objcryst-2022.1/ObjCryst/ObjCryst/PowderPatternBackgroundBayesianMinimiser.h000066400000000000000000000074641430515525000272500ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* PowderPatternBackgroundBayesianMinimiser.h * Bayesian estimation of powder pattern background * */ #ifndef __POWDERPATTERNBACKGROUNDBAYESIANMINIMISER_H #define __POWDERPATTERNBACKGROUNDBAYESIANMINIMISER_H #include "ObjCryst/CrystVector/CrystVector.h" #include "ObjCryst/RefinableObj/RefinableObj.h" #include "ObjCryst/ObjCryst/PowderPattern.h" namespace ObjCryst { /** This object is used to estimate the background in a powder pattern, * using a Bayesian approach (David & Sivia, Acta Cryst A50 (1994), 703) * */ class PowderPatternBackgroundBayesianMinimiser:public RefinableObj { public: PowderPatternBackgroundBayesianMinimiser(PowderPatternBackground &backgd); ~PowderPatternBackgroundBayesianMinimiser(); virtual const string& GetClassName()const; virtual REAL GetLogLikelihood()const; virtual unsigned int GetNbLSQFunction () const ; virtual const CrystVector_REAL & GetLSQCalc (const unsigned int) const; virtual const CrystVector_REAL & GetLSQObs (const unsigned int) const; virtual const CrystVector_REAL & GetLSQWeight (const unsigned int) const; //private: /** Returns the log(likelihood) of a background by marginalizing the effect of Bragg peaks, following the method described by David and Sivia (\e J.Appl.Cryst. \b 34(2001), 318). * * \returns * - \f$ L(t) = \frac{\left(y^{calc}_{Background}-y^{obs}\right)^2}{2\sigma^2}\f$ * for \t<0 * - \f$ L(t) = A-\log{\int_\epsilon^{\infty} {\frac{1}{u} e^{-(t-u)^2} du}}\f$ for t>0, * with: \f$\epsilon = 1e-6\f$, \f$ t = \frac{y^{calc}_{Background}-y^{obs}}{\sigma\sqrt{2}}\f$ * and A a normalizing constant so that the function is continuous for t=0 (i.e. \e L(0)=0). * * \param \f$ t = \frac{y^{calc}_{Background}-y^{obs}}{\sigma\sqrt{2}}\f$ * * For small \e t>0 values, \e L(t) behaves like a quadratic function, and for large * positive values it is equivalent to \f$ \log{\frac{\sqrt{\pi}}{t}}\f$. * * As the integral diverges for \f$\epsilon=0\f$, it is necessary to use * a small, non-null \f$\epsilon\f$. The use of a smaller \f$\epsilon\f$ changes * the range over which the function behaves quadratically, as well as the maximum * value (at \e t=0), but does not affect the asymptotic value. * * See tabulated values in the source code. The function is approximated with a cubic * spline until \e t=8, and then uses the asymptotic\f$A-\log{\frac{\sqrt{\pi}}{t}}\f$ value. * * \note For a more strict calculation, we should include a normalizing constant (?) */ static REAL BayesianBackgroundLogLikelihood(const REAL t); PowderPatternBackground *mpBackground; /// Bayesian cost (-log(likelihood)) for each point mutable CrystVector_REAL mBayesianCalc; /// Obs==0 (desired -log(likelihood)) mutable CrystVector_REAL mBayesianObs; /// Weight=1 mutable CrystVector_REAL mBayesianWeight; }; }//namespace #endif //__POWDERPATTERNBACKGROUNDBAYESIANMINIMISER_H objcryst-2022.1/ObjCryst/ObjCryst/ReflectionProfile.cpp000066400000000000000000001611211430515525000230560ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2005 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * source file for LibCryst++ ReflectionProfile and derived classes * */ #include #include "ObjCryst/ObjCryst/ReflectionProfile.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" #ifdef __WX__CRYST__ #include "ObjCryst/wxCryst/wxPowderPattern.h" #endif #ifdef HAVE_SSE_MATHFUN #include "ObjCryst/Quirks/sse_mathfun.h" #endif namespace ObjCryst { #if defined(_MSC_VER) || defined(__BORLANDC__) #undef min // Predefined macros.... (wx?) #undef max double erfc(const double x)// in C99, but not in VC++.... { if(x<0.0) return 2.0-erfc(-x); if(x<3.8) { // Series, Abramowitz & Stegun 7.1.6 double y=x,y0=x; for(int i=1;i<=50;i++) { y0*=2*x*x/(2*i+1.0); y+=y0; } static const double spi=2/sqrt(M_PI); return 1-spi*exp(-x*x)*y; } double y=1.0,y0=1.0; for(int i=1;i<=10;i++) {// Asymptotic, Abramowitz & Stegun 7.1.23 y0*=-(2*i-1)/(2*x*x); y+=y0; } static const double invsqrtpi=1.0/sqrt(M_PI); return invsqrtpi*exp(-x*x)/x*y; } #endif extern const RefParType *gpRefParTypeScattDataProfile; extern const RefParType *gpRefParTypeScattDataProfileType; extern const RefParType *gpRefParTypeScattDataProfileWidth; extern const RefParType *gpRefParTypeScattDataProfileAsym; ObjRegistry gReflectionProfileRegistry("List of all ReflectionProfile types");; //////////////////////////////////////////////////////////////////////// // // ReflectionProfile // //////////////////////////////////////////////////////////////////////// ReflectionProfile::ReflectionProfile(): RefinableObj() {} ReflectionProfile::ReflectionProfile(const ReflectionProfile &old) {} ReflectionProfile::~ReflectionProfile() {} bool ReflectionProfile::IsAnisotropic()const {return false;} //////////////////////////////////////////////////////////////////////// // // ReflectionProfilePseudoVoigt // //////////////////////////////////////////////////////////////////////// ReflectionProfilePseudoVoigt::ReflectionProfilePseudoVoigt(): ReflectionProfile(), mCagliotiU(0),mCagliotiV(0),mCagliotiW(.01*DEG2RAD*DEG2RAD), mPseudoVoigtEta0(0.5),mPseudoVoigtEta1(0.0), mAsymBerarBaldinozziA0(0.0),mAsymBerarBaldinozziA1(0.0), mAsymBerarBaldinozziB0(0.0),mAsymBerarBaldinozziB1(0.0), mAsym0(1.0),mAsym1(0.0),mAsym2(0.0) { this->InitParameters(); } ReflectionProfilePseudoVoigt::ReflectionProfilePseudoVoigt (const ReflectionProfilePseudoVoigt &old): mCagliotiU(old.mCagliotiU),mCagliotiV(old.mCagliotiV),mCagliotiW(old.mCagliotiW), mPseudoVoigtEta0(old.mPseudoVoigtEta0),mPseudoVoigtEta1(old.mPseudoVoigtEta1), mAsymBerarBaldinozziA0(old.mAsymBerarBaldinozziA0), mAsymBerarBaldinozziA1(old.mAsymBerarBaldinozziA1), mAsymBerarBaldinozziB0(old.mAsymBerarBaldinozziB0), mAsymBerarBaldinozziB1(old.mAsymBerarBaldinozziB1), mAsym0(old.mAsym0),mAsym1(old.mAsym1),mAsym2(old.mAsym2) { this->InitParameters(); } ReflectionProfilePseudoVoigt::~ReflectionProfilePseudoVoigt() { #ifdef __WX__CRYST__ if(mpWXCrystObj!=0) { delete mpWXCrystObj; mpWXCrystObj=0; } #endif } ReflectionProfilePseudoVoigt* ReflectionProfilePseudoVoigt::CreateCopy()const { return new ReflectionProfilePseudoVoigt(*this); } const string& ReflectionProfilePseudoVoigt::GetClassName()const { static string className="ReflectionProfilePseudoVoigt"; return className; } CrystVector_REAL ReflectionProfilePseudoVoigt::GetProfile(const CrystVector_REAL &x, const REAL center,const REAL h, const REAL k, const REAL l)const { VFN_DEBUG_ENTRY("ReflectionProfilePseudoVoigt::GetProfile(),c="<1) eta=1; if(eta<0) eta=0; profile *= 1-eta; tmpV=PowderProfileLorentz(x,fwhm,center,asym); tmpV *= eta; profile += tmpV; //profile *= AsymmetryBerarBaldinozzi(x,fwhm,center, // mAsymBerarBaldinozziA0,mAsymBerarBaldinozziA1, // mAsymBerarBaldinozziB0,mAsymBerarBaldinozziB1); VFN_DEBUG_EXIT("ReflectionProfilePseudoVoigt::GetProfile()",2) return profile; } void ReflectionProfilePseudoVoigt::SetProfilePar(const REAL fwhmCagliotiW, const REAL fwhmCagliotiU, const REAL fwhmCagliotiV, const REAL eta0, const REAL eta1) { mCagliotiU=fwhmCagliotiU; mCagliotiV=fwhmCagliotiV; mCagliotiW=fwhmCagliotiW; mPseudoVoigtEta0=eta0; mPseudoVoigtEta1=eta1; mClockMaster.Click(); } bool ReflectionProfilePseudoVoigt::IsAnisotropic()const{return false;} REAL ReflectionProfilePseudoVoigt::GetFullProfileWidth(const REAL relativeIntensity, const REAL center,const REAL h, const REAL k, const REAL l) { VFN_DEBUG_ENTRY("ReflectionProfilePseudoVoigt::GetFullProfileWidth()",2) const int nb=100; const int halfnb=nb/2; CrystVector_REAL x(nb); REAL n=5.0; REAL fwhm= mCagliotiW +mCagliotiV*tan(center/2.0) +mCagliotiU*pow(tan(center/2.0),2); if(fwhm<=0) fwhm=1e-6; else fwhm=sqrt(fwhm); CrystVector_REAL prof; while(true) { //Create an X array with 100 elements reaching +/- n*FWHM/2 REAL *p=x.data(); const REAL tmp=fwhm*n/nb; for(int i=0;iGetProfile(x,center,0,0,0); const REAL max=prof.max(); const REAL test=max*relativeIntensity; int n1=0,n2=0; if((prof(0)test){ p++; n2++;} VFN_DEBUG_EXIT("ReflectionProfilePseudoVoigt::GetFullProfileWidth():"<(x,prof),2) n*=2.0; //if(n>200) exit(0); } } void ReflectionProfilePseudoVoigt::InitParameters() { { RefinablePar tmp("U",&mCagliotiU,-1/RAD2DEG/RAD2DEG,1./RAD2DEG/RAD2DEG, gpRefParTypeScattDataProfileWidth, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,RAD2DEG*RAD2DEG); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-9); this->AddPar(tmp); } { RefinablePar tmp("V",&mCagliotiV,-1/RAD2DEG/RAD2DEG,1./RAD2DEG/RAD2DEG, gpRefParTypeScattDataProfileWidth, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,RAD2DEG*RAD2DEG); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-9); this->AddPar(tmp); } { RefinablePar tmp("W",&mCagliotiW,0,1./RAD2DEG/RAD2DEG, gpRefParTypeScattDataProfileWidth, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,RAD2DEG*RAD2DEG); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-9); this->AddPar(tmp); } { RefinablePar tmp("Eta0",&mPseudoVoigtEta0,0,1.,gpRefParTypeScattDataProfileType, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { RefinablePar tmp("Eta1",&mPseudoVoigtEta1,-1,1.,gpRefParTypeScattDataProfileType, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } #if 0 { RefinablePar tmp("AsymA0",&mAsymBerarBaldinozziA0,-0.05,0.05,gpRefParTypeScattDataProfileAsym, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { RefinablePar tmp("AsymA1",&mAsymBerarBaldinozziA1,-0.05,0.05,gpRefParTypeScattDataProfileAsym, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { RefinablePar tmp("AsymB0",&mAsymBerarBaldinozziB0,-0.01,0.01,gpRefParTypeScattDataProfileAsym, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { RefinablePar tmp("AsymB1",&mAsymBerarBaldinozziB1,-0.01,0.01,gpRefParTypeScattDataProfileAsym, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } #endif { RefinablePar tmp("Asym0",&mAsym0,0.01,10.0,gpRefParTypeScattDataProfileAsym, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { RefinablePar tmp("Asym1",&mAsym1,-1.0,1.0,gpRefParTypeScattDataProfileAsym, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { RefinablePar tmp("Asym2",&mAsym2,-1.0,1.0,gpRefParTypeScattDataProfileAsym, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } } void ReflectionProfilePseudoVoigt::XMLOutput(ostream &os,int indent)const { VFN_DEBUG_ENTRY("ReflectionProfilePseudoVoigt::XMLOutput():"<GetName(),5) for(int i=0;iGetPar(&mCagliotiU).XMLOutput(os,"U",indent); os <GetPar(&mCagliotiV).XMLOutput(os,"V",indent); os <GetPar(&mCagliotiW).XMLOutput(os,"W",indent); os <GetPar(&mPseudoVoigtEta0).XMLOutput(os,"Eta0",indent); os <GetPar(&mPseudoVoigtEta1).XMLOutput(os,"Eta1",indent); os <GetPar(&mAsym0).XMLOutput(os,"Asym0",indent); os <GetPar(&mAsym1).XMLOutput(os,"Asym1",indent); os <GetPar(&mAsym2).XMLOutput(os,"Asym2",indent); os <GetPar(&mAsymBerarBaldinozziA0).XMLOutput(os,"AsymA0",indent); os <GetPar(&mAsymBerarBaldinozziA1).XMLOutput(os,"AsymA1",indent); os <GetPar(&mAsymBerarBaldinozziB0).XMLOutput(os,"AsymB0",indent); os <GetPar(&mAsymBerarBaldinozziB1).XMLOutput(os,"AsymB1",indent); os <GetName(),5) } void ReflectionProfilePseudoVoigt::XMLInput(istream &is,const XMLCrystTag &tagg) { VFN_DEBUG_ENTRY("ReflectionProfilePseudoVoigt::XMLInput():"<GetName(),5) for(unsigned int i=0;iSetName(tagg.GetAttributeValue(i)); } while(true) { XMLCrystTag tag(is); if(("ReflectionProfilePseudoVoigt"==tag.GetName())&&tag.IsEndTag()) { this->UpdateDisplay(); VFN_DEBUG_EXIT("ReflectionProfilePseudoVoigt::Exit():"<GetName(),5) return; } if("Par"==tag.GetName()) { for(unsigned int i=0;iGetPar(&mCagliotiU).XMLInput(is,tag); break; } if("V"==tag.GetAttributeValue(i)) { this->GetPar(&mCagliotiV).XMLInput(is,tag); break; } if("W"==tag.GetAttributeValue(i)) { this->GetPar(&mCagliotiW).XMLInput(is,tag); break; } if("Eta0"==tag.GetAttributeValue(i)) { this->GetPar(&mPseudoVoigtEta0).XMLInput(is,tag); break; } if("Eta1"==tag.GetAttributeValue(i)) { this->GetPar(&mPseudoVoigtEta1).XMLInput(is,tag); break; } if("Asym0"==tag.GetAttributeValue(i)) { this->GetPar(&mAsym0).XMLInput(is,tag); break; } if("Asym1"==tag.GetAttributeValue(i)) { this->GetPar(&mAsym1).XMLInput(is,tag); break; } if("Asym2"==tag.GetAttributeValue(i)) { this->GetPar(&mAsym2).XMLInput(is,tag); break; } #if 0 if("AsymA0"==tag.GetAttributeValue(i)) { this->GetPar(&mAsymBerarBaldinozziA0).XMLInput(is,tag); break; } if("AsymA1"==tag.GetAttributeValue(i)) { this->GetPar(&mAsymBerarBaldinozziA1).XMLInput(is,tag); break; } if("AsymB0"==tag.GetAttributeValue(i)) { this->GetPar(&mAsymBerarBaldinozziB0).XMLInput(is,tag); break; } if("AsymB1"==tag.GetAttributeValue(i)) { this->GetPar(&mAsymBerarBaldinozziB1).XMLInput(is,tag); break; } #endif } } continue; } if("Option"==tag.GetName()) { for(unsigned int i=0;iInitParameters(); } ReflectionProfilePseudoVoigtAnisotropic::ReflectionProfilePseudoVoigtAnisotropic(const ReflectionProfilePseudoVoigtAnisotropic &old): mCagliotiU(old.mCagliotiU),mCagliotiV(old.mCagliotiV),mCagliotiW(old.mCagliotiW),mScherrerP(old.mScherrerP),mLorentzX(old.mLorentzX),mLorentzY(old.mLorentzY), mLorentzGammaHH(old.mLorentzGammaHH),mLorentzGammaKK(old.mLorentzGammaKK),mLorentzGammaLL(old.mLorentzGammaLL),mLorentzGammaHK(old.mLorentzGammaHK),mLorentzGammaHL(old.mLorentzGammaHL),mLorentzGammaKL(old.mLorentzGammaKL), mPseudoVoigtEta0(old.mPseudoVoigtEta0),mPseudoVoigtEta1(old.mPseudoVoigtEta1),mAsym0(old.mAsym0),mAsym1(old.mAsym1),mAsym2(old.mAsym2) { this->InitParameters(); } ReflectionProfilePseudoVoigtAnisotropic::~ReflectionProfilePseudoVoigtAnisotropic() { #ifdef __WX__CRYST__ if(mpWXCrystObj!=0) { delete mpWXCrystObj; mpWXCrystObj=0; } #endif } ReflectionProfilePseudoVoigtAnisotropic* ReflectionProfilePseudoVoigtAnisotropic::CreateCopy()const { return new ReflectionProfilePseudoVoigtAnisotropic(*this); } const string& ReflectionProfilePseudoVoigtAnisotropic::GetClassName()const { static string className="ReflectionProfilePseudoVoigtAnisotropic"; return className; } CrystVector_REAL ReflectionProfilePseudoVoigtAnisotropic::GetProfile(const CrystVector_REAL &x, const REAL center, const REAL h, const REAL k, const REAL l)const { VFN_DEBUG_ENTRY("ReflectionProfilePseudoVoigtAnisotropic::GetProfile()",2) const REAL tantheta=tan(center/2.0); const REAL costheta=cos(center/2.0); const REAL sintheta=sin(center/2.0); const REAL fwhmG=sqrt(abs( mCagliotiW+mCagliotiV*tantheta+mCagliotiU*tantheta*tantheta+mScherrerP/(costheta*costheta))); const REAL gam=mLorentzGammaHH*h*h+mLorentzGammaKK*k*k+mLorentzGammaLL*l*l+2*mLorentzGammaHK*h*k+2*mLorentzGammaHL*h*l+2*mLorentzGammaKL*k*l; const REAL fwhmL= mLorentzX/costheta+(mLorentzY+gam/(sintheta*sintheta))*tantheta; // Eta for gaussian/lorentzian mix. Make sure 0<=eta<=1, else profiles could be <0 ! REAL eta=mPseudoVoigtEta0+center*mPseudoVoigtEta1; if(eta>1) eta=1; if(eta<0) eta=0; CrystVector_REAL profile(x.numElements()),tmpV(x.numElements()); const REAL asym=mAsym0+mAsym1/sin(center)+mAsym2/pow((REAL)sin(center),(REAL)2.0); VFN_DEBUG_MESSAGE("ReflectionProfilePseudoVoigtAnisotropic::GetProfile():("<0) { profile=PowderProfileGauss(x,fwhmG,center,asym); profile *= 1-eta; } else profile=0; if(fwhmL>0) { tmpV=PowderProfileLorentz(x,fwhmL,center,asym); tmpV *= eta; profile += tmpV; } VFN_DEBUG_MESSAGE(FormatVertVector(x,profile),1) VFN_DEBUG_EXIT("ReflectionProfilePseudoVoigtAnisotropic::GetProfile()",2) return profile; } void ReflectionProfilePseudoVoigtAnisotropic::SetProfilePar(const REAL fwhmCagliotiW, const REAL fwhmCagliotiU, const REAL fwhmCagliotiV, const REAL fwhmGaussP, const REAL fwhmLorentzX, const REAL fwhmLorentzY, const REAL fwhmLorentzGammaHH, const REAL fwhmLorentzGammaKK, const REAL fwhmLorentzGammaLL, const REAL fwhmLorentzGammaHK, const REAL fwhmLorentzGammaHL, const REAL fwhmLorentzGammaKL, const REAL pseudoVoigtEta0, const REAL pseudoVoigtEta1, const REAL asymA0, const REAL asymA1, const REAL asymA2 ) { mCagliotiU=fwhmCagliotiU; mCagliotiV=fwhmCagliotiV; mCagliotiW=fwhmCagliotiW; mLorentzX=fwhmLorentzX; mLorentzY=fwhmLorentzY; mLorentzGammaHH=fwhmLorentzGammaHH; mLorentzGammaKK=fwhmLorentzGammaKK; mLorentzGammaLL=fwhmLorentzGammaLL; mLorentzGammaHK=fwhmLorentzGammaHK; mLorentzGammaHL=fwhmLorentzGammaHL; mLorentzGammaKL=fwhmLorentzGammaKL; mPseudoVoigtEta0=pseudoVoigtEta0; mPseudoVoigtEta1=pseudoVoigtEta1; mAsym0=asymA0; mAsym1=asymA1; mAsym2=asymA2; mClockMaster.Click(); } REAL ReflectionProfilePseudoVoigtAnisotropic::GetFullProfileWidth(const REAL relativeIntensity, const REAL center, const REAL h, const REAL k, const REAL l) { VFN_DEBUG_ENTRY("ReflectionProfilePseudoVoigt::GetFullProfileWidth()",2) const int nb=100; const int halfnb=nb/2; CrystVector_REAL x(nb); REAL n=5.0; const REAL tantheta=tan(center/2.0); const REAL costheta=cos(center/2.0); const REAL sintheta=sin(center/2.0); const REAL fwhmG=sqrt(abs( mCagliotiW+mCagliotiV*tantheta+mCagliotiU*tantheta*tantheta+mScherrerP/(costheta*costheta))); const REAL gam=mLorentzGammaHH*h*h+mLorentzGammaKK*k*k+mLorentzGammaLL*l*l+2*mLorentzGammaHK*h*k+2*mLorentzGammaHL*h*l+2*mLorentzGammaKL*k*l; const REAL fwhmL= mLorentzX/costheta+(mLorentzY+gam/(sintheta*sintheta))*tantheta; const REAL eta=mPseudoVoigtEta0+mPseudoVoigtEta1*center; // Obviously this is not the REAL FWHM, just a _very_ crude starting approximation REAL fwhm=fwhmL*eta+fwhmG*(1-eta); if(fwhm<=0) fwhm=1e-3; CrystVector_REAL prof; while(true) { //Create an X array with 100 elements reaching +/- n*FWHM/2 REAL *p=x.data(); const REAL tmp=fwhm*n/nb; for(int i=0;iGetProfile(x,center,h,k,l); const REAL max=prof.max(); const REAL test=max*relativeIntensity; int n1=0,n2=0; if((prof(0)test){ p++; n2++;} VFN_DEBUG_EXIT("ReflectionProfilePseudoVoigtAnisotropic::GetFullProfileWidth():"<(x,prof),1) n*=2.0; } } bool ReflectionProfilePseudoVoigtAnisotropic::IsAnisotropic()const { return true; } void ReflectionProfilePseudoVoigtAnisotropic::XMLOutput(ostream &os,int indent)const { VFN_DEBUG_ENTRY("ReflectionProfilePseudoVoigtAnisotropic::XMLOutput():"<GetName(),5) for(int i=0;iGetPar(&mCagliotiU).XMLOutput(os,"U",indent); os <GetPar(&mCagliotiV).XMLOutput(os,"V",indent); os <GetPar(&mCagliotiW).XMLOutput(os,"W",indent); os <GetPar(&mScherrerP).XMLOutput(os,"P",indent); os <GetPar(&mLorentzX).XMLOutput(os,"X",indent); os <GetPar(&mLorentzY).XMLOutput(os,"Y",indent); os <GetPar(&mLorentzGammaHH).XMLOutput(os,"G_HH",indent); os <GetPar(&mLorentzGammaKK).XMLOutput(os,"G_KK",indent); os <GetPar(&mLorentzGammaLL).XMLOutput(os,"G_LL",indent); os <GetPar(&mLorentzGammaHK).XMLOutput(os,"G_HK",indent); os <GetPar(&mLorentzGammaHL).XMLOutput(os,"G_HL",indent); os <GetPar(&mLorentzGammaKL).XMLOutput(os,"G_KL",indent); os <GetPar(&mPseudoVoigtEta0).XMLOutput(os,"Eta0",indent); os <GetPar(&mPseudoVoigtEta1).XMLOutput(os,"Eta1",indent); os <GetPar(&mAsym0).XMLOutput(os,"Asym0",indent); os <GetPar(&mAsym1).XMLOutput(os,"Asym1",indent); os <GetPar(&mAsym2).XMLOutput(os,"Asym2",indent); os <GetName(),5) } void ReflectionProfilePseudoVoigtAnisotropic::XMLInput(istream &is,const XMLCrystTag &tagg) { VFN_DEBUG_ENTRY("ReflectionProfilePseudoVoigtAnisotropic::XMLInput():"<GetName(),5) for(unsigned int i=0;iSetName(tagg.GetAttributeValue(i)); } while(true) { XMLCrystTag tag(is); if(("ReflectionProfilePseudoVoigtAnisotropic"==tag.GetName())&&tag.IsEndTag()) { this->UpdateDisplay(); VFN_DEBUG_EXIT("ReflectionProfilePseudoVoigtAnisotropic::Exit():"<GetName(),5) return; } if("Par"==tag.GetName()) { for(unsigned int i=0;iGetPar(&mCagliotiU).XMLInput(is,tag); break; } if("V"==tag.GetAttributeValue(i)) { this->GetPar(&mCagliotiV).XMLInput(is,tag); break; } if("W"==tag.GetAttributeValue(i)) { this->GetPar(&mCagliotiW).XMLInput(is,tag); break; } if("P"==tag.GetAttributeValue(i)) { this->GetPar(&mScherrerP).XMLInput(is,tag); break; } if("X"==tag.GetAttributeValue(i)) { this->GetPar(&mLorentzX).XMLInput(is,tag); break; } if("Y"==tag.GetAttributeValue(i)) { this->GetPar(&mLorentzY).XMLInput(is,tag); break; } if("G_HH"==tag.GetAttributeValue(i)) { this->GetPar(&mLorentzGammaHH).XMLInput(is,tag); break; } if("G_KK"==tag.GetAttributeValue(i)) { this->GetPar(&mLorentzGammaKK).XMLInput(is,tag); break; } if("G_LL"==tag.GetAttributeValue(i)) { this->GetPar(&mLorentzGammaLL).XMLInput(is,tag); break; } if("G_HK"==tag.GetAttributeValue(i)) { this->GetPar(&mLorentzGammaHK).XMLInput(is,tag); break; } if("G_HL"==tag.GetAttributeValue(i)) { this->GetPar(&mLorentzGammaHL).XMLInput(is,tag); break; } if("G_KL"==tag.GetAttributeValue(i)) { this->GetPar(&mLorentzGammaKL).XMLInput(is,tag); break; } if("Eta0"==tag.GetAttributeValue(i)) { this->GetPar(&mPseudoVoigtEta0).XMLInput(is,tag); break; } if("Eta1"==tag.GetAttributeValue(i)) { this->GetPar(&mPseudoVoigtEta1).XMLInput(is,tag); break; } if("Asym0"==tag.GetAttributeValue(i)) { this->GetPar(&mAsym0).XMLInput(is,tag); break; } if("Asym1"==tag.GetAttributeValue(i)) { this->GetPar(&mAsym1).XMLInput(is,tag); break; } if("Asym2"==tag.GetAttributeValue(i)) { this->GetPar(&mAsym2).XMLInput(is,tag); break; } } } continue; } if("Option"==tag.GetName()) { for(unsigned int i=0;iAddPar(tmp); } { RefinablePar tmp("V",&mCagliotiV,-1/RAD2DEG/RAD2DEG,1./RAD2DEG/RAD2DEG, gpRefParTypeScattDataProfileWidth, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,RAD2DEG*RAD2DEG); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-9); this->AddPar(tmp); } { RefinablePar tmp("W",&mCagliotiW,0,1./RAD2DEG/RAD2DEG, gpRefParTypeScattDataProfileWidth, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,RAD2DEG*RAD2DEG); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-9); this->AddPar(tmp); } { RefinablePar tmp("P",&mScherrerP,-1./RAD2DEG/RAD2DEG,1./RAD2DEG/RAD2DEG, gpRefParTypeScattDataProfileWidth, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,RAD2DEG*RAD2DEG); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-9); this->AddPar(tmp); } { RefinablePar tmp("X",&mLorentzX,0,1./RAD2DEG, gpRefParTypeScattDataProfileWidth, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,RAD2DEG); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-9); this->AddPar(tmp); } { RefinablePar tmp("Y",&mLorentzY,-1./RAD2DEG,1./RAD2DEG, gpRefParTypeScattDataProfileWidth, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,RAD2DEG); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-9); this->AddPar(tmp); } { RefinablePar tmp("G_HH",&mLorentzGammaHH,-1./RAD2DEG,1./RAD2DEG, gpRefParTypeScattDataProfileWidth, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,RAD2DEG); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-9); this->AddPar(tmp); } { RefinablePar tmp("G_KK",&mLorentzGammaKK,-1./RAD2DEG,1./RAD2DEG, gpRefParTypeScattDataProfileWidth, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,RAD2DEG); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-9); this->AddPar(tmp); } { RefinablePar tmp("G_LL",&mLorentzGammaLL,-1./RAD2DEG,1./RAD2DEG, gpRefParTypeScattDataProfileWidth, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,RAD2DEG); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-9); this->AddPar(tmp); } { RefinablePar tmp("G_HK",&mLorentzGammaHK,-1./RAD2DEG,1./RAD2DEG, gpRefParTypeScattDataProfileWidth, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,RAD2DEG); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-9); this->AddPar(tmp); } { RefinablePar tmp("G_HL",&mLorentzGammaHL,-1./RAD2DEG,1./RAD2DEG, gpRefParTypeScattDataProfileWidth, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,RAD2DEG); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-9); this->AddPar(tmp); } { RefinablePar tmp("G_KL",&mLorentzGammaKL,-1./RAD2DEG,1./RAD2DEG, gpRefParTypeScattDataProfileWidth, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,RAD2DEG); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-9); this->AddPar(tmp); } { RefinablePar tmp("Eta0",&mPseudoVoigtEta0,0,1.,gpRefParTypeScattDataProfileType, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { RefinablePar tmp("Eta1",&mPseudoVoigtEta1,-1,1.,gpRefParTypeScattDataProfileType, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { RefinablePar tmp("Asym0",&mAsym0,0.01,10.0,gpRefParTypeScattDataProfileAsym, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { RefinablePar tmp("Asym1",&mAsym1,-1.0,1.0,gpRefParTypeScattDataProfileAsym, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { RefinablePar tmp("Asym2",&mAsym2,-1.0,1.0,gpRefParTypeScattDataProfileAsym, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } } #ifdef __WX__CRYST__ WXCrystObjBasic* ReflectionProfilePseudoVoigtAnisotropic::WXCreate(wxWindow* parent) { VFN_DEBUG_ENTRY("ReflectionProfilePseudoVoigt::WXCreate()",6) if(mpWXCrystObj==0) mpWXCrystObj=new WXProfilePseudoVoigtAnisotropic(parent,this); VFN_DEBUG_EXIT("ReflectionProfilePseudoVoigt::WXCreate()",6) return mpWXCrystObj; } #endif //////////////////////////////////////////////////////////////////////// // // ReflectionProfileDoubleExponentialPseudoVoigt // //////////////////////////////////////////////////////////////////////// ReflectionProfileDoubleExponentialPseudoVoigt::ReflectionProfileDoubleExponentialPseudoVoigt(): ReflectionProfile(), mInstrumentAlpha0(0.0), mInstrumentAlpha1(0.0952), mInstrumentBeta0(0.0239), mInstrumentBeta1(0.0043), mGaussianSigma0(0.0), mGaussianSigma1(7.0), mGaussianSigma2(0.0), mLorentzianGamma0(0.0), mLorentzianGamma1(0.0), mLorentzianGamma2(0.414), mpCell(0) { VFN_DEBUG_MESSAGE("ReflectionProfileDoubleExponentialPseudoVoigt::ReflectionProfileDoubleExponentialPseudoVoigt()",10) this->InitParameters(); } ReflectionProfileDoubleExponentialPseudoVoigt ::ReflectionProfileDoubleExponentialPseudoVoigt(const UnitCell &cell): ReflectionProfile(), mInstrumentAlpha0(0.0), mInstrumentAlpha1(0.0952), mInstrumentBeta0(0.0239), mInstrumentBeta1(0.0043), mGaussianSigma0(0.0), mGaussianSigma1(7.0), mGaussianSigma2(0.0), mLorentzianGamma0(0.0), mLorentzianGamma1(0.0), mLorentzianGamma2(0.414), mpCell(&cell) { VFN_DEBUG_MESSAGE("ReflectionProfileDoubleExponentialPseudoVoigt::ReflectionProfileDoubleExponentialPseudoVoigt()",10) this->InitParameters(); } ReflectionProfileDoubleExponentialPseudoVoigt::ReflectionProfileDoubleExponentialPseudoVoigt (const ReflectionProfileDoubleExponentialPseudoVoigt &old): ReflectionProfile(), mInstrumentAlpha0(old.mInstrumentAlpha0), mInstrumentAlpha1(old.mInstrumentAlpha1), mInstrumentBeta0(old.mInstrumentBeta0), mInstrumentBeta1(old.mInstrumentBeta1), mGaussianSigma0(old.mGaussianSigma0), mGaussianSigma1(old.mGaussianSigma1), mGaussianSigma2(old.mGaussianSigma2), mLorentzianGamma0(old.mLorentzianGamma0), mLorentzianGamma1(old.mLorentzianGamma1), mLorentzianGamma2(old.mLorentzianGamma2), mpCell(old.mpCell) { VFN_DEBUG_MESSAGE("ReflectionProfileDoubleExponentialPseudoVoigt::ReflectionProfileDoubleExponentialPseudoVoigt()",10) this->InitParameters(); } ReflectionProfileDoubleExponentialPseudoVoigt::~ReflectionProfileDoubleExponentialPseudoVoigt() { #ifdef __WX__CRYST__ if(mpWXCrystObj!=0) { delete mpWXCrystObj; mpWXCrystObj=0; } #endif } ReflectionProfileDoubleExponentialPseudoVoigt* ReflectionProfileDoubleExponentialPseudoVoigt::CreateCopy()const { return new ReflectionProfileDoubleExponentialPseudoVoigt(*this); } const string& ReflectionProfileDoubleExponentialPseudoVoigt::GetClassName()const { static string className="ReflectionProfileDoubleExponentialPseudoVoigt"; return className; } CrystVector_REAL ReflectionProfileDoubleExponentialPseudoVoigt ::GetProfile(const CrystVector_REAL &x, const REAL center, const REAL h, const REAL k, const REAL l)const { VFN_DEBUG_ENTRY("ReflectionProfileDoubleExponentialPseudoVoigt::GetProfile()",4) REAL dcenter=0; if(mpCell!=0) { REAL hh=h,kk=k,ll=l;// orthonormal coordinates in reciprocal space mpCell->MillerToOrthonormalCoords(hh,kk,ll); dcenter=1.0/sqrt(hh*hh+kk*kk+ll*ll);//d_hkl, in Angstroems } const REAL alpha=mInstrumentAlpha0+mInstrumentAlpha1/dcenter; const REAL beta=mInstrumentBeta0+mInstrumentBeta1/pow(dcenter,4); const REAL siggauss2= mGaussianSigma0 +mGaussianSigma1*pow(dcenter,2) +mGaussianSigma2*pow(dcenter,4); static const REAL log2=log(2.0); const REAL hg=sqrt(8*siggauss2*log2); const REAL hl= mLorentzianGamma0 +mLorentzianGamma1*dcenter +mLorentzianGamma2*dcenter*dcenter; const REAL hcom=pow(pow(hg,5)+2.69269*pow(hg,4)*hl+2.42843*pow(hg,3)*hl*hl +4.47163*hg*hg*pow(hl,3)+0.07842*hg*pow(hl,4)+pow(hl,5),0.2); const REAL sigcom2=hcom*hcom/(8.0*log2); const REAL eta=1.36603*hl/hcom-0.47719*pow(hl/hcom,2)+0.11116*pow(hl/hcom,3); const long nbPoints=x.numElements(); VFN_DEBUG_MESSAGE("ReflectionProfileDoubleExponentialPseudoVoigt::GetProfile():alpha=" <10.0) expnu_erfcz=exp(nu-z*z)/(z*sqrt(M_PI)); else expnu_erfcz=exp(nu)*erfc(z); if(y>10.0) expu_erfcy=exp(u-y*y)/(y*sqrt(M_PI)); else expu_erfcy=exp(u)*erfc(y); #if 0 double tmp=(1-eta)*alpha*beta/(2*(alpha+beta))*(expu_erfcy+expnu_erfcz) -eta*alpha*beta/(M_PI*(alpha+beta))*(e1p.imag()+e1q.imag()); if(isnan(*pp))// Is this portable ? Test for numeric_limits::quiet_NaN() { cout<<"*pp==numeric_limits::quiet_NaN()"<::infinity()) { cout<<"*pp==numeric_limits::infinity()"<1e30) exit(0); #endif *pp++=(1-eta)*alpha*beta/(2*(alpha+beta))*(expu_erfcy+expnu_erfcz) -eta*alpha*beta/(M_PI*(alpha+beta))*(e1p.imag()+e1q.imag()); } VFN_DEBUG_EXIT("ReflectionProfileDoubleExponentialPseudoVoigt::GetProfile()",4) return prof; } void ReflectionProfileDoubleExponentialPseudoVoigt ::SetProfilePar(const REAL instrumentAlpha0, const REAL instrumentAlpha1, const REAL instrumentBeta0, const REAL instrumentBeta1, const REAL gaussianSigma0, const REAL gaussianSigma1, const REAL gaussianSigma2, const REAL lorentzianGamma0, const REAL lorentzianGamma1, const REAL lorentzianGamma2) { mInstrumentAlpha0=instrumentAlpha0; mInstrumentAlpha1=instrumentAlpha1; mInstrumentBeta0=instrumentBeta0; mInstrumentBeta1=instrumentBeta1; mGaussianSigma0=gaussianSigma0; mGaussianSigma1=gaussianSigma1; mGaussianSigma2=gaussianSigma2; mLorentzianGamma0=lorentzianGamma0; mLorentzianGamma1=lorentzianGamma1; mLorentzianGamma2=lorentzianGamma2; mClockMaster.Click(); } REAL ReflectionProfileDoubleExponentialPseudoVoigt ::GetFullProfileWidth(const REAL relativeIntensity, const REAL center, const REAL h, const REAL k, const REAL l) { VFN_DEBUG_ENTRY("ReflectionProfileDoubleExponentialPseudoVoigt::GetFullProfileWidth()",5) REAL dcenter=0; if(mpCell!=0) { REAL hh=h,kk=k,ll=l;// orthonormal coordinates in reciprocal space VFN_DEBUG_MESSAGE("ReflectionProfileDoubleExponentialPseudoVoigt::GetFullProfileWidth(),"<GetName(),5) mpCell->MillerToOrthonormalCoords(hh,kk,ll); VFN_DEBUG_MESSAGE("ReflectionProfileDoubleExponentialPseudoVoigt::GetFullProfileWidth(),"<GetProfile(x,center,h,k,l); const REAL max=prof.max(); const REAL test=max*relativeIntensity; int n1=0,n2=0; if((prof(0)test){ p++; n2++;} VFN_DEBUG_EXIT("ReflectionProfilePseudoVoigt::GetFullProfileWidth():"<(x,prof),5) n*=2.0; //if(n>200) exit(0); } // unreachable code. // VFN_DEBUG_EXIT("ReflectionProfileDoubleExponentialPseudoVoigt::GetFullProfileWidth()",5) } bool ReflectionProfileDoubleExponentialPseudoVoigt ::IsAnisotropic()const{return false;} void ReflectionProfileDoubleExponentialPseudoVoigt ::XMLOutput(ostream &os,int indent)const { VFN_DEBUG_ENTRY("ReflectionProfileDoubleExponentialPseudoVoigt::XMLOutput():"<GetName(),5) for(int i=0;iGetPar(&mInstrumentAlpha0).XMLOutput(os,"Alpha0",indent); os <GetPar(&mInstrumentAlpha1).XMLOutput(os,"Alpha1",indent); os <GetPar(&mInstrumentBeta0).XMLOutput(os,"Beta0",indent); os <GetPar(&mInstrumentBeta1).XMLOutput(os,"Beta1",indent); os <GetPar(&mGaussianSigma0).XMLOutput(os,"GaussianSigma0",indent); os <GetPar(&mGaussianSigma1).XMLOutput(os,"GaussianSigma1",indent); os <GetPar(&mGaussianSigma2).XMLOutput(os,"GaussianSigma2",indent); os <GetPar(&mLorentzianGamma0).XMLOutput(os,"LorentzianGamma0",indent); os <GetPar(&mLorentzianGamma1).XMLOutput(os,"LorentzianGamma1",indent); os <GetPar(&mLorentzianGamma2).XMLOutput(os,"LorentzianGamma2",indent); os <GetName(),5) } void ReflectionProfileDoubleExponentialPseudoVoigt ::XMLInput(istream &is,const XMLCrystTag &tagg) { VFN_DEBUG_ENTRY("ReflectionProfileDoubleExponentialPseudoVoigt::XMLInput():"<GetName(),5) for(unsigned int i=0;iSetName(tagg.GetAttributeValue(i)); } while(true) { XMLCrystTag tag(is); if(("ReflectionProfileDoubleExponentialPseudoVoigt"==tag.GetName())&&tag.IsEndTag()) { this->UpdateDisplay(); VFN_DEBUG_EXIT("ReflectionProfileDoubleExponentialPseudoVoigt::Exit():"<GetName(),5) return; } if("Par"==tag.GetName()) { for(unsigned int i=0;iGetPar(tag.GetAttributeValue(i)).XMLInput(is,tag); } } continue; } if("Option"==tag.GetName()) { for(unsigned int i=0;iAddPar(tmp); } { RefinablePar tmp("Alpha1",&mInstrumentAlpha1,0,1e6,gpRefParTypeScattDataProfile, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-6); this->AddPar(tmp); } { RefinablePar tmp("Beta0",&mInstrumentBeta0,0,1e6,gpRefParTypeScattDataProfile, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-6); this->AddPar(tmp); } { RefinablePar tmp("Beta1",&mInstrumentBeta1,0,1e6,gpRefParTypeScattDataProfile, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-6); this->AddPar(tmp); } { RefinablePar tmp("GaussianSigma0",&mGaussianSigma0,0,1e6,gpRefParTypeScattDataProfileWidth, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { RefinablePar tmp("GaussianSigma1",&mGaussianSigma1,0,1e6,gpRefParTypeScattDataProfileWidth, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { RefinablePar tmp("GaussianSigma2",&mGaussianSigma2,0,1e6,gpRefParTypeScattDataProfileWidth, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { RefinablePar tmp("LorentzianGamma0",&mLorentzianGamma0,0,1e6,gpRefParTypeScattDataProfileWidth, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { RefinablePar tmp("LorentzianGamma1",&mLorentzianGamma1,0,1e6,gpRefParTypeScattDataProfileWidth, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } { RefinablePar tmp("LorentzianGamma2",&mLorentzianGamma2,0,1e6,gpRefParTypeScattDataProfileWidth, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false); tmp.AssignClock(mClockMaster); tmp.SetDerivStep(1e-4); this->AddPar(tmp); } } #ifdef __WX__CRYST__ WXCrystObjBasic* ReflectionProfileDoubleExponentialPseudoVoigt::WXCreate(wxWindow* parent) { if(mpWXCrystObj==0) mpWXCrystObj=new WXProfileDoubleExponentialPseudoVoigt(parent,this); return mpWXCrystObj; } #endif //###################################################################### // Basic PROFILE FUNCTIONS //###################################################################### CrystVector_REAL PowderProfileGauss (const CrystVector_REAL ttheta,const REAL fw, const REAL center, const REAL asym) { TAU_PROFILE("PowderProfileGauss()","Vector (Vector,REAL)",TAU_DEFAULT); REAL fwhm=fw; if(fwhm<=0) fwhm=1e-6; const long nbPoints=ttheta.numElements(); CrystVector_REAL result(nbPoints); result=ttheta; result+= -center; result *= result; REAL *p; if(false)// fabs(asym-1.) < 1e-5) { //reference: IUCr Monographs on Crystallo 5 - The Rietveld Method (ed RA Young) result *= -4.*log(2.)/fwhm/fwhm; } else { // Adapted from Toraya J. Appl. Cryst 23(1990),485-491 const REAL c1= -(1.+asym)/asym*(1.+asym)/asym*log(2.)/fwhm/fwhm; const REAL c2= -(1.+asym) *(1.+asym) *log(2.)/fwhm/fwhm; long i; p=result.data(); const REAL *pt=ttheta.data(); for(i=0;icenter) break;} i++; for( ;i3;i-=4) { #ifdef HAVE_SSE_MATHFUN v4sf x=_mm_loadu_ps(p); _mm_storeu_ps(p,exp_ps(x)); p+=4; #else for(unsigned int j=0;j<4;++j) {// Fixed-length loop enables vectorization *p = exp(*p) ; p++ ; } #endif } for(;i>0;i--) { *p = exp(*p) ; p++ ;} #endif #if 0 #if 1 //def _MSC_VER // Bug from Hell (in MSVC++) ! // The *last* point ends up sometimes with an arbitrary large value... long i=0; for(;icenter) break;} i++; for( ;iz(1.0,0.0); complexce1=ExponentialIntegral1(z); cout<<"CE1("<z(0.0,1.0); complexce1=ExponentialIntegral1(z); cout<<"CE1("<z(1.0,1.0); complexce1=ExponentialIntegral1(z); cout<<"CE1("<z(100.0,1.0); complexce1=ExponentialIntegral1(z); cout<<"CE1("<z(10.0,20.0); complexce1=ExponentialIntegral1(z); cout<<"CE1("<std::complexExponentialIntegral1(const complex z) { return exp(-z)*ExponentialIntegral1_ExpZ(z); } template std::complexExponentialIntegral1_ExpZ(const complex z) { const T zr=z.real(); const T zn=abs(z); complex ce1; if(zn==0.0) return 1e100;// Should return an error ? std::numeric_limits::quiet_NaN() ? if((zn<10.0)||((zr<0.0)&&(zn<20.0)))// Abramowitz & Stegun 5.1.11 { ce1=complex(1,0); complex y(1,0); for(unsigned int i=1;i<=150;i++) { y=-y*(T)i*z / (T)((i+1)*(i+1)); ce1+=y; if(abs(y)<=abs(ce1)*1e-15) break; } static const T EulerMascheroni=0.5772156649015328606065120900; return exp(z)*(z*ce1-EulerMascheroni-log(z));// Euler-Mascheroni constant } else// Abramowitz & Stegun 5.1.51 { if(zn>500) return 1.0/z; complex y(0.0,0.0); for(unsigned int i=120;i>=1;i--) y=(T)i/((T)1+(T)i/(z+y)); ce1/=(z+y); if((zr<0)&&(z.imag()==0)) ce1 -= complex(0.0,M_PI)*exp(z); return ce1; } } } objcryst-2022.1/ObjCryst/ObjCryst/ReflectionProfile.h000066400000000000000000000342231430515525000225250ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2005 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _OBJCRYST_REFLECTIONPROFILE_H_ #define _OBJCRYST_REFLECTIONPROFILE_H_ #include #include "ObjCryst/CrystVector/CrystVector.h" #include "ObjCryst/ObjCryst/General.h" #include "ObjCryst/ObjCryst/UnitCell.h" #include "ObjCryst/RefinableObj/RefinableObj.h" namespace ObjCryst { //###################################################################### // basic functions used for profiles //###################################################################### ///Gaussian, normalized (ie integral is equal to 1), as a function of theta /// and of the FWHM. The input is an array of the theta values. The maximum of the ///function is in theta=center. If asymmetry is used, negative tth values must be first. CrystVector_REAL PowderProfileGauss (const CrystVector_REAL theta, const REAL fwhm, const REAL center, const REAL asym=1.0); ///Lorentzian, normalized (ie integral is equal to 1), as a function of theta /// and of the FWHM. The input is an array of the theta values. The maximum of the ///function is in theta=center. If asymmetry is used, negative tth values must be first. CrystVector_REAL PowderProfileLorentz(const CrystVector_REAL theta, const REAL fwhm, const REAL center, const REAL asym=1.0); /// Asymmetry function [Ref J. Appl. Cryst 26 (1993), 128-129 CrystVector_REAL AsymmetryBerarBaldinozzi(const CrystVector_REAL theta, const REAL fwhm, const REAL center, const REAL A0, const REAL A1, const REAL B0, const REAL B1); /** Complex exponential integral E1(z) (Abramowitz & Stegun, chap. 5) * * Using A&S 5.1.11 (series) and 5.1.51 (asymptotic) expansions */ template std::complexExponentialIntegral1(const complex z); /** E1(z)*exp(z) * * This can be computed for large z values to avoid floating-point exceptions. */ template std::complexExponentialIntegral1_ExpZ(const complex z); /** Abstract base class for reflection profiles. * */ class ReflectionProfile:public RefinableObj { public: ReflectionProfile(); ReflectionProfile(const ReflectionProfile &old); virtual ~ReflectionProfile(); virtual ReflectionProfile* CreateCopy()const=0; /** Get the reflection profile * *\param x: the vector of x coordinates (i.e. either 2theta or time-of-flight) *\param xcenter: coordinate (2theta, tof) of the center of the peak *\param h,k,l: reflection Miller indices *\note: derived classes who need either d_hkl or the orthonormal coordinates * of the scattering vector should be passed a ObjCryst::UnitCell object in * the constructor so that they can use ObjCryst::UnitCell::MillerToOrthonormalCoords() */ virtual CrystVector_REAL GetProfile(const CrystVector_REAL &x, const REAL xcenter, const REAL h, const REAL k, const REAL l)const=0; /// Get the (approximate) full profile width at a given percentage /// of the profile maximum (e.g. FWHM=GetFullProfileWidth(0.5)). virtual REAL GetFullProfileWidth(const REAL relativeIntensity, const REAL xcenter, const REAL h, const REAL k, const REAL l)=0; /// Is the profile anisotropic ? virtual bool IsAnisotropic()const; virtual void XMLOutput(ostream &os,int indent=0)const=0; virtual void XMLInput(istream &is,const XMLCrystTag &tag)=0; private: #ifdef __WX__CRYST__ public: virtual WXCrystObjBasic* WXCreate(wxWindow* parent)=0; #endif }; /** Pseudo-Voigt reflection profile. * */ class ReflectionProfilePseudoVoigt:public ReflectionProfile { public: ReflectionProfilePseudoVoigt(); ReflectionProfilePseudoVoigt(const ReflectionProfilePseudoVoigt &old); virtual ~ReflectionProfilePseudoVoigt(); virtual ReflectionProfilePseudoVoigt* CreateCopy()const; virtual const string& GetClassName()const; CrystVector_REAL GetProfile(const CrystVector_REAL &x, const REAL xcenter, const REAL h, const REAL k, const REAL l)const; /** Set reflection profile parameters * * \param fwhmCagliotiW,fwhmCagliotiU,fwhmCagliotiV : these are the U,V and W * parameters in the Caglioti's law : * \f$ fwhm^2= U \tan^2(\theta) + V \tan(\theta) +W \f$ * if only W is given, the width is constant * \param eta0,eta1: these are the mixing parameters. */ void SetProfilePar(const REAL fwhmCagliotiW, const REAL fwhmCagliotiU=0, const REAL fwhmCagliotiV=0, const REAL eta0=0.5, const REAL eta1=0.); virtual REAL GetFullProfileWidth(const REAL relativeIntensity, const REAL xcenter, const REAL h, const REAL k, const REAL l); bool IsAnisotropic()const; virtual void XMLOutput(ostream &os,int indent=0)const; virtual void XMLInput(istream &is,const XMLCrystTag &tag); private: /// Initialize parameters void InitParameters(); ///FWHM parameters, following Caglioti's law REAL mCagliotiU,mCagliotiV,mCagliotiW; ///Pseudo-Voigt mixing parameter : eta=eta0 +2*theta*eta1 /// eta=1 -> pure Lorentzian ; eta=0 -> pure Gaussian REAL mPseudoVoigtEta0,mPseudoVoigtEta1; /** Asymmetry parameters, following the Bérar \& Baldinozzi approach * ( Bérar \& baldinozzi, J. Appl. Cryst 26 (1993), 128-129) * * \note: these are not used right now. */ REAL mAsymBerarBaldinozziA0,mAsymBerarBaldinozziA1, mAsymBerarBaldinozziB0,mAsymBerarBaldinozziB1; /** Asymmetry parameters, following the analytical function for asymmetric pseudo-voigt * given by Toraya in J. Appl. Cryst 23(1990),485-491 * * Asymmetric coefficient: * \f[ A=A_0+A_1/\sin(2\vartheta)+A_2/\sin^2(2\vartheta) \f] * * Asymmetric profile: * \f[ Prof(\vartheta-\vartheta_{max}<=0)=Prof_0(\frac{1+A}{A})(\vartheta-\vartheta_{max})) \f] * \f[ Prof(\vartheta-\vartheta_{max}>=0)=Prof_0((1+A) (\vartheta-\vartheta_{max})) \f] */ REAL mAsym0,mAsym1,mAsym2; #ifdef __WX__CRYST__ public: virtual WXCrystObjBasic* WXCreate(wxWindow* parent); #endif }; /** Pseudo-Voigt reflection profile, with 6-parameters anisotropic Lorentzian broadening and Toraya asymmetric modelling. * */ class ReflectionProfilePseudoVoigtAnisotropic:public ReflectionProfile { public: ReflectionProfilePseudoVoigtAnisotropic(); ReflectionProfilePseudoVoigtAnisotropic(const ReflectionProfilePseudoVoigtAnisotropic &old); virtual ~ReflectionProfilePseudoVoigtAnisotropic(); virtual ReflectionProfilePseudoVoigtAnisotropic* CreateCopy()const; virtual const string& GetClassName()const; CrystVector_REAL GetProfile(const CrystVector_REAL &x, const REAL xcenter, const REAL h, const REAL k, const REAL l)const; /** Set reflection profile parameters * * if only W is given, the width is constant * * See documentation for mCagliotiU,mCagliotiV,mCagliotiW,mScherrerP,mLorentzX,mLorentzY, * mLorentzGammaHH,mLorentzGammaKK,mLorentzGammaLL,mLorentzGammaHK,mLorentzGammaHL,mLorentzGammaKL * mAsym0,mAsym1,mAsym2. */ void SetProfilePar(const REAL fwhmCagliotiW, const REAL fwhmCagliotiU=0, const REAL fwhmCagliotiV=0, const REAL fwhmGaussP=0, const REAL fwhmLorentzX=0, const REAL fwhmLorentzY=0, const REAL fwhmLorentzGammaHH=0, const REAL fwhmLorentzGammaKK=0, const REAL fwhmLorentzGammaLL=0, const REAL fwhmLorentzGammaHK=0, const REAL fwhmLorentzGammaHL=0, const REAL fwhmLorentzGammaKL=0, const REAL pseudoVoigtEta0=0, const REAL pseudoVoigtEta1=0, const REAL asymA0=0, const REAL asymA1=0, const REAL asymA2=0 ); virtual REAL GetFullProfileWidth(const REAL relativeIntensity, const REAL xcenter, const REAL h, const REAL k, const REAL l); bool IsAnisotropic()const; virtual void XMLOutput(ostream &os,int indent=0)const; virtual void XMLInput(istream &is,const XMLCrystTag &tag); private: /// Initialize parameters void InitParameters(); /** FWHM parameters: * * Profile:\f$ Prof(\vartheta) = \eta Lorentz(\vartheta) + (1-\eta) Gauss(\vartheta) \f$ * * This pseudo-Voigt profile is the linear combination of a Gaussian and a Lorentzian: * \f[ Profile(\vartheta)= Lorentz(\vartheta) + Gauss(\vartheta)\f] * * Gaussian FWHM parameters, following Caglioti's law and Scherrer broadening coefficient: * \f[ fwhm_g^2= U \tan^2(\theta) + V \tan(\theta) +W +\frac{P}{\cos^2\vartheta} \f] * See Cagliotti, Pauletti & Ricci, Nucl. Instrum. 3 (1958), 223. * * Lorentzian FWHM parameters * * \f[ fwhm_l= \frac{X}{\cos\vartheta} +(Y + \frac{\gamma_L}{\sin^2\vartheta})\tan\vartheta \f] * with anisotropic broadening factor: * \f[ \gamma_L = \gamma_{HH}h^2 + \gamma_{KK}k^2 + \gamma_{LL}l^2 + 2\gamma_{HK}hk + 2\gamma_{hl} + 2\gamma_{kl}kl\f] * * \note: in the above formula we use \f$ \frac{\gamma_L}{\sin^2\vartheta} \f$ rather than the more usual\f$ \gamma_L d^2 \f$ * for computing purposes (the model being purely phenomenological). */ REAL mCagliotiU,mCagliotiV,mCagliotiW,mScherrerP,mLorentzX,mLorentzY, mLorentzGammaHH,mLorentzGammaKK,mLorentzGammaLL,mLorentzGammaHK,mLorentzGammaHL,mLorentzGammaKL; ///Pseudo-Voigt mixing parameter : \f$ \eta=\eta_0 +2*\vartheta*\eta_1\f$ /// eta=1 -> pure Lorentzian ; eta=0 -> pure Gaussian REAL mPseudoVoigtEta0,mPseudoVoigtEta1; /** Asymmetry parameters, following the analytical function for asymmetric pseudo-voigt * given by Toraya in J. Appl. Cryst 23(1990),485-491 * * Asymmetric coefficient: * \f[ A=A_0+A_1/\sin(2\vartheta)+A_2/\sin^2(2\vartheta) \f] * * Asymmetric profile: * \f[ Prof(\vartheta-\vartheta_{max}<=0)=Prof_0(\frac{1+A}{A})(\vartheta-\vartheta_{max})) \f] * \f[ Prof(\vartheta-\vartheta_{max}>=0)=Prof_0((1+A) (\vartheta-\vartheta_{max})) \f] */ REAL mAsym0,mAsym1,mAsym2; #ifdef __WX__CRYST__ public: virtual WXCrystObjBasic* WXCreate(wxWindow* parent); #endif }; /** Double-Exponential Pseudo-Voigt profile for TOF. * * Ref Mark Pitt */ class ReflectionProfileDoubleExponentialPseudoVoigt:public ReflectionProfile { public: /** Constructor, without unit cell */ ReflectionProfileDoubleExponentialPseudoVoigt(); /** Constructor, with unit cell */ ReflectionProfileDoubleExponentialPseudoVoigt(const UnitCell &cell); ReflectionProfileDoubleExponentialPseudoVoigt (const ReflectionProfileDoubleExponentialPseudoVoigt &old); virtual ~ReflectionProfileDoubleExponentialPseudoVoigt(); virtual ReflectionProfileDoubleExponentialPseudoVoigt* CreateCopy()const; virtual const string& GetClassName()const; CrystVector_REAL GetProfile(const CrystVector_REAL &x, const REAL xcenter, const REAL h, const REAL k, const REAL l)const; /** Set reflection profile parameters * */ void SetProfilePar(const REAL instrumentAlpha0, const REAL instrumentAlpha1, const REAL instrumentBeta0, const REAL instrumentBeta1, const REAL gaussianSigma0, const REAL gaussianSigma1, const REAL gaussianSigma2, const REAL lorentzianGamma0, const REAL lorentzianGamma1, const REAL lorentzianGamma2); virtual REAL GetFullProfileWidth(const REAL relativeIntensity, const REAL xcenter, const REAL h, const REAL k, const REAL l); bool IsAnisotropic()const; virtual void XMLOutput(ostream &os,int indent=0)const; virtual void XMLInput(istream &is,const XMLCrystTag &tag); /** Set unit cell. This is used to compute d_hkl for reflections. * */ void SetUnitCell(const UnitCell &cell); private: /// Initialize parameters void InitParameters(); REAL mInstrumentAlpha0; REAL mInstrumentAlpha1; REAL mInstrumentBeta0; REAL mInstrumentBeta1; REAL mGaussianSigma0; REAL mGaussianSigma1; REAL mGaussianSigma2; REAL mLorentzianGamma0; REAL mLorentzianGamma1; REAL mLorentzianGamma2; const UnitCell *mpCell; #ifdef __WX__CRYST__ public: virtual WXCrystObjBasic* WXCreate(wxWindow* parent); #endif }; /// Global registry for all ReflectionProfile objects extern ObjRegistry gReflectionProfileRegistry; }//namespace #endif objcryst-2022.1/ObjCryst/ObjCryst/Scatterer.cpp000066400000000000000000000127051430515525000214020ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // // source file for the base Scatterer classe #include #include #include #include //for sprintf() #include "ObjCryst/ObjCryst/Crystal.h" #include "ObjCryst/ObjCryst/Scatterer.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" //simple formatting of integers, REALs.. #include "ObjCryst/Quirks/VFNDebug.h" #ifdef __WX__CRYST__ #include "ObjCryst/wxCryst/wxScatterer.h" #endif #include "ObjCryst/ObjCryst/Colours.h" #include #include namespace ObjCryst { const RefParType *gpRefParTypeScatt=0; const RefParType *gpRefParTypeScattTransl=0; const RefParType *gpRefParTypeScattTranslX=0; const RefParType *gpRefParTypeScattTranslY=0; const RefParType *gpRefParTypeScattTranslZ=0; const RefParType *gpRefParTypeScattOrient=0; const RefParType *gpRefParTypeScattConform=0; const RefParType *gpRefParTypeScattConformBondLength=0; const RefParType *gpRefParTypeScattConformBondAngle=0; const RefParType *gpRefParTypeScattConformDihedAngle=0; const RefParType *gpRefParTypeScattConformX=0; const RefParType *gpRefParTypeScattConformY=0; const RefParType *gpRefParTypeScattConformZ=0; const RefParType *gpRefParTypeScattOccup=0; long NiftyStaticGlobalObjectsInitializer_Scatterer::mCount=0; //////////////////////////////////////////////////////////////////////// // // SCATTERER : generic type of scatterer // // //////////////////////////////////////////////////////////////////////// ObjRegistry gScattererRegistry("Global Scatterer Registry"); Scatterer::Scatterer():mXYZ(3),mOccupancy(1.0),mColourName("White"),mpCryst(0) { VFN_DEBUG_MESSAGE("Scatterer::Scatterer()",5) mXYZ=0; this->InitRGBColour(); gScattererRegistry.Register(*this); mClockMaster.AddChild(mClockScatterer); } Scatterer::Scatterer(const Scatterer &old): //RefinableObj(), mXYZ(old.mXYZ), mOccupancy(old.mOccupancy), mColourName(old.mColourName),mpCryst(old.mpCryst) { VFN_DEBUG_MESSAGE("Scatterer::Scatterer(&old)",5) mName=old.GetName(); this->InitRGBColour(); gScattererRegistry.Register(*this); mClockMaster.AddChild(mClockScatterer); } Scatterer::~Scatterer() { VFN_DEBUG_MESSAGE("Scatterer::~Scatterer():("<GetPar(mXYZ.data()).MutateTo(x);} void Scatterer::SetY(const REAL y) { this->GetPar(mXYZ.data()+1).MutateTo(y);} void Scatterer::SetZ(const REAL z) { this->GetPar(mXYZ.data()+2).MutateTo(z);} void Scatterer::SetOccupancy(const REAL occupancy) { mClockScatterer.Click(); mOccupancy=occupancy; } Scatterer::operator string() const {return this->GetName();} /* void Scatterer::Print() const { cout << "Scatterer : " << FormatString(this->GetName()) << " at :" ; cout << FormatFloat(this->X()); cout << FormatFloat(this->Y()); cout << FormatFloat(this->Z()); cout << endl; } */ const string& Scatterer::GetColour()const{ return mColourName;} const float* Scatterer::GetColourRGB()const{ return mColourRGB;} const RefinableObjClock& Scatterer::GetClockScatterer()const {return mClockScatterer;} RefinableObjClock& Scatterer::GetClockScatterer() {return mClockScatterer;} void Scatterer::SetCrystal(Crystal &cryst){mpCryst=&cryst;} const Crystal& Scatterer::GetCrystal()const{return *mpCryst;} Crystal& Scatterer::GetCrystal(){return *mpCryst;} void Scatterer::InitRGBColour() { //mClockScatterer.Click(); VFN_DEBUG_MESSAGE("Scatterer::InitRGBColour()",2) for(long i=0;;) { if(gPOVRayColours[i].mName==mColourName) { mColourRGB[0]=gPOVRayColours[i].mRGB[0]; mColourRGB[1]=gPOVRayColours[i].mRGB[1]; mColourRGB[2]=gPOVRayColours[i].mRGB[2]; break; } i++; if(strncmp(gPOVRayColours[i].mName,"",3 )==0) {//could not find colour ! cout << "Could not find colour:"<RGBColour:"< namespace ObjCryst { class Crystal ; //forward declaration.:KLUDGE: ? extern const RefParType *gpRefParTypeScatt; extern const RefParType *gpRefParTypeScattTransl; extern const RefParType *gpRefParTypeScattTranslX; extern const RefParType *gpRefParTypeScattTranslY; extern const RefParType *gpRefParTypeScattTranslZ; extern const RefParType *gpRefParTypeScattOrient; extern const RefParType *gpRefParTypeScattConform; extern const RefParType *gpRefParTypeScattConformBondLength; extern const RefParType *gpRefParTypeScattConformBondAngle; extern const RefParType *gpRefParTypeScattConformDihedAngle; extern const RefParType *gpRefParTypeScattConformX; extern const RefParType *gpRefParTypeScattConformY; extern const RefParType *gpRefParTypeScattConformZ; extern const RefParType *gpRefParTypeScattOccup; class NiftyStaticGlobalObjectsInitializer_Scatterer { public: NiftyStaticGlobalObjectsInitializer_Scatterer() { if (mCount++ == 0) { gpRefParTypeScatt=new RefParType(gpRefParTypeObjCryst,"Scatterer"); gpRefParTypeScattTransl=new RefParType(gpRefParTypeScatt,"Translation"); gpRefParTypeScattTranslX=new RefParType(gpRefParTypeScattTransl,"Translation along X"); gpRefParTypeScattTranslY=new RefParType(gpRefParTypeScattTransl,"Translation along Y"); gpRefParTypeScattTranslZ=new RefParType(gpRefParTypeScattTransl,"Translation along Z"); gpRefParTypeScattOrient=new RefParType(gpRefParTypeScatt,"Orientation"); gpRefParTypeScattConform=new RefParType(gpRefParTypeScatt,"Conformation"); gpRefParTypeScattConformBondLength=new RefParType(gpRefParTypeScattConform,"BondLengths"); gpRefParTypeScattConformBondAngle=new RefParType(gpRefParTypeScattConform,"Bond Angles"); gpRefParTypeScattConformDihedAngle=new RefParType(gpRefParTypeScattConform,"Dihedral Angles "); gpRefParTypeScattConformX=new RefParType(gpRefParTypeScattConform,"Orth. X coordinates"); gpRefParTypeScattConformY=new RefParType(gpRefParTypeScattConform,"Orth. Y coordinates"); gpRefParTypeScattConformZ=new RefParType(gpRefParTypeScattConform,"Orth. Z coordinates"); gpRefParTypeScattOccup=new RefParType(gpRefParTypeScatt,"Occupancy"); } } ~NiftyStaticGlobalObjectsInitializer_Scatterer() { if (--mCount == 0) { delete gpRefParTypeScatt; delete gpRefParTypeScattTransl; delete gpRefParTypeScattTranslX; delete gpRefParTypeScattTranslY; delete gpRefParTypeScattTranslZ; delete gpRefParTypeScattOrient; delete gpRefParTypeScattConform; delete gpRefParTypeScattConformBondLength; delete gpRefParTypeScattConformBondAngle; delete gpRefParTypeScattConformDihedAngle; delete gpRefParTypeScattConformX; delete gpRefParTypeScattConformY; delete gpRefParTypeScattConformZ; delete gpRefParTypeScattOccup; gpRefParTypeScatt=0; gpRefParTypeScattTransl=0; gpRefParTypeScattTranslX=0; gpRefParTypeScattTranslY=0; gpRefParTypeScattTranslZ=0; gpRefParTypeScattOrient=0; gpRefParTypeScattConform=0; gpRefParTypeScattConformBondLength=0; gpRefParTypeScattConformBondAngle=0; gpRefParTypeScattConformDihedAngle=0; gpRefParTypeScattConformX=0; gpRefParTypeScattConformY=0; gpRefParTypeScattConformZ=0; gpRefParTypeScattOccup=0; } } private: static long mCount; }; static NiftyStaticGlobalObjectsInitializer_Scatterer NiftyStaticGlobalObjectsInitializer_Scatterer_counter; //###################################################################### // // SCATTERER /** \brief Generic type of scatterer: can be an atom, or a more complex assembly of atoms. * * A Scatterer is able to give its position (in fractionnal coordinates) * in the unit cell, and more generally the position of all point * scattering centers (ScatteringComponent), along with the ScatteringPower * associated with each position. * * For simple atoms, there is only one scattering position with the associated * scattering power (scattering factor, anomalous, thermic). For complex * scatterers (molecules: ZScatterer) there are as many positions as atoms. * * A scatterer also has a few functions to display itself in 3D * * This is an abstract base class. */ //###################################################################### class Scatterer:virtual public RefinableObj { public: /// Constructor Scatterer(); /// Copy Constructor Scatterer(const Scatterer &old); /// Destructor virtual ~Scatterer(); /// \internal so-called Virtual copy constructor, needed to make copies /// of arrays of Scatterers virtual Scatterer* CreateCopy() const=0; virtual const string& GetClassName() const; /// Number of components in the scatterer (eg number of point scatterers) virtual int GetNbComponent() const=0; /** \brief Get the list of all scattering components for this scatterer. * * This is the most important function of this class, giving the list of * scattering positions along with the associated ScatteringPower. * */ virtual const ScatteringComponentList& GetScatteringComponentList() const=0; /// Name for the i-th component of this scatterer. If the component is an Atom, /// Then the name is that of the atom. Else, it is the name of the scatterer /// plus the component number in the scatterer plus the name of the ScatteringPower. /// \note It would be better to return a reference, but we don't want to keep /// a name for all components... Weeelll, needs some more thinking... see what /// performance hit results (if any). /// /// \bug does not take into account dummy atoms !! virtual string GetComponentName(const int i) const=0; /// X coordinate (fractionnal) of the scatterer (for complex scatterers, /// this corresponds to the position of one atom of the Scatterer, ideally /// it should be near the center of the Scatterer. REAL GetX() const; /// Y coordinate (fractionnal) of the scatterer (for complex scatterers, /// this corresponds to the position of one atom of the Scatterer, ideally /// it should be near the center of the Scatterer. REAL GetY() const; /// Z coordinate (fractionnal) of the scatterer (for complex scatterers, /// this corresponds to the position of one atom of the Scatterer, ideally /// it should be near the center of the Scatterer. REAL GetZ() const; /** \brief Get the occupancy of the scatterer (0. -> 1.0) * * The occupancy is given in %, and must take into account the * 'special position' character of atoms (ie an atom on a 2fold axis * should have at most a .5 population, etc...). * For a multi-atom scatterer (polyhedra), this is the \b overall occupancy * of the scatterer, affecting all atoms. */ REAL GetOccupancy() const ; /// X coordinate (fractionnal) of the scatterer (for complex scatterers, /// this corresponds to the position of one atom of the Scatterer, ideally /// it should be near the center of the Scatterer. virtual void SetX(const REAL x); /// Y coordinate (fractionnal) of the scatterer (for complex scatterers, /// this corresponds to the position of one atom of the Scatterer, ideally /// it should be near the center of the Scatterer. virtual void SetY(const REAL y); /// Z coordinate (fractionnal) of the scatterer (for complex scatterers, /// this corresponds to the position of one atom of the Scatterer, ideally /// it should be near the center of the Scatterer. virtual void SetZ(const REAL z); /** \brief Change the occupancy of the scatterer (0. -> 1.0) * * The occupancy is given in %, and must take into account the * 'special position' character of atoms (ie an atom on a 2fold axis * should have at most a .5 population, etc...). * For a multi-atom scatterer (polyhedra), this is the \b overall occupancy * of the scatterer, affecting all atoms. */ virtual void SetOccupancy(const REAL occupancy) ; /// Conversion function.-> returns the scatt name /// /// \warning EXPERIMENTAL. DO NOT USE, as this may be removed. operator string()const; /// Print some info about the scatterer (ideally this should be one line...). virtual void Print() const=0; /** \brief Colour associated to this scatterer (using POVRay names) * */ virtual const string& GetColour()const; /** \brief Colour associated to this scatterer, 3 RGB Coordinates. * */ virtual const float* GetColourRGB()const; /** \brief \internal Output a description of the scatterer for POVRay. * This should only be called by the Crystal Object to which belongs this * scatterer. * */ virtual ostream& POVRayDescription(ostream &os, const CrystalPOVRayOptions &options)const=0; #ifdef OBJCRYST_GL /** \internal Create an OpenGL Display List of the scatterer. This should only * be called by a Crystal object. * * \param noSymmetrics: if false (the default), then all symmetrics are shown in the * 3D display, within the limits defined by the min/max parameters * \ param xMin,xMax,yMin,yMax,zMin,zMax: in fractionnal coordinates, the region * in which we want scaterrer to be displayed. The test is made on the center * of the scatterer (eg a ZScatterer (molecule) will not be 'cut' on the border). * \param displayNames: if true, only the names of the scatterers will be displayed, * at the position of the scatterers (to actually see them, they will have to * be translated with respect to the drawing of the scatterers). * \param hideHydrogens: if true, do not display hydrogens/deuterium and their bonds * \param fadeDistance: atoms which are beyond the display limits are still showm, but * with transparency which is progressively fading up to a certain distance. * \param fullMoleculeInLimits: if true, molecules which are centered inside the * display limits will be shown completely without fading. (default=false) */ virtual void GLInitDisplayList(const bool noSymmetrics=false, const REAL xMin=-.1,const REAL xMax=1.1, const REAL yMin=-.1,const REAL yMax=1.1, const REAL zMin=-.1,const REAL zMax=1.1, const bool displayEnantiomer=false, const bool displayNames=false, const bool hideHydrogens=false, const REAL fadeDistance=0, const bool fullMoleculeInLimits=false)const=0; #endif // OBJCRYST_GL /// Last time anything in the scatterer was changed (atoms, positions, scattering power) const RefinableObjClock& GetClockScatterer()const; /// Last time anything in the scatterer was changed (atoms, positions, scattering power) RefinableObjClock& GetClockScatterer(); /// Set the crystal in which is included this Scatterer void SetCrystal(Crystal&); /// In which crystal is this Scatterer included ? const Crystal& GetCrystal()const; /// In which crystal is this Scatterer included ? Crystal& GetCrystal(); protected: /// \internal Prepare refinable parameters for the scatterer object virtual void InitRefParList()=0; /** Get RGB Colour coordinates from Colour Name. Note that the colour * used for display is usually that of the ScatteringPower, not that of the Scatterer * */ virtual void InitRGBColour(); /// Last time the ScatteringComponentList was generated const RefinableObjClock& GetClockScattCompList()const; ///coordinates of the scatterer (or of its center..) CrystVector_REAL mXYZ; /** \brief Occupancy : 0 <= occ <= 1 * For a multi-atom scatterer (polyhedron,..), this is the \b overall occupancy * of the scatterer (affects all components of the scatterer). */ REAL mOccupancy; /// Colour for this scatterer (from POVRay) string mColourName; /// Colour for this scatterer using RGB float mColourRGB[3]; /// Last time anything (number of atoms, positions, scattering power) was changed RefinableObjClock mClockScatterer; /// \internal Last time the ScatteringComponentList was generated mutable RefinableObjClock mClockScattCompList; /// The crystal in which the Scatterer is /// This is needed so that we can know which scattering powers are available /// in the crystal, and also to convert fractionnal to orthonormal /// coordinates (for some scatterers only). /// It cannot be const since some scatterers may want to modify /// the list of scattering powers of the crystal... Crystal *mpCryst; private: #ifdef __WX__CRYST__ public: virtual WXCrystObjBasic* WXCreate(wxWindow*); friend class WXScatterer; #endif }; /// Global registry for all Scatterer objects extern ObjRegistry gScattererRegistry; }//namespace #include "ObjCryst/ObjCryst/Crystal.h" #endif //_OBJCRYST_SCATTERER_H_ objcryst-2022.1/ObjCryst/ObjCryst/ScatteringCorr.cpp000066400000000000000000001063221430515525000223760ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ObjCryst/ObjCryst/ScatteringCorr.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" #include //for sprintf() #include #ifdef __WX__CRYST__ namespace ObjCryst { class TexturePhaseMarchDollase; } #include "ObjCryst/wxCryst/wxPowderPattern.h" #endif namespace ObjCryst { //////////////////////////////////////////////////////////////////////// // // ScatteringCorr // //////////////////////////////////////////////////////////////////////// ScatteringCorr::ScatteringCorr(const ScatteringData & data): mpData(&data) { VFN_DEBUG_MESSAGE("ScatteringCorr::ScatteringCorr(&scattData)",5) } ScatteringCorr::~ScatteringCorr() { VFN_DEBUG_MESSAGE("ScatteringCorr::~ScatteringCorr()",5) } const CrystVector_REAL& ScatteringCorr::GetCorr() const { this->CalcCorr(); return mCorr; } const RefinableObjClock& ScatteringCorr::GetClockCorr()const {return mClockCorrCalc;} //////////////////////////////////////////////////////////////////////// // // LorentzCorr // //////////////////////////////////////////////////////////////////////// LorentzCorr::LorentzCorr(const ScatteringData & data): ScatteringCorr(data) {} LorentzCorr::~LorentzCorr() {} const string & LorentzCorr::GetName() const { //So far, we do not need a personalized name... const static string mName="LorentzCorr"; return mName; } const string & LorentzCorr::GetClassName() const { const static string className="LorentzCorr"; return className; } void LorentzCorr::CalcCorr() const { const CrystVector_REAL *theta=&(mpData->GetTheta()); if(mpData->GetClockTheta()GetNbRefl()); for(long i=0;iGetNbRefl();i++)mCorr(i) =1/sin(2*(*theta)(i)); mClockCorrCalc.Click(); } //////////////////////////////////////////////////////////////////////// // // PolarizationCorr // //////////////////////////////////////////////////////////////////////// PolarizationCorr::PolarizationCorr(const ScatteringData & data): ScatteringCorr(data),mPolarAfactor(1) {} PolarizationCorr::~PolarizationCorr() {} const string & PolarizationCorr::GetName() const { //So far, we do not need a personalized name... const static string mName="PolarizationCorr"; return mName; } const string & PolarizationCorr::GetClassName() const { const static string className="PolarizationCorr"; return className; } void PolarizationCorr::CalcCorr() const { const CrystVector_REAL *theta=&(mpData->GetTheta()); const REAL f=mpData->GetRadiation().GetLinearPolarRate(); if( (mpData->GetClockTheta()GetNbRefl()); // cos^2(2*theta)=0.5+0.5*cos(4*theta) for(long i=0;iGetNbRefl();i++) mCorr(i) =(1.+mPolarAfactor*(0.5+0.5*cos(4*(*theta)(i))))/(1.+mPolarAfactor); mClockCorrCalc.Click(); } //////////////////////////////////////////////////////////////////////// // // PowderSlitApertureCorr // //////////////////////////////////////////////////////////////////////// PowderSlitApertureCorr::PowderSlitApertureCorr(const ScatteringData & data): ScatteringCorr(data) {} PowderSlitApertureCorr::~PowderSlitApertureCorr() {} const string & PowderSlitApertureCorr::GetName() const { //So far, we do not need a personalized name... const static string mName="PowderSlitApertureCorr"; return mName; } const string & PowderSlitApertureCorr::GetClassName() const { const static string className="PowderSlitApertureCorr"; return className; } void PowderSlitApertureCorr::CalcCorr() const { const CrystVector_REAL *theta=&(mpData->GetTheta()); if(mpData->GetClockTheta()GetNbRefl()); for(long i=0;iGetNbRefl();i++)mCorr(i) =1/sin((*theta)(i)); mClockCorrCalc.Click(); } //////////////////////////////////////////////////////////////////////// // // TexturePhaseMarchDollase // //////////////////////////////////////////////////////////////////////// TexturePhaseMarchDollase::TexturePhaseMarchDollase(const REAL f, const REAL c, const REAL h, const REAL k, const REAL l, TextureMarchDollase &tex): mFraction(f),mMarchCoeff(c),mH(h),mK(k),mL(l),mpTextureMarchDollase(&tex) #ifdef __WX__CRYST__ ,mpWXCrystObj(0) #endif {} TexturePhaseMarchDollase::~TexturePhaseMarchDollase() { #ifdef __WX__CRYST__ this->WXDelete(); #endif } const string& TexturePhaseMarchDollase::GetClassName()const { const static string className="March-Dollase Texture Phase"; return className; } const string& TexturePhaseMarchDollase::GetName()const { const static string name="March-Dollase Texture Phase"; return name; } void TexturePhaseMarchDollase::SetPar(const REAL f, const REAL c,const REAL h,const REAL k, const REAL l) {mFraction=f;mMarchCoeff=c;mH=h;mK=k;mL=l;} void TexturePhaseMarchDollase::XMLOutput(ostream &os,int indent)const { VFN_DEBUG_ENTRY("TexturePhaseMarchDollase::XMLOutput():"<GetName(),5) for(int i=0;iGetPar(&mFraction).XMLOutput(os,"Fraction",indent); os <GetPar(&mMarchCoeff).XMLOutput(os,"MarchCoeff",indent); os <GetPar(&mH).XMLOutput(os,"H",indent); os <GetPar(&mK).XMLOutput(os,"K",indent); os <GetPar(&mL).XMLOutput(os,"L",indent); os <GetName(),5) } void TexturePhaseMarchDollase::XMLInput(istream &is,const XMLCrystTag &tagg) { VFN_DEBUG_ENTRY("TexturePhaseMarchDollase::XMLInput():",5) for(unsigned int i=0;iGetPar(&mFraction).XMLInput(is,tag); break; } if("MarchCoeff"==tag.GetAttributeValue(i)) { mpTextureMarchDollase->GetPar(&mMarchCoeff).XMLInput(is,tag); break; } if("H"==tag.GetAttributeValue(i)) { mpTextureMarchDollase->GetPar(&mH).XMLInput(is,tag); break; } if("K"==tag.GetAttributeValue(i)) { mpTextureMarchDollase->GetPar(&mK).XMLInput(is,tag); break; } if("L"==tag.GetAttributeValue(i)) { mpTextureMarchDollase->GetPar(&mL).XMLInput(is,tag); break; } } } continue; } } } #ifdef __WX__CRYST__ WXCrystObjBasic* TexturePhaseMarchDollase::WXCreate(wxWindow* parent) { mpWXCrystObj=new WXTexturePhaseMarchDollase(parent,this,mpTextureMarchDollase); return mpWXCrystObj; } WXCrystObjBasic* TexturePhaseMarchDollase::WXGet() { return mpWXCrystObj; } void TexturePhaseMarchDollase::WXDelete() { if(0!=mpWXCrystObj) { VFN_DEBUG_MESSAGE("TexturePhaseMarchDollase::WXDelete()",5) delete mpWXCrystObj; } } void TexturePhaseMarchDollase::WXNotifyDelete(){mpWXCrystObj=0;} #endif //////////////////////////////////////////////////////////////////////// // // TextureMarchDollase // //////////////////////////////////////////////////////////////////////// TextureMarchDollase::TextureMarchDollase(const ScatteringData & data): ScatteringCorr(data),mNbReflUsed(0) { mClockMaster.AddChild(mClockTexturePar); } TextureMarchDollase::~TextureMarchDollase() { } const string & TextureMarchDollase::GetName() const { //So far, we do not need a personalized name... const static string name="TextureMarchDollase"; return name; } const string & TextureMarchDollase::GetClassName() const { //So far, we do not need a personalized name... const static string name="TextureMarchDollase"; return name; } void TextureMarchDollase::AddPhase(const REAL f, const REAL c, const REAL h,const REAL k, const REAL l) { VFN_DEBUG_ENTRY("TextureMarchDollase::AddPhase()",5) TexturePhaseMarchDollase* phase=new TexturePhaseMarchDollase(f,c,h,k,l,*this); this->Print(); //Add parameters const unsigned int nbPhase=this->GetNbPhase(); char buf [5]; sprintf(buf,"%d",nbPhase); { RefinablePar tmp("Fraction_"+(string)buf,&(phase->mFraction),0.,1., gpRefParTypeScattDataCorrIntPO_Fraction, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,1.); tmp.AssignClock(mClockTexturePar); tmp.SetDerivStep(1e-7); tmp.SetGlobalOptimStep(.05); this->AddPar(tmp); } { RefinablePar tmp("MarchCoeff_"+(string)buf,&(phase->mMarchCoeff),.1,10., gpRefParTypeScattDataCorrIntPO_Amplitude, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,1.); tmp.AssignClock(mClockTexturePar); tmp.SetDerivStep(1e-7); tmp.SetGlobalOptimStep(.1); this->AddPar(tmp); } { RefinablePar tmp("H_"+(string)buf,&(phase->mH),-10.,10., gpRefParTypeScattDataCorrIntPO_Direction, REFPAR_DERIV_STEP_ABSOLUTE,false,true,true,false,1.); tmp.AssignClock(mClockTexturePar); tmp.SetDerivStep(1e-7); tmp.SetGlobalOptimStep(.01); this->AddPar(tmp); } { RefinablePar tmp("K_"+(string)buf,&(phase->mK),-10.,10., gpRefParTypeScattDataCorrIntPO_Direction, REFPAR_DERIV_STEP_ABSOLUTE,false,true,true,false,1.); tmp.AssignClock(mClockTexturePar); tmp.SetDerivStep(1e-7); tmp.SetGlobalOptimStep(.01); this->AddPar(tmp); } { RefinablePar tmp("L_"+(string)buf,&(phase->mL),-10.,10., gpRefParTypeScattDataCorrIntPO_Direction, REFPAR_DERIV_STEP_ABSOLUTE,false,true,true,false,1.); tmp.AssignClock(mClockTexturePar); tmp.SetDerivStep(1e-7); tmp.SetGlobalOptimStep(.01); this->AddPar(tmp); } this->Print(); mPhaseRegistry.Register(*phase); VFN_DEBUG_EXIT("TextureMarchDollase::AddPhase()=",5) } void TextureMarchDollase::SetPhasePar(const unsigned int i, const REAL f, const REAL c, const REAL h,const REAL k, const REAL l) { mPhaseRegistry.GetObj(i).SetPar(f,c,h,k,l); } //void DeletePhase(const unsigned int i); unsigned int TextureMarchDollase::GetNbPhase() const {return mPhaseRegistry.GetNb();} REAL TextureMarchDollase::GetFraction(const unsigned int i)const {return mPhaseRegistry.GetObj(i).mFraction;} REAL TextureMarchDollase::GetMarchCoeff(const unsigned int i)const {return mPhaseRegistry.GetObj(i).mMarchCoeff;} REAL TextureMarchDollase::GetPhaseH(const unsigned int i)const {return mPhaseRegistry.GetObj(i).mH;} REAL TextureMarchDollase::GetPhaseK(const unsigned int i)const {return mPhaseRegistry.GetObj(i).mK;} REAL TextureMarchDollase::GetPhaseL(const unsigned int i)const {return mPhaseRegistry.GetObj(i).mL;} void TextureMarchDollase::GlobalOptRandomMove(const REAL mutationAmplitude, const RefParType *type) { if(mRandomMoveIsDone) return; if(!(gpRefParTypeScattDataCorrInt->IsDescendantFromOrSameAs(type))) { mRandomMoveIsDone=true; return; } //if((rand()/(REAL)RAND_MAX)<.3)//only 30% proba to make a random move { VFN_DEBUG_MESSAGE("TextureMarchDollase::GlobalOptRandomMove()",1) for(unsigned int i=0;iGetNbPhase();i++) { // :TODO: Give some probability (1% ?) to invert the March coefficient // with a direction perpendicular to the current one ? RefinablePar *pF=&(this->GetPar(&(mPhaseRegistry.GetObj(i).mFraction))); RefinablePar *pM=&(this->GetPar(&(mPhaseRegistry.GetObj(i).mMarchCoeff))); RefinablePar *pH=&(this->GetPar(&(mPhaseRegistry.GetObj(i).mH))); RefinablePar *pK=&(this->GetPar(&(mPhaseRegistry.GetObj(i).mK))); RefinablePar *pL=&(this->GetPar(&(mPhaseRegistry.GetObj(i).mL))); if(pF->IsFixed()==false) { const REAL delta=pF->GetGlobalOptimStep()*mutationAmplitude; const REAL sig=4*delta; const REAL y0=mPhaseRegistry.GetObj(i).mBiasFraction; REAL y,ymin,ymax; y=pF->GetValue(); ymax=.5+1/M_PI*atan((y+delta-y0)/(2.*sig)); ymin=.5+1/M_PI*atan((y-delta-y0)/(2.*sig)); y=ymin+rand()/(REAL)RAND_MAX*(ymax-ymin); y-=.5; if(y<-.499)y=-.499;//Should not happen but make sure we remain in [-pi/2;pi/2] if(y> .499)y= .499; pF->MutateTo(y0+2*sig*tan(M_PI*y)); } if((pH->IsFixed()==false)||(pK->IsFixed()==false)||(pL->IsFixed()==false)) { REAL tx=pH->GetValue(); REAL ty=pK->GetValue(); REAL tz=pL->GetValue(); mpData->GetCrystal().MillerToOrthonormalCoords(tx,ty,tz); { REAL tx0=mPhaseRegistry.GetObj(i).mBiasH; REAL ty0=mPhaseRegistry.GetObj(i).mBiasK; REAL tz0=mPhaseRegistry.GetObj(i).mBiasL; mpData->GetCrystal().MillerToOrthonormalCoords(tx0,ty0,tz0); const REAL delta=pH->GetGlobalOptimStep()*mutationAmplitude*mPhaseRegistry.GetObj(i).mNorm; const REAL sig=2*delta; REAL y,ymin,ymax; ymax=.5+1/M_PI*atan((tx+delta-tx0)/(2.*sig)); ymin=.5+1/M_PI*atan((tx-delta-tx0)/(2.*sig)); y=ymin+rand()/(REAL)RAND_MAX*(ymax-ymin); y-=.5; if(y<-.499)y=-.499; if(y> .499)y= .499; tx=tx0+2*sig*tan(M_PI*y); ymax=.5+1/M_PI*atan((ty+delta-ty0)/(2.*sig)); ymin=.5+1/M_PI*atan((ty-delta-ty0)/(2.*sig)); y=ymin+rand()/(REAL)RAND_MAX*(ymax-ymin); y-=.5; if(y<-.499)y=-.499; if(y> .499)y= .499; ty=ty0+2*sig*tan(M_PI*y); ymax=.5+1/M_PI*atan((tz+delta-tz0)/(2.*sig)); ymin=.5+1/M_PI*atan((tz-delta-tz0)/(2.*sig)); y=ymin+rand()/(REAL)RAND_MAX*(ymax-ymin); y-=.5; if(y<-.499)y=-.499; if(y> .499)y= .499; tz=tz0+2*sig*tan(M_PI*y); } const REAL factor=mPhaseRegistry.GetObj(i).mNorm/sqrt(tx*tx+ty*ty+tz*tz); tx *= factor; ty *= factor; tz *= factor; mpData->GetCrystal().OrthonormalToMillerCoords(tx,ty,tz); pH->MutateTo(tx); pK->MutateTo(ty); pL->MutateTo(tz); } if(pM->IsFixed()==false) { // Given the nature of this param, we use a proportionnal max step const REAL delta=pM->GetGlobalOptimStep()*mutationAmplitude; const REAL sig=2*delta; REAL y,ymin,ymax; y=log(pM->GetValue()); const REAL y0=log(mPhaseRegistry.GetObj(i).mBiasMarchCoeff); ymin=.5+1/M_PI*atan((y-delta-y0)/(2.*sig)); ymax=.5+1/M_PI*atan((y+delta-y0)/(2.*sig)); y=ymin+rand()/(REAL)RAND_MAX*(ymax-ymin); y-=.5; if(y<-.499)y=-.499; if(y> .499)y= .499; pM->MutateTo(exp(y0+2*sig*tan(M_PI*y))); } } } //this->RefinableObj::Print(); mRandomMoveIsDone=true; } REAL TextureMarchDollase::GetBiasingCost()const { REAL cost=0; REAL tmp; for(unsigned int i=0; iGetNbPhase();i++) { tmp =(mPhaseRegistry.GetObj(i).mBiasFraction-mPhaseRegistry.GetObj(i).mFraction)/.04; cost += tmp*tmp; tmp =log10(mPhaseRegistry.GetObj(i).mBiasMarchCoeff/mPhaseRegistry.GetObj(i).mMarchCoeff)/.04; cost += tmp*tmp; REAL tx=mPhaseRegistry.GetObj(i).mH-mPhaseRegistry.GetObj(i).mBiasH; REAL ty=mPhaseRegistry.GetObj(i).mK-mPhaseRegistry.GetObj(i).mBiasK; REAL tz=mPhaseRegistry.GetObj(i).mL-mPhaseRegistry.GetObj(i).mBiasL; mpData->GetCrystal().MillerToOrthonormalCoords(tx,ty,tz); cost +=(tx*tx+ty*ty+tz*tz)/mPhaseRegistry.GetObj(i).mNorm/.04; } VFN_DEBUG_MESSAGE("TextureMarchDollase::GetBiasingCost()="<GetName(),5) } void TextureMarchDollase::XMLInput(istream &is,const XMLCrystTag &tagg) { VFN_DEBUG_ENTRY("TextureMarchDollase::XMLInput():"<GetName(),5) for(unsigned int i=0;iAddPhase(0.,1.,1.,0.,0.); mPhaseRegistry.GetObj(nb).XMLInput(is,tag); } } } void TextureMarchDollase::BeginOptimization(const bool allowApproximations, const bool enableRestraints) { for(unsigned int i=0; iGetNbPhase();i++) { RefinablePar *pH=&(this->GetPar(&(mPhaseRegistry.GetObj(i).mH))); RefinablePar *pK=&(this->GetPar(&(mPhaseRegistry.GetObj(i).mK))); RefinablePar *pL=&(this->GetPar(&(mPhaseRegistry.GetObj(i).mL))); if((pH->IsFixed()==false)||(pK->IsFixed()==false)||(pL->IsFixed()==false)) { pH->SetIsFixed(false); pK->SetIsFixed(false); pL->SetIsFixed(false); } REAL tx=pH->GetValue(); REAL ty=pK->GetValue(); REAL tz=pL->GetValue(); mpData->GetCrystal().MillerToOrthonormalCoords(tx,ty,tz); mPhaseRegistry.GetObj(i).mNorm=sqrt(tx*tx+ty*ty+tz*tz); // Something went wrong, preferred orientation vector has null norm ! if(mPhaseRegistry.GetObj(i).mNorm<1e-6) mPhaseRegistry.GetObj(i).mNorm=1; } this->RefinableObj::BeginOptimization(allowApproximations,enableRestraints); } void TextureMarchDollase::TagNewBestConfig()const { for(unsigned int i=0; iGetNbPhase();i++) { mPhaseRegistry.GetObj(i).mBiasFraction =mPhaseRegistry.GetObj(i).mFraction; mPhaseRegistry.GetObj(i).mBiasMarchCoeff=mPhaseRegistry.GetObj(i).mMarchCoeff; mPhaseRegistry.GetObj(i).mBiasH =mPhaseRegistry.GetObj(i).mH; mPhaseRegistry.GetObj(i).mBiasK =mPhaseRegistry.GetObj(i).mK; mPhaseRegistry.GetObj(i).mBiasL =mPhaseRegistry.GetObj(i).mL; } } void TextureMarchDollase::CalcCorr() const { if(this->GetNbPhase()==0) { mCorr.resize(0); return; } const long nbReflUsed=mpData->GetNbReflBelowMaxSinThetaOvLambda(); if( (mClockTextureParGetClockTheta()GetNbPhase();i++) fractionNorm+=this->GetFraction(i); if(fractionNorm<1) { nonTexturedFraction= 1.-fractionNorm; fractionNorm=1.; } else nonTexturedFraction=0.; //compute correction for each phase const long nbRefl=mpData->GetNbRefl(); mCorr.resize(nbRefl); mCorr=nonTexturedFraction; CrystVector_REAL reflNorm(nbRefl); { const REAL *xx=mpData->GetReflX().data(); const REAL *yy=mpData->GetReflY().data(); const REAL *zz=mpData->GetReflZ().data(); for(long i=0;iGetNbPhase();i++) { // We are using multiplicity for powder diffraction, therefore with only // unique reflections. But Equivalent reflections do not have the same // texture correction ! So we must use the symmetry oprators, and it is simpler // to apply the symmetries to the texture vector than to all reflections hkl=mpData->GetCrystal().GetSpaceGroup() .GetAllEquivRefl(this->GetPhaseH(i),this->GetPhaseK(i),this->GetPhaseL(i),true); //coefficients const REAL march=1./(this->GetMarchCoeff(i)+1e-6); const REAL march2=this->GetMarchCoeff(i)*this->GetMarchCoeff(i)-march; // Normalized by the number of symmetrical reflections const REAL frac=this->GetFraction(i)/(fractionNorm+1e-6)/hkl.rows(); for(long j=0;jGetReflX().data(); const REAL *yy=mpData->GetReflY().data(); const REAL *zz=mpData->GetReflZ().data(); const REAL *xyznorm=reflNorm.data(); { mpData->GetCrystal().MillerToOrthonormalCoords(tx,ty,tz); const REAL norm=sqrt(tx*tx+ty*ty+tz*tz); tx/=(norm+1e-6); ty/=(norm+1e-6); tz/=(norm+1e-6); } // Calculation REAL tmp; for(long k=0;kIsbeingRefined()==false) //{ // cout <(mpData->GetH(), // mpData->GetK(), // mpData->GetL(), // mpData->GetSinThetaOverLambda(), // mCorr)<Print(); //} mClockCorrCalc.Click(); VFN_DEBUG_EXIT("TextureMarchDollase::CalcCorr()",3) } void TextureMarchDollase::DeleteAllPhase() { } #ifdef __WX__CRYST__ WXCrystObjBasic* TextureMarchDollase::WXCreate(wxWindow* parent) { //:TODO: Check mpWXCrystObj==0 //mpWXCrystObj=new WXTextureMarchDollase(parent,this); return mpWXCrystObj; } #endif //////////////////////////////////////////////////////////////////////// // // TextureEllipsoid // //////////////////////////////////////////////////////////////////////// TextureEllipsoid::TextureEllipsoid(const ScatteringData & data, const REAL EPR1, const REAL EPR2, const REAL EPR3, const REAL EPR4, const REAL EPR5, const REAL EPR6): ScatteringCorr(data),mNbReflUsed(0) { mClockMaster.AddChild(mClockTextureEllipsoidPar); mEPR[0]=EPR1; mEPR[1]=EPR2; mEPR[2]=EPR3; mEPR[3]=EPR4; mEPR[4]=EPR5; mEPR[5]=EPR6; InitRefParList(); } TextureEllipsoid::~TextureEllipsoid() { #ifdef __WX__CRYST__ if(mpWXCrystObj!=0) { delete mpWXCrystObj; mpWXCrystObj=0; } #endif } const string & TextureEllipsoid::GetName() const { //So far, we do not need a personalized name... const static string name="TextureEllipsoid"; return name; } const string & TextureEllipsoid::GetClassName() const { //So far, we do not need a personalized name... const static string name="TextureEllipsoid"; return name; } void TextureEllipsoid::SetParams(const REAL EPR1, const REAL EPR2, const REAL EPR3, const REAL EPR4, const REAL EPR5, const REAL EPR6) { mEPR[0]=EPR1; mEPR[1]=EPR2; mEPR[2]=EPR3; mEPR[3]=EPR4; mEPR[4]=EPR5; mEPR[5]=EPR6; UpdateEllipsoidPar(); } void TextureEllipsoid::GlobalOptRandomMove(const REAL mutationAmplitude, const RefParType *type) { if(mRandomMoveIsDone) return; /* if(!(gpRefParTypeScattDataCorrInt->IsDescendantFromOrSameAs(type))) { mRandomMoveIsDone=true; return; } */ { VFN_DEBUG_MESSAGE("TextureEllipsoid::GlobalOptRandomMove()",1) RefinablePar *pEPR[6]; for (int i=0; i<6; i++) { pEPR[i] = &(this->GetPar(&(mEPR[i]))); if (pEPR[i]->IsFixed()==false) pEPR[i]->Mutate(pEPR[i]->GetGlobalOptimStep()*2*(rand()/(REAL)RAND_MAX-0.5)*mutationAmplitude); } UpdateEllipsoidPar(); } //this->RefinableObj::Print(); mRandomMoveIsDone=true; } void TextureEllipsoid::XMLOutput(ostream &os,int indent)const { if((mEPR[0]==0) && (mEPR[1]==0) && (mEPR[2]==0) && (mEPR[3]==0) && (mEPR[4]==0) && (mEPR[5]==0)) return; VFN_DEBUG_ENTRY("TextureEllipsoid::XMLOutput():"<GetName(),5) for(int i=0;iGetName(),5) } void TextureEllipsoid::XMLInput(istream &is,const XMLCrystTag &tagg) { VFN_DEBUG_ENTRY("TextureEllipsoid::XMLInput():"<GetName(),5) for(unsigned int i=0;iRefinableObj::BeginOptimization(allowApproximations,enableRestraints); } void TextureEllipsoid::CalcCorr() const { if((mEPR[0]==0) && (mEPR[1]==0) && (mEPR[2]==0) && (mEPR[3]==0) && (mEPR[4]==0) && (mEPR[5]==0)) { mCorr.resize(0); return; } const long nbReflUsed=mpData->GetNbReflBelowMaxSinThetaOvLambda(); if( (mClockTextureEllipsoidParGetClockTheta()GetClockNbReflBelowMaxSinThetaOvLambda()GetNbRefl(); mCorr.resize(nbRefl); ///mCorr=1.0; /// Icorr = Iobs[1 + (EPR1*h^2 + EPR2*k^2 + EPR3*l^2 + EPR4*2hk + EPR5*2hl + EPR6*2kl) * 0.001d^2]^-1.5 REAL tmp, dhkl; REAL sum=0; REAL *pCorr=mCorr.data(); const REAL *pH=mpData->GetH().data(); const REAL *pK=mpData->GetH().data(); const REAL *pL=mpData->GetH().data(); const REAL *pstol=mpData->GetSinThetaOverLambda().data(); for(long i=0;iHasCrystal()) num = mpData->GetCrystal().GetSpaceGroup().GetSpaceGroupNumber(); bool bEPR [6]; for (int i=0; i<6; i++) bEPR[i] = true; if(num <=2) { } else if((num <=15) && (0==mpData->GetCrystal().GetSpaceGroup().GetUniqueAxis())) { mEPR[4]=0.0; mEPR[5]=0.0; bEPR[4]=false; bEPR[5]=false; } else if((num <=15) && (1==mpData->GetCrystal().GetSpaceGroup().GetUniqueAxis())) { mEPR[3]=0.0; mEPR[5]=0.0; bEPR[3]=false; bEPR[5]=false; } else if((num <=15) && (2==mpData->GetCrystal().GetSpaceGroup().GetUniqueAxis())) { mEPR[3]=0.0; mEPR[4]=0.0; bEPR[3]=false; bEPR[4]=false; } else if(num <=74) { mEPR[3]=0.0; mEPR[4]=0.0; mEPR[5]=0.0; bEPR[3]=false; bEPR[4]=false; bEPR[5]=false; } else if(num <= 142) { mEPR[1]=mEPR[0]; mEPR[3]=0.0; mEPR[4]=0.0; mEPR[5]=0.0; bEPR[1]=false; bEPR[3]=false; bEPR[4]=false; bEPR[5]=false; } else if(num <= 194) {//Hexagonal axes, for hexagonal and non-rhomboedral trigonal cells mEPR[1]=mEPR[0]; mEPR[3]=mEPR[0]*0.5; mEPR[4]=0.0; mEPR[5]=0.0; bEPR[1]=false; bEPR[3]=false; bEPR[4]=false; bEPR[5]=false; } else { mEPR[1]=mEPR[0]; mEPR[2]=mEPR[0]; mEPR[3]=0.0; mEPR[4]=0.0; mEPR[5]=0.0; bEPR[1]=false; bEPR[2]=false; bEPR[3]=false; bEPR[4]=false; bEPR[5]=false; } for (int i=0; i<6; i++) this->GetPar(i).SetIsUsed(bEPR[i]); VFN_DEBUG_EXIT("TextureEllipsoid::UpdateEllipsoidPar().",3) } void TextureEllipsoid::InitRefParList() { VFN_DEBUG_ENTRY("TextureEllipsoid::InitRefParList()",5) if(this->GetNbPar()==0) { char buf [5]; for (int i=0; i<6; i++) { sprintf(buf,"%d",i+1); RefinablePar tmp("EPR"+(string)buf, &(mEPR[i]), -10., 10., gpRefParTypeScattDataCorrInt_Ellipsoid, REFPAR_DERIV_STEP_ABSOLUTE, false, true, true, false, 1.0); tmp.AssignClock(mClockTextureEllipsoidPar); tmp.SetDerivStep(1e-4); tmp.SetGlobalOptimStep(0.1); this->AddPar(tmp); } } VFN_DEBUG_EXIT("TextureEllipsoid::InitRefParList():Finished",5) } #ifdef __WX__CRYST__ WXCrystObjBasic* TextureEllipsoid::WXCreate(wxWindow* parent) { VFN_DEBUG_ENTRY("TextureEllipsoid::WXCreate()",6) if(mpWXCrystObj==0) mpWXCrystObj=new WXTextureEllipsoid(parent,this); VFN_DEBUG_EXIT("TextureEllipsoid::WXCreate()",6) return mpWXCrystObj; } #endif //////////////////////////////////////////////////////////////////////// // // Time Of Flight correction // //////////////////////////////////////////////////////////////////////// TOFCorr::TOFCorr(const ScatteringData & data): ScatteringCorr(data) {} TOFCorr::~TOFCorr() {} const string & TOFCorr::GetName() const { //So far, we do not need a personalized name... const static string mName="TOFCorr"; return mName; } const string & TOFCorr::GetClassName() const { const static string className="TOFCorr"; return className; } void TOFCorr::CalcCorr() const { const REAL *pstol=mpData->GetSinThetaOverLambda().data(); if(mpData->GetClockTheta()GetNbRefl()); for(long i=0;iGetNbRefl();i++) mCorr(i) = pow((float)(1.0/(2.0* *pstol++)),(int)4); mClockCorrCalc.Click(); } }//namespace objcryst-2022.1/ObjCryst/ObjCryst/ScatteringCorr.h000066400000000000000000000241351430515525000220440ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _OBJCRYST_SCATTERING_CORR_H_ #define _OBJCRYST_SCATTERING_CORR_H_ #include "ObjCryst/ObjCryst/ScatteringData.h" namespace ObjCryst { /** Base class to compute all kind of corrections to intensities: Lorentz, Polar, * absorption, texcture, extinction, etc... * * The computed intensities are to be multiplied by all the ScatteringCorr calculated. * * * This is an abstract base class. */ class ScatteringCorr { public: /// Constructor, with the associated ScatteringData object. ScatteringCorr(const ScatteringData & data); virtual ~ScatteringCorr(); /// Get the name of this object virtual const string & GetName() const=0; /// Get the name of the class virtual const string & GetClassName() const=0; /// Get the vector of corrections for all reflections. Calculated values must /// be multiplied by these values. /// If the vector is empty (size==0), then no correction should be applied const CrystVector_REAL& GetCorr() const; /// Get the value of the clock corresponding to the last time the correction /// was actually computed const RefinableObjClock& GetClockCorr()const; protected: /// Do the computation of corrected intensities virtual void CalcCorr() const=0; /// The associated ScatteringData object const ScatteringData *mpData; /// The vector of correction to intensities. mutable CrystVector_REAL mCorr; /// The clock marking the last time the correction was calculated mutable RefinableObjClock mClockCorrCalc; }; /** Lorentz Correction * * So far, it only considers the correction for equatorial diffraction: * \f$ L = \frac{1}{\sin(2\theta)} \f$ */ class LorentzCorr:public ScatteringCorr { public: LorentzCorr(const ScatteringData & data); virtual ~LorentzCorr(); virtual const string & GetName() const; virtual const string & GetClassName() const; protected: virtual void CalcCorr() const; }; /** Polarization Correction * * So far, it only considers the correction for equatorial diffraction: *\f$ P = \frac{1}{1+A}\left(1+A\cos^2(2\theta)\right) \f$ (Polarization factor), with * \f$ A = \frac{1-f}{1+f} \f$, where f is the polarization rate of the incident *beam in the plane which (i) includes the incident beam, and (ii) is perpendicular to *the diffracting plane. For an X-Ray Tube without monochromator, A=1, and *if there is a monochromator : \f$ A = \cos^2(2\theta_{mono}) \f$ * * Currently, the linear polarization factor is directly read from the radiation object, * and the linear polarization (if any) is assumed to be perpendicular to the diffracting * plane (standard synchrotron geometry). * * \todo: extend this to take into account other diffracting & monochromatic geometries. */ class PolarizationCorr:public ScatteringCorr { public: PolarizationCorr(const ScatteringData & data); virtual ~PolarizationCorr(); virtual const string & GetName() const; virtual const string & GetClassName() const; protected: virtual void CalcCorr() const; mutable REAL mPolarAfactor; }; /** Slit aperture correction (for powder) * * This correction takes into account the fact that diffraction * rings (cones) have a portion of the ring proportionnal to * \f$ SlitAp = \frac{1}{\sin(\theta)} \f$ which falls into the detector * (due to slits in the direction perpendicular to the incident beam/ detector plane). */ class PowderSlitApertureCorr:public ScatteringCorr { public: PowderSlitApertureCorr(const ScatteringData & data); virtual ~PowderSlitApertureCorr(); virtual const string & GetName() const; virtual const string & GetClassName() const; protected: virtual void CalcCorr() const; }; class TextureMarchDollase; /** One texture phase for the March-Dollase model. * */ struct TexturePhaseMarchDollase { TexturePhaseMarchDollase(const REAL f, const REAL c,const REAL h,const REAL k, const REAL l, TextureMarchDollase &); ~TexturePhaseMarchDollase(); const string& GetClassName()const; const string& GetName()const; void SetPar(const REAL f, const REAL c,const REAL h,const REAL k, const REAL l); void XMLOutput(ostream &os,int indent=0)const; void XMLInput(istream &is,const XMLCrystTag &tag); REAL mFraction,mMarchCoeff,mH,mK,mL; /// Norm of the (HKL) vector, to keep it constant during optimization mutable REAL mNorm; /// The parent TextureMarchDollase object. TextureMarchDollase *mpTextureMarchDollase; /// Values of parameters towards which the optimization is biased (if biasing /// is used). These are normally dynamically updated to the last "best" values found. mutable REAL mBiasFraction,mBiasMarchCoeff,mBiasH,mBiasK,mBiasL; #ifdef __WX__CRYST__ WXCrystObjBasic* WXCreate(wxWindow*); WXCrystObjBasic* WXGet(); void WXDelete(); void WXNotifyDelete(); WXCrystObjBasic *mpWXCrystObj; #endif }; /** Texture correction using the March-Dollase model. * * This can include several phases. * */ class TextureMarchDollase:public ScatteringCorr,public RefinableObj { public: TextureMarchDollase(const ScatteringData & data); virtual ~TextureMarchDollase(); virtual const string & GetName() const; virtual const string & GetClassName() const; void AddPhase(const REAL fraction, const REAL coeffMarch, const REAL h,const REAL k, const REAL l); void SetPhasePar(const unsigned int i, const REAL fraction, const REAL coeffMarch, const REAL h,const REAL k, const REAL l); void DeletePhase(const unsigned int i); unsigned int GetNbPhase() const; REAL GetFraction(const unsigned int i)const; REAL GetMarchCoeff(const unsigned int i)const; REAL GetPhaseH(const unsigned int i)const; REAL GetPhaseK(const unsigned int i)const; REAL GetPhaseL(const unsigned int i)const; virtual void GlobalOptRandomMove(const REAL mutationAmplitude, const RefParType *type=gpRefParTypeObjCryst); virtual REAL GetBiasingCost()const; virtual void XMLOutput(ostream &os,int indent=0)const; virtual void XMLInput(istream &is,const XMLCrystTag &tag); virtual void BeginOptimization(const bool allowApproximations=false, const bool enableRestraints=false); virtual void TagNewBestConfig()const; protected: virtual void CalcCorr() const; void DeleteAllPhase(); ObjRegistry mPhaseRegistry; RefinableObjClock mClockTexturePar; /// Number of reflexion for which the calculation is actually done. /// This is automaticaly updated during CalcCorr, from the parent /// ScatteringData::GetMaxSinThetaOvLambda() mutable unsigned long mNbReflUsed; #ifdef __WX__CRYST__ public: virtual WXCrystObjBasic* WXCreate(wxWindow*); friend class WXTextureMarchDollase; #endif }; /** Texture correction using the Ellipsoidal preferred orientation function. * * Icorr = Iobs[ 1 + (EPR1*h^2 + EPR2*k^2 + EPR3*l^2 + EPR4*2hk + EPR5*2hl + EPR6*2kl) * 0.001d^2 ]^-1.5 * */ class TextureEllipsoid:public ScatteringCorr,public RefinableObj { public: TextureEllipsoid(const ScatteringData & data, const REAL EPR1=0.0, const REAL EPR2=0.0, const REAL EPR3=0.0, const REAL EPR4=0.0, const REAL EPR5=0.0, const REAL EPR6=0.0); virtual ~TextureEllipsoid(); virtual const string & GetName() const; virtual const string & GetClassName() const; void SetParams(const REAL EPR1, const REAL EPR2, const REAL EPR3, const REAL EPR4, const REAL EPR5, const REAL EPR6); REAL mEPR[6]; virtual void GlobalOptRandomMove(const REAL mutationAmplitude, const RefParType *type=gpRefParTypeObjCryst); virtual void XMLOutput(ostream &os,int indent=0)const; virtual void XMLInput(istream &is,const XMLCrystTag &tag); virtual void BeginOptimization(const bool allowApproximations=false, const bool enableRestraints=false); /// Prepare the refinable parameters list void InitRefParList(); /// Update ellipsoid parameters for tetragonal, trigonal, hexagonal, cubic lattices. /// This is needed during Refinement, since for example in a quadratic spg, /// only a is refined and we need to have b=a... void UpdateEllipsoidPar(); protected: virtual void CalcCorr() const; RefinableObjClock mClockTextureEllipsoidPar; /// Number of reflexion for which the calculation is actually done. /// This is automaticaly updated during CalcCorr, from the parent /// ScatteringData::GetMaxSinThetaOvLambda() mutable unsigned long mNbReflUsed; #ifdef __WX__CRYST__ public: virtual WXCrystObjBasic* WXCreate(wxWindow* parent); #endif }; /** Time-Of-Flight Correction * * * \f$ T = d^4\sin(\theta) \f$ * * The \theta angle of the detector is ignored, as it is just a scale factor. */ class TOFCorr:public ScatteringCorr { public: TOFCorr(const ScatteringData & data); virtual ~TOFCorr(); virtual const string & GetName() const; virtual const string & GetClassName() const; protected: virtual void CalcCorr() const; }; }//namespace #endif //_OBJCRYST_SCATTERING_CORR_H_ objcryst-2022.1/ObjCryst/ObjCryst/ScatteringData.cpp000066400000000000000000003066651430515525000223560ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * source file for LibCryst++ ScatteringData class * */ #include #include #include "cctbx/sgtbx/space_group.h" #include "cctbx/miller/index_generator.h" #include "cctbx/miller/sym_equiv.h" #include "cctbx/eltbx/wavelengths.h" #include "ObjCryst/ObjCryst/ScatteringData.h" #include "ObjCryst/Quirks/VFNDebug.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" #include "ObjCryst/Quirks/Chronometer.h" #ifdef __WX__CRYST__ #include "ObjCryst/wxCryst/wxPowderPattern.h" #include "ObjCryst/wxCryst/wxRadiation.h" #endif #include #include #include //for sprintf() #ifdef HAVE_SSE_MATHFUN #include "ObjCryst/Quirks/sse_mathfun.h" #endif #define POSSIBLY_UNUSED(expr) (void)(expr) namespace ObjCryst { const RefParType *gpRefParTypeScattData= 0; const RefParType *gpRefParTypeScattDataScale=0; const RefParType *gpRefParTypeScattDataProfile=0; const RefParType *gpRefParTypeScattDataProfileType=0; const RefParType *gpRefParTypeScattDataProfileWidth=0; const RefParType *gpRefParTypeScattDataProfileAsym=0; const RefParType *gpRefParTypeScattDataCorr=0; const RefParType *gpRefParTypeScattDataCorrInt=0; const RefParType *gpRefParTypeScattDataCorrIntPO_Direction=0; const RefParType *gpRefParTypeScattDataCorrIntPO_Fraction=0; const RefParType *gpRefParTypeScattDataCorrIntPO_Amplitude=0; const RefParType *gpRefParTypeScattDataCorrInt_Ellipsoid=0; const RefParType *gpRefParTypeScattDataCorrIntAbsorp=0; const RefParType *gpRefParTypeScattDataCorrIntPolar=0; const RefParType *gpRefParTypeScattDataCorrIntExtinc=0; const RefParType *gpRefParTypeScattDataCorrPos=0; const RefParType *gpRefParTypeScattDataBackground=0; const RefParType *gpRefParTypeRadiation=0; const RefParType *gpRefParTypeRadiationWavelength=0; long NiftyStaticGlobalObjectsInitializer_ScatteringData::mCount=0; #ifndef HAVE_SSE_MATHFUN //###################################################################### // Tabulated math functions for faster (&less precise) F(hkl) calculation //These function are defined and used in cristallo-spacegroup.cpp //Currently tabulating sine and cosine only //###################################################################### //static bool sLibCrystTabulCosineIsInit=false; //conversion value static REAL sLibCrystTabulCosineRatio; // Number of tabulated values of cosine between [0;2pi] // 100 000 is far enough for a model search, yielding a maximum // error less than .05%... 10000 should be enough, too, with (probably) a higher cache hit #define sLibCrystNbTabulSine 8192 #define sLibCrystNbTabulSineMASK 8191 //storage of tabulated values of cosine, and a table with interlaced csoine/sine values static REAL *spLibCrystTabulCosine; static REAL *spLibCrystTabulCosineSine; void InitLibCrystTabulCosine() { VFN_DEBUG_MESSAGE("InitLibCrystTabulCosine()",10) spLibCrystTabulCosine=new REAL[sLibCrystNbTabulSine]; spLibCrystTabulCosineSine=new REAL[sLibCrystNbTabulSine*2]; REAL *tmp=spLibCrystTabulCosine; sLibCrystTabulCosineRatio=sLibCrystNbTabulSine/2./M_PI; for(REAL i=0;iInitOptions(); mRadiationType.SetChoice(RAD_XRAY); mClockMaster.AddChild(mClockWavelength); mClockMaster.AddChild(mClockRadiation); this->SetWavelengthType(WAVELENGTH_MONOCHROMATIC); } Radiation::Radiation(const RadiationType rad,const REAL wavelength) { this->InitOptions(); mRadiationType.SetChoice(rad); mWavelength=wavelength; mXRayTubeName=""; mXRayTubeDeltaLambda=0.;//useless here mXRayTubeAlpha2Alpha1Ratio=0.5;//useless here mLinearPolarRate=0.95;//assume it's synchrotron ? mClockMaster.AddChild(mClockWavelength); mClockMaster.AddChild(mClockRadiation); this->SetWavelengthType(WAVELENGTH_MONOCHROMATIC); } Radiation::Radiation(const string &XRayTubeElementName,const REAL alpha2Alpha2ratio) { this->InitOptions(); this->SetWavelength(XRayTubeElementName,alpha2Alpha2ratio); mClockMaster.AddChild(mClockWavelength); mClockMaster.AddChild(mClockRadiation); } Radiation::Radiation(const Radiation &old): mRadiationType(old.mRadiationType), mWavelengthType(old.mWavelengthType), mWavelength(old.mWavelength), mXRayTubeName(old.mXRayTubeName), mXRayTubeDeltaLambda(old.mXRayTubeDeltaLambda), mXRayTubeAlpha2Alpha1Ratio(old.mXRayTubeAlpha2Alpha1Ratio), mLinearPolarRate(old.mLinearPolarRate) { mClockWavelength.Click(); mClockMaster.AddChild(mClockWavelength); mClockMaster.AddChild(mClockRadiation); this->SetWavelengthType((WavelengthType)old.mWavelengthType.GetChoice()); } Radiation::~Radiation() {} const string& Radiation::GetClassName() const { const static string className="Radiation"; return className; } void Radiation::operator=(const Radiation &old) { mRadiationType =old.mRadiationType; mWavelength =old.mWavelength; mXRayTubeName =old.mXRayTubeName; mXRayTubeDeltaLambda =old.mXRayTubeDeltaLambda; mXRayTubeAlpha2Alpha1Ratio =old.mXRayTubeAlpha2Alpha1Ratio; mClockWavelength.Click(); mRadiationType.SetChoice(old.mRadiationType.GetChoice()); this->SetWavelengthType((WavelengthType) old.mWavelengthType.GetChoice()); } RadiationType Radiation::GetRadiationType()const {return (RadiationType) mRadiationType.GetChoice();} void Radiation::SetRadiationType(const RadiationType rad) { mRadiationType.SetChoice(rad); if(rad == RAD_NEUTRON) mLinearPolarRate=0; if(rad == RAD_ELECTRON) { mLinearPolarRate=0; this->SetWavelengthType(WAVELENGTH_MONOCHROMATIC); } else this->UpdateDisplay(); } void Radiation::SetWavelengthType(const WavelengthType &type) { mWavelengthType.SetChoice((unsigned long) type); if(type==WAVELENGTH_TOF) { this->SetRadiationType(RAD_NEUTRON); this->GetPar("XRayTubeDeltaLambda").SetIsUsed(false); this->GetPar("XRayTubeAlpha2Alpha1Ratio").SetIsUsed(false); } if(type==WAVELENGTH_ALPHA12) { this->SetRadiationType(RAD_XRAY); this->GetPar("XRayTubeDeltaLambda").SetIsUsed(true); this->GetPar("XRayTubeAlpha2Alpha1Ratio").SetIsUsed(true); } if(type==WAVELENGTH_MONOCHROMATIC) { this->GetPar("XRayTubeDeltaLambda").SetIsUsed(false); this->GetPar("XRayTubeAlpha2Alpha1Ratio").SetIsUsed(false); } this->UpdateDisplay(); } WavelengthType Radiation::GetWavelengthType()const {return (WavelengthType) mWavelengthType.GetChoice();} const CrystVector_REAL& Radiation::GetWavelength() const {return mWavelength;} void Radiation::SetWavelength(const REAL l) { mWavelength.resize(1); mWavelength=l; mClockWavelength.Click(); this->GetPar("XRayTubeDeltaLambda").SetIsUsed(false); this->GetPar("XRayTubeAlpha2Alpha1Ratio").SetIsUsed(false); } void Radiation::SetWavelength(const string &XRayTubeElementName, const REAL alpha2Alpha2ratio) { VFN_DEBUG_MESSAGE("Radiation::SetWavelength(tubeName,ratio):",5) mXRayTubeName=XRayTubeElementName; this->SetRadiationType(RAD_XRAY); mWavelength.resize(1); mLinearPolarRate=0; if(XRayTubeElementName.length() >=3) //:KLUDGE: { if(XRayTubeElementName=="CoA1") { mWavelength=1.78901; this->SetWavelengthType(WAVELENGTH_MONOCHROMATIC); } else { try { cctbx::eltbx::wavelengths::characteristic ch(mXRayTubeName); if(!ch.is_valid()) { cout << "WARNING: could not interpret X-Ray tube name:"<SetWavelengthType(WAVELENGTH_MONOCHROMATIC); } catch(cctbx::error) { cout << "WARNING: could not interpret X-Ray tube name:"<SetWavelengthType(WAVELENGTH_ALPHA12); } mClockWavelength.Click(); } REAL Radiation::GetXRayTubeDeltaLambda()const {return mXRayTubeDeltaLambda;} REAL Radiation::GetXRayTubeAlpha2Alpha1Ratio()const {return mXRayTubeAlpha2Alpha1Ratio;} const RefinableObjClock& Radiation::GetClockWavelength() const {return mClockWavelength;} const RefinableObjClock& Radiation::GetClockRadiation()const {return mRadiationType.GetClock();} void Radiation::Print()const { VFN_DEBUG_MESSAGE("Radiation::Print():"<GetName(),5) cout << "Radiation:" << " " ; switch(mRadiationType.GetChoice()) { case RAD_NEUTRON: cout<< "Neutron,";break; case RAD_XRAY: cout<< "X-Ray,";break; case RAD_ELECTRON: cout<< "Electron,";break; } cout << "Wavelength=" <<" "; switch(mWavelengthType.GetChoice()) { case WAVELENGTH_MONOCHROMATIC: cout<< "monochromatic:"<<" "<AddOption(&mRadiationType); this->AddOption(&mWavelengthType); {//Fixed by default RefinablePar tmp("Wavelength",mWavelength.data(),0.05,20., gpRefParTypeRadiationWavelength,REFPAR_DERIV_STEP_ABSOLUTE, true,true,true,false,1.0); tmp.SetDerivStep(1e-4); tmp.AssignClock(mClockWavelength); this->AddPar(tmp); } {//Fixed by default RefinablePar tmp("XRayTubeDeltaLambda",&mXRayTubeDeltaLambda,0.001,20., gpRefParTypeRadiationWavelength,REFPAR_DERIV_STEP_ABSOLUTE, true,true,true,false,1.0); tmp.SetDerivStep(1e-4); tmp.AssignClock(mClockWavelength); this->AddPar(tmp); } {//Fixed by default RefinablePar tmp("XRayTubeAlpha2Alpha1Ratio",&mXRayTubeAlpha2Alpha1Ratio,0.5,0.5, gpRefParTypeRadiationWavelength,REFPAR_DERIV_STEP_ABSOLUTE, true,true,true,false,1.0); tmp.SetDerivStep(1e-4); tmp.AssignClock(mClockWavelength); this->AddPar(tmp); } } #ifdef __WX__CRYST__ WXCrystObjBasic* Radiation::WXCreate(wxWindow* parent) { //:TODO: Check mpWXCrystObj==0 mpWXCrystObj=new WXRadiation(parent,this); return mpWXCrystObj; } #endif //////////////////////////////////////////////////////////////////////// // // ScatteringData // //////////////////////////////////////////////////////////////////////// ScatteringData::ScatteringData(): mNbRefl(0), mpCrystal(0),mGlobalBiso(0),mUseFastLessPreciseFunc(false), mIgnoreImagScattFact(false),mMaxSinThetaOvLambda(10) { VFN_DEBUG_MESSAGE("ScatteringData::ScatteringData()",10) {//This should be done elsewhere... RefinablePar tmp("Global Biso",&mGlobalBiso,-1.,1., gpRefParTypeScattPowTemperatureIso,REFPAR_DERIV_STEP_ABSOLUTE, true,true,true,false,1.0); tmp.SetDerivStep(1e-4); tmp.AssignClock(mClockGlobalBiso); this->AddPar(tmp); } mClockMaster.AddChild(mClockHKL); mClockMaster.AddChild(mClockGlobalBiso); mClockMaster.AddChild(mClockNbReflUsed); mClockMaster.AddChild(mClockFhklObsSq); } ScatteringData::ScatteringData(const ScatteringData &old): mNbRefl(old.mNbRefl), mpCrystal(old.mpCrystal),mUseFastLessPreciseFunc(old.mUseFastLessPreciseFunc), //Do not copy temporary arrays mClockHKL(old.mClockHKL), mIgnoreImagScattFact(old.mIgnoreImagScattFact), mMaxSinThetaOvLambda(old.mMaxSinThetaOvLambda) { VFN_DEBUG_MESSAGE("ScatteringData::ScatteringData(&old)",10) mClockStructFactor.Reset(); mClockTheta.Reset(); mClockScattFactor.Reset(); mClockScattFactorResonant.Reset(); mClockThermicFact.Reset(); this->SetHKL(old.GetH(),old.GetK(),old.GetL()); VFN_DEBUG_MESSAGE("ScatteringData::ScatteringData(&old):End",5) {//This should be done elsewhere... RefinablePar tmp("Global Biso",&mGlobalBiso,-1.,1., gpRefParTypeScattPowTemperatureIso,REFPAR_DERIV_STEP_ABSOLUTE, true,true,true,false,1.0); tmp.SetDerivStep(1e-4); tmp.AssignClock(mClockGlobalBiso); this->AddPar(tmp); } mClockMaster.AddChild(mClockHKL); mClockMaster.AddChild(mClockGlobalBiso); mClockMaster.AddChild(mClockNbReflUsed); mClockMaster.AddChild(mClockFhklObsSq); } ScatteringData::~ScatteringData() { VFN_DEBUG_MESSAGE("ScatteringData::~ScatteringData()",10) } void ScatteringData::SetHKL(const CrystVector_REAL &h, const CrystVector_REAL &k, const CrystVector_REAL &l) { VFN_DEBUG_ENTRY("ScatteringData::SetHKL(h,k,l)",5) mNbRefl=h.numElements(); mH=h; mK=k; mL=l; mClockHKL.Click(); this->PrepareHKLarrays(); VFN_DEBUG_EXIT("ScatteringData::SetHKL(h,k,l):End",5) } void ScatteringData::GenHKLFullSpace2(const REAL maxSTOL,const bool unique) { //(*fpObjCrystInformUser)("Generating Full HKL list..."); VFN_DEBUG_ENTRY("ScatteringData::GenHKLFullSpace2()",5) TAU_PROFILE("ScatteringData::GenHKLFullSpace2()","void (REAL,bool)",TAU_DEFAULT); if(0==mpCrystal) { throw ObjCrystException("ScatteringData::GenHKLFullSpace2() \ no crystal assigned yet to this ScatteringData object."); } cctbx::uctbx::unit_cell uc=cctbx::uctbx::unit_cell(scitbx::af::double6(mpCrystal->GetLatticePar(0), mpCrystal->GetLatticePar(1), mpCrystal->GetLatticePar(2), mpCrystal->GetLatticePar(3)*RAD2DEG, mpCrystal->GetLatticePar(4)*RAD2DEG, mpCrystal->GetLatticePar(5)*RAD2DEG)); cctbx::miller::index_generator igen(uc, this->GetCrystal().GetSpaceGroup().GetCCTbxSpg().type(), !(this->IsIgnoringImagScattFact()), 1/(2*maxSTOL)); if(unique) { mNbRefl=0; CrystVector_long H(mNbRefl); CrystVector_long K(mNbRefl); CrystVector_long L(mNbRefl); mMultiplicity.resize(mNbRefl); for(;;) { if(mNbRefl==H.numElements()) { H.resizeAndPreserve(mNbRefl+100); K.resizeAndPreserve(mNbRefl+100); L.resizeAndPreserve(mNbRefl+100); mMultiplicity.resizeAndPreserve(mNbRefl+100); } cctbx::miller::index<> h = igen.next(); if (h.is_zero()) break; H(mNbRefl)=h[0]; K(mNbRefl)=h[1]; L(mNbRefl)=h[2]; cctbx::miller::sym_equiv_indices sei(this->GetCrystal().GetSpaceGroup().GetCCTbxSpg(),h); mMultiplicity(mNbRefl)=sei.multiplicity(!(this->IsIgnoringImagScattFact())); mNbRefl++; } H.resizeAndPreserve(mNbRefl); K.resizeAndPreserve(mNbRefl); L.resizeAndPreserve(mNbRefl); mMultiplicity.resizeAndPreserve(mNbRefl); this->SetHKL(H,K,L); this->SortReflectionBySinThetaOverLambda(maxSTOL); } else { mNbRefl=0; CrystVector_long H(mNbRefl); CrystVector_long K(mNbRefl); CrystVector_long L(mNbRefl); mMultiplicity.resize(mNbRefl); for(;;) { cctbx::miller::index<> h = igen.next(); if (h.is_zero()) break; cctbx::miller::sym_equiv_indices sei(this->GetCrystal().GetSpaceGroup().GetCCTbxSpg(),h); for(int i=0;i k = sei(i).h(); if(mNbRefl==H.numElements()) { H.resizeAndPreserve(mNbRefl+100); K.resizeAndPreserve(mNbRefl+100); L.resizeAndPreserve(mNbRefl+100); mMultiplicity.resizeAndPreserve(mNbRefl+100); } mMultiplicity(mNbRefl)=sei.multiplicity(!(this->IsIgnoringImagScattFact())); H(mNbRefl)=k[0]; K(mNbRefl)=k[1]; L(mNbRefl++)=k[2]; } } H.resizeAndPreserve(mNbRefl); K.resizeAndPreserve(mNbRefl); L.resizeAndPreserve(mNbRefl); mMultiplicity.resizeAndPreserve(mNbRefl); this->SetHKL(H,K,L); this->SortReflectionBySinThetaOverLambda(maxSTOL); } mClockHKL.Click(); /*{ char buf [200]; sprintf(buf,"Generating Full HKL list...Done (kept %d reflections)",(int)mNbRefl); (*fpObjCrystInformUser)((string)buf); }*/ VFN_DEBUG_EXIT("ScatteringData::GenHKLFullSpace2():End",5) } void ScatteringData::GenHKLFullSpace(const REAL maxTheta,const bool useMultiplicity) { VFN_DEBUG_ENTRY("ScatteringData::GenHKLFullSpace()",5) if(this->GetRadiation().GetWavelength()(0) <=.01) { throw ObjCrystException("ScatteringData::GenHKLFullSpace() \ no wavelength assigned yet to this ScatteringData object.");; } this->GenHKLFullSpace2(sin(maxTheta)/this->GetRadiation().GetWavelength()(0),useMultiplicity); VFN_DEBUG_EXIT("ScatteringData::GenHKLFullSpace()",5) } RadiationType ScatteringData::GetRadiationType()const {return this->GetRadiation().GetRadiationType();} void ScatteringData::SetCrystal(Crystal &crystal) { VFN_DEBUG_MESSAGE("ScatteringData::SetCrystal()",5) if(mpCrystal!=0) mpCrystal->DeRegisterClient(*this); mpCrystal=&crystal; this->AddSubRefObj(crystal); crystal.RegisterClient(*this); mClockMaster.AddChild(mpCrystal->GetClockLatticePar()); mClockGeomStructFact.Reset(); mClockStructFactor.Reset(); } const Crystal& ScatteringData::GetCrystal()const {return *mpCrystal;} Crystal& ScatteringData::GetCrystal() {return *mpCrystal;} bool ScatteringData::HasCrystal()const {return mpCrystal!=0;} long ScatteringData::GetNbRefl() const {return mNbRefl;} const CrystVector_REAL& ScatteringData::GetH() const {return mH;} const CrystVector_REAL& ScatteringData::GetK() const {return mK;} const CrystVector_REAL& ScatteringData::GetL() const {return mL;} const CrystVector_REAL& ScatteringData::GetH2Pi() const {return mH2Pi;} const CrystVector_REAL& ScatteringData::GetK2Pi() const {return mK2Pi;} const CrystVector_REAL& ScatteringData::GetL2Pi() const {return mH2Pi;} const CrystVector_REAL& ScatteringData::GetReflX() const { VFN_DEBUG_ENTRY("ScatteringData::GetReflX()",1) this->CalcSinThetaLambda(); VFN_DEBUG_EXIT("ScatteringData::GetReflX()",1) return mX; } const CrystVector_REAL& ScatteringData::GetReflY() const { VFN_DEBUG_ENTRY("ScatteringData::GetReflY()",1) this->CalcSinThetaLambda(); VFN_DEBUG_EXIT("ScatteringData::GetReflY()",1) return mY; } const CrystVector_REAL& ScatteringData::GetReflZ() const { VFN_DEBUG_ENTRY("ScatteringData::GetReflZ()",1) this->CalcSinThetaLambda(); VFN_DEBUG_EXIT("ScatteringData::GetReflZ()",1) return mZ; } const CrystVector_REAL& ScatteringData::GetSinThetaOverLambda()const { VFN_DEBUG_ENTRY("ScatteringData::GetSinThetaOverLambda()",1) this->CalcSinThetaLambda(); VFN_DEBUG_EXIT("ScatteringData::GetSinThetaOverLambda()",1) return mSinThetaLambda; } const CrystVector_REAL& ScatteringData::GetTheta()const { VFN_DEBUG_ENTRY("ScatteringData::GetTheta()",1) this->CalcSinThetaLambda(); VFN_DEBUG_EXIT("ScatteringData::GetTheta()",1) return mTheta; } const RefinableObjClock& ScatteringData::GetClockTheta()const { return mClockTheta; } const CrystVector_REAL& ScatteringData::GetFhklCalcSq() const { VFN_DEBUG_ENTRY("ScatteringData::GetFhklCalcSq()",2) this->CalcStructFactor(); if(mClockStructFactorSq>mClockStructFactor) return mFhklCalcSq; #ifdef __LIBCRYST_VECTOR_USE_BLITZ__ mFhklCalcSq=pow2(mFhklCalcReal)+pow2(mFhklCalcImag); #else const REAL *pr,*pi; REAL *p; pr=mFhklCalcReal.data(); pi=mFhklCalcImag.data(); p=mFhklCalcSq.data(); for(long i=0;i& ScatteringData::GetFhklCalcSq_FullDeriv(std::set &vPar) { TAU_PROFILE("ScatteringData::GetFhklCalcSq_FullDeriv()","void ()",TAU_DEFAULT); VFN_DEBUG_ENTRY("ScatteringData::GetFhklCalcSq()",2) this->CalcStructFactor_FullDeriv(vPar); mFhklCalcSq_FullDeriv[0]=this->GetFhklCalcSq(); mFhklCalcSq_FullDeriv.clear();// :TODO: avoid complete clear const REAL *pr,*pi,*prd,*pid; REAL *p; for(std::set::iterator par=vPar.begin();par!=vPar.end();par++) { if((*par)==0) continue; if(mFhklCalcReal_FullDeriv[*par].size()==0) { mFhklCalcSq_FullDeriv[*par].resize(0); continue; } mFhklCalcSq_FullDeriv[*par].resize(mNbRefl);//Should use mNbRefleUsed instead ? pr=mFhklCalcReal.data(); pi=mFhklCalcImag.data(); prd=mFhklCalcReal_FullDeriv[*par].data(); pid=mFhklCalcImag_FullDeriv[*par].data(); p=mFhklCalcSq_FullDeriv[*par].data(); for(long i=0;iCalcStructFactor(); VFN_DEBUG_EXIT("ScatteringData::GetFhklCalcReal()",2) return mFhklCalcReal; } const CrystVector_REAL& ScatteringData::GetFhklCalcImag() const { VFN_DEBUG_ENTRY("ScatteringData::GetFhklCalcImag()",2) this->CalcStructFactor(); VFN_DEBUG_EXIT("ScatteringData::GetFhklCalcImag()",2) return mFhklCalcImag; } const CrystVector_REAL& ScatteringData::GetFhklObsSq() const { return mFhklObsSq; } void ScatteringData::SetFhklObsSq(const CrystVector_REAL &obs) { if(obs.numElements() != mNbRefl) throw ObjCrystException("ScatteringData::SetFhklObsSq(): incorrect number of reflections !"); mFhklObsSq = obs; mClockFhklObsSq.Click(); } const map& ScatteringData::GetScatteringFactor() const { this->CalcScattFactor(); return mvScatteringFactor; } CrystVector_REAL ScatteringData::GetWavelength()const {return this->GetRadiation().GetWavelength();} #if 0 void ScatteringData::SetUseFastLessPreciseFunc(const bool useItOrNot) { mUseFastLessPreciseFunc=useItOrNot; mClockGeomStructFact.Reset(); mClockStructFactor.Reset(); } #endif void ScatteringData::SetIsIgnoringImagScattFact(const bool b) { VFN_DEBUG_MESSAGE("ScatteringData::SetIsIgnoringImagScattFact():"<GetFhklCalcSq(); CrystVector_REAL theta; theta=mTheta; theta *= RAD2DEG; os <<" Number of reflections:"< (mH,mK,mL,mFhklCalcSq,mFhklCalcReal,mFhklCalcImag,theta,mSinThetaLambda,12,4,mNbReflUsed); VFN_DEBUG_EXIT("ScatteringData::PrintFhklCalc()",5) } void ScatteringData::PrintFhklCalcDetail(ostream &os)const { VFN_DEBUG_ENTRY("ScatteringData::PrintFhklCalcDetail()",5) this->GetFhklCalcSq(); CrystVector_REAL theta; theta=mTheta; theta *= RAD2DEG; vector v; v.push_back(&mH); v.push_back(&mK); v.push_back(&mL); v.push_back(&mSinThetaLambda); v.push_back(&theta); v.push_back(&mFhklCalcSq); v.push_back(&mFhklCalcReal); v.push_back(&mFhklCalcImag); os <<" Number of reflections:"< sf; sf.resize(mvRealGeomSF.size()*2); long i=0; for(map::const_iterator pos=mvRealGeomSF.begin();pos!=mvRealGeomSF.end();++pos) { os << FormatString("Re(F)_"+pos->first->GetName(),14) << FormatString("Im(F)_"+pos->first->GetName(),14); cout<first->GetName()<<":"<first->GetForwardScatteringFactor(RAD_XRAY)<first]; sf[2*i] *= mvScatteringFactor[pos->first]; sf[2*i] *= mvTemperatureFactor[pos->first]; sf[2*i+1] = mvImagGeomSF[pos->first]; sf[2*i+1] *= mvScatteringFactor[pos->first]; sf[2*i+1] *= mvTemperatureFactor[pos->first]; v.push_back(&(sf[2*i])); v.push_back(&(sf[2*i+1])); //v.push_back(mvRealGeomSF[pos->first]); //v.push_back(mvImagGeomSF[pos->first]); //v.push_back(mvScatteringFactor[pos->first]); i++; } os<(v,12,4,mNbReflUsed); VFN_DEBUG_EXIT("ScatteringData::PrintFhklCalcDetail()",5) } void ScatteringData::BeginOptimization(const bool allowApproximations, const bool enableRestraints) { if(mUseFastLessPreciseFunc!=allowApproximations) { mClockGeomStructFact.Reset(); mClockStructFactor.Reset(); mClockMaster.Click(); } mUseFastLessPreciseFunc=allowApproximations; this->RefinableObj::BeginOptimization(allowApproximations,enableRestraints); } void ScatteringData::EndOptimization() { if(mOptimizationDepth==1) { if(mUseFastLessPreciseFunc==true) { mClockGeomStructFact.Reset(); mClockStructFactor.Reset(); mClockMaster.Click(); } mUseFastLessPreciseFunc=false; } this->RefinableObj::EndOptimization(); } void ScatteringData::SetApproximationFlag(const bool allow) { if(mUseFastLessPreciseFunc!=allow) { mClockGeomStructFact.Reset(); mClockStructFactor.Reset(); mClockMaster.Click(); } mUseFastLessPreciseFunc=allow; this->RefinableObj::SetApproximationFlag(allow); } void ScatteringData::PrepareHKLarrays() { VFN_DEBUG_ENTRY("ScatteringData::PrepareHKLarrays()"<GetSpaceGroup().GetClockSpaceGroup()0) && (abs(mFhklObsSq.numElements()-mNbRefl)<(0.1*mNbRefl)) && (noSpgChange) ) mFhklObsSq.resizeAndPreserve(mNbRefl); else mFhklObsSq.resize(0); mClockFhklObsSq.Click(); mNbReflUsed=mNbRefl; mExpectedIntensityFactor.resize(mNbRefl); for(long i=0;iGetSpaceGroup().GetExpectedIntensityFactor(mH(i),mK(i),mL(i)); } /* { mpCrystal->GetSpaceGroup().Print(); for(long i=0;iIsBeingRefined()) return mNbReflUsed; VFN_DEBUG_MESSAGE("ScatteringData::GetNbReflBelowMaxSinThetaOvLambda()",4) this->CalcSinThetaLambda(); if((mNbReflUsed>0)&&(mNbReflUsedmMaxSinThetaOvLambda) &&(mSinThetaLambda(mNbReflUsed-1)<=mMaxSinThetaOvLambda)) return mNbReflUsed; } if((mNbReflUsed==mNbRefl)&&(mSinThetaLambda(mNbRefl-1)<=mMaxSinThetaOvLambda)) return mNbReflUsed; long i; for(i=0;imMaxSinThetaOvLambda) break; if(i!=mNbReflUsed) { mNbReflUsed=i; mClockNbReflUsed.Click(); VFN_DEBUG_MESSAGE("->Changed Max sin(theta)/lambda="<CalcSinThetaLambda(); CrystVector_long sortedSubs; sortedSubs=SortSubs(mSinThetaLambda); CrystVector_long oldH,oldK,oldL,oldMult; oldH=mH; oldK=mK; oldL=mL; oldMult=mMultiplicity; long subs; long shift=0; //get rid of [0,0,0] reflection VFN_DEBUG_MESSAGE("ScatteringData::SortReflectionBySinThetaOverLambda() 1",2) if(0==mSinThetaLambda(sortedSubs(0))) { shift=1; mNbRefl -= 1; mH.resize(mNbRefl); mK.resize(mNbRefl); mL.resize(mNbRefl); mMultiplicity.resize(mNbRefl); } VFN_DEBUG_MESSAGE("ScatteringData::SortReflectionBySinThetaOverLambda() 2",2) for(long i=0;iPrepareHKLarrays(); this->CalcSinThetaLambda(); VFN_DEBUG_MESSAGE("ScatteringData::SortReflectionBySinThetaOverLambda() 4",2) if(0PrepareHKLarrays(); } VFN_DEBUG_EXIT("ScatteringData::SortReflectionBySinThetaOverLambda():"<GetCrystal().GetSpaceGroup().IsReflSystematicAbsent(mH(j),mK(j),mL(j))==false ) subscriptKeptRefl(nbKeptRefl++)=j; } VFN_DEBUG_MESSAGE("ScatteringData::EliminateExtinctReflections():4",5) //Keep only the elected reflections mNbRefl=nbKeptRefl; { CrystVector_long oldH,oldK,oldL; CrystVector_int oldMulti; long subs; oldH=mH; oldK=mK; oldL=mL; oldMulti=mMultiplicity; mMultiplicity.resize(mNbRefl); mH.resize(mNbRefl); mK.resize(mNbRefl); mL.resize(mNbRefl); for(long i=0;iPrepareHKLarrays(); VFN_DEBUG_EXIT("ScatteringData::EliminateExtinctReflections():End",7) return subscriptKeptRefl; } void ScatteringData::CalcSinThetaLambda()const { if(mClockTheta>mClockMaster) return; if( 0 == mpCrystal) throw ObjCrystException("ScatteringData::CalcSinThetaLambda() \ Cannot compute sin(theta)/lambda : there is no crystal affected to this \ ScatteringData object yet."); if( 0 == this->GetNbRefl()) throw ObjCrystException("ScatteringData::CalcSinThetaLambda() \ Cannot compute sin(theta)/lambda : there are no reflections !"); if( (mClockTheta>this->GetRadiation().GetClockWavelength()) &&(mClockTheta>mClockHKL) &&(mClockTheta>mpCrystal->GetClockLatticePar()) &&(mClockTheta>mpCrystal->GetSpaceGroup().GetClockSpaceGroup())) return; VFN_DEBUG_ENTRY("ScatteringData::CalcSinThetaLambda()",3) TAU_PROFILE("ScatteringData::CalcSinThetaLambda()","void (bool)",TAU_DEFAULT); mSinThetaLambda.resize(mNbRefl); const CrystMatrix_REAL bMatrix= this->GetBMatrix(); mX.resize(this->GetNbRefl()); mY.resize(this->GetNbRefl()); mZ.resize(this->GetNbRefl()); for(int i=0;iGetNbRefl();i++) { //:TODO: faster,nicer mX(i)=bMatrix(0,0)*mH(i)+bMatrix(0,1)*mK(i)+bMatrix(0,2)*mL(i); mY(i)=bMatrix(1,0)*mH(i)+bMatrix(1,1)*mK(i)+bMatrix(1,2)*mL(i); mZ(i)=bMatrix(2,0)*mH(i)+bMatrix(2,1)*mK(i)+bMatrix(2,2)*mL(i); } //cout << bMatrix << endl << xyz<GetNbRefl());i++) mSinThetaLambda(i)=sqrt(pow(mX(i),2)+pow(mY(i),2)+pow(mZ(i),2))/2; #if 0 // Direct calculation from a,b,c,alpha,beta,gamma const REAL a=mpCrystal->GetLatticePar(0); const REAL b=mpCrystal->GetLatticePar(1); const REAL c=mpCrystal->GetLatticePar(2); const REAL ca=cos(mpCrystal->GetLatticePar(3)); const REAL sa=sin(mpCrystal->GetLatticePar(3)); const REAL cb=cos(mpCrystal->GetLatticePar(4)); const REAL sb=sin(mpCrystal->GetLatticePar(4)); const REAL cg=cos(mpCrystal->GetLatticePar(5)); const REAL sg=sin(mpCrystal->GetLatticePar(5)); for(int i=0;i< (this->GetNbRefl());i++) { const REAL h=mH(i),k=mK(i),l=mL(i); mSinThetaLambda(i)=0.5*sqrt((h*h/(a*a)*sa*sa+k*k/(b*b)*sb*sb+l*l/(c*c)*sg*sg+2*k*l/(b*c)*(cb*cg-ca)+2*l*h/(c*a)*(cg*ca-cb)+2*h*k/(a*b)*(ca*cb-cg))/(1-ca*ca-cb*cb-cg*cg+2*ca*cb*cg)); } #endif if(this->GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) { if(this->GetRadiation().GetWavelength()(0) > 0) { mTheta.resize(mNbRefl); for(int i=0;i< (this->GetNbRefl());i++) { if( (mSinThetaLambda(i)*this->GetRadiation().GetWavelength()(0))>1) { //:KLUDGE: :TODO: mTheta(i)=M_PI; /* ofstream out("log.txt"); out << "Error when computing Sin(theta) :" << "i="<GetRadiation().GetWavelength()(0)=" << this->GetRadiation().GetWavelength()(0) << " ,H="<GetBMatrix(); const REAL x=bMatrix(0,0)*h+bMatrix(0,1)*k+bMatrix(0,2)*l; const REAL y=bMatrix(1,0)*h+bMatrix(1,1)*k+bMatrix(1,2)*l; const REAL z=bMatrix(2,0)*h+bMatrix(2,1)*k+bMatrix(2,2)*l; return sqrt(x*x+y*y+z*z)/2; } const CrystMatrix_REAL& ScatteringData::GetBMatrix() const { return this->GetCrystal().GetBMatrix(); } void ScatteringData::CalcScattFactor()const { //if(mClockScattFactor>mClockMaster) return; if( (mClockScattFactor>this->GetRadiation().GetClockWavelength()) &&(mClockScattFactor>mClockHKL) &&(mClockScattFactor>mClockTheta) &&(mClockScattFactor>mpCrystal->GetClockLatticePar()) &&(mClockThermicFact>mpCrystal->GetMasterClockScatteringPower())) return; TAU_PROFILE("ScatteringData::CalcScattFactor()","void (bool)",TAU_DEFAULT); VFN_DEBUG_ENTRY("ScatteringData::CalcScattFactor()",4) this->CalcResonantScattFactor(); mvScatteringFactor.clear(); for(int i=mpCrystal->GetScatteringPowerRegistry().GetNb()-1;i>=0;i--) { const ScatteringPower *pScattPow=&(mpCrystal->GetScatteringPowerRegistry().GetObj(i)); mvScatteringFactor[pScattPow]=pScattPow->GetScatteringFactor(*this); //Directly add Fprime mvScatteringFactor[pScattPow]+= this->mvFprime[pScattPow]; VFN_DEBUG_MESSAGE("-> H K L sin(t/l) f0+f'" <(mH,mK,mL,mSinThetaLambda, mvScatteringFactor[pScattPow],10,4,mNbReflUsed),1); } mClockScattFactor.Click(); VFN_DEBUG_EXIT("ScatteringData::CalcScattFactor()",4) } void ScatteringData::CalcTemperatureFactor()const { //if(mClockThermicFact>mClockMaster) return; if( (mClockThermicFact>this->GetRadiation().GetClockWavelength()) &&(mClockThermicFact>mClockHKL) &&(mClockThermicFact>mClockTheta) &&(mClockThermicFact>mpCrystal->GetClockLatticePar()) &&(mClockThermicFact>mpCrystal->GetMasterClockScatteringPower())) return; TAU_PROFILE("ScatteringData::CalcTemperatureFactor()","void (bool)",TAU_DEFAULT); VFN_DEBUG_ENTRY("ScatteringData::CalcTemperatureFactor()",4) mvTemperatureFactor.clear(); for(int i=mpCrystal->GetScatteringPowerRegistry().GetNb()-1;i>=0;i--) { const ScatteringPower *pScattPow=&(mpCrystal->GetScatteringPowerRegistry().GetObj(i)); mvTemperatureFactor[pScattPow]=pScattPow->GetTemperatureFactor(*this); VFN_DEBUG_MESSAGE("-> H K L sin(t/l) DebyeWaller"<(mH,mK,mL,mSinThetaLambda, mvTemperatureFactor[pScattPow],10,4,mNbReflUsed),1); } mClockThermicFact.Click(); VFN_DEBUG_EXIT("ScatteringData::CalcTemperatureFactor()",4) } void ScatteringData::CalcResonantScattFactor()const { if( (mClockScattFactorResonant>mpCrystal->GetMasterClockScatteringPower()) &&(mClockScattFactorResonant>this->GetRadiation().GetClockWavelength())) return; VFN_DEBUG_ENTRY("ScatteringData::CalcResonantScattFactor()",4) TAU_PROFILE("ScatteringData::CalcResonantScattFactor()","void (bool)",TAU_DEFAULT); mvFprime.clear(); mvFsecond.clear(); if(this->GetRadiation().GetWavelength()(0) == 0) { VFN_DEBUG_EXIT("ScatteringData::CalcResonantScattFactor()->Lambda=0. fprime=fsecond=0",4) return; } else { for(int i=mpCrystal->GetScatteringPowerRegistry().GetNb()-1;i>=0;i--) { const ScatteringPower *pScattPow=&(mpCrystal->GetScatteringPowerRegistry().GetObj(i)); mvFprime [pScattPow]=pScattPow->GetResonantScattFactReal(*this)(0); mvFsecond[pScattPow]=pScattPow->GetResonantScattFactImag(*this)(0); } } mClockScattFactorResonant.Click(); VFN_DEBUG_EXIT("ScatteringData::CalcResonantScattFactor()",4) } void ScatteringData::CalcGlobalTemperatureFactor() const { this->GetNbReflBelowMaxSinThetaOvLambda();//update mNbReflUsed, also recalc sin(theta)/lambda if(mClockGlobalTemperatureFact>mClockMaster) return; if( (mClockGlobalBisoGetSinThetaOverLambda().data(); REAL *fact=mGlobalTemperatureFactor.data(); for(long i=0;iGetNbReflBelowMaxSinThetaOvLambda();//check mNbReflUsed, also recalc sin(theta)/lambda if(mClockStructFactor>mClockMaster) return; //:TODO: Anisotropic Thermic factors //TAU_PROFILE_TIMER(timer1,"ScatteringData::CalcStructFactor1:Prepare","", TAU_FIELD); //TAU_PROFILE_TIMER(timer2,"ScatteringData::CalcStructFactor2:GeomStructFact","", TAU_FIELD); //TAU_PROFILE_TIMER(timer3,"ScatteringData::CalcStructFactor3:Scatt.Factors","", TAU_FIELD); //TAU_PROFILE_TIMER(timer4,"ScatteringData::CalcStructFactor4:Finish,DynCorr","", TAU_FIELD); //TAU_PROFILE_START(timer1); const long nbRefl=this->GetNbRefl(); this->CalcSinThetaLambda(); //TAU_PROFILE_STOP(timer1); //TAU_PROFILE_START(timer2); this->CalcGeomStructFactor(); //TAU_PROFILE_STOP(timer2); //TAU_PROFILE_START(timer3); this->CalcScattFactor(); this->CalcResonantScattFactor(); this->CalcTemperatureFactor(); this->CalcGlobalTemperatureFactor(); this->CalcLuzzatiFactor(); this->CalcStructFactVariance(); //TAU_PROFILE_STOP(timer3); //OK, really must recompute SFs? VFN_DEBUG_MESSAGE("ScatteringData::CalcStructFactor():Fhkl Recalc ?"<mClockGlobalTemperatureFact) &&(mClockStructFactor>mClockGeomStructFact) &&(mClockStructFactor>mClockScattFactorResonant) &&(mClockStructFactor>mClockThermicFact) &&(mClockStructFactor>mClockFhklCalcVariance) &&(mClockStructFactor>mClockLuzzatiFactor)) return; VFN_DEBUG_ENTRY("ScatteringData::CalcStructFactor()",3) TAU_PROFILE("ScatteringData::CalcStructFactor()","void ()",TAU_DEFAULT); //TAU_PROFILE_START(timer4); //reset Fcalc mFhklCalcReal.resize(nbRefl); mFhklCalcImag.resize(nbRefl); mFhklCalcReal=0; mFhklCalcImag=0; //Add all contributions for(map::const_iterator pos=mvRealGeomSF.begin(); pos!=mvRealGeomSF.end();++pos) { const ScatteringPower* pScattPow=pos->first; VFN_DEBUG_MESSAGE("ScatteringData::CalcStructFactor():Fhkl Recalc, "<GetName(),2) const REAL * RESTRICT pGeomR=mvRealGeomSF[pScattPow].data(); const REAL * RESTRICT pGeomI=mvImagGeomSF[pScattPow].data(); const REAL * RESTRICT pScatt=mvScatteringFactor[pScattPow].data(); const REAL * RESTRICT pTemp=mvTemperatureFactor[pScattPow].data(); REAL * RESTRICT pReal=mFhklCalcReal.data(); REAL * RESTRICT pImag=mFhklCalcImag.data(); VFN_DEBUG_MESSAGE("->mvRealGeomSF[i] " <mvImagGeomSF[i] " <mvScatteringFactor[i]" <mvTemperatureFactor[i]" <mFhklCalcReal "<mFhklCalcImag "< H K L sin(t/l) Re(F) Im(F) scatt Temp->"<GetName(),1) VFN_DEBUG_MESSAGE(FormatVertVectorHKLFloats(mH,mK,mL,mSinThetaLambda, mvRealGeomSF[pScattPow], mvImagGeomSF[pScattPow], mvScatteringFactor[pScattPow], mvTemperatureFactor[pScattPow],10,4,mNbReflUsed ),1); if(mvLuzzatiFactor[pScattPow].numElements()>0) {// using maximum likelihood const REAL* RESTRICT pLuzzati=mvLuzzatiFactor[pScattPow].data(); if(false==mIgnoreImagScattFact) { const REAL fsecond=mvFsecond[pScattPow]; VFN_DEBUG_MESSAGE("->fsecond= "<0;j--) { VFN_DEBUG_MESSAGE("-->"<0;j--) { *pReal++ += *pGeomR++ * *pTemp * *pScatt * *pLuzzati; *pImag++ += *pGeomI++ * *pTemp++ * *pScatt++ * *pLuzzati++; } } VFN_DEBUG_MESSAGE("ScatteringData::CalcStructFactor():"<fsecond= "<0;j--) { *pReal += (*pGeomR * *pScatt - *pGeomI * fsecond)* *pTemp; *pImag += (*pGeomI * *pScatt + *pGeomR * fsecond)* *pTemp; VFN_DEBUG_MESSAGE("-->"<0;j--) { *pReal++ += *pGeomR++ * *pTemp * *pScatt; *pImag++ += *pGeomI++ * *pTemp++ * *pScatt++; } } VFN_DEBUG_MESSAGE(FormatVertVectorHKLFloats(mH,mK,mL,mSinThetaLambda, mvRealGeomSF[pScattPow], mvImagGeomSF[pScattPow], mvScatteringFactor[pScattPow], mvTemperatureFactor[pScattPow], mFhklCalcReal, mFhklCalcImag,10,4,mNbReflUsed ),2); } } //TAU_PROFILE_STOP(timer4); { //this->CalcGlobalTemperatureFactor(); if(mGlobalTemperatureFactor.numElements()>0) {//else for some reason it's useless REAL *pReal=mFhklCalcReal.data(); REAL *pImag=mFhklCalcImag.data(); const REAL *pTemp=mGlobalTemperatureFactor.data(); for(long j=0;j &vPar) { TAU_PROFILE("ScatteringData::CalcStructFactor_FullDeriv()","void ()",TAU_DEFAULT); this->GetNbReflBelowMaxSinThetaOvLambda(); this->CalcSinThetaLambda(); this->CalcGeomStructFactor_FullDeriv(vPar); this->CalcStructFactor();//called after CalcGeomStructFactor_FullDeriv, so that CalcGeomStructFactor is not redone mFhklCalcReal_FullDeriv.clear();//:TODO: avoid full clear mFhklCalcImag_FullDeriv.clear(); mFhklCalcReal_FullDeriv[0]=mFhklCalcReal; mFhklCalcImag_FullDeriv[0]=mFhklCalcImag; for(std::set::iterator par=vPar.begin();par!=vPar.end();++par) { if(*par==0) continue; if((*par)->GetType()->IsDescendantFromOrSameAs(gpRefParTypeScatt)==false) {//:TODO: allow derivatives from other parameters (ML, temperature factors, etc..) // No derivatives -> empty vectors mFhklCalcReal_FullDeriv[*par].resize(0); mFhklCalcImag_FullDeriv[*par].resize(0); continue; } for(map::const_iterator pos=mvRealGeomSF.begin(); pos!=mvRealGeomSF.end();++pos) { const ScatteringPower* pScattPow=pos->first; if(mvRealGeomSF_FullDeriv[*par][pScattPow].size()==0) { continue;//null derivative, so the array was empty } if(mFhklCalcReal_FullDeriv[*par].size()==0) { mFhklCalcReal_FullDeriv[*par].resize(mNbRefl); mFhklCalcImag_FullDeriv[*par].resize(mNbRefl); mFhklCalcReal_FullDeriv[*par]=0; mFhklCalcImag_FullDeriv[*par]=0; } const REAL * RESTRICT pGeomRd=mvRealGeomSF_FullDeriv[*par][pScattPow].data(); const REAL * RESTRICT pGeomId=mvImagGeomSF_FullDeriv[*par][pScattPow].data(); const REAL * RESTRICT pScatt=mvScatteringFactor[pScattPow].data(); const REAL * RESTRICT pTemp=mvTemperatureFactor[pScattPow].data(); REAL * RESTRICT pReal=mFhklCalcReal_FullDeriv[*par].data(); REAL * RESTRICT pImag=mFhklCalcImag_FullDeriv[*par].data(); if(mvLuzzatiFactor[pScattPow].numElements()>0) {// using maximum likelihood const REAL* RESTRICT pLuzzati=mvLuzzatiFactor[pScattPow].data(); if(false==mIgnoreImagScattFact) { const REAL fsecond=mvFsecond[pScattPow]; for(long j=mNbReflUsed;j>0;j--) { *pReal++ += (*pGeomRd * *pScatt - *pGeomId * fsecond)* *pTemp * *pLuzzati; *pImag++ += (*pGeomId++ * *pScatt++ + *pGeomRd++ * fsecond)* *pTemp++ * *pLuzzati++; } } else { for(long j=mNbReflUsed;j>0;j--) { *pReal++ += *pGeomRd++ * *pTemp * *pScatt * *pLuzzati; *pImag++ += *pGeomId++ * *pTemp++ * *pScatt++ * *pLuzzati++; } } } else { if(false==mIgnoreImagScattFact) { const REAL fsecond=mvFsecond[pScattPow]; for(long j=mNbReflUsed;j>0;j--) { *pReal += (*pGeomRd * *pScatt - *pGeomId * fsecond)* *pTemp; *pImag += (*pGeomId * *pScatt + *pGeomRd * fsecond)* *pTemp; pGeomRd++;pGeomId++;pTemp++;pScatt++;pReal++;pImag++; } } else { for(long j=mNbReflUsed;j>0;j--) { *pReal++ += *pGeomRd++ * *pTemp * *pScatt; *pImag++ += *pGeomId++ * *pTemp++ * *pScatt++; } } } } //TAU_PROFILE_STOP(timer4); { //this->CalcGlobalTemperatureFactor(); if( (mGlobalTemperatureFactor.numElements()>0) &&(mFhklCalcReal_FullDeriv[*par].size()>0) &&(mFhklCalcImag_FullDeriv[*par].size()>0)) {//else for some reason it's useless REAL * RESTRICT pReal=mFhklCalcReal_FullDeriv[*par].data(); REAL * RESTRICT pImag=mFhklCalcImag_FullDeriv[*par].data(); const REAL *pTemp=mGlobalTemperatureFactor.data(); for(long j=0;j v; v.push_back(&mH); v.push_back(&mK); v.push_back(&mL); std::map oldDerivR,oldDerivI; for(std::set::iterator par=vPar.begin();par!=vPar.end();++par) { const REAL step=(*par)->GetDerivStep(); (*par)->Mutate(step); this->CalcStructFactor(); oldDerivR[*par]=mFhklCalcReal; oldDerivI[*par]=mFhklCalcImag; (*par)->Mutate(-2*step); this->CalcStructFactor(); oldDerivR[*par]-=mFhklCalcReal; oldDerivR[*par]/=2*step; oldDerivI[*par]-=mFhklCalcImag; oldDerivI[*par]/=2*step; (*par)->Mutate(step); v.push_back(&(mFhklCalcReal_FullDeriv[*par])); v.push_back(&(oldDerivR[*par])); v.push_back(&(mFhklCalcImag_FullDeriv[*par])); v.push_back(&(oldDerivI[*par])); if(v.size()>14) break; } cout<<"############################ Fhkl Deriv Real, Imag ##############################" <(v,14,4,20) <<"############################ END Fhkl Deriv Real, Imag ##############################"<GetCrystal().GetScatteringComponentList()); if( (mClockGeomStructFact>mpCrystal->GetClockScattCompList()) &&(mClockGeomStructFact>mClockHKL) &&(mClockGeomStructFact>mClockNbReflUsed) &&(mClockGeomStructFact>mpCrystal->GetMasterClockScatteringPower())) return; TAU_PROFILE("ScatteringData::GeomStructFactor()","void (Vx,Vy,Vz,data,M,M,bool)",TAU_DEFAULT); VFN_DEBUG_ENTRY("ScatteringData::GeomStructFactor(Vx,Vy,Vz,...)",3) VFN_DEBUG_MESSAGE("-->Using fast functions:"<Number of translation vectors:" <GetCrystal().GetSpaceGroup().GetNbTranslationVectors()-1,2) VFN_DEBUG_MESSAGE("-->Has an inversion Center:" <GetCrystal().GetSpaceGroup().HasInversionCenter(),2) VFN_DEBUG_MESSAGE("-->Number of symetry operations (w/o transl&inv cent.):"\ <GetCrystal().GetSpaceGroup().GetNbSymmetrics(true,true),2) VFN_DEBUG_MESSAGE("-->Number of Scattering Components :" <GetCrystal().GetScatteringComponentList().GetNbComponent(),2) VFN_DEBUG_MESSAGE("-->Number of reflections:" <GetNbRefl()<<" (actually used:"<Number of GeomStructFactor calculations so far:"<IsCentrosymmetric())return; // (*mfpImagGeomStructFactor)(x,y,z,data.H2Pi(),data.K2Pi(),data.L2Pi(),isf); // return; //} //else { const SpaceGroup *pSpg=&(this->GetCrystal().GetSpaceGroup()); const int nbSymmetrics=pSpg->GetNbSymmetrics(true,true); const int nbTranslationVectors=pSpg->GetNbTranslationVectors(); const long nbComp=pScattCompList->GetNbComponent(); const std::vector *pTransVect=&(pSpg->GetTranslationVectors()); CrystMatrix_REAL allCoords(nbSymmetrics,3); CrystVector_REAL tmpVect(mNbReflUsed); #ifndef HAVE_SSE_MATHFUN const int nbRefl=this->GetNbRefl(); CrystVector_long intVect(nbRefl);//not used if mUseFastLessPreciseFunc==false #endif // which scattering powers are actually used ? map vUsed; // Add existing previously used scattering power to the test; for(map::const_iterator pos=mvRealGeomSF.begin();pos!=mvRealGeomSF.end();++pos) vUsed[pos->first]=false;// this will be changed to true later if they are actually used for(int i=mpCrystal->GetScatteringPowerRegistry().GetNb()-1;i>=0;i--) {// Here we make sure scattering power that only contribute ghost atoms are taken into account const ScatteringPower*pow=&(mpCrystal->GetScatteringPowerRegistry().GetObj(i)); if(pow->GetMaximumLikelihoodNbGhostAtom()>0) vUsed[pow]=true; else vUsed[pow]=false; } for(long i=0;i::const_iterator pos=vUsed.begin();pos!=vUsed.end();++pos) { if(pos->second) {// this will create the entry if it does not already exist mvRealGeomSF[pos->first].resize(mNbReflUsed); mvImagGeomSF[pos->first].resize(mNbReflUsed); mvRealGeomSF[pos->first]=0; mvImagGeomSF[pos->first]=0; } else {// erase entries that are not useful any more (e.g. ScatteringPower that were // used but are not any more). map::iterator poubelle=mvRealGeomSF.find(pos->first); if(poubelle!=mvRealGeomSF.end()) mvRealGeomSF.erase(poubelle); poubelle=mvImagGeomSF.find(pos->first); if(poubelle!=mvImagGeomSF.end()) mvImagGeomSF.erase(poubelle); } } REAL centrMult=1.0; if(true==pSpg->HasInversionCenter()) centrMult=2.0; for(long i=0;iGetAllSymmetrics(x,y,z,true,true); if((true==pSpg->HasInversionCenter()) && (false==pSpg->IsInversionCenterAtOrigin())) { const REAL STBF=2.*pSpg->GetCCTbxSpg().inv_t().den(); for(int j=0;jGetCCTbxSpg().inv_t()[0])/STBF; allCoords(j,1) -= ((REAL)pSpg->GetCCTbxSpg().inv_t()[1])/STBF; allCoords(j,2) -= ((REAL)pSpg->GetCCTbxSpg().inv_t()[2])/STBF; } } for(int j=0;j0;jj--) *tmpInt++ = (*intH++ * intX + *intK++ * intY + *intL++ *intZ) &sLibCrystNbTabulSineMASK; if(false==pSpg->HasInversionCenter()) { tmpInt=intVect.data(); for(int jj=mNbReflUsed;jj>0;jj--) { const REAL *pTmp=&spLibCrystTabulCosineSine[*tmpInt++ <<1]; *rrsf++ += popu * *pTmp++; *iisf++ += popu * *pTmp; } } else { tmpInt=intVect.data(); for(int jj=mNbReflUsed;jj>0;jj--) *rrsf++ += popu * spLibCrystTabulCosine[*tmpInt++]; } } else #endif { const REAL x=allCoords(j,0); const REAL y=allCoords(j,1); const REAL z=allCoords(j,2); const REAL *hh=mH2Pi.data(); const REAL *kk=mK2Pi.data(); const REAL *ll=mL2Pi.data(); #ifdef HAVE_SSE_MATHFUN #if 0 // This not much faster and is incorrect (does not take into account sign of h k l) //cout<<__FILE__<<":"<<__LINE__<<":"<HasInversionCenter()) {// Slow ? REAL *rsf=mvRealGeomSF[pScattPow].data(); REAL *isf=mvImagGeomSF[pScattPow].data(); const long *h=mIntH.data(); const long *k=mIntK.data(); const long *l=mIntL.data(); int jj; const v4sf v4popu=_mm_set1_ps(popu); for(jj=mNbReflUsed;jj>3;jj-=4) { //cout<<__FILE__<<":"<<__LINE__<<":"<0;jj--) { const float ch=pcnxyz0[*h *4]; const float sh=psnxyz0[*h++ *4]; const float ck=pcnxyz0[*k *4+1]; const float sk=psnxyz0[*k++ *4+1]; const float cl=pcnxyz0[*l *4+2]; const float sl=psnxyz0[*l++ *4+2]; *rsf++ += popu*(ch*(ck*cl-sk*sl)-sh*(sk*cl+ck*sl)); *isf++ += popu*(sh*(ck*cl-sk*sl)+ch*(sk*cl+ck*sl)); } } else { REAL *rsf=mvRealGeomSF[pScattPow].data(); const long *h=mIntH.data(); const long *k=mIntK.data(); const long *l=mIntL.data(); int jj; const v4sf v4popu=_mm_set1_ps(popu); for(jj=mNbReflUsed;jj>3;jj-=4) { //cout<<__FILE__<<":"<<__LINE__<<":"<0;jj--) { const float ch=pcnxyz0[*h *4]; const float sh=psnxyz0[*h++ *4]; const float ck=pcnxyz0[*k *4+1]; const float sk=psnxyz0[*k++ *4+1]; const float cl=pcnxyz0[*l *4+2]; const float sl=psnxyz0[*l++ *4+2]; *rsf++ += popu*(ch*(ck*cl-sk*sl)-sh*(sk*cl+ck*sl)); } } #else const v4sf v4x=_mm_load1_ps(&x); const v4sf v4y=_mm_load1_ps(&y); const v4sf v4z=_mm_load1_ps(&z); const v4sf v4popu=_mm_load1_ps(&popu);// Can't multiply directly a vector by a scalar ? if(false==pSpg->HasInversionCenter()) { REAL *rsf=mvRealGeomSF[pScattPow].data(); REAL *isf=mvImagGeomSF[pScattPow].data(); int jj=mNbReflUsed; for(;jj>3;jj-=4) { v4sf v4sin,v4cos; // sincos_ps(_mm_setr_ps(*(hh )*x+ *(kk )*y + *(ll )*z, // *(hh+1)*x+ *(kk+1)*y + *(ll+1)*z, // *(hh+2)*x+ *(kk+2)*y + *(ll+2)*z, // *(hh+3)*x+ *(kk+3)*y + *(ll+3)*z),&v4sin,&v4cos); sincos_ps(_mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_loadu_ps(hh),v4x), _mm_mul_ps(_mm_loadu_ps(kk),v4y) ), _mm_mul_ps(_mm_loadu_ps(ll),v4z) ),&v4sin,&v4cos);// A bit faster _mm_storeu_ps(rsf,_mm_add_ps(_mm_mul_ps(v4cos,v4popu),_mm_loadu_ps(rsf))); _mm_storeu_ps(isf,_mm_add_ps(_mm_mul_ps(v4sin,v4popu),_mm_loadu_ps(isf))); hh+=4;kk+=4;ll+=4;rsf+=4;isf+=4; } for(;jj>0;jj--) { const REAL tmp = *hh++ * x + *kk++ * y + *ll++ *z; *rsf++ += popu * cos(tmp); *isf++ += popu * sin(tmp); } } else { REAL *rsf=mvRealGeomSF[pScattPow].data(); int jj=mNbReflUsed; for(;jj>3;jj-=4) { // const v4sf v4cos=cos_ps(_mm_setr_ps(*(hh )*x+ *(kk )*y + *(ll )*z, // *(hh+1)*x+ *(kk+1)*y + *(ll+1)*z, // *(hh+2)*x+ *(kk+2)*y + *(ll+2)*z, // *(hh+3)*x+ *(kk+3)*y + *(ll+3)*z)); const v4sf v4cos=cos_ps(_mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_loadu_ps(hh),v4x), _mm_mul_ps(_mm_loadu_ps(kk),v4y) ), _mm_mul_ps(_mm_loadu_ps(ll),v4z))); _mm_storeu_ps(rsf,_mm_add_ps(_mm_loadu_ps(rsf),_mm_mul_ps(v4cos,v4popu))); hh+=4;kk+=4;ll+=4;rsf+=4; } for(;jj>0;jj--) { const REAL tmp = *hh++ * x + *kk++ * y + *ll++ *z; *rsf++ += popu * cos(tmp); } } #endif #else REAL *tmp=tmpVect.data(); for(int jj=0;jjHasInversionCenter()) { sf=mvImagGeomSF[pScattPow].data(); tmp=tmpVect.data(); for(int jj=0;jj 1) { tmpVect=1; if( (pSpg->GetSpaceGroupNumber()>= 143) && (pSpg->GetSpaceGroupNumber()<= 167)) {//Special case for trigonal groups R3,... REAL * RESTRICT p1=tmpVect.data(); const REAL * RESTRICT hh=mH2Pi.data(); const REAL * RESTRICT kk=mK2Pi.data(); const REAL * RESTRICT ll=mL2Pi.data(); for(long j=mNbReflUsed;j>0;j--) *p1++ += 2*cos((*hh++ - *kk++ - *ll++)/3.); } else { for(int j=1;j0;j--) *p1++ += cos(*hh++ *x + *kk++ *y + *ll++ *z ); } } for(map::iterator pos=mvRealGeomSF.begin();pos!=mvRealGeomSF.end();++pos) pos->second *= tmpVect; if(false==pSpg->HasInversionCenter()) for(map::iterator pos=mvImagGeomSF.begin();pos!=mvImagGeomSF.end();++pos) pos->second *= tmpVect; } if(true==pSpg->HasInversionCenter()) { // we already multiplied real geom struct factor by 2 if(false==pSpg->IsInversionCenterAtOrigin()) { VFN_DEBUG_MESSAGE("ScatteringData::GeomStructFactor(Vx,Vy,Vz):\ Inversion Center not at the origin...",2) //fix the phase of each reflection when the inversion center is not //at the origin, using : // Re(F) = RSF*cos(2pi(h*Xc+k*Yc+l*Zc)) // Re(F) = RSF*sin(2pi(h*Xc+k*Yc+l*Zc)) //cout << "Glop Glop"<GetCCTbxSpg().inv_t().den(); { const REAL xc=((REAL)pSpg->GetCCTbxSpg().inv_t()[0])/STBF; const REAL yc=((REAL)pSpg->GetCCTbxSpg().inv_t()[1])/STBF; const REAL zc=((REAL)pSpg->GetCCTbxSpg().inv_t()[2])/STBF; #ifdef __LIBCRYST_VECTOR_USE_BLITZ__ tmpVect = mH2Pi() * xc + mK2PI() * yc + mL2PI() * zc; #else { const REAL * RESTRICT hh=mH2Pi.data(); const REAL * RESTRICT kk=mK2Pi.data(); const REAL * RESTRICT ll=mL2Pi.data(); REAL * RESTRICT ttmpVect=tmpVect.data(); for(long ii=mNbReflUsed;ii>0;ii--) *ttmpVect++ = *hh++ * xc + *kk++ * yc + *ll++ * zc; } #endif } CrystVector_REAL cosTmpVect; CrystVector_REAL sinTmpVect; cosTmpVect=cos(tmpVect); sinTmpVect=sin(tmpVect); map::iterator posi=mvImagGeomSF.begin(); map::iterator posr=mvRealGeomSF.begin(); for(;posi!=mvImagGeomSF.end();) { posi->second = posr->second; posi->second *= sinTmpVect; posr->second *= cosTmpVect; posi++;posr++; } } } } //cout << FormatVertVector(*mvRealGeomSF,*mvImagGeomSF)< &vPar) { TAU_PROFILE("ScatteringData::CalcGeomStructFactor_FullDeriv()","void (..)",TAU_DEFAULT); TAU_PROFILE_TIMER(timer1,"ScatteringData::CalcGeomStructFactor_FullDeriv:1-ScattCompList deriv","", TAU_FIELD); TAU_PROFILE_TIMER(timer2,"ScatteringData::CalcGeomStructFactor_FullDeriv:2-Geom SF","", TAU_FIELD); this->CalcGeomStructFactor();//:TODO: avoid calling CalcGeomStructFactor() //:TODO: this->GetCrystal().GetScatteringComponentList_FullDeriv() const ScatteringComponentList *pScattCompList =&(this->GetCrystal().GetScatteringComponentList()); const SpaceGroup *pSpg=&(this->GetCrystal().GetSpaceGroup()); const int nbSymmetrics=pSpg->GetNbSymmetrics(true,true); const int nbTranslationVectors=pSpg->GetNbTranslationVectors(); const unsigned long nbComp=pScattCompList->GetNbComponent(); const std::vector *pTransVect=&(pSpg->GetTranslationVectors()); CrystMatrix_REAL allCoords(nbSymmetrics,3); const bool hasinv=pSpg->HasInversionCenter(); TAU_PROFILE_START(timer1); // Calculate derivatives of the scattering component list vs all parameters std::map vdx,vdy,vdz,vdocc; for(std::set::iterator par=vPar.begin();par!=vPar.end();++par) {// :TODO: get this done in Crystal or Scatterers, and use analytical derivatives if(*par==0) continue; CrystVector_REAL *pdx =&(vdx[*par]); CrystVector_REAL *pdy =&(vdy[*par]); CrystVector_REAL *pdz =&(vdz[*par]); CrystVector_REAL *pdocc=&(vdocc[*par]); pdx->resize(nbComp); pdy->resize(nbComp); pdz->resize(nbComp); pdocc->resize(nbComp); const REAL p0=(*par)->GetValue(); const REAL step=(*par)->GetDerivStep(); (*par)->Mutate(step); pScattCompList=&(this->GetCrystal().GetScatteringComponentList()); REAL *ppdx =pdx->data(); REAL *ppdy =pdy->data(); REAL *ppdz =pdz->data(); REAL *ppdocc=pdocc->data(); for(unsigned long i=0;iMutate(-2*step); pScattCompList=&(this->GetCrystal().GetScatteringComponentList()); ppdx =pdx->data(); ppdy =pdy->data(); ppdz =pdz->data(); ppdocc=pdocc->data(); for(unsigned long i=0;iSetValue(p0); if( (MaxAbs(vdx[*par])==0)&&(MaxAbs(vdy[*par])==0)&&(MaxAbs(vdz[*par])==0)&&(MaxAbs(vdocc[*par])==0)) { pdx->resize(0); pdy->resize(0); pdz->resize(0); pdocc->resize(0); } } TAU_PROFILE_STOP(timer1); TAU_PROFILE_START(timer2); CrystVector_REAL transMult(mNbReflUsed); if(!hasinv) transMult=1; else transMult=2; if(nbTranslationVectors > 1) { if( (pSpg->GetSpaceGroupNumber()>= 143) && (pSpg->GetSpaceGroupNumber()<= 167)) {//Special case for trigonal groups R3,... REAL * RESTRICT p1=transMult.data(); const REAL * RESTRICT hh=mH2Pi.data(); const REAL * RESTRICT kk=mK2Pi.data(); const REAL * RESTRICT ll=mL2Pi.data(); for(long j=mNbReflUsed;j>0;j--) *p1++ += 2*cos((*hh++ - *kk++ - *ll++)/3.); } else { for(int j=1;j0;j--) *p1++ += cos(*hh++ *x + *kk++ *y + *ll++ *z ); } } } pScattCompList=&(this->GetCrystal().GetScatteringComponentList()); mvRealGeomSF_FullDeriv.clear();//:TODO: avoid clearing memory as much as possible mvImagGeomSF_FullDeriv.clear(); CrystVector_REAL c(mNbReflUsed),s(mNbReflUsed); CrystMatrix_REAL allCoordsDeriv(nbSymmetrics,3); for(unsigned long i=0;iGetAllSymmetrics(x0,y0,z0,true,true); for(int j=0;j3;jj-=4) { v4sf v4sin,v4cos; // sincos_ps(_mm_setr_ps(*(hh )*x+ *(kk )*y + *(ll )*z, // *(hh+1)*x+ *(kk+1)*y + *(ll+1)*z, // *(hh+2)*x+ *(kk+2)*y + *(ll+2)*z, // *(hh+3)*x+ *(kk+3)*y + *(ll+3)*z),&v4sin,&v4cos); sincos_ps(_mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_load_ps(hh),v4x), _mm_mul_ps(_mm_load_ps(kk),v4y) ), _mm_mul_ps(_mm_load_ps(ll),v4z) ),&v4sin,&v4cos); _mm_store_ps(pc,v4cos); _mm_store_ps(ps,v4sin); hh+=4;kk+=4;ll+=4;pc+=4;ps+=4; } for(;jj>0;jj--) { const REAL tmp = *hh++ * x + *kk++ * y + *ll++ *z; *pc++ =cos(tmp); *ps++ =sin(tmp); } #else for(int jj=0;jj::iterator par=vPar.begin();par!=vPar.end();++par) { if((*par)==0) continue; if(vdx[*par].size()==0) continue; REAL dx =vdx[*par](i); REAL dy =vdy[*par](i); REAL dz =vdz[*par](i); const REAL dpopu=vdocc[*par](i); if((abs(dx)+abs(dy)+abs(dz)+abs(dpopu))==0) continue; if(mvRealGeomSF_FullDeriv[*par][pScattPow].size()==0) { mvRealGeomSF_FullDeriv[*par][pScattPow].resize(mNbRefl); mvRealGeomSF_FullDeriv[*par][pScattPow]=0; } if(mvImagGeomSF_FullDeriv[*par][pScattPow].size()==0) { mvImagGeomSF_FullDeriv[*par][pScattPow].resize(mNbRefl); mvImagGeomSF_FullDeriv[*par][pScattPow]=0; } pSpg->GetSymmetric(j,dx,dy,dz,true,true,true); const REAL *hh=mH2Pi.data(); const REAL *kk=mK2Pi.data(); const REAL *ll=mL2Pi.data(); const REAL *pmult=transMult.data(); REAL *rsf=mvRealGeomSF_FullDeriv[*par][pScattPow].data(); REAL *isf=mvImagGeomSF_FullDeriv[*par][pScattPow].data(); VFN_DEBUG_MESSAGE("ScatteringData::CalcGeomStructFactor_FullDeriv()comp="<GetName()<<":"<HasInversionCenter()) { if(false==pSpg->IsInversionCenterAtOrigin()) { //:TODO: if there is an inversion center not in (0,0,0), apply a constant phase } } TAU_PROFILE_STOP(timer2); #if 0 std::vector v; v.push_back(&mH); v.push_back(&mK); v.push_back(&mL); std::map< std::pair,CrystVector_REAL> mr,mi; mUseFastLessPreciseFunc=false; for(std::set::iterator par=vPar.begin();par!=vPar.end();++par) { for(std::map::iterator pos=mvRealGeomSF.begin();pos!=mvRealGeomSF.end();++pos) { const ScatteringPower *pScattPow=pos->first; cout<<(*par)->GetName()<<","<GetName(); if(mvRealGeomSF_FullDeriv[*par][pScattPow].size()==0) { cout<<" => skipped (deriv==0)"<GetDerivStep(); (*par)->Mutate(step); this->CalcGeomStructFactor(); mr[make_pair(pScattPow,*par)]=mvRealGeomSF[pScattPow]; mi[make_pair(pScattPow,*par)]=mvImagGeomSF[pScattPow]; (*par)->Mutate(-2*step); this->CalcGeomStructFactor(); mr[make_pair(pScattPow,*par)]-=mvRealGeomSF[pScattPow]; mr[make_pair(pScattPow,*par)]/=step*2; mi[make_pair(pScattPow,*par)]-=mvImagGeomSF[pScattPow]; mi[make_pair(pScattPow,*par)]/=step*2; (*par)->Mutate(step); v.push_back(&(mvRealGeomSF_FullDeriv[*par][pScattPow])); v.push_back(&(mr[make_pair(pScattPow,*par)])); if(!hasinv) { v.push_back(&(mvImagGeomSF_FullDeriv[*par][pScattPow])); v.push_back(&(mi[make_pair(pScattPow,*par)])); } if(v.size()>20)break; } if(v.size()>20)break; } cout<<"############################ Geom Fhkl Deriv Real, Imag ##############################" <(v,11,4,20) <<"############################ END GeomF hkl Deriv Real, Imag ##############################"<(vdx[*(vPar.begin())],vdy[*(vPar.begin())],vdz[*(vPar.begin())],vdocc[*(vPar.begin())],8,4,20)<::const_iterator pos=mvRealGeomSF.begin();pos!=mvRealGeomSF.end();++pos) { if(pos->first->GetMaximumLikelihoodPositionError()!=0) { useLuzzati=true; break; } } if(!useLuzzati) { mvLuzzatiFactor.clear(); VFN_DEBUG_EXIT("ScatteringData::CalcLuzzatiFactor(): not needed, no positionnal errors",3) return; } bool recalc=false; if( (mClockTheta >mClockLuzzatiFactor) ||(mClockGeomStructFact>mClockLuzzatiFactor)//checks if occupancies changed ||(mClockNbReflUsed>mClockLuzzatiFactor)) { //if(mClockTheta >mClockLuzzatiFactor)cout<<"1"<mClockLuzzatiFactor)cout<<"2"<mClockLuzzatiFactor)cout<<"3"<GetScatteringPowerRegistry().GetNb()-1;i>=0;i--) { if(mpCrystal->GetScatteringPowerRegistry().GetObj(i) .GetMaximumLikelihoodParClock()>mClockLuzzatiFactor) { recalc=true; break; } } } if(false==recalc) { VFN_DEBUG_EXIT("ScatteringData::CalcLuzzatiFactor(): no recalc needed",3) return; } TAU_PROFILE("ScatteringData::CalcLuzzatiFactor()","void ()",TAU_DEFAULT); for(int i=mpCrystal->GetScatteringPowerRegistry().GetNb()-1;i>=0;i--) { const ScatteringPower* pScattPow=&(mpCrystal->GetScatteringPowerRegistry().GetObj(i)); if(0 == pScattPow->GetMaximumLikelihoodPositionError()) { mvLuzzatiFactor[pScattPow].resize(0); } else { mvLuzzatiFactor[pScattPow].resize(mNbRefl); const REAL b=-(8*M_PI*M_PI)* pScattPow->GetMaximumLikelihoodPositionError() * pScattPow->GetMaximumLikelihoodPositionError(); const REAL *stol=this->GetSinThetaOverLambda().data(); REAL *fact=mvLuzzatiFactor[pScattPow].data(); for(long j=0;jGetName()<(mH,mK,mL,mSinThetaLambda, mvRealGeomSF[pScattPow],mvImagGeomSF[pScattPow], mvScatteringFactor[pScattPow],mvLuzzatiFactor[pScattPow],10,4,mNbReflUsed ),2); } } mClockLuzzatiFactor.Click(); VFN_DEBUG_EXIT("ScatteringData::CalcLuzzatiFactor(): no recalc needed",3) } void ScatteringData::CalcStructFactVariance()const { // this is called by CalcStructFactor(), after the calculation of the structure factors, // and the recomputation of Luzzati factors has already been asked // So we only recompute if these clocks have changed. // // The Crystal::mMasterClockScatteringPower will tell the last time the number of ghost // atoms has been changed in any of the scattpow. if( (mClockFhklCalcVariance>mClockLuzzatiFactor) &&(mClockFhklCalcVariance>mClockStructFactor) &&(mClockFhklCalcVariance>mpCrystal->GetMasterClockScatteringPower())) return; bool hasGhostAtoms=false; for(map::const_iterator pos=mvRealGeomSF.begin();pos!=mvRealGeomSF.end();++pos) { if(pos->first->GetMaximumLikelihoodNbGhostAtom()!=0) { hasGhostAtoms=true; break; } } if( (0==mvLuzzatiFactor.size())&&(!hasGhostAtoms)) { mFhklCalcVariance.resize(0); return; } VFN_DEBUG_ENTRY("ScatteringData::CalcStructFactVariance()",3) TAU_PROFILE("ScatteringData::CalcStructFactVariance()","void ()",TAU_DEFAULT); bool needVar=false; map vComp; { const ScatteringComponentList *pList= & (this->GetCrystal().GetScatteringComponentList()); const long nbComp=pList->GetNbComponent(); const ScatteringComponent *pComp; for(long i=0;impScattPow]=0; } for(long i=0;impScattPow]+= pComp->mOccupancy * pComp->mDynPopCorr; } for(map::iterator pos=vComp.begin();pos!=vComp.end();++pos) pos->second *= this->GetCrystal().GetSpaceGroup().GetNbSymmetrics(); } // Ghost atoms map vGhost; { const long nbScattPow=mpCrystal->GetScatteringPowerRegistry().GetNb(); const long mult=this->GetCrystal().GetSpaceGroup().GetNbSymmetrics(); for(int i=0;iGetScatteringPowerRegistry().GetObj(i)); const REAL nb=pow->GetMaximumLikelihoodNbGhostAtom(); vGhost[pow]=nb*mult; } } if(mFhklCalcVariance.numElements() == mNbRefl) { REAL *pVar=mFhklCalcVariance.data(); for(long j=0;jGetScatteringPowerRegistry().GetNb()-1;i>=0;i--) { const ScatteringPower* pScattPow=&(mpCrystal->GetScatteringPowerRegistry().GetObj(i)); if( (mvLuzzatiFactor[pScattPow].numElements()==0) &&(vGhost[pScattPow]==0)) continue; needVar=true; if(mFhklCalcVariance.numElements() != mNbRefl) { mFhklCalcVariance.resize(mNbRefl); REAL *pVar=mFhklCalcVariance.data(); for(long j=0;j #include //#include //#include //#include //#include //#include namespace ObjCryst { #ifndef HAVE_SSE_MATHFUN //initialize tabulated values of cosine void InitLibCrystTabulCosine(); void DeleteLibCrystTabulCosine(); void InitLibCrystTabulExp(); void DeleteLibCrystTabulExp(); #endif /// Generic type for scattering data extern const RefParType *gpRefParTypeScattData; /// Type for scattering data scale factors extern const RefParType *gpRefParTypeScattDataScale; /// Type for reflection profile extern const RefParType *gpRefParTypeScattDataProfile; /// Type for reflection profiles type (e.g. gaussian/lorentzian mix) extern const RefParType *gpRefParTypeScattDataProfileType; /// Type for reflection profile width extern const RefParType *gpRefParTypeScattDataProfileWidth; /// Type for reflection profile asymmetry extern const RefParType *gpRefParTypeScattDataProfileAsym; /// Generic type for scattering data correction parameter extern const RefParType *gpRefParTypeScattDataCorr; /// Generic type for correction to calculated intensities extern const RefParType *gpRefParTypeScattDataCorrInt; /// Parameter type for preferred orientation direction extern const RefParType *gpRefParTypeScattDataCorrIntPO_Direction; /// Parameter type for fraction of preferred orientation extern const RefParType *gpRefParTypeScattDataCorrIntPO_Fraction; /// Parameter type for the amplitude of preferred orientation extern const RefParType *gpRefParTypeScattDataCorrIntPO_Amplitude; /// Parameter type for the ellipsoid coefficient extern const RefParType *gpRefParTypeScattDataCorrInt_Ellipsoid; /// Parameter type for absorption correction extern const RefParType *gpRefParTypeScattDataCorrIntAbsorp; /// Parameter type for polarization correction extern const RefParType *gpRefParTypeScattDataCorrIntPolar; /// Parameter type for extinction correction extern const RefParType *gpRefParTypeScattDataCorrIntExtinc; /// Parameter type for correction to peak positions extern const RefParType *gpRefParTypeScattDataCorrPos; /// Parameter type for background intensity extern const RefParType *gpRefParTypeScattDataBackground; extern const RefParType *gpRefParTypeRadiation; extern const RefParType *gpRefParTypeRadiationWavelength; class NiftyStaticGlobalObjectsInitializer_ScatteringData { public: NiftyStaticGlobalObjectsInitializer_ScatteringData() { if (mCount++ == 0) { #ifndef HAVE_SSE_MATHFUN InitLibCrystTabulCosine(); InitLibCrystTabulExp(); #endif gpRefParTypeScattData= new RefParType(gpRefParTypeObjCryst,"Scattering Data"); gpRefParTypeScattDataScale= new RefParType(gpRefParTypeObjCryst,"Scale Factor"); gpRefParTypeScattDataProfile= new RefParType(gpRefParTypeScattData,"Profile"); gpRefParTypeScattDataProfileType= new RefParType(gpRefParTypeScattDataProfile,"Type"); gpRefParTypeScattDataProfileWidth= new RefParType(gpRefParTypeScattDataProfile,"Width"); gpRefParTypeScattDataProfileAsym= new RefParType(gpRefParTypeScattDataProfile,"Asymmetry"); gpRefParTypeScattDataCorr= new RefParType(gpRefParTypeScattData,"Correction"); gpRefParTypeScattDataCorrInt= new RefParType(gpRefParTypeScattDataCorr,"Intensities"); gpRefParTypeScattDataCorrIntPO_Direction= new RefParType(gpRefParTypeScattDataCorrIntPO_Direction,"Preferred orientation direction"); gpRefParTypeScattDataCorrIntPO_Fraction= new RefParType(gpRefParTypeScattDataCorrIntPO_Fraction,"Preferred orientation fraction"); gpRefParTypeScattDataCorrIntPO_Amplitude= new RefParType(gpRefParTypeScattDataCorrIntPO_Amplitude,"Preferred orientation amplitude"); gpRefParTypeScattDataCorrInt_Ellipsoid= new RefParType(gpRefParTypeScattDataCorrInt_Ellipsoid,"Preferred orientation ellipsoid"); gpRefParTypeScattDataCorrIntAbsorp= new RefParType(gpRefParTypeScattDataCorrInt,"Absorption"); gpRefParTypeScattDataCorrIntPolar= new RefParType(gpRefParTypeScattDataCorrInt,"Polarization"); gpRefParTypeScattDataCorrIntExtinc= new RefParType(gpRefParTypeScattDataCorrInt,"Extinction"); gpRefParTypeScattDataCorrPos= new RefParType(gpRefParTypeScattDataCorr,"Reflections Positions"); gpRefParTypeScattDataBackground= new RefParType(gpRefParTypeScattData,"Background"); gpRefParTypeRadiation= new RefParType(gpRefParTypeObjCryst,"Radiation"); gpRefParTypeRadiationWavelength= new RefParType(gpRefParTypeRadiation,"Wavelength"); } } ~NiftyStaticGlobalObjectsInitializer_ScatteringData() { if (--mCount == 0) { #ifndef HAVE_SSE_MATHFUN DeleteLibCrystTabulCosine(); DeleteLibCrystTabulExp(); #endif delete gpRefParTypeScattData; delete gpRefParTypeScattDataScale; delete gpRefParTypeScattDataProfile; delete gpRefParTypeScattDataProfileType; delete gpRefParTypeScattDataProfileWidth; delete gpRefParTypeScattDataProfileAsym; delete gpRefParTypeScattDataCorr; delete gpRefParTypeScattDataCorrInt; delete gpRefParTypeScattDataCorrIntAbsorp; delete gpRefParTypeScattDataCorrIntPolar; delete gpRefParTypeScattDataCorrIntExtinc; delete gpRefParTypeScattDataCorrPos; delete gpRefParTypeScattDataBackground; delete gpRefParTypeRadiation; delete gpRefParTypeRadiationWavelength; gpRefParTypeScattData=0; gpRefParTypeScattDataScale=0; gpRefParTypeScattDataProfile=0; gpRefParTypeScattDataProfileType=0; gpRefParTypeScattDataProfileWidth=0; gpRefParTypeScattDataProfileAsym=0; gpRefParTypeScattDataCorr=0; gpRefParTypeScattDataCorrInt=0; gpRefParTypeScattDataCorrIntAbsorp=0; gpRefParTypeScattDataCorrIntPolar=0; gpRefParTypeScattDataCorrIntExtinc=0; gpRefParTypeScattDataCorrPos=0; gpRefParTypeScattDataBackground=0; gpRefParTypeRadiation=0; gpRefParTypeRadiationWavelength=0; } } private: static long mCount; }; static NiftyStaticGlobalObjectsInitializer_ScatteringData NiftyStaticGlobalObjectsInitializer_ScatteringData_counter; //###################################################################### /** \brief Class to define the radiation (type, monochromaticity, wavelength(s)) of an experiment * * This can be developped for more complex experiments, hence the \e vector of * wavelengths (so far it is not possible to use several wavelengths, though). * * X-Rays and Neutrons are available. Electrons are not available yet in * ScatteringData classes. * * \todo also add here information about the polarization of the beam. */ //###################################################################### class Radiation: public RefinableObj { public: /// Default constructor Radiation(); /** \ brief Constructor * * \param rad the RadiationType used (X-Rays, neutrons) * \param wavelength the wavelength (in Angstroems) of the monochromatic * radiation. */ Radiation(const RadiationType rad,const REAL wavelength); /** \ brief Constructor for X-Ray tube radiation * *\param XRayTubeElementName : name of the anticathode element name. Known *ones are Cr, Fe, Cu, Mo, Ag. *\param alpha2Alpha2ratio: Kalpha2/Kalpha1 ratio (0.5 by default) * *the average wavelength is calculated *using the alpha2/alpha1 weight. All structure factors computation are made *using the average wavelength, and for powder diffraction, profiles are output *at the alpha1 and alpha2 ratio for the calculated pattern. * *NOTE : if the name of the wavelength is generic (eg"Cu"), *then the program considers that *there are both Alpha1 and Alpha2, and thus automatically changes the WavelengthType *to WAVELENGTH_ALPHA12. If instead either alpha1 or alpha2 (eg "CuA1") is asked for, *the WavelengthType is set to WAVELENGTH_MONOCHROMATIC. In both cases, * the radiation type is set to X-Ray. */ Radiation(const string &XRayTubeElementName,const REAL alpha2Alpha2ratio=0.5); /// Copy constructor Radiation(const Radiation&); ~Radiation(); virtual const string& GetClassName() const; void operator=(const Radiation&); /// Get the radiation type (X-Rays, Neutron) RadiationType GetRadiationType()const; /// Set the radiation type (X-Rays, Neutron) void SetRadiationType(const RadiationType); /// Set the Wavelength type (monochromatic, Alpha1+Alpha2, Time Of Flight...) void SetWavelengthType(const WavelengthType &type); /// Get the Wavelength type (monochromatic, Alpha1+Alpha2, Time Of Flight...) WavelengthType GetWavelengthType()const; /// Get the wavelength(s) in Angstroems. Currently only /// monochromatic is used, so the vector should only return /// only one wavelength. const CrystVector_REAL& GetWavelength()const; /// Set the (monochromatic) wavelength of the beam. void SetWavelength(const REAL ); /** \ brief Set X-Ray tube radiation. * *\param XRayTubeElementName : name of the anticathode element name. Known *ones are Cr, Fe, Cu, Mo, Ag. *\param alpha2Alpha2ratio: Kalpha2/Kalpha1 ratio (0.5 by default) * *the average wavelength is calculated *using the alpha2/alpha1 weight. All structure factors computation are made *using the average wavelength, and for powder diffraction, profiles are output *at the alpha1 and alpha2 ratio for the calculated pattern. * *NOTE : if the name of the wavelength is generic (eg"Cu"), *then the program considers that *there are both Alpha1 and Alpha2, and thus automatically changes the WavelengthType *to WAVELENGTH_ALPHA12. If instead either alpha1 or alpha2 (eg "CuA1") is asked for, *the WavelengthType is set to WAVELENGTH_MONOCHROMATIC. In both cases, * the radiation type is set to X-Ray. */ void SetWavelength(const string &XRayTubeElementName,const REAL alpha2Alpha2ratio=0.5); /// Get the wavelength difference for Alpha1 and Alpha2 REAL GetXRayTubeDeltaLambda()const; /// Get the Kalpha2/Kalpha1 ratio REAL GetXRayTubeAlpha2Alpha1Ratio()const; /// Last time the wavelength has been changed const RefinableObjClock& GetClockWavelength()const ; /// Last time the nature (X-Rays/Neutron, number of wavelengths)radiation has been changed const RefinableObjClock& GetClockRadiation()const ; virtual void XMLOutput(ostream &os,int indent=0)const; virtual void XMLInput(istream &is,const XMLCrystTag &tag); //virtual void XMLInputOld(istream &is,const IOCrystTag &tag); /// Print to screen/console the charcteristics of the radiation. void Print()const; REAL GetLinearPolarRate()const; void SetLinearPolarRate(const REAL f); private: void InitOptions(); /// Neutron ? X-Ray ? (Electron: unimplemented) RefObjOpt mRadiationType; /// monochromatic ? Alpha1 & Alpha2 ? Multi-Wavelength ? RefObjOpt mWavelengthType; ///Wavelength of the Experiment, in Angstroems. CrystVector_REAL mWavelength; ///Name of the X-Ray tube used, if relevant. ie "Cu", "Fe",etc... /// "CuA1" for Cu-alpha1, etc... string mXRayTubeName; ///Absolute difference between alpha1 and alpha2, in angstroems REAL mXRayTubeDeltaLambda; ///Ratio alpha2/alpha1 (should be 0.5) REAL mXRayTubeAlpha2Alpha1Ratio; //Clocks RefinableObjClock mClockWavelength; RefinableObjClock mClockRadiation; /// Linear Polarization Rate (default:0, X-Ray tube unmonochromatized) REAL mLinearPolarRate; #ifdef __WX__CRYST__ public: virtual WXCrystObjBasic* WXCreate(wxWindow*); friend class WXRadiation; #endif }; //###################################################################### /** \brief Class to compute structure factors for a set of reflections and a Crystal. * * This class only computes structure factor, but no intensity. i.e. it does * not include any correction such as absorption, Lorentz or Polarization. * * Does this really need to be a RefinableObj ? * \todo Optimize computation for Bijvoet/Friedel mates. To do this, generate * an internal list of 'true independent reflections', with two entries for each, * for both mates, and make the 'real' reflections only a reference to these reflections. * * \todo a \b lot of cleaning is necessary in the computing of structure * factors, for (1) the 'preparation' part (deciding what needs to be recomputed) * and (2) to allow anisotropic temperature factors (or other anisotropic parts) */ //###################################################################### class ScatteringData: virtual public RefinableObj { public: ScatteringData(); ScatteringData(const ScatteringData &old); ~ScatteringData(); /// So-called virtual copy constructor virtual ScatteringData* CreateCopy()const=0; /** \brief input H,K,L * * \param h,k,l: REAL arrays (vectors with NbRefl elements -same size), *with the h, k and l coordinates of all reflections. */ virtual void SetHKL( const CrystVector_REAL &h, const CrystVector_REAL &k, const CrystVector_REAL &l); /** \brief Generate a list of h,k,l to describe a full reciprocal space, * up to a given maximum theta value * * \param maxTheta:maximum theta value * \param unique: if set to true, only unique reflections will be listed. * Bijvoet (Friedel) pairs * are NOT merged, for 'anomalous' reasons, unless you have chosen to ignore the * imaginary part of the scattering factor. * * The multiplicity is always stored in ScatteringData::mMultiplicity. * * \warning The ScatteringData object must already have been assigned * a crystal object using SetCrystal(), and the experimental wavelength * must also have been set before calling this function. */ virtual void GenHKLFullSpace2(const REAL maxsithsl, const bool unique=false); /** \brief Generate a list of h,k,l to describe a full reciprocal space, * up to a given maximum theta value * * \param maxsithsl:maximum sin(theta)/lambda=1/2d value * \param unique: if set to true, only unique reflections will be listed. * Bijvoet (Friedel) pairs * are NOT merged, for 'anomalous' reasons, unless you have chosen to ignore the * imaginary part of the scattering factor. * * The multiplicity is always stored in ScatteringData::mMultiplicity. * * \warning The ScatteringData object must already have been assigned * a crystal object using SetCrystal(), and the experimental wavelength * must also have been set before calling this function. * * \deprecated Rather use PowderPattern::GenHKLFullSpace2, * with a maximum sin(theta)/lambda value, which also works for dispersive experiments. */ virtual void GenHKLFullSpace(const REAL maxTheta, const bool unique=false); ///Neutron or x-ray experiment ? Wavelength ? RadiationType GetRadiationType()const; /// Get the radiation object for this data virtual const Radiation& GetRadiation()const=0; /**Set the crystal for this experiment * */ virtual void SetCrystal(Crystal &crystal); /// Const access to the data's crystal const Crystal& GetCrystal()const ; /// Access to the data's crystal Crystal& GetCrystal() ; /// Has a Crystal structure associated yet ? bool HasCrystal()const; ///Return the number of reflections in this experiment. long GetNbRefl() const; ///Return the 1D array of H coordinates for all reflections const CrystVector_REAL& GetH() const; ///Return the 1D array of K coordinates for all reflections const CrystVector_REAL& GetK() const; ///Return the 1D array of L coordinates for all reflections const CrystVector_REAL& GetL() const; /// Return the 1D array of H coordinates for all reflections, multiplied by 2*pi /// \internal Should be private const CrystVector_REAL& GetH2Pi() const; ///Return the 1D array of K coordinates for all reflections, multiplied by 2*pi /// \internal Should be private const CrystVector_REAL& GetK2Pi() const; ///Return the 1D array of L coordinates for all reflections, multiplied by 2*pi /// \internal Should be private const CrystVector_REAL& GetL2Pi() const; ///Return the 1D array of orthonormal x coordinates for all reflections (recipr. space) const CrystVector_REAL& GetReflX() const; ///Return the 1D array of orthonormal y coordinates for all reflections (recipr. space) const CrystVector_REAL& GetReflY() const; ///Return the 1D array of orthonormal z coordinates for all reflections (recipr. space) const CrystVector_REAL& GetReflZ() const; /// Return an array with \f$ \frac{sin(\theta)}{\lambda} = \frac{1}{2d_{hkl}}\f$ ///for all reflections const CrystVector_REAL& GetSinThetaOverLambda()const; /// Return an array with theta values for all reflections const CrystVector_REAL& GetTheta()const; /// Clock the last time the sin(theta)/lambda and theta arrays were re-computed const RefinableObjClock& GetClockTheta()const; /// Returns the Array of calculated |F(hkl)|^2 for all reflections. const CrystVector_REAL& GetFhklCalcSq() const; std::map & GetFhklCalcSq_FullDeriv(std::set &vPar); /// Access to real part of F(hkl)calc const CrystVector_REAL& GetFhklCalcReal() const; /// Access to imaginary part of F(hkl)calc const CrystVector_REAL& GetFhklCalcImag() const; /// Returns the vector of observed |F(hkl)|^2 for all reflections. const CrystVector_REAL& GetFhklObsSq() const; /// Set the vector of observed |F(hkl)|^2 for all reflections. The supplied vector must have the same size /// as the mH, mK, mL vectors. void SetFhklObsSq(const CrystVector_REAL &obs); /// Scattering factors for each ScatteringPower, as vectors with NbRefl elements const map &GetScatteringFactor() const; ///wavelength of the experiment (in Angstroems) CrystVector_REAL GetWavelength()const; /// If true, then the imaginary part of the scattering factor is ignored during /// Structure factor computation. (default value=false) /// /// \todo this should become useless once we take fully advantage of coupled /// computation of Structure Factors for Fridel/Bijvoet mates using an internal /// list of 'fully unique' reflections. Then only one of the mates need to be computed.. void SetIsIgnoringImagScattFact(const bool b); /// If true, then the imaginary part of the scattering factor is ignored during /// Structure factor computation. bool IsIgnoringImagScattFact() const; // Set an option so that only low-amgle reflections (theta < angle) // are used. See DiffractionData::mUseOnlyLowAngleData //virtual void SetUseOnlyLowAngleData(const bool useOnlyLowAngle,const REAL angle)=0; /** \brief Print H, K, L F^2 Re(F) Im(F) theta sin(theta)/lambda for all reflections * */ virtual void PrintFhklCalc(ostream &os=cout)const; /** \brief Print H, K, L sin(theta)/lambda theta F^2 Re(F) Im(F) [Re(F) Im(F)]_i, * where [Re(F) Im(F)]_i are the real and imaginary contribution of the different * scattering powers to the overall structure factor */ virtual void PrintFhklCalcDetail(ostream &os=cout)const; virtual void BeginOptimization(const bool allowApproximations=false, const bool enableRestraints=false); virtual void EndOptimization(); virtual void SetApproximationFlag(const bool allow); /// Set the maximum value for sin(theta)/lambda. All data (reflections,..) still /// exist but are ignored for all calculations. virtual void SetMaxSinThetaOvLambda(const REAL max); /// Get the maximum value for sin(theta)/lambda. REAL GetMaxSinThetaOvLambda()const; /// Recalc, and get the number of reflections which should be actually used, /// due to the maximuml sin(theta)/lambda value set. virtual long GetNbReflBelowMaxSinThetaOvLambda()const; /// Clock the last time the number of reflections used was changed const RefinableObjClock& GetClockNbReflBelowMaxSinThetaOvLambda()const; protected: /// \internal This function is called after H,K and L arrays have /// been initialized or modified. virtual void PrepareHKLarrays() ; /// \internal sort reflections by theta values (also get rid of [0,0,0] if present) /// If maxSTOL >0, then only reflections where sin(theta)/lambda &vPar); /** \brief Compute the 'Geometrical Structure Factor' for each ScatteringPower * of the Crystal * */ void CalcGeomStructFactor() const; void CalcGeomStructFactor_FullDeriv(std::set &vPar); /** Calculate the Luzzati factor associated to each ScatteringPower and * each reflection, for maximum likelihood optimization. * */ void CalcLuzzatiFactor()const; /** Calculate the variance associated to the calculated structure factor * */ void CalcStructFactVariance()const; /// Number of H,K,L reflections long mNbRefl; /// H,K,L coordinates CrystVector_REAL mH, mK, mL ; /// H,K,L integer coordinates mutable CrystVector_long mIntH, mIntK, mIntL ; /// H,K,L coordinates, multiplied by 2PI mutable CrystVector_REAL mH2Pi, mK2Pi, mL2Pi ; /// reflection coordinates in an orthonormal base mutable CrystVector_REAL mX, mY, mZ ; ///Multiplicity for each reflections (mostly for powder diffraction) CrystVector_int mMultiplicity ; /** Expected intensity factor for all reflections. * * See SpaceGroup::GetExpectedIntensityFactor() */ CrystVector_int mExpectedIntensityFactor; /// real &imaginary parts of F(HKL)calc mutable CrystVector_REAL mFhklCalcReal, mFhklCalcImag ; mutable std::map mFhklCalcReal_FullDeriv, mFhklCalcImag_FullDeriv ; /// F(HKL)^2 calc for each reflection mutable CrystVector_REAL mFhklCalcSq ; mutable std::map mFhklCalcSq_FullDeriv; /** Pointer to the crystal corresponding to this experiment. * * This gives an access to the UB matrix for the crystal, * as well as to the list of Scatterer. */ Crystal *mpCrystal; /** Global Biso, affecting the overall structure factor for all * reflections (but not the structure factors of individual atoms or * type of atomes). * */ REAL mGlobalBiso; /// Global Biso factor mutable CrystVector_REAL mGlobalTemperatureFactor; ///Use faster, but less precise, approximations for functions? (integer ///approximations to compute sin and cos in structure factors, and also ///to compute interatomic distances). /// This is activated by global optimization algortithms, only during the /// optimization. bool mUseFastLessPreciseFunc; //The Following members are only kept to avoid useless re-computation //during global refinements. They are used \b only by CalcStructFactor() /// \f$ \frac{sin(\theta)}{\lambda} = \frac{1}{2d_{hkl}}\f$ ///for the crystal and the reflections in ReciprSpace mutable CrystVector_REAL mSinThetaLambda; /// theta for the crystal and the HKL in ReciprSpace (in radians) mutable CrystVector_REAL mTheta; /// Anomalous X-Ray scattering term f' and f" are stored here for each ScatteringPower /// We store here only a value. For multi-wavelength support this should be changed /// to a vector... or to a matrix to take into account anisotropy of anomalous /// scattering... mutable map mvFprime,mvFsecond; /// Thermic factors for each ScatteringPower, as vectors with NbRefl elements mutable map mvTemperatureFactor; /// Scattering factors for each ScatteringPower, as vectors with NbRefl elements mutable map mvScatteringFactor; /// Geometrical Structure factor for each ScatteringPower, as vectors with NbRefl elements mutable map mvRealGeomSF,mvImagGeomSF; mutable map > mvRealGeomSF_FullDeriv,mvImagGeomSF_FullDeriv; //Public Clocks /// Clock for the list of hkl RefinableObjClock mClockHKL; /// Clock for the structure factor mutable RefinableObjClock mClockStructFactor; /// Clock for the square modulus of the structure factor mutable RefinableObjClock mClockStructFactorSq; //Internal Clocks /// Clock the last time theta was computed mutable RefinableObjClock mClockTheta; /// Clock the last time scattering factors were computed mutable RefinableObjClock mClockScattFactor; /// Clock the last time resonant scattering factors were computed mutable RefinableObjClock mClockScattFactorResonant; /// Clock the last time the geometrical structure factors were computed mutable RefinableObjClock mClockGeomStructFact; /// Clock the last time temperature factors were computed mutable RefinableObjClock mClockThermicFact; /// last time the global Biso factor was modified RefinableObjClock mClockGlobalBiso; /// last time the global temperature factor was computed mutable RefinableObjClock mClockGlobalTemperatureFact; /** \brief Ignore imaginary part of scattering factor. * * This can be used either to speed up computation, or when f" * has a small effect on calculated intensities, mostly for powder * diffraction (GenHKLFullSpace will not generate Friedel pairs, reducing * the number of reflections by a factor up to 2 for some structures). * * Practically this makes f"=0 during computation. The real resonant contribution (f') * is not affected. * * This may be removed later on... */ bool mIgnoreImagScattFact; // Maximum sin(theta)/lambda /** Maximum sin(theta)/lambda for all calculations (10 by default). * * This keeps all data in memory, but only the part which is below * the max is calculated. * * This affects the computing of structure factors, intensities (for single * crystal and powder patterns), R and Rw. * * The reflections \b must be sorted by increasing sin(theta)/lambda for * this to work correctly. */ REAL mMaxSinThetaOvLambda; /// Number of reflections which are below the max. This is updated automatically /// from ScatteringData::mMaxSinThetaOvLambda mutable long mNbReflUsed; /// Clock recording the last time the number of reflections used has increased. mutable RefinableObjClock mClockNbReflUsed; // Maximum Likelihood /// The Luzzati 'D' factor for each scattering power and each reflection mutable map mvLuzzatiFactor; /** The variance on all calculated structure factors, taking into account * the positionnal errors and the expected intensity factor. * * Actually this is the variance on both real and imaginary parts. */ mutable CrystVector_REAL mFhklCalcVariance; mutable RefinableObjClock mClockLuzzatiFactor; mutable RefinableObjClock mClockFhklCalcVariance; /// Observed squared structure factors (zero-sized if none) CrystVector_REAL mFhklObsSq; /// Last time observed squared structure factors were altered RefinableObjClock mClockFhklObsSq; #ifdef __WX__CRYST__ //to access mMaxSinThetaOvLambda friend class WXDiffractionSingleCrystal; friend class WXPowderPattern; #endif }; }//namespace ObjCryst #endif // _OBJCRYST_SCATTERINGDATA_H_ objcryst-2022.1/ObjCryst/ObjCryst/ScatteringPower.cpp000066400000000000000000001000231430515525000225550ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include //for sprintf() #include "cctbx/eltbx/xray_scattering.h" #include "cctbx/eltbx/tiny_pse.h" #include "cctbx/eltbx/icsd_radii.h" #include "cctbx/eltbx/covalent_radii.h" #include "cctbx/eltbx/henke.h" #include "cctbx/eltbx/neutron.h" #include "ObjCryst/ObjCryst/ScatteringPower.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" #include "ObjCryst/Quirks/VFNDebug.h" #include "ObjCryst/ObjCryst/Colours.h" #ifdef __WX__CRYST__ #include "ObjCryst/wxCryst/wxScatteringPower.h" #endif namespace ObjCryst { const RefParType *gpRefParTypeScattPow=0; const RefParType *gpRefParTypeScattPowResonant=0; const RefParType *gpRefParTypeScattPowTemperature=0; const RefParType *gpRefParTypeScattPowTemperatureIso=0; const RefParType *gpRefParTypeScattPowTemperatureAniso=0; long NiftyStaticGlobalObjectsInitializer_ScatteringPower::mCount=0; //###################################################################### // // Bij to Betaij conversion // //###################################################################### CrystMatrix_REAL Bij2Betaij(const CrystVector_REAL &Bij, const UnitCell &cell) { // Willis & Pryor,p 101: (betaij) = 2*pi^2 * transpose(cell.Bmatrix) * (Bij) * cell.Bmatrix // :TODO: this needs to be checked before being used const REAL B11=Bij(0); const REAL B22=Bij(1); const REAL B33=Bij(2); const REAL B12=Bij(3); const REAL B13=Bij(4); const REAL B23=Bij(5); CrystMatrix_REAL B(3,3); B(0,0)=B11; B(0,1)=B12; B(0,1)=B13; B(1,0)=B12; B(1,1)=B22; B(1,1)=B23; B(2,0)=B13; B(2,1)=B23; B(2,1)=B33; CrystMatrix_REAL b(3,3); b=cell.GetBMatrix().transpose().Mult(B.Mult(cell.GetBMatrix())); b*=2*M_PI*M_PI; return b; } //###################################################################### // // SCATTERING POWER // //###################################################################### ObjRegistry gScatteringPowerRegistry("Global ScatteringPower Registry"); ScatteringPower::ScatteringPower():mDynPopCorrIndex(0),mBiso(1.0),mIsIsotropic(true), mMaximumLikelihoodNbGhost(0),mFormalCharge(0.0) { VFN_DEBUG_MESSAGE("ScatteringPower::ScatteringPower():"<Init(); mClockMaster.AddChild(mClock); mClockMaster.AddChild(mMaximumLikelihoodParClock); } ScatteringPower::ScatteringPower(const ScatteringPower& old): mDynPopCorrIndex(old.mDynPopCorrIndex),mBiso(old.mBiso),mIsIsotropic(old.mIsIsotropic), mBeta(old.mBeta),mB(old.mB), mFormalCharge(old.mFormalCharge) { VFN_DEBUG_MESSAGE("ScatteringPower::ScatteringPower(&old):"<Init(); mMaximumLikelihoodPositionError=old.mMaximumLikelihoodPositionError; mMaximumLikelihoodNbGhost=old.mMaximumLikelihoodNbGhost; mClockMaster.AddChild(mClock); mClockMaster.AddChild(mMaximumLikelihoodParClock); } ScatteringPower::~ScatteringPower() { VFN_DEBUG_MESSAGE("ScatteringPower::~ScatteringPower():"<GetBij(i) != rhs.GetBij(i)) return false; if(this->GetClassName() != rhs.GetClassName()) return false; if(this->GetSymbol() != rhs.GetSymbol()) return false; return true; } bool ScatteringPower::operator!=(const ScatteringPower& rhs) const { return !(*this == rhs); } bool ScatteringPower::IsScatteringFactorAnisotropic()const{return false;} bool ScatteringPower::IsTemperatureFactorAnisotropic()const{return false;} bool ScatteringPower::IsResonantScatteringAnisotropic()const{return false;} const string& ScatteringPower::GetSymbol() const {return this->GetName();} REAL ScatteringPower::GetBiso() const {return mBiso;} REAL& ScatteringPower::GetBiso() {mClock.Click();return mBiso;} void ScatteringPower::SetBiso(const REAL newB) { mClock.Click();mBiso=newB;mIsIsotropic=true;} REAL ScatteringPower::GetBij(const size_t &i, const size_t &j) const { size_t idx = 0; if(i == j) { idx = i - 1; } else { idx = i + j; } return this->GetBij(idx); } REAL ScatteringPower::GetBij(const size_t &idx) const { return mB(idx); } void ScatteringPower::SetBij(const size_t &i, const size_t &j, const REAL newB) { size_t idx = 0; if(i == j) { idx = i - 1; } else { idx = i + j; } this->SetBij(idx, newB); } void ScatteringPower::SetBij(const size_t &idx, const REAL newB) { mClock.Click(); mIsIsotropic=false; mB(idx) = newB; } bool ScatteringPower::IsIsotropic() const {return mIsIsotropic;} long ScatteringPower::GetDynPopCorrIndex() const {return mDynPopCorrIndex;} long ScatteringPower::GetNbScatteringPower()const {return gScatteringPowerRegistry.GetNb();} const RefinableObjClock& ScatteringPower::GetLastChangeClock()const {return mClock;} const string& ScatteringPower::GetColourName()const{ return mColourName;} const float* ScatteringPower::GetColourRGB()const{ return mColourRGB;} void ScatteringPower::SetColour(const string& colourName) { mColourName=colourName; this->InitRGBColour(); } void ScatteringPower::SetColour(const float r,const float g,const float b) { mColourRGB[0]=r; mColourRGB[1]=g; mColourRGB[2]=b; } void ScatteringPower::GetGeneGroup(const RefinableObj &obj, CrystVector_uint & groupIndex, unsigned int &first) const { // One group for all parameters unsigned int index=0; VFN_DEBUG_MESSAGE("ScatteringPower::GetGeneGroup()",4) for(long i=0;iGetNbPar();j++) if(&(obj.GetPar(i)) == &(this->GetPar(j))) { if(index==0) index=first++; groupIndex(i)=index; } } REAL ScatteringPower::GetMaximumLikelihoodPositionError()const {return mMaximumLikelihoodPositionError;} const RefinableObjClock& ScatteringPower::GetMaximumLikelihoodParClock()const {return mMaximumLikelihoodParClock;} void ScatteringPower::SetMaximumLikelihoodPositionError(const REAL mle) { if(mle!=mMaximumLikelihoodPositionError) { mMaximumLikelihoodPositionError=mle; mMaximumLikelihoodParClock.Click(); } } REAL ScatteringPower::GetMaximumLikelihoodNbGhostAtom()const {return mMaximumLikelihoodNbGhost;} void ScatteringPower::SetMaximumLikelihoodNbGhostAtom(const REAL nb) { if(nb!=mMaximumLikelihoodNbGhost) { mMaximumLikelihoodNbGhost=nb; mMaximumLikelihoodParClock.Click(); } } REAL ScatteringPower::GetFormalCharge()const{return mFormalCharge;} void ScatteringPower::SetFormalCharge(const REAL charge) {mFormalCharge=charge;} void ScatteringPower::Init() { VFN_DEBUG_MESSAGE("ScatteringPower::Init():"<RGBColour:"< gScatteringPowerAtomRegistry("Global ScatteringPowerAtom Registry"); ScatteringPowerAtom::ScatteringPowerAtom(): ScatteringPower(),mSymbol(""),mAtomicNumber(0),mpGaussian(0) { VFN_DEBUG_MESSAGE("ScatteringPowerAtom::ScatteringPowerAtom():"<InitRefParList(); } ScatteringPowerAtom::ScatteringPowerAtom(const string &name, const string &symbol, const REAL bIso): mpGaussian(0) { VFN_DEBUG_MESSAGE("ScatteringPowerAtom::ScatteringPowerAtom(n,s,B):"<InitRefParList(); this->Init(name,symbol,bIso); } ScatteringPowerAtom::ScatteringPowerAtom(const ScatteringPowerAtom& old): mpGaussian(0) { VFN_DEBUG_MESSAGE("ScatteringPowerAtom::ScatteringPowerAtom(&old):"<Init(old.GetName(),old.mSymbol,old.mBiso); //this->InitRefParList(); //?? :TODO: Check } ScatteringPowerAtom::~ScatteringPowerAtom() { VFN_DEBUG_MESSAGE("ScatteringPowerAtom::~ScatteringPowerAtom():"<ScatteringPower::Init(); this->SetName(name); mSymbol=symbol; mBiso=bIso; mIsIsotropic=true; if(mpGaussian!=0) delete mpGaussian; try { cctbx::eltbx::xray_scattering::wk1995 wk95t(mSymbol); mpGaussian=new cctbx::eltbx::xray_scattering::gaussian(wk95t.fetch()); this->InitAtNeutronScattCoeffs(); cctbx::eltbx::tiny_pse::table tpse(mSymbol); mAtomicNumber=tpse.atomic_number(); mAtomicWeight=tpse.weight(); cctbx::eltbx::icsd_radii::table ticsd(mSymbol); mRadius= ticsd.radius(); cctbx::eltbx::covalent_radii::table tcov(mSymbol); mCovalentRadius=tcov.radius(); } catch(exception &err) { cout << "WARNING: could not interpret Symbol name !"<Init(name,"H",bIso); } VFN_DEBUG_MESSAGE("ScatteringPowerAtom::Init():/Name="<GetName() \ <<" /Symbol="<at_stol(*pstol++); } else sf=1.0;//:KLUDGE: Should never happen break; } case(RAD_ELECTRON): { VFN_DEBUG_MESSAGE("ScatteringPower::GetScatteringFactor():ELECTRON:"<GetAtomicNumber(); const long nb=data.GetSinThetaOverLambda().numElements(); const REAL *pstol=data.GetSinThetaOverLambda().data(); for(long i=0;iat_stol(*pstol))/(*pstol * *pstol); pstol++; } } else sf=1.0;//:KLUDGE: Should never happen break; } } VFN_DEBUG_MESSAGE("ScatteringPower::GetScatteringFactor(&data):End",3) return sf; } REAL ScatteringPowerAtom::GetForwardScatteringFactor(const RadiationType type) const { REAL sf = 0; switch(type) { case(RAD_NEUTRON): { sf=mNeutronScattLengthReal; break; } case(RAD_XRAY): { if(mpGaussian!=0) sf=mpGaussian->at_stol(0); else sf=1.0; break; } case(RAD_ELECTRON): { const REAL z=this->GetAtomicNumber(); sf=(z-mpGaussian->at_stol(0.0001))/(.0001 * .0001); } } VFN_DEBUG_MESSAGE("ScatteringPower::GetScatteringFactor(&data):End",3) return sf; } static bool warnADP=true; CrystVector_REAL ScatteringPowerAtom::GetTemperatureFactor(const ScatteringData &data, const int spgSymPosIndex) const { VFN_DEBUG_MESSAGE("ScatteringPower::GetTemperatureFactor(&data):"<The Debye-Waller calculations will instead use only isotropic DPs"<Init(this->GetName(),symbol,this->GetBiso()); } const string& ScatteringPowerAtom::GetSymbol() const { VFN_DEBUG_MESSAGE("ScatteringPowerAtom::GetSymbol():"<GetName()<<"," << FormatString(this->GetSymbol(),4) << ") :" << FormatFloat(this->GetBiso()); VFN_DEBUG_MESSAGE_SHORT("at "<AddPar(tmp); } { REAL* bdata = (REAL*) mB.data(); RefinablePar B11("B11",&bdata[0],0.1,5., gpRefParTypeScattPowTemperatureAniso,REFPAR_DERIV_STEP_ABSOLUTE, true,true,false,false); B11.SetDerivStep(1e-3); B11.SetGlobalOptimStep(.5); B11.AssignClock(mClock); this->AddPar(B11); RefinablePar B22("B22",&bdata[1],0.1,5., gpRefParTypeScattPowTemperatureAniso,REFPAR_DERIV_STEP_ABSOLUTE, true,true,false,false); B22.SetDerivStep(1e-3); B22.SetGlobalOptimStep(.5); B22.AssignClock(mClock); this->AddPar(B22); RefinablePar B33("B33",&bdata[2],0.1,5., gpRefParTypeScattPowTemperatureAniso,REFPAR_DERIV_STEP_ABSOLUTE, true,true,false,false); B33.SetDerivStep(1e-3); B33.SetGlobalOptimStep(.5); B33.AssignClock(mClock); this->AddPar(B33); RefinablePar B12("B12",&bdata[3],-5,5., gpRefParTypeScattPowTemperatureAniso,REFPAR_DERIV_STEP_ABSOLUTE, true,true,false,false); B12.SetDerivStep(1e-3); B12.SetGlobalOptimStep(.5); B12.AssignClock(mClock); this->AddPar(B12); RefinablePar B13("B13",&bdata[4],-5,5., gpRefParTypeScattPowTemperatureAniso,REFPAR_DERIV_STEP_ABSOLUTE, true,true,false,false); B13.SetDerivStep(1e-3); B13.SetGlobalOptimStep(.5); B13.AssignClock(mClock); this->AddPar(B13); RefinablePar B23("B23",&bdata[5],-5,5., gpRefParTypeScattPowTemperatureAniso,REFPAR_DERIV_STEP_ABSOLUTE, true,true,false,false); B23.SetDerivStep(1e-3); B23.SetGlobalOptimStep(.5); B23.AssignClock(mClock); this->AddPar(B23); } { RefinablePar tmp("ML Error",&mMaximumLikelihoodPositionError,0.,1., gpRefParTypeScattPow,REFPAR_DERIV_STEP_ABSOLUTE, false,true,true,false); tmp.SetDerivStep(1e-4); tmp.SetGlobalOptimStep(.001); tmp.AssignClock(mMaximumLikelihoodParClock); this->AddPar(tmp); } { RefinablePar tmp("ML-Nb Ghost Atoms",&mMaximumLikelihoodNbGhost,0.,10., gpRefParTypeScattPow,REFPAR_DERIV_STEP_ABSOLUTE, true,true,true,false); tmp.SetDerivStep(1e-3); tmp.SetGlobalOptimStep(.05); tmp.AssignClock(mMaximumLikelihoodParClock); this->AddPar(tmp); } { RefinablePar tmp("Formal Charge",&mFormalCharge,-10.,10., gpRefParTypeScattPow,REFPAR_DERIV_STEP_ABSOLUTE, true,true,true,false); tmp.SetDerivStep(1e-3); tmp.SetGlobalOptimStep(.05); tmp.AssignClock(mClock); this->AddPar(tmp); } } #ifdef __WX__CRYST__ WXCrystObjBasic* ScatteringPowerAtom::WXCreate(wxWindow* parent) { //:TODO: Check mpWXCrystObj==0 mpWXCrystObj=new WXScatteringPowerAtom(parent,this); return mpWXCrystObj; } #endif //###################################################################### // // SCATTERING COMPONENT // //###################################################################### ScatteringComponent::ScatteringComponent(): mX(0),mY(0),mZ(0),mOccupancy(0),mpScattPow(0),mDynPopCorr(0) {} bool ScatteringComponent::operator==(const ScatteringComponent& rhs) const { return ((mX==rhs.mX) && (mY==rhs.mY) && (mZ==rhs.mZ) && (mOccupancy==rhs.mOccupancy) && (mpScattPow==rhs.mpScattPow)); } bool ScatteringComponent::operator!=(const ScatteringComponent& rhs) const { return ((mX!=rhs.mX) || (mY!=rhs.mY) || (mZ!=rhs.mZ) || (mOccupancy!=rhs.mOccupancy) || (mpScattPow!=rhs.mpScattPow)); } void ScatteringComponent::Print()const { cout <GetName(); cout<=this->GetNbComponent()) { this->Print(); throw ObjCrystException("ScatteringComponentList::operator()(i)::i>mNbComponent!!"); } if(i<0) throw ObjCrystException("ScatteringComponentList::operator()&(i)::i<0!!"); return mvScattComp[i]; } ScatteringComponent& ScatteringComponentList::operator()(const long i) { VFN_DEBUG_MESSAGE("ScatteringComponentList::operator()&("<=this->GetNbComponent()) { this->Print(); throw ObjCrystException("ScatteringComponentList::operator()&(i)::i>mNbComponent!!"); } if(i<0) throw ObjCrystException("ScatteringComponentList::operator()&(i):: i<0!!"); return mvScattComp[i]; } long ScatteringComponentList::GetNbComponent() const {return mvScattComp.size();} void ScatteringComponentList::operator=(const ScatteringComponentList &rhs) { VFN_DEBUG_MESSAGE("ScatteringComponentList::operator=()",1) mvScattComp=rhs.mvScattComp; VFN_DEBUG_MESSAGE("ScatteringComponentList::operator=():End",0) } bool ScatteringComponentList::operator==(const ScatteringComponentList &rhs)const { if(rhs.GetNbComponent() != this->GetNbComponent()) return false; for(long i=0;iGetNbComponent();i++) if( (*this)(i) != rhs(i) ) return false; return true; } void ScatteringComponentList::operator+=(const ScatteringComponentList &rhs) { for(long i=0;iGetNbComponent()+1); } void ScatteringComponentList::operator--() { VFN_DEBUG_MESSAGE("ScatteringComponentList::operator--()",1) if(this->GetNbComponent()>0) mvScattComp.resize(this->GetNbComponent()-1); } void ScatteringComponentList::Print()const { VFN_DEBUG_ENTRY("ScatteringComponentList::Print()",5) cout<<"Number of Scattering components:"<GetNbComponent()<GetNbComponent();i++) { cout << i<<":"; (*this)(i).Print(); } VFN_DEBUG_EXIT("ScatteringComponentList::Print()",5) } }//namespace objcryst-2022.1/ObjCryst/ObjCryst/ScatteringPower.h000066400000000000000000000601451430515525000222340ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _OBJCRYST_SCATTPOWER_H_ #define _OBJCRYST_SCATTPOWER_H_ #include "ObjCryst/CrystVector/CrystVector.h" #include "ObjCryst/ObjCryst/General.h" #include "ObjCryst/RefinableObj/RefinableObj.h" //#include //#include //#include //#include //#include //#include //#include // forward declaration to avoid including boost headers namespace cctbx { namespace eltbx { namespace xray_scattering {class gaussian;}}} namespace ObjCryst { extern const RefParType *gpRefParTypeScattPow; extern const RefParType *gpRefParTypeScattPowResonant; extern const RefParType *gpRefParTypeScattPowTemperature; extern const RefParType *gpRefParTypeScattPowTemperatureIso; extern const RefParType *gpRefParTypeScattPowTemperatureAniso; class NiftyStaticGlobalObjectsInitializer_ScatteringPower { public: NiftyStaticGlobalObjectsInitializer_ScatteringPower() { if (mCount++ == 0) { gpRefParTypeScattPow=new RefParType(gpRefParTypeObjCryst,"Scattering Power"); gpRefParTypeScattPowResonant=new RefParType(gpRefParTypeScattPow,"Resonant Scatt."); gpRefParTypeScattPowTemperature=new RefParType(gpRefParTypeScattPow,"Temperature"); gpRefParTypeScattPowTemperatureIso=new RefParType(gpRefParTypeScattPowTemperature,"Isotropic"); gpRefParTypeScattPowTemperatureAniso=new RefParType(gpRefParTypeScattPowTemperatureIso,"Anisotropic"); } } ~NiftyStaticGlobalObjectsInitializer_ScatteringPower() { if (--mCount == 0) { delete gpRefParTypeScattPow; delete gpRefParTypeScattPowResonant; delete gpRefParTypeScattPowTemperature; delete gpRefParTypeScattPowTemperatureIso; delete gpRefParTypeScattPowTemperatureAniso; gpRefParTypeScattPow=0; gpRefParTypeScattPowResonant=0; gpRefParTypeScattPowTemperature=0; gpRefParTypeScattPowTemperatureIso=0; gpRefParTypeScattPowTemperatureAniso=0; } } private: static long mCount; }; static NiftyStaticGlobalObjectsInitializer_ScatteringPower NiftyStaticGlobalObjectsInitializer_ScatteringPower_counter; class ScatteringData;//forward declaration :KLUDGE: ? //###################################################################### // // SCATTERING POWER /** \brief Abstract Base Class to describe the scattering power of any * Scatterer component in a crystal. * * This includes: * - the scattering factor, * - the temperature factor * - real and imaginary parts of the resonant * scattering factor. * * The interface is independent of the radiation type. * * This base class is designed to handle both isotropic and anisotropic * versions of scattering, temperature and anomalous factors. * * \todo Anisotropic scattering (temperature factor especially) code, using derived * classes * \todo Clarify organization by removing any 'real' data from the top, abstract * base class (eg remove Biso and Betaij), and by creating derived classes. * Optionnaly 3 classes (used as members of ScatteringPower) could be created, * TemperatureFactor, ScatteringFactor, and ResonantScatteringFactor. In any way * the design of this class should not evolve, so that code using the ScatteringPower * interface will remain compatible whatever modifications are made. * \warning: there is currently a storage for Anisotropic Displacement Parameters, * but Debye-Waller calculation is \e only isotropic. */ //###################################################################### class ScatteringPower:virtual public RefinableObj { public: ScatteringPower(); ScatteringPower(const ScatteringPower& old); virtual ~ScatteringPower(); virtual const string& GetClassName() const; virtual void operator=(const ScatteringPower& rhs); /** Comparison operator. Two scattering powers are equal if they have the same * displacement parameter, correspond to same element, and are of the same class. */ virtual bool operator==(const ScatteringPower& rhs) const; /** Comparison operator. Two scattering powers are equal if they have the same * displacement parameter, correspond to same element, and are of the same class. */ virtual bool operator!=(const ScatteringPower& rhs) const; /** \brief Get the Scattering factor for all reflections of a given * ScatteringData object. * * \return a vector with the scattering factor for all reflections, in the same * order as in the ScatteringData object. This format is independent of the radiation * type (X-Ray, neutron..). * \param data: the ScatteringData object, giving access to all the reflections. * \param spgSymPosIndex: if the ScatteringPower is anisotropic, then the * different symmetrics will not have the same scattering power for all reflections. * This parameter is the index of the symmetric position in the Spacegroup. * If spgSymPosIndex=-1, the isotropic values are returned. * \warning There is no anisotropic code yet, so spgSymPosIndex is simply ignored so far * , but the design of this function is general for any anisotropic scattering. */ virtual CrystVector_REAL GetScatteringFactor(const ScatteringData &data, const int spgSymPosIndex=-1) const=0; /// Get the scattering factor at (0,0,0). Used for scatterer (electron, nucleus) /// density generation. virtual REAL GetForwardScatteringFactor(const RadiationType) const=0; /** \brief Get the temperature factor for all reflections of a given * ScatteringData object. * * \return a vector with the temperature factor for all reflections, in the same * order as in the ScatteringData object. * \param data: the ScatteringData object, giving access to all the reflections. * \param spgSymPosIndex: if the ScatteringPower is anisotropic, then the * different symmetrics will not have the same scattering power for all reflections. * This parameter is the index of the symmetric position in the Spacegroup. * If spgSymPosIndex=-1, the isotropic values are returned. * \warning There is no anisotropic code yet, so spgSymPosIndex is simply ignored so far * , but the design of this function is general for any anisotropic scattering. */ virtual CrystVector_REAL GetTemperatureFactor(const ScatteringData &data, const int spgSymPosIndex=-1) const=0; /** \brief Get the real part of the resonant scattering factor. * * \return a matrix where each row corresponds to each wavelength (currently only * monochromatic experiments are made so there is only one row), and each column * corresponds to each reflection \e only if the scattering term is anisotropic, which * is not the case so far... * \param data: the ScatteringData object, giving access to all the reflections and * a list of wavelengths). * \param spgSymPosIndex: if the ScatteringPower is anisotropic, then the * different symmetrics will not have the same scattering power for all reflections. * This parameter is the index of the symmetric position in the Spacegroup. * If spgSymPosIndex=-1, the isotropic values are returned. * \warning There is no anisotropic code yet, so spgSymPosIndex is simply ignored so far * , but the design of this function is general for any anisotropic scattering. */ virtual CrystMatrix_REAL GetResonantScattFactReal(const ScatteringData &data, const int spgSymPosIndex=-1) const=0; /** \brief Get the imaginary part of the resonant scattering factor. * * \return a matrix where each row corresponds to each wavelength (currently only * monochromatic experiments are made so there is only one row), and each column * corresponds to each reflection \e only if the scattering term is anisotropic, which * is not the case so far... * \param data: the ScatteringData object, giving access to all the reflections, * and a list of wavelengths. * \param spgSymPosIndex: if the ScatteringPower is anisotropic, then the * different symmetrics will not have the same scattering power for all reflections. * This parameter is the index of the symmetric position in the Spacegroup. * If spgSymPosIndex=-1, the isotropic values are returned. * \warning There is no anisotropic code yet, so spgSymPosIndex is simply ignored so far * , but the design of this function is general for any anisotropic scattering. */ virtual CrystMatrix_REAL GetResonantScattFactImag(const ScatteringData &data, const int spgSymPosIndex=-1) const=0; /// Is the scattering factor anisotropic ? virtual bool IsScatteringFactorAnisotropic()const; /// Is the thermic factor anisotropic ? virtual bool IsTemperatureFactorAnisotropic()const; /// Are the resonant scattering terms anisotropic ? virtual bool IsResonantScatteringAnisotropic()const; /** \brief Symbol for this Scattering power (the atom name for atoms) * */ virtual const string& GetSymbol() const; /** \brief Returns the isotropic temperature B factor * */ REAL GetBiso() const; /** \brief Returns the isotropic temperature B factor * */ REAL& GetBiso(); /** \brief Sets the isotropic temperature B factor * */ virtual void SetBiso(const REAL newB); /** \brief Returns the anisotropic temperature B factor for (i, j) pair. * * \warning: this is ambiguous, as it is Beta_ij which are stored, and not Bij... */ REAL GetBij(const size_t &i, const size_t &j) const; /** \brief Returns the anisotropic temperature B factor for given index. * * 0 -> (1, 1) * 1 -> (2, 2) * 2 -> (3, 3) * 3 -> (1, 2) * 4 -> (1, 3) * 5 -> (2, 3) * * \warning: this is ambiguous, as it is Beta_ij which are stored, and not Bij... */ REAL GetBij(const size_t &idx) const; /** \brief Sets the anisotropic temperature B factor for (i, j) pair. * * \warning: this is ambiguous, as it is Beta_ij which are stored, and not Bij... */ virtual void SetBij(const size_t &i, const size_t &j, const REAL newB); /** \brief Sets the anisotropic temperature B factor for given index. * * 0 -> (1, 1) * 1 -> (2, 2) * 2 -> (3, 3) * 3 -> (1, 2) * 4 -> (1, 3) * 5 -> (2, 3) * * \warning: this is ambiguous, as it is Beta_ij which are stored, and not Bij... */ virtual void SetBij(const size_t &idx, const REAL newB); /** \brief Returns true if the scattering power is isotropic, else false. * * */ bool IsIsotropic()const ; /// Get the number identifying this kind of scatterer, used to decide whether two /// scatterers are equivalent, for the dynamical occupancy correction. long GetDynPopCorrIndex()const; /// Total number of ScatteringPower object long GetNbScatteringPower()const; /// ObjCrystClock time when the last modification was made to the object const RefinableObjClock& GetLastChangeClock()const; ///Get the (POV-Ray) name associated to the color (if any) const string& GetColourName()const; /// Get the float[3] array of RGB components defining the colour of this scattering power const float* GetColourRGB()const; /// Set the colour from the associated POV-Ray name void SetColour(const string& colorName); /// Set the colour from RGB components (all between 0 and 1.) void SetColour(const float r,const float g,const float b); /// Return the physical radius of this type of scatterer (for 3D display purposes). /// \warning this may be removed later. virtual REAL GetRadius()const=0; virtual void GetGeneGroup(const RefinableObj &obj, CrystVector_uint & groupIndex, unsigned int &firstGroup) const; /// Maximum Likelihood: get the estimated error (sigma) on the positions /// for this kind of element. REAL GetMaximumLikelihoodPositionError()const; /// Maximum Likelihood: set the estimated error (sigma) on the positions /// for this kind of element. void SetMaximumLikelihoodPositionError(const REAL mle); /// Maximum Likelihood: get the number of ghost elements per asymmetric unit. REAL GetMaximumLikelihoodNbGhostAtom()const; /// Maximum Likelihood: set the number of ghost elements per asymmetric unit. void SetMaximumLikelihoodNbGhostAtom(const REAL nb); /// Get the clock value for the last change on the maximum likelihood parameters /// (positionnal error, number of ghost atoms). const RefinableObjClock& GetMaximumLikelihoodParClock()const; virtual REAL GetFormalCharge()const; virtual void SetFormalCharge(const REAL charge); protected: virtual void InitRefParList()=0; /// Initialization of the object, used by all constructors, and operator=. virtual void Init(); ///Get RGB Colour coordinates from Colour Name virtual void InitRGBColour(); /// number identifying this kind of scatterer, for the dynamical occupancy correction. /// Right now it is the atomic number. long mDynPopCorrIndex; /// Temperature isotropic B factor. REAL mBiso; /// Is the scattering isotropic ? bool mIsIsotropic; /** Anisotropic Beta(ij) * * \internal * These are stored temporarily, and derived from the Bij */ mutable CrystVector_REAL mBeta; /// Anisotropic B(ij) CrystVector_REAL mB; /// Clock. RefinableObjClock mClock; /// Colour for this ScatteringPower (from POVRay) string mColourName; /// Colour for this ScatteringPower using RGB float mColourRGB[3]; // Maximum Likelihood /// estimated error (sigma) on the positions for this type of element. REAL mMaximumLikelihoodPositionError; /// RefinableObjClock mMaximumLikelihoodParClock; /// Number of ghost atoms in the asymmetric unit. /// These contribute to the variance of the structure factor, but not to the structure /// factor as the uncertainty on their position is infinite. REAL mMaximumLikelihoodNbGhost; /** Formal Charge. This can be used for bond valence analysis, * or energy calculations. * * Default value is 0. */ REAL mFormalCharge; }; /// Global registry for all ScatteringPower objects extern ObjRegistry gScatteringPowerRegistry; //###################################################################### // // SCATTERING POWER ATOM /** \brief The Scattering Power for an Atom * */ //###################################################################### class ScatteringPowerAtom:virtual public ScatteringPower { public: ScatteringPowerAtom(); /** \brief Atom constructor * \param symbol : 'Ti' , 'Ti4+', 'Cl1-' *These symbols \e must correspond to one of the entries of the international tables *for crystallography (1995) giving the analytical approximation for scattering factors. * \param name : name of the atom ('Ta1','Sm2', 'Tungsten_1'...). *The name can have \e any format but spaces should be avoided, since it *will generate problems when reading the names from a file... * \param biso : Isotropic thermic coefficient */ ScatteringPowerAtom(const string &name,const string &symbol,const REAL bIso=1.0); ScatteringPowerAtom(const ScatteringPowerAtom& old); ~ScatteringPowerAtom(); virtual const string& GetClassName() const; /// Re-initialize parameters (after using the default constructor). void Init(const string &name,const string &symbol,const REAL bIso=1.0); virtual CrystVector_REAL GetScatteringFactor(const ScatteringData &data, const int spgSymPosIndex=0) const; virtual REAL GetForwardScatteringFactor(const RadiationType) const; virtual CrystVector_REAL GetTemperatureFactor(const ScatteringData &data, const int spgSymPosIndex=0) const; virtual CrystMatrix_REAL GetResonantScattFactReal(const ScatteringData &data, const int spgSymPosIndex=0) const; virtual CrystMatrix_REAL GetResonantScattFactImag(const ScatteringData &data, const int spgSymPosIndex=0) const; /// Set the symbol for this atom void SetSymbol(const string &symbol) ; /// Returns the symbol ('Ta', 'O2-',...) of the atom virtual const string& GetSymbol() const; /** \brief Returns the standard name of the element (ie "hydrogen", "tantalum",..). * * Names are extracted form Grosse-Kunstleve 'atominfo' package, *which uses data from the CRC Handbook of Chemistry & Physics, 63rd & 70th editions */ string GetElementName() const; /// Atomic number for this atom int GetAtomicNumber() const; /// Atomic weight (g/mol) for this atom REAL GetAtomicWeight() const; /// Atomic radius for this atom or ion, in Angstroems (ICSD table from cctbx) REAL GetRadius() const; /// Covalent Radius for this atom, in Angstroems (from cctbx) REAL GetCovalentRadius() const; /// Maximum number of covalent bonds (from openbabel element.txt) unsigned int GetMaxCovBonds() const; virtual void Print()const; virtual void XMLOutput(ostream &os,int indent=0)const; virtual void XMLInput(istream &is,const XMLCrystTag &tag); //virtual void XMLInputOld(istream &is,const IOCrystTag &tag); protected: /** \internal * Fetch the coefficients for analytical approximation of the *atomic scattering factor. */ void InitAtScattCoeffsWK95(); /** \internal * Fetch the coefficients neutron scattering. */ void InitAtNeutronScattCoeffs(); virtual void InitRefParList(); /** \brief Symbol of this atom * *This symbol \e must correspond to one of the entries of the international tables *for crystallography (1995) giving the analytical approximation for scattering factors. */ string mSymbol; /// atomic number (Z) for the atom int mAtomicNumber; /// atomic weight (g/mol) for the atom REAL mAtomicWeight; /** Pointer to cctbx's gaussian describing the thomson x-ray * scattering factor. */ cctbx::eltbx::xray_scattering::gaussian *mpGaussian; /** \brief Neutron Bond Coherent Scattering lengths * *Real and imaginary (for atoms who have an imaginary part) * *Reference : Neutron News, Vol. 3, No. 3, 1992, pp. 29-37. */ REAL mNeutronScattLengthReal,mNeutronScattLengthImag; /// Radius of the atom or ion, in Angstroems (ICSD table from cctbx) REAL mRadius; /// Covalent Radius for this atom, in Angstroems (from cctbx) REAL mCovalentRadius; /// Maximum number of covalent bonds unsigned int mMaxCovBonds; /** \brief Neutron Absorption cross section (barn) * *For 2200 m/s neutrons. * *Reference : Neutron News, Vol. 3, No. 3, 1992, pp. 29-37. */ REAL mNeutronAbsCrossSection; private: // Avoid compiler warnings. Explicitly hide the base-class method. void Init(); #ifdef __WX__CRYST__ public: virtual WXCrystObjBasic* WXCreate(wxWindow*); friend class WXScatteringPowerAtom; #endif }; /// Global registry for all ScatteringPowerAtom objects extern ObjRegistry gScatteringPowerAtomRegistry; //###################################################################### // // SCATTERING COMPONENT /** \brief A scattering position in a crystal, associated with the corresponding * occupancy and a pointer to the ScatteringPower. Also given is the * */ //###################################################################### struct ScatteringComponent { // Default Constructor ScatteringComponent(); bool operator==(const ScatteringComponent& rhs)const; bool operator!=(const ScatteringComponent& rhs)const; ///Print one line oabout this component void Print() const; /// Coordinates of scattering positions i the crystal with the corresponding occupancy REAL mX,mY,mZ,mOccupancy; /// The ScatteringPower associated with this position const ScatteringPower *mpScattPow; /// Dynamical Population Correction. /// /// The population of any atom is given by mOccupancy*mDynPopCorr. /// mPopu is the \e real mOccupancy (0<.<1), and should be the only one /// used during a refinement. However during a \e model \e search for the structure, /// atoms may fall unexpectedly in a special position or with an overlap of /// two atoms (the shared oxygen between two polyhedras, for example). In these /// cases it is necessary to dynamically correct the population during the /// generation of structural models. /// See also Crystal::CalcDynPopCorr /// /// \note this parameter is mutable, and is computed by the Crystal object mutable REAL mDynPopCorr; // The scatterer to which this component is associated // Scatterer *mScatterer; }; //###################################################################### // // SCATTERING COMPONENT LIST /** \brief list of scattering positions in a crystal, associated with the corresponding * occupancy and a pointer to the ScatteringPower. * */ //###################################################################### class ScatteringComponentList { public: ScatteringComponentList(); ScatteringComponentList(const long nbComponent); ScatteringComponentList(const ScatteringComponentList &old); ~ScatteringComponentList(); /// Reset the list. This does \b not free the memory, but simply forgets /// that there already are some entries. void Reset(); /// Access to a component const ScatteringComponent& operator()(const long i) const; ScatteringComponent& operator()(const long i); /// Number of components long GetNbComponent() const; /// Assignement operator void operator=(const ScatteringComponentList &rhs); /// Compare two lists. bool operator==(const ScatteringComponentList &rhs)const; /// Add another list of components void operator+=(const ScatteringComponentList &rhs); /// Add component void operator+=(const ScatteringComponent &rhs); /// Add component (the whole list should be updated after that) void operator++(); /// Remove component (the whole list should be updated after that) void operator--(); /// Print the list of Scattering components. For debugging void Print() const; protected: /// The vector of components vector mvScattComp; }; }//namespace #include "ObjCryst/ObjCryst/ScatteringData.h" #endif //_OBJCRYST_SCATTPOWER_H_ objcryst-2022.1/ObjCryst/ObjCryst/ScatteringPowerSphere.cpp000066400000000000000000000215531430515525000237360ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* ScatteringPowerSphere.cpp * source file for the spherical scattering power * */ #include #include #include "ObjCryst/ObjCryst/ScatteringPowerSphere.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" #ifdef __WX__CRYST__ #include "ObjCryst/wxCryst/wxScatteringPowerSphere.h" #endif namespace ObjCryst { //////////////////////////////////////////////////////////////////////// // // ScatteringPowerSphere // //////////////////////////////////////////////////////////////////////// ScatteringPowerSphere::ScatteringPowerSphere() { cout<<"Creating scattering power for fullerene"<Init("C60",3.56,1.0); } ScatteringPowerSphere::ScatteringPowerSphere(const string &name, const REAL radius, const REAL bIso) { this->Init(name,radius,bIso); } ScatteringPowerSphere::ScatteringPowerSphere(const ScatteringPowerSphere& old) {} ScatteringPowerSphere::~ScatteringPowerSphere() { } // Disable the base-class function. void ScatteringPowerSphere::Init() { // This should be never called. abort(); } void ScatteringPowerSphere::Init(const string &name, const REAL radius, const REAL bIso) { this->SetName(name); mRadius=radius; mColourRGB[0]=0.2; mColourRGB[1]=0.2; mColourRGB[2]=0.2; if(this->GetNbPar()==0) this->InitRefParList(); } const string& ScatteringPowerSphere::GetClassName() const { const static string className="ScatteringPowerSphere"; return className; } CrystVector_REAL ScatteringPowerSphere::GetScatteringFactor(const ScatteringData &data, const int spgSymPosIndex) const { CrystVector_REAL sf; #if 0 // :TODO: Support anisotropic form factor. For the moment use only mAxisLengthX REAL a,b,c; CrystMatrix_REAL phiMatrix(3,3),chiMatrix(3,3),psiMatrix(3,3); phiMatrix= cos(mPhi) , -sin(mPhi) , 0, sin(mPhi) , cos(mPhi) , 0, 0 ,0 ,1; chiMatrix= cos(mChi) ,0 ,-sin(mChi), 0 ,1 ,0, sin(mChi) ,0 ,cos(mChi); psiMatrix= 1 , 0 , 0, 0 ,cos(mPsi) ,-sin(mPsi), 0 ,sin(mPsi) ,cos(mPsi); CrystMatrix_REAL phiChiPsiMatrix=product(chiMatrix,product(phiMatrix,psiMatrix)); a=phiChiPsiMatrix(0,0)*mAxisLengthX+phiChiPsiMatrix(0,1)*mAxisLengthY+phiChiPsiMatrix(0,2)*mAxisLengthZ; b=phiChiPsiMatrix(1,0)*mAxisLengthX+phiChiPsiMatrix(1,1)*mAxisLengthY+phiChiPsiMatrix(1,2)*mAxisLengthZ; c=phiChiPsiMatrix(2,0)*mAxisLengthX+phiChiPsiMatrix(2,1)*mAxisLengthY+phiChiPsiMatrix(2,2)*mAxisLengthZ; const REAL *pX=data.GetReflX().data(); const REAL *pY=data.GetReflY().data(); const REAL *pZ=data.GetReflZ().data(); sf.resize(data.GetNbRefl()); REAL *pSF=sf.data(); for(long i=0;iGetName(),5) for(int i=0;iGetPar(&mRadius).XMLOutput(os,"Radius",0); os<GetPar(&mBiso).XMLOutput(os,"Biso",0); os<GetName(),5) } void ScatteringPowerSphere::XMLInput(istream &is,const XMLCrystTag &tagg) { VFN_DEBUG_ENTRY("ScatteringPowerSphere::XMLInput():"<GetName(),5) string symbol; for(unsigned int i=0;iSetName(tagg.GetAttributeValue(i)); if("Symbol"==tagg.GetAttributeName(i)) symbol=tagg.GetAttributeValue(i); } this->Init(mName,3.56,1.0); while(true) { XMLCrystTag tag(is); if(("ScatteringPowerSphere"==tag.GetName())&&tag.IsEndTag()) { VFN_DEBUG_EXIT("ScatteringPowerSphere::Exit():"<GetName(),5) return; } if("RGBColour"==tag.GetName()) { float r,g,b; is>>r>>g>>b; this->SetColour(r,g,b); XMLCrystTag junk(is); } if("Par"==tag.GetName()) { for(unsigned int i=0;iGetPar(&mRadius).XMLInput(is,tag); if("Biso"==tag.GetAttributeValue(i)) this->GetPar(&mBiso).XMLInput(is,tag); break; } } continue; } } } void ScatteringPowerSphere::InitRefParList() { { RefinablePar tmp("Radius",&mRadius,3.,5., gpRefParTypeScattPow,REFPAR_DERIV_STEP_RELATIVE, true,true,true,false); tmp.SetDerivStep(1e-3); tmp.SetGlobalOptimStep(.1); tmp.AssignClock(mClock); this->AddPar(tmp); } { RefinablePar tmp("Biso",&mBiso,0.1,5., gpRefParTypeScattPowTemperatureIso,REFPAR_DERIV_STEP_ABSOLUTE, true,true,true,false); tmp.SetDerivStep(1e-3); tmp.SetGlobalOptimStep(.5); tmp.AssignClock(mClock); this->AddPar(tmp); } } #ifdef __WX__CRYST__ WXCrystObjBasic* ScatteringPowerSphere::WXCreate(wxWindow* parent) { //:TODO: Check mpWXCrystObj==0 mpWXCrystObj=new WXScatteringPowerSphere(parent,this); return mpWXCrystObj; } #endif }//namespace objcryst-2022.1/ObjCryst/ObjCryst/ScatteringPowerSphere.h000066400000000000000000000073711430515525000234050ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* ScatteringPowerSphere.h * header file for the Spherical scattering power (fullerenes, etc..) * */ #ifndef _OBJCRYST_SCATTPOWERSPHERE_H_ #define _OBJCRYST_SCATTPOWERSPHERE_H_ #include "ObjCryst/CrystVector/CrystVector.h" #include "ObjCryst/ObjCryst/ScatteringPower.h" namespace ObjCryst { /** \ brief ScatteringPower for a spherical particule * * This can be used to modelize the form factor of disordered (or low-resolution) * of fullerene-type compounds, where all atoms are located on a * sphere. * * This actually modelizes a spherical distribution of a \e single electron, so to modelize * C60 the occupancy must be set to 60*6. */ class ScatteringPowerSphere: public ScatteringPower { public: /// Default constructor ScatteringPowerSphere(); /** \brief constructor * \param name : name of the ScatteringPower ('C60','France 98'...). *The name can have \e any format * \param nbAtom: the number of atoms * \param biso : Isotropic thermic coefficient * \param AxisLengthX,AxisLengthY,AxisLengthZ: length of the different * main axis of the ellipsoid * \param symbol: the symbol of the element associated to this fullerene. By * default it is assumed to be carbon */ ScatteringPowerSphere(const string &name,const REAL radius,const REAL bIso=1.0); ScatteringPowerSphere(const ScatteringPowerSphere& old); ~ScatteringPowerSphere(); void Init(const string &name,const REAL radius,const REAL bIso=1.0); virtual const string& GetClassName() const; virtual CrystVector_REAL GetScatteringFactor(const ScatteringData &data, const int spgSymPosIndex=0) const; virtual REAL GetForwardScatteringFactor(const RadiationType) const; virtual CrystVector_REAL GetTemperatureFactor(const ScatteringData &data, const int spgSymPosIndex=0) const; virtual CrystMatrix_REAL GetResonantScattFactReal(const ScatteringData &data, const int spgSymPosIndex=0) const; virtual CrystMatrix_REAL GetResonantScattFactImag(const ScatteringData &data, const int spgSymPosIndex=0) const; REAL GetRadius()const; virtual void Print()const; virtual void XMLOutput(ostream &os,int indent=0)const; virtual void XMLInput(istream &is,const XMLCrystTag &tag); private: virtual void InitRefParList(); // Avoid compiler warnings. Explicitly hide the base-class method. void Init(); /// Isotropic temperature B-factor. REAL mBiso; /** Radius of the sphere. */ REAL mRadius; #ifdef __WX__CRYST__ public: virtual WXCrystObjBasic* WXCreate(wxWindow*); friend class WXScatteringPowerSphere; #endif }; }//namespace #endif objcryst-2022.1/ObjCryst/ObjCryst/SpaceGroup.cpp000066400000000000000000000614611430515525000215210ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * source file LibCryst++ AsymmetricUnit and SpaceGroup classes * */ #include #include #include #include "cctbx/sgtbx/space_group.h" #include "cctbx/sgtbx/brick.h" #include "cctbx/miller/sym_equiv.h" #include #include "ObjCryst/ObjCryst/SpaceGroup.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" //simple formatting of integers, REALs.. #include "ObjCryst/ObjCryst/GeomStructFactor.h" //Geometrical Struct Factor definitions #include "ObjCryst/Quirks/VFNDebug.h" #include #define POSSIBLY_UNUSED(expr) (void)(expr) namespace ObjCryst { #include "ObjCryst/Quirks/VFNDebug.h" // We need to force the C locale when using cctbx (when interpreting xyz strings) tmp_C_Numeric_locale::tmp_C_Numeric_locale() { char *old; old=setlocale(LC_NUMERIC,NULL); mLocale=old; setlocale(LC_NUMERIC,"C"); } tmp_C_Numeric_locale::~tmp_C_Numeric_locale() { setlocale(LC_NUMERIC,mLocale.c_str()); } //////////////////////////////////////////////////////////////////////// // // AsymmetricUnit // //////////////////////////////////////////////////////////////////////// AsymmetricUnit::AsymmetricUnit() { VFN_DEBUG_MESSAGE("AsymmetricUnit::AsymmetricUnit()",5) mXmin=0; mYmin=0; mZmin=0; mXmax=1; mYmax=1; mZmax=1; } AsymmetricUnit::AsymmetricUnit(const SpaceGroup &spg) { VFN_DEBUG_MESSAGE("AsymmetricUnit::AsymmetricUnit(SpGroup)",5) this->SetSpaceGroup(spg); } AsymmetricUnit::~AsymmetricUnit() { VFN_DEBUG_MESSAGE("AsymmetricUnit::~AsymmetricUnit(SpGroup)",5) } void AsymmetricUnit::SetSpaceGroup(const SpaceGroup &spg) { VFN_DEBUG_MESSAGE("AsymmetricUnit::SetSpaceGroup(SpGroup)",5) tmp_C_Numeric_locale tmploc; # if 0 TAU_PROFILE("(AsymmetricUnit::SetSpaceGroup)","void (SpaceGroup)",TAU_DEFAULT); mXmin=0.; mYmin=0.; mZmin=0.; mXmax=1.; mYmax=1.; mZmax=1.; if(1==spg.GetSpaceGroupNumber()) return;//no need to search an asymmetric unit // Test points=reular grid of points inside the unit cell // All points must be or have at least a symmetric in the asymmetric unit const long nbPoints=13; CrystMatrix_REAL testPoints(nbPoints*nbPoints*nbPoints,3); { long l=0; for(long i=0;iACCEPTED:" << mXmax <<" "<< mYmax <<" "<< mZmax <ACCEPTED:" << mXmax <<" "<< mYmax <<" "<< mZmax <Finished Generating (pseudo) Asymmetric Unit, with:"<>Parallelepipedic Asymmetric Unit, from cctbx::sgtbx::brick:"<(b(0,0).value()); mYmin=boost::rational_cast(b(1,0).value()); mZmin=boost::rational_cast(b(2,0).value()); mXmax=boost::rational_cast(b(0,1).value()); mYmax=boost::rational_cast(b(1,1).value()); mZmax=boost::rational_cast(b(2,1).value()); #endif } bool AsymmetricUnit::IsInAsymmetricUnit(const REAL x, const REAL y, const REAL z)const { return ( ( x <= mXmin) && ( x >= mXmax) &&( y <= mYmin) && ( y >= mYmax) &&( z <= mZmin) && ( z >= mZmax)); } REAL AsymmetricUnit::Xmin() const {return mXmin;} REAL AsymmetricUnit::Xmax() const {return mXmax;} REAL AsymmetricUnit::Ymin() const {return mYmin;} REAL AsymmetricUnit::Ymax() const {return mYmax;} REAL AsymmetricUnit::Zmin() const {return mZmin;} REAL AsymmetricUnit::Zmax() const {return mZmax;} //////////////////////////////////////////////////////////////////////// // // SpaceGroup // //////////////////////////////////////////////////////////////////////// SpaceGroup::SpaceGroup():mId("P1"),mpCCTbxSpaceGroup(0) { InitSpaceGroup(mId); } SpaceGroup::SpaceGroup(const string &spgId):mId(spgId),mpCCTbxSpaceGroup(0) { InitSpaceGroup(spgId); } SpaceGroup::~SpaceGroup() { if(mpCCTbxSpaceGroup!=0) delete mpCCTbxSpaceGroup; } void SpaceGroup::ChangeSpaceGroup(const string &spgId) { VFN_DEBUG_MESSAGE("SpaceGroup::ChangeSpaceGroup():"<InitSpaceGroup(spgId); } const string& SpaceGroup::GetName()const{return mId;} bool SpaceGroup::IsInAsymmetricUnit(const REAL x, const REAL y, const REAL z) const { return mAsymmetricUnit.IsInAsymmetricUnit(x,y,z); } void SpaceGroup::ChangeToAsymmetricUnit(REAL x, REAL y, REAL z) const { //:TODO: } const AsymmetricUnit& SpaceGroup::GetAsymUnit() const {return mAsymmetricUnit;} /// Id number of the spacegroup int SpaceGroup::GetSpaceGroupNumber()const { return mSpgNumber; } bool SpaceGroup::IsCentrosymmetric()const { return mHasInversionCenter; } int SpaceGroup::GetNbTranslationVectors()const { return mNbTrans; } const std::vector& SpaceGroup::GetTranslationVectors()const { return mvTrans; } const std::vector& SpaceGroup::GetSymmetryOperations()const { return mvSym; } CrystMatrix_REAL SpaceGroup::GetAllSymmetrics(const REAL x, const REAL y, const REAL z, const bool noCenter,const bool noTransl, const bool noIdentical)const { //TAU_PROFILE("SpaceGroup::GetAllSymmetrics()","Matrix (x,y,z)",TAU_DEFAULT); VFN_DEBUG_MESSAGE("SpaceGroup::GetAllSymmetrics()",0) int nbMatrix, nbTrans,coeffInvert,i,j,k; nbMatrix=this->GetCCTbxSpg().n_smx(); nbTrans=this->GetNbTranslationVectors(); if(this->IsCentrosymmetric()) coeffInvert=2 ; else coeffInvert=1; if(noCenter==true) coeffInvert=1; //skip center of symmetry if(noTransl==true) nbTrans=1; //skip translation operations CrystMatrix_REAL coords(nbMatrix*nbTrans*coeffInvert,3); k=0; for(i=0;iGetCCTbxSpg().ltr(i).den()); const REAL tx=this->GetCCTbxSpg().ltr(i)[0]*ltr_den; const REAL ty=this->GetCCTbxSpg().ltr(i)[1]*ltr_den; const REAL tz=this->GetCCTbxSpg().ltr(i)[2]*ltr_den; //if(noTransl==false) cout << nbTrans <GetCCTbxSpg().smx(j)); const cctbx::sgtbx::rot_mx *pRot=&(pMatrix->r()); const cctbx::sgtbx::tr_vec *pTrans=&(pMatrix->t()); const REAL r_den=1/(REAL)(pMatrix->r().den()); const REAL t_den=1/(REAL)(pMatrix->t().den()); coords(k,0)= ((*pRot)[0]*x+(*pRot)[1]*y+(*pRot)[2]*z)*r_den+(*pTrans)[0]*t_den+tx; coords(k,1)= ((*pRot)[3]*x+(*pRot)[4]*y+(*pRot)[5]*z)*r_den+(*pTrans)[1]*t_den+ty; coords(k,2)= ((*pRot)[6]*x+(*pRot)[7]*y+(*pRot)[8]*z)*r_den+(*pTrans)[2]*t_den+tz; k++; } } if(coeffInvert==2) //inversion center not in ListSeitzMx, but to be applied { int shift=nbMatrix*nbTrans; const REAL dx=((REAL)this->GetCCTbxSpg().inv_t()[0])/(REAL)this->GetCCTbxSpg().inv_t().den();//inversion not at the origin const REAL dy=((REAL)this->GetCCTbxSpg().inv_t()[1])/(REAL)this->GetCCTbxSpg().inv_t().den(); const REAL dz=((REAL)this->GetCCTbxSpg().inv_t()[2])/(REAL)this->GetCCTbxSpg().inv_t().den(); for(i=0;iGetCCTbxSpg().n_smx(); int nbTrans=this->GetNbTranslationVectors(); POSSIBLY_UNUSED(nbTrans); if(this->IsCentrosymmetric()) coeffInvert=2 ; else coeffInvert=1; if(noCenter==true) coeffInvert=1; //skip center of symmetry if(noTransl==true) nbTrans=1; //skip translation operations const int i=idx/nbMatrix;//translation index const int j=idx%nbMatrix; const REAL ltr_den=1/(REAL)(this->GetCCTbxSpg().ltr(i).den()); const REAL tx=this->GetCCTbxSpg().ltr(i)[0]*ltr_den; const REAL ty=this->GetCCTbxSpg().ltr(i)[1]*ltr_den; const REAL tz=this->GetCCTbxSpg().ltr(i)[2]*ltr_den; const cctbx::sgtbx::rt_mx *pMatrix=&(this->GetCCTbxSpg().smx(j)); const cctbx::sgtbx::rot_mx *pRot=&(pMatrix->r()); const cctbx::sgtbx::tr_vec *pTrans=&(pMatrix->t()); const REAL r_den=1/(REAL)(pMatrix->r().den()); const REAL t_den=1/(REAL)(pMatrix->t().den()); const REAL x1= ((*pRot)[0]*x+(*pRot)[1]*y+(*pRot)[2]*z)*r_den; const REAL y1= ((*pRot)[3]*x+(*pRot)[4]*y+(*pRot)[5]*z)*r_den; const REAL z1= ((*pRot)[6]*x+(*pRot)[7]*y+(*pRot)[8]*z)*r_den; if(derivative==false) { x=x1+(*pTrans)[0]*t_den+tx; y=y1+(*pTrans)[1]*t_den+ty; z=z1+(*pTrans)[2]*t_den+tz; } else { x=x1; y=y1; z=z1; } if(coeffInvert==2) //inversion center not in ListSeitzMx, but to be applied { const REAL dx=((REAL)this->GetCCTbxSpg().inv_t()[0])/(REAL)this->GetCCTbxSpg().inv_t().den();//inversion not at the origin const REAL dy=((REAL)this->GetCCTbxSpg().inv_t()[1])/(REAL)this->GetCCTbxSpg().inv_t().den(); const REAL dz=((REAL)this->GetCCTbxSpg().inv_t()[2])/(REAL)this->GetCCTbxSpg().inv_t().den(); x=dx-x; y=dy-y; z=dz-z; } } int SpaceGroup::GetNbSymmetrics(const bool noCenter,const bool noTransl)const { if(noCenter || (!mHasInversionCenter)) { if(noTransl) return mNbSym; else return mNbSym*mNbTrans; } else { if(noTransl) return 2*mNbSym; else return 2*mNbSym*mNbTrans; } return 2*mNbSym*mNbTrans; } void SpaceGroup::Print() const { cout << "SpaceGroup:" <GetCCTbxSpg().n_smx();i++) cout << " " << this->GetCCTbxSpg().smx(i).as_xyz() <GetCCTbxSpg().inv_t()[0])/(REAL)this->GetCCTbxSpg().inv_t().den()/2. << " " << (this->GetCCTbxSpg().inv_t()[1])/(REAL)this->GetCCTbxSpg().inv_t().den()/2. << " " << (this->GetCCTbxSpg().inv_t()[2])/(REAL)this->GetCCTbxSpg().inv_t().den()/2. << endl; } if(this->GetCCTbxSpg().n_ltr()>0) { cout <<" List of Translation vectors :"<GetCCTbxSpg().n_ltr();i++) cout << " "<< this->GetCCTbxSpg().ltr(i)[0]/(REAL)this->GetCCTbxSpg().ltr(i).den()<<"," << this->GetCCTbxSpg().ltr(i)[1]/(REAL)this->GetCCTbxSpg().ltr(i).den()<<"," << this->GetCCTbxSpg().ltr(i)[2]/(REAL)this->GetCCTbxSpg().ltr(i).den()<GetCCTbxSpg().inv_t()[0]; center(1) = this->GetCCTbxSpg().inv_t()[1]; center(2) = this->GetCCTbxSpg().inv_t()[2]; // inv_t is the overall translation associated with inversion, // the actual inversion center is therefore at midpoint. center /= 2 * this->GetCCTbxSpg().inv_t().den(); return center; } unsigned int SpaceGroup::AreReflEquiv(const REAL h1, const REAL k1, const REAL l1, const REAL h2, const REAL k2, const REAL l2)const { const int ih1=scitbx::math::iround(h1); const int ik1=scitbx::math::iround(k1); const int il1=scitbx::math::iround(l1); cctbx::miller::index h0(scitbx::vec3(ih1,ik1,il1)); const int ih2=scitbx::math::iround(h2); const int ik2=scitbx::math::iround(k2); const int il2=scitbx::math::iround(l2); cctbx::miller::index k0(scitbx::vec3(ih2,ik2,il2)); cctbx::miller::sym_equiv_indices sei(this->GetCCTbxSpg(),k0); int equiv=0; //cout< k = sei(i_mate, i_indices).h(); //cout<<" ->("< h(scitbx::vec3(ih0,ik0,il0)); cctbx::miller::sym_equiv_indices sei(this->GetCCTbxSpg(),h); int nbEquiv; if(forceFriedelLaw) nbEquiv=sei.multiplicity(false); else nbEquiv=sei.multiplicity(true); if( ((this->IsCentrosymmetric())||forceFriedelLaw) && excludeFriedelMate) nbEquiv/=2; CrystMatrix_REAL equivReflList(nbEquiv,5); complex sf0((double)(sf_re),(double)(sf_im)); for(int i=0;i k = sei(i).h(); equivReflList(i,0)=(REAL)k[0]; equivReflList(i,1)=(REAL)k[1]; equivReflList(i,2)=(REAL)k[2]; equivReflList(i,3)=(REAL)sei(i).complex_eq(sf0).real(); equivReflList(i,4)=(REAL)sei(i).complex_eq(sf0).imag(); } VFN_DEBUG_EXIT("SpaceGroup::GetAllEquivRefl():",5) return equivReflList; } bool SpaceGroup::IsReflSystematicAbsent(const REAL h0, const REAL k0, const REAL l0)const { const int ih0=scitbx::math::iround(h0); const int ik0=scitbx::math::iround(k0); const int il0=scitbx::math::iround(l0); cctbx::miller::index h(scitbx::vec3(ih0,ik0,il0)); return this->GetCCTbxSpg().is_sys_absent(h); } bool SpaceGroup::IsReflCentric(const REAL h0, const REAL k0, const REAL l0)const { const int ih0=scitbx::math::iround(h0); const int ik0=scitbx::math::iround(k0); const int il0=scitbx::math::iround(l0); cctbx::miller::index h(scitbx::vec3(ih0,ik0,il0)); return this->GetCCTbxSpg().is_centric(h); } unsigned int SpaceGroup::GetExpectedIntensityFactor(const REAL h0, const REAL k0, const REAL l0)const { const int ih0=scitbx::math::iround(h0); const int ik0=scitbx::math::iround(k0); const int il0=scitbx::math::iround(l0); cctbx::miller::index h(scitbx::vec3(ih0,ik0,il0)); return this->GetCCTbxSpg().epsilon(h); } void SpaceGroup::InitSpaceGroup(const string &spgId) { if((mId==spgId)&&(mpCCTbxSpaceGroup!=0)) return; VFN_DEBUG_ENTRY("SpaceGroup::InitSpaceGroup():"<GetCCTbxSpg().f_inv() == 2) { mHasInversionCenter=true ; if( (this->GetCCTbxSpg().inv_t()[0] !=0) || (this->GetCCTbxSpg().inv_t()[1] !=0) || (this->GetCCTbxSpg().inv_t()[2] !=0) ) mIsInversionCenterAtOrigin=false; else mIsInversionCenterAtOrigin=true; } else { mHasInversionCenter=false ; mIsInversionCenterAtOrigin=true; } //initialize asymmetric unit mAsymmetricUnit.SetSpaceGroup(*this); mUniqueAxisId=0; if( (this->GetCCTbxSpg().type().number() >2) &&(this->GetCCTbxSpg().type().number() <16)) { string ch=this->GetCCTbxSpg().match_tabulated_settings().hall(); if(ch.find("x")!=std::string::npos) {mUniqueAxisId=0;} else if(ch.find("y")!=std::string::npos) {mUniqueAxisId=1;} else mUniqueAxisId=2; } mNbSym =this->GetCCTbxSpg().n_smx(); mNbTrans =this->GetCCTbxSpg().n_ltr(); mSpgNumber=this->GetCCTbxSpg().type().number(); mExtension='\0'; //this->GetCCTbxSpg().type().extension(); } catch(exception ex) { (*fpObjCrystInformUser)("Error initializing spacegroup (Incorrect Hall symbol ?):"+spgId); if (mId != spgId) { (*fpObjCrystInformUser)("Reverting to spacegroup symbol:"+mId); this->InitSpaceGroup(mId); } VFN_DEBUG_EXIT("SpaceGroup::InitSpaceGroup() could not interpret spacegroup:"<GetCCTbxSpg().match_tabulated_settings().extension(); // Force using the H-M symbol if(mExtension=='\0') mId=this->GetCCTbxSpg().match_tabulated_settings().hermann_mauguin(); else mId=this->GetCCTbxSpg().match_tabulated_settings().hermann_mauguin()+":"+mExtension; // Store rotation matrices & translation vectors mvTrans.resize(mNbTrans); for(unsigned int i=0;iGetCCTbxSpg().ltr(i)[j]/(REAL)(this->GetCCTbxSpg().ltr(i).den()); } mvSym.resize(mNbSym); for(unsigned int j=0;jGetCCTbxSpg().smx(j)); const cctbx::sgtbx::rot_mx *pRot=&(pMatrix->r()); const cctbx::sgtbx::tr_vec *pTrans=&(pMatrix->t()); const REAL r_den=1/(REAL)(pMatrix->r().den()); const REAL t_den=1/(REAL)(pMatrix->t().den()); for(unsigned int i=0;i<9;++i) mvSym[j].mx[i]=(*pRot)[i]*r_den; for(unsigned int i=0;i<3;++i) mvSym[j].tr[i]=(*pTrans)[i]*t_den; } #ifdef __DEBUG__ this->Print(); #endif mClock.Click(); string extension(""); if(mExtension=='1') extension=" (Using origin choice #1)"; if(mExtension=='2') extension=" (Using origin choice #2)"; if(mExtension=='R') extension=" (Using Rhombohedral cell)"; if(mExtension=='H') extension=" (Using Hexagonal cell)"; #ifdef __DEBUG__ (*fpObjCrystInformUser)("Initialized spacegroup, HM: "+spgId+extension+" , Hall:"+this->GetCCTbxSpg().type().hall_symbol()); #endif VFN_DEBUG_EXIT("SpaceGroup::InitSpaceGroup():"< //#include "cctbx/sgtbx/space_group.h" namespace cctbx{namespace sgtbx{class space_group;}} namespace ObjCryst { class SpaceGroup; //###################################################################### // AsymmetricUnit. /** * * \brief The basic description of spacegroup asymmetric unit. * * Only xmin,xmax,ymin,ymax and zmin,zmax are recorded, thus resulting * in a parallelepipedic unit with one (0,0,0) corner. * It is not really 'asymmetric' since more than the crystallographic asymmetric * unit can be included in it. * * \todo Currently the initialization of the asymmetric unit is done * numerically, slowly. A faster algorithm should be used (using * dichotomy), or we could switch to using a table of asymmetric units. */ //###################################################################### class AsymmetricUnit { public: /// Default Constructor. AsymmetricUnit(); /// Constructor, for a given spacegroup. AsymmetricUnit(const SpaceGroup &spg); ~AsymmetricUnit(); /// Assign a SpaceGroup and generate the corrsponding Xmax, Ymax, ZMax. void SetSpaceGroup(const SpaceGroup &spg); /// Test if (x,y,z) is in the asymmetric unit bool IsInAsymmetricUnit(const REAL x, const REAL y, const REAL z)const; REAL Xmin() const; REAL Xmax() const; REAL Ymin() const; REAL Ymax() const; REAL Zmin() const; REAL Zmax() const; protected: private: REAL mXmin,mXmax,mYmin,mYmax,mZmin,mZmax; }; //###################################################################### // SpaceGroup /** * \brief The crystallographic space group, and the cell choice. * * This class includes functions to get basic information about * the symmetries, as well as getting all symmetrics for a given * position in a unit cell. * * This class included a pointer to a function calculating the "geometrical * structure factor" (ie the sum of sin() and cos() for all symetrics, as * could be found in the old version of the (red) International Tables), * which was used to speed up computation of structure factors * by using pre-factorised formulas. * This is not used anymore, since methods can be used to speed up computations. * * This class uses R. Grosse-Kunstleve 'SgLite' package, * which is part of the Pymol package : http://pymol.sourceforge.net/ * *\warning: the interface of the class will somewhat change when switching * from sgLite to cctbx (http://cctbx.sourceforge.net). Particularly * functions Spacegroup::GetSgOps() and Spacegroup::GetHM_as_Hall() will * be removed. */ //###################################################################### class SpaceGroup { public: /// Default Constructor (initializes in P1) /// /// You can use later SpaceGroup::ChangeSpaceGroup() to set the spacegroup. SpaceGroup(); /** \brief Constructor with a specified spacegroup symbol or number * * \param spgId The space group identifier, either an Hermann-Maugin, * or Hall, or Schonflies symbol. */ SpaceGroup(const string &spgId); /// Destructor ~SpaceGroup(); /// Change the Spacegroup void ChangeSpaceGroup(const string &spgId); /// Get the name of this spacegroup (its name, as supplied initially by /// the calling program or user) const string& GetName()const; /// Test if a given scatterer at (x,y,z) is in the asymmetric unit. bool IsInAsymmetricUnit(const REAL x, const REAL y, const REAL z) const; /// Move (x,y,z) coordinates to their equivalent in the asym unit /// \warning Not implemented yet. /// \todo SpaceGroup::IsInAsymmetricUnit() void ChangeToAsymmetricUnit(REAL x, REAL y, REAL z) const;//:TODO: /// Get the AsymmetricUnit for this spacegroup const AsymmetricUnit& GetAsymUnit() const; /// Id number of the spacegroup int GetSpaceGroupNumber()const; /// Is the crystal centrosymmetric ? bool IsCentrosymmetric()const; /** \brief Number of translation vectors * (1 for 'P' cells, 2 for 'I', 4 for 'F',etc..) * */ int GetNbTranslationVectors()const; /// Struct to store trans matrix struct TRx { REAL tr[3]; }; /// Struct to store rot+trans matrix struct SMx { REAL mx[9]; REAL tr[3]; }; /** Return all Translation Vectors, as a 3 columns-array * * The first vector is always [0,0,0] * \return * \f$ \left[ \begin {array}{ccc} 0 & 0 & 0 \end{array} \right] \f$ * for a 'P' Cell, * \f$ \left[ \begin {array}{ccc} 0 & 0 & 0 \\ * \frac{1}{2} & \frac{1}{2} & \frac{1}{2} \\ \end{array} \right] \f$ * for a 'I' cell, and * \f$ \left[ \begin {array}{ccc} 0 & 0 & 0 \\ * \frac{1}{2} & \frac{1}{2} & 0 \\ * \frac{1}{2} & 0 & \frac{1}{2} \\ * 0 & \frac{1}{2} & \frac{1}{2} \\ \end{array} \right] \f$ *for a 'F' cell,etc... */ const std::vector& GetTranslationVectors()const; /** Get all symmetry operations stored in vector of struct SMx. */ const std::vector& GetSymmetryOperations()const; /** \brief Get all equivalent positions of a (xyz) position * * \param x,y,z fractional coordinates of the position * \param noCenter if set to 'false' (the default), then the center of * symmetry (if any) is used to generate ALL positions. If 'true', then * only one half of equivalent positions are generated. This has * no influence if the group is not centrosymmetric. (\b note Not generating * symmetrical positions from center of symmetry is useful to speed up computation * of structure factor, but is a bit tricky if the inversion is not at the origin. * This is taken into account) * \param noTransl if set to 'false' (the default), then translation are * taken into account to generate all atom positions. This affect * only body or face(s)-centered spacegroups. * \param noIdentical if set to true, then atom in special positions * will only return the distinct atomic positions. Currently two atoms are considered * distinct if the difference for all of their fractionnal coordinates is less than 1e-5 * \return a 3-column (x,y,z) matrix with as many rows as symmetric atoms * \warning 'special' positions are not taken into account. (ie an * atom in special position will return duplicate entries. This may be * corrected automatically later.) You can use the 'noIdentical' option for that, */ CrystMatrix_REAL GetAllSymmetrics(const REAL x, const REAL y, const REAL z, const bool noCenter=false,const bool noTransl=false, const bool noIdentical=false) const; /** \brief Get all equivalent positions of a (xyz) position * * \param x,y,z: fractional coordinates of the position. On return, * these will contain the new values. * \param noCenter if set to 'false' (the default), then the center of * symmetry (if any) is used to generate ALL positions. If 'true', then * only one half of equivalent positions are generated. This has * no influence if the group is not centrosymmetric. (\b note Not generating * symmetrical positions from center of symmetry is useful to speed up computation * of structure factor, but is a bit tricky if the inversion is not at the origin. * This is taken into account) * \param noTransl if set to 'false' (the default), then translation are * taken into account to generate all atom positions. This affect * only body or face(s)-centered spacegroups. * \param derivative: if true, then this is used to calculate the displacement * vector of s symmetric, given the orginal (dx,dy,dz)=> the translation * components of gliding axis/plane are then ignored. */ void GetSymmetric(unsigned int i, REAL &x, REAL &y, REAL &z, const bool noCenter=false,const bool noTransl=false, const bool derivative=false) const; /** \brief Return the number of equivalent positions in the spacegroup, *ie the multilicity of the general position. * * \param noCenter if 'true', do not take into account the center of symmetry * \param noTransl if 'true', do not take into account translations */ int GetNbSymmetrics(const bool noCenter=false,const bool noTransl=false)const; /// Prints a description of the spacegroup (symbol, properties). /// /// \todo void Print()const; /// Is centrosymmetric ? bool HasInversionCenter()const; /// Is the center of symmetry at the origin ? bool IsInversionCenterAtOrigin()const; /// Get the underlying cctbx Spacegroup object const cctbx::sgtbx::space_group& GetCCTbxSpg()const; /// Get the SpaceGroup Clock (corresponding to the time of the /// initialization of the SpaceGroup) const RefinableObjClock& GetClockSpaceGroup() const; /// Which is the unique axis (for monoclinic space groups ) unsigned int GetUniqueAxis()const; /// Extension to space group symbol ('1','2':origin choice ; 'R','H'=rhomboedral/hexagonal) char GetExtension()const; /// Get the inversion center CrystVector_REAL GetInversionCenter()const; /** Are these reflections equivalent ? * * \return 1 if they are equivalent, 2 if they are Friedel/Bijvoet mates, and else 0. */ unsigned int AreReflEquiv(const REAL h1, const REAL k1, const REAL l1, const REAL h2, const REAL k2, const REAL l2)const; /** Get the list of all equivalent reflections. * * \return a matrix with 5 columns for h,k,l,Re(F),Im(F) and as many rows as there are * reflections (the input reflection is included), with the associated structure factor, * from the structure factor of the input reflection. * \param excludeFriedelMate if true, then Friedel mates of reflections will not * be listed, even if there is a center of symmetry. * \param forceFriedelLaw if true, a center of symmetry will be added (to force * considering Friedel mates as equivalent). This as no effect if * excludeFriedelMate=true * * \param sf_re, sf_im: the real & imaginary part of the structure factor of the original reflection */ CrystMatrix_REAL GetAllEquivRefl(const REAL h, const REAL k, const REAL l, const bool excludeFriedelMate=false, const bool forceFriedelLaw=false, const REAL sf_re=0,const REAL sf_im=0) const; /// Is the reflection systematically absent ? bool IsReflSystematicAbsent(const REAL h, const REAL k, const REAL l)const; /// Is the reflection centric ? bool IsReflCentric(const REAL h, const REAL k, const REAL l)const; /** Get the "expected intensity factor" for a given reflection. * This is the * number of times the reflection is identical to the reflections deduced by * the symmetry operators, under all distinct pure rotationnal symmetry operations * of the space group. * * This is used for the probability distribution of reflection intensities. * * See: * - Stewart & Karle, Acta. Cryst 132 (1976), 1005 * - Wilson, Acta Cryst 3 (1950), 258 */ unsigned int GetExpectedIntensityFactor(const REAL h, const REAL k, const REAL l)const; protected: private: /** \brief Init the spaceGroup object from its name * *Initialize the SgOps & HM_as_Hall structures (SgLite), *and set the function pointers to the functions used to *compute the geometrical structure factors. */ void InitSpaceGroup(const string &spgId); /// Spacegroup's name ( 'I422', 'D2^8','230') /// Maybe we should only store the Hermann-Mauguin symbol, rather than storing /// the string which was initially given by the user/program for the initialization. string mId; /** \brief SgOps structure for this spacegroup. (Symmetry operations) * * See sglite subdirectory for more information. * This is (c) R. Gross-Kunstleve, part of PyMol software * http://pymol.sourceforge.net/ */ cctbx::sgtbx::space_group *mpCCTbxSpaceGroup; /** \brief Is spacegroup centrosymmetric ? * */ bool mHasInversionCenter; /** \brief Is center of symmetry at the origin ? * */ bool mIsInversionCenterAtOrigin; /// The spacegroup asymmetric unit AsymmetricUnit mAsymmetricUnit; /// The Spacegroup clock RefinableObjClock mClock; /// Unique axis number (0=a,1=b,2=c) unsigned int mUniqueAxisId; /// Number of symmetry operations (excluding center, and translations). unsigned long mNbSym; /// Number of lattice translations, including (0,0,0). unsigned long mNbTrans; /// SpaceGroup Number unsigned long mSpgNumber; /// Extension to space group symbol (1,2:origin choice ; R,H=rhomboedral/hexagonal) char mExtension; /// Store floating-point matrices for faster use std::vector mvSym; /// Store floating-point translation vectors for faster use std::vector mvTrans; }; }//namespace #endif //_OBJCRYST_SPACEGROUP_H_ objcryst-2022.1/ObjCryst/ObjCryst/Undo.cpp000066400000000000000000000450031430515525000203500ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000- Vincent Favre-Nicolin vincefn@gmail.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include "ObjCryst/ObjCryst/Undo.h" namespace ObjCryst { XMLConfigHistory gConfigHistory; //////////////////////////////////////////////////////////////////////// // // XMLConfig // //////////////////////////////////////////////////////////////////////// XMLConfig::XMLConfig() { mClock.Click(); mTime = boost::posix_time::second_clock::local_time(); for(std::vector::const_iterator pos=gCrystalRegistry.begin();pos!=gCrystalRegistry.end();++pos) { VFN_DEBUG_MESSAGE("XMLConfig::XMLConfig(): storing "<< (*pos)->GetClassName() << ":" << (*pos)->GetName(), 10) stringstream ss; (*pos)->XMLOutput(ss,0); mvpCrystalXML[*pos] = boost::shared_ptr(new std::string(ss.str())); } for(std::vector::const_iterator pos=gDiffractionDataSingleCrystalRegistry.begin();pos!=gDiffractionDataSingleCrystalRegistry.end();++pos) { VFN_DEBUG_MESSAGE("XMLConfig::XMLConfig(): storing "<< (*pos)->GetClassName() << ":" << (*pos)->GetName(), 10) stringstream ss; (*pos)->XMLOutput(ss,0); mvpDiffractionDataSingleCrystalXML[*pos] = boost::shared_ptr(new std::string(ss.str())); } for(std::vector::const_iterator pos=gPowderPatternRegistry.begin();pos!=gPowderPatternRegistry.end();++pos) { VFN_DEBUG_MESSAGE("XMLConfig::XMLConfig(): storing "<< (*pos)->GetClassName() << ":" << (*pos)->GetName(), 10) stringstream ss; (*pos)->XMLOutput(ss,0); mvpPowderPatternXML[*pos] = boost::shared_ptr(new std::string(ss.str())); } for(std::vector::const_iterator pos=gOptimizationObjRegistry.begin();pos!=gOptimizationObjRegistry.end();++pos) { VFN_DEBUG_MESSAGE("XMLConfig::XMLConfig(): storing "<< (*pos)->GetClassName() << ":" << (*pos)->GetName(), 10) stringstream ss; (*pos)->XMLOutput(ss,0); mvpOptimizationObjXML[*pos] = boost::shared_ptr(new std::string(ss.str())); } mClock.Click(); } XMLConfig::XMLConfig(const XMLConfig &old) { mTime = boost::posix_time::second_clock::local_time(); for(std::vector::const_iterator pos=gCrystalRegistry.begin();pos!=gCrystalRegistry.end();++pos) { VFN_DEBUG_MESSAGE("XMLConfig::XMLConfig(&old): storing "<< (*pos)->GetClassName() << ":" << (*pos)->GetName(), 10) std::map >::const_iterator pos2 = old.mvpCrystalXML.find(*pos); if(pos2 != old.mvpCrystalXML.end()) { if((*pos)->GetClockMaster() <= old.GetClock()) mvpCrystalXML[*pos] = boost::shared_ptr(pos2->second); else { stringstream ss; (*pos)->XMLOutput(ss,0); if(ss.str() == *(pos2->second)) mvpCrystalXML[*pos] = boost::shared_ptr(pos2->second); else mvpCrystalXML[*pos] = boost::shared_ptr(new std::string(ss.str())); } } else { stringstream ss; (*pos)->XMLOutput(ss,0); mvpCrystalXML[*pos] = boost::shared_ptr(new std::string(ss.str())); } } for(std::vector::const_iterator pos=gDiffractionDataSingleCrystalRegistry.begin();pos!=gDiffractionDataSingleCrystalRegistry.end();++pos) { VFN_DEBUG_MESSAGE("XMLConfig::XMLConfig(&old): storing "<< (*pos)->GetClassName() << ":" << (*pos)->GetName(), 10) std::map >::const_iterator pos2 = old.mvpDiffractionDataSingleCrystalXML.find(*pos); if(pos2 != old.mvpDiffractionDataSingleCrystalXML.end()) { if((*pos)->GetClockMaster() <= old.GetClock()) mvpDiffractionDataSingleCrystalXML[*pos] = boost::shared_ptr(pos2->second); else { stringstream ss; (*pos)->XMLOutput(ss,0); if(ss.str() == *(pos2->second)) mvpDiffractionDataSingleCrystalXML[*pos] = boost::shared_ptr(pos2->second); else mvpDiffractionDataSingleCrystalXML[*pos] = boost::shared_ptr(new std::string(ss.str())); } } else { stringstream ss; (*pos)->XMLOutput(ss,0); mvpDiffractionDataSingleCrystalXML[*pos] = boost::shared_ptr(new std::string(ss.str())); } } for(std::vector::const_iterator pos=gPowderPatternRegistry.begin();pos!=gPowderPatternRegistry.end();++pos) { VFN_DEBUG_MESSAGE("XMLConfig::XMLConfig(&old): storing "<< (*pos)->GetClassName() << ":" << (*pos)->GetName(), 10) std::map >::const_iterator pos2 = old.mvpPowderPatternXML.find(*pos); if(pos2 != old.mvpPowderPatternXML.end()) { if((*pos)->GetClockMaster() <= old.GetClock()) mvpPowderPatternXML[*pos] = boost::shared_ptr(pos2->second); else { stringstream ss; (*pos)->XMLOutput(ss,0); if(ss.str() == *(pos2->second)) mvpPowderPatternXML[*pos] = boost::shared_ptr(pos2->second); else mvpPowderPatternXML[*pos] = boost::shared_ptr(new std::string(ss.str())); } } else { stringstream ss; (*pos)->XMLOutput(ss,0); mvpPowderPatternXML[*pos] = boost::shared_ptr(new std::string(ss.str())); } } for(std::vector::const_iterator pos=gOptimizationObjRegistry.begin();pos!=gOptimizationObjRegistry.end();++pos) { VFN_DEBUG_MESSAGE("XMLConfig::XMLConfig(&old): storing "<< (*pos)->GetClassName() << ":" << (*pos)->GetName(), 10) std::map >::const_iterator pos2 = old.mvpOptimizationObjXML.find(*pos); if(pos2 != old.mvpOptimizationObjXML.end()) { stringstream ss; (*pos)->XMLOutput(ss,0); if(ss.str() == *(pos2->second)) mvpOptimizationObjXML[*pos] = boost::shared_ptr(pos2->second); else mvpOptimizationObjXML[*pos] = boost::shared_ptr(new std::string(ss.str())); } else { stringstream ss; (*pos)->XMLOutput(ss,0); mvpOptimizationObjXML[*pos] = boost::shared_ptr(new std::string(ss.str())); } } mClock.Click(); } void XMLConfig::Restore() { VFN_DEBUG_ENTRY("XMLConfig::Restore()", 10) std::list vpRefObjUpdated; std::list vpOptimObjUpdated; std::list vpRefObjDeleted; std::list vpOptimObjDeleted; // Restore objects configuration and load new ones for(std::map >::const_iterator pos= mvpCrystalXML.begin(); pos!=mvpCrystalXML.end();++pos) { VFN_DEBUG_MESSAGE("XMLConfig::Restore(): found "<< pos->first->GetClassName() << ":" << pos->first->GetName(), 10) Crystal *p; if(gCrystalRegistry.Find(pos->first) >= 0) { p = pos->first; stringstream ss; p->XMLOutput(ss,0); if(ss.str()== *(pos->second)) continue; } else p = new Crystal; stringstream ss; ss << *(pos->second); VFN_DEBUG_MESSAGE("XMLConfig::Restore():Crystal:xml="<<*(pos->second), 5) VFN_DEBUG_MESSAGE("XMLConfig::Restore():Crystal:xml="<GetClassName()<<":"<GetName(), 10) p->XMLInput(ss,tag); VFN_DEBUG_EXIT("XMLConfig::Restore()"<GetClassName()<<":"<GetName(), 10) vpRefObjUpdated.push_back(p); } for(std::map >::const_iterator pos= mvpDiffractionDataSingleCrystalXML.begin(); pos!=mvpDiffractionDataSingleCrystalXML.end();++pos) { VFN_DEBUG_MESSAGE("XMLConfig::Restore(): found "<< pos->first->GetClassName() << ":" << pos->first->GetName(), 10) DiffractionDataSingleCrystal *p; if(gDiffractionDataSingleCrystalRegistry.Find(pos->first) >= 0) { p = pos->first; stringstream ss; p->XMLOutput(ss,0); if(ss.str()== *(pos->second)) continue; } else p = new DiffractionDataSingleCrystal; stringstream ss; ss << pos->second; XMLCrystTag tag(ss); VFN_DEBUG_ENTRY("XMLConfig::Restore()"<GetClassName()<<":"<GetName(), 10) p->XMLInput(ss,tag); VFN_DEBUG_EXIT("XMLConfig::Restore()"<GetClassName()<<":"<GetName(), 10) vpRefObjUpdated.push_back(p); } for(std::map >::const_iterator pos= mvpPowderPatternXML.begin(); pos!=mvpPowderPatternXML.end();++pos) { VFN_DEBUG_MESSAGE("XMLConfig::Restore(): found "<< pos->first->GetClassName() << ":" << pos->first->GetName(), 10) PowderPattern *p; if(gPowderPatternRegistry.Find(pos->first) >= 0) { p = pos->first; stringstream ss; p->XMLOutput(ss,0); if(ss.str()== *(pos->second)) continue; } else p = new PowderPattern; stringstream ss; ss << pos->second; XMLCrystTag tag(ss); VFN_DEBUG_ENTRY("XMLConfig::Restore()"<GetClassName()<<":"<GetName(), 10) p->XMLInput(ss,tag); VFN_DEBUG_EXIT("XMLConfig::Restore()"<GetClassName()<<":"<GetName(), 10) vpRefObjUpdated.push_back(p); } for(std::map >::const_iterator pos= mvpOptimizationObjXML.begin(); pos!=mvpOptimizationObjXML.end();++pos) { VFN_DEBUG_MESSAGE("XMLConfig::Restore(): found "<< pos->first->GetClassName() << ":" << pos->first->GetName(), 10) OptimizationObj *p; if(gOptimizationObjRegistry.Find(pos->first) >= 0) { p = pos->first; stringstream ss; p->XMLOutput(ss,0); if(ss.str()== *(pos->second)) continue; } else p = new MonteCarloObj; stringstream ss; ss << pos->second; XMLCrystTag tag(ss); VFN_DEBUG_ENTRY("XMLConfig::Restore()"<GetClassName()<<":"<GetName(), 10) p->XMLInput(ss,tag); VFN_DEBUG_EXIT("XMLConfig::Restore()"<GetClassName()<<":"<GetName(), 10) vpOptimObjUpdated.push_back(p); } // List objects which don't exist in the loaded configuration and which should be deleted for(std::vector::const_iterator pos=gCrystalRegistry.begin();pos!=gCrystalRegistry.end();++pos) if(mvpCrystalXML.find(*pos) == mvpCrystalXML.end()) vpRefObjDeleted.push_back(*pos); for(std::vector::const_iterator pos=gDiffractionDataSingleCrystalRegistry.begin();pos!=gDiffractionDataSingleCrystalRegistry.end();++pos) if(mvpDiffractionDataSingleCrystalXML.find(*pos) == mvpDiffractionDataSingleCrystalXML.end()) vpRefObjDeleted.push_back(*pos); for(std::vector::const_iterator pos=gPowderPatternRegistry.begin();pos!=gPowderPatternRegistry.end();++pos) if(mvpPowderPatternXML.find(*pos) == mvpPowderPatternXML.end()) vpRefObjDeleted.push_back(*pos); for(std::vector::const_iterator pos=gOptimizationObjRegistry.begin();pos!=gOptimizationObjRegistry.end();++pos) if(mvpOptimizationObjXML.find(*pos) == mvpOptimizationObjXML.end()) vpOptimObjDeleted.push_back(*pos); // Objects are destroyed after listing all, to avoid unvalidating the ObjRegistry containers (std::vector) // First optimisation obj, then diffraction data, then crystals for(std::list::const_iterator pos = vpOptimObjDeleted.begin();pos!=vpOptimObjDeleted.end();++pos) { VFN_DEBUG_MESSAGE("XMLConfig::Restore(): deleting "<< (*pos)->GetClassName() << ":" << (*pos)->GetName(), 10) delete *pos; } for(std::list::const_reverse_iterator pos = vpRefObjDeleted.rbegin();pos!=vpRefObjDeleted.rend();++pos) { VFN_DEBUG_MESSAGE("XMLConfig::Restore(): deleting "<< (*pos)->GetClassName() << ":" << (*pos)->GetName(), 10) delete *pos; } // Update display. Order should not matter for(std::list::const_iterator pos = vpOptimObjUpdated.begin() ; pos!=vpOptimObjUpdated.end() ; ++pos) (*pos)->UpdateDisplay(); for(std::list::const_iterator pos = vpRefObjUpdated.begin() ; pos!=vpRefObjUpdated.end() ; ++pos) (*pos)->UpdateDisplay(); VFN_DEBUG_EXIT("XMLConfig::Restore()", 10) } bool XMLConfig::operator==(const ObjCryst::XMLConfig &rhs) const { if(mvpCrystalXML.size() != rhs.mvpCrystalXML.size()) return false; if(mvpDiffractionDataSingleCrystalXML.size() != rhs.mvpDiffractionDataSingleCrystalXML.size()) return false; if(mvpPowderPatternXML.size() != rhs.mvpPowderPatternXML.size()) return false; if(mvpOptimizationObjXML.size() != rhs.mvpOptimizationObjXML.size()) return false; for(std::map >::const_iterator pos = mvpCrystalXML.begin(); pos!=mvpCrystalXML.end(); pos++) { std::map >::const_iterator pos2 = rhs.mvpCrystalXML.find(pos->first); if(pos2==rhs.mvpCrystalXML.end()) return false; if(*(pos->second) != *(pos2->second)) return false; } for(std::map >::const_iterator pos = mvpDiffractionDataSingleCrystalXML.begin(); pos!=mvpDiffractionDataSingleCrystalXML.end(); pos++) { std::map >::const_iterator pos2 = rhs.mvpDiffractionDataSingleCrystalXML.find(pos->first); if(pos2==rhs.mvpDiffractionDataSingleCrystalXML.end()) return false; if(*(pos->second) != *(pos2->second)) return false; } for(std::map >::const_iterator pos = mvpPowderPatternXML.begin(); pos!=mvpPowderPatternXML.end(); pos++) { std::map >::const_iterator pos2 = rhs.mvpPowderPatternXML.find(pos->first); if(pos2==rhs.mvpPowderPatternXML.end()) return false; if(*(pos->second) != *(pos2->second)) return false; } for(std::map >::const_iterator pos = mvpOptimizationObjXML.begin(); pos!=mvpOptimizationObjXML.end(); pos++) { std::map >::const_iterator pos2 = rhs.mvpOptimizationObjXML.find(pos->first); if(pos2==rhs.mvpOptimizationObjXML.end()) return false; if(*(pos->second) != *(pos2->second)) return false; } return true; } bool XMLConfig::operator!=(const ObjCryst::XMLConfig &rhs) const { return !(this->operator==(rhs)); } const RefinableObjClock& XMLConfig::GetClock() const { return mClock;} //////////////////////////////////////////////////////////////////////// // // XMLConfigHistory // //////////////////////////////////////////////////////////////////////// XMLConfigHistory::XMLConfigHistory(const int maxnb): mMaxNb(maxnb), mpCurrentConfig(), mLock(false) {} bool XMLConfigHistory::Store() { if(mLock) return false; mLock=true; VFN_DEBUG_ENTRY("XMLConfigHistory::Store()", 10) if(mvpConfig.size()==0) mvpConfig.push_front(boost::shared_ptr(new XMLConfig)); else { boost::shared_ptr previous = mpCurrentConfig; if(mpCurrentConfig==NULL) // C++11 could use nullptr previous = mvpConfig.front(); boost::shared_ptr newconf(new XMLConfig(*previous)); if(*newconf == *previous) { VFN_DEBUG_EXIT("XMLConfigHistory::Store(): nothing new", 10) mLock=false; return false; } mvpConfig.push_front(newconf); } mpCurrentConfig = boost::shared_ptr(); if(mvpConfig.size()>mMaxNb) mvpConfig.pop_back(); (*fpObjCrystInformUser)("XMLConfigHistory::Store()"); VFN_DEBUG_EXIT("XMLConfigHistory::Store(): new config", 10) mLock=false; return true; } void XMLConfigHistory::Restore(boost::shared_ptr &p) { mLock=true; p->Restore(); mpCurrentConfig = p; mLock=false; } std::list > XMLConfigHistory::GetList() { return mvpConfig;} const std::list > XMLConfigHistory::GetList() const { return mvpConfig;} bool XMLConfigHistory::Previous() { if(mvpConfig.size()==0) return false; if(mpCurrentConfig == mvpConfig.back()) { fpObjCrystInformUser("XMLConfigHistory::Previous(): already at last stored configuration"); return false; } mLock=true; boost::shared_ptr p; if(mpCurrentConfig==NULL) p = mvpConfig.front(); else { std::list >::const_iterator pos; for(pos=mvpConfig.begin();pos!=mvpConfig.end();++pos) if(*pos == mpCurrentConfig) {++pos ; break;} p = *pos; } (*fpObjCrystInformUser)("XMLConfigHistory::Previous()"); mpCurrentConfig = p; p->Restore(); mLock=false; return true; } bool XMLConfigHistory::Next() { if((mvpConfig.size()==0) || (mpCurrentConfig==NULL)) return false; if(mpCurrentConfig == mvpConfig.front()) { fpObjCrystInformUser("XMLConfigHistory::Next(): already at first stored configuration"); return false; } mLock=true; (*fpObjCrystInformUser)("XMLConfigHistory::Next()"); std::list >::const_reverse_iterator pos; for(pos=mvpConfig.rbegin();pos!=mvpConfig.rend();++pos) if(*pos == mpCurrentConfig) {++pos ; break;} (*pos)->Restore(); mpCurrentConfig = *pos; mLock=false; return true; } } // namespace ObjCryst objcryst-2022.1/ObjCryst/ObjCryst/Undo.h000066400000000000000000000100111430515525000200040ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000- Vincent Favre-Nicolin vincefn@gmail.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _OBJCRYST_UNDO_H_ #define _OBJCRYST_UNDO_H_ #include #include // With C++11, could used std shared_ptr instead of boost #include #include #include "ObjCryst/RefinableObj/IO.h" #include "ObjCryst/ObjCryst/Crystal.h" #include "ObjCryst/ObjCryst/PowderPattern.h" #include "ObjCryst/ObjCryst/DiffractionDataSingleCrystal.h" #include "ObjCryst/RefinableObj/GlobalOptimObj.h" namespace ObjCryst { /** Class to store & restore all top-level ObjCryst++ objects as their XML description. * Storage uses a shared_ptr to avoid useless copies. * */ class XMLConfig { public: /// Default cronstructor XMLConfig(); /// Constructor based on a previous instance XMLConfig(const XMLConfig &old); /// Restore the saved XML configuration void Restore(); /// Equality operator bool operator==(const XMLConfig &rhs) const; /// Non-equality operator bool operator!=(const XMLConfig &rhs) const; /// Access the clock corresponding to the creation of this config const RefinableObjClock& GetClock() const; protected: std::map > mvpCrystalXML; std::map > mvpPowderPatternXML; std::map > mvpDiffractionDataSingleCrystalXML; std::map > mvpOptimizationObjXML; boost::posix_time::ptime mTime; /// Clock recording the creation of this XMLConfig RefinableObjClock mClock; }; /** Class to store XMLConfig configurations * */ class XMLConfigHistory { public: /** Constructor * \param maxnb: maximum size of history */ XMLConfigHistory(const int maxnb=20); /// Store a new configuration. If there is no difference with the previous one, /// nothing is done. /// \return: true if a new configuration was saved, false otherwise bool Store(); /// Restore a configuration void Restore(boost::shared_ptr &p); /// Access the list of configurations std::list > GetList(); /// Access the list of configurations const std::list > GetList() const; /** Reload the previous (older) configuration in the list * \return: true if the loading was done, false otherwise (no available configuration or last) */ bool Previous(); /** Reload the next (more recent) configuration in the list * \return: true if the loading was done, false otherwise (no available configuration or last) */ bool Next(); private: /// Maximum number of stored configurations int mMaxNb; /// List of configurations std::list > mvpConfig; /// The current configuration loaded (can be null if none is selected) /// This is reset every time a change is manually made boost::shared_ptr mpCurrentConfig; /// Lock used during Store and Restore bool mLock; }; /// Global object to hold configurations history extern XMLConfigHistory gConfigHistory; } #endif //_OBJCRYST_UNDO_H_ objcryst-2022.1/ObjCryst/ObjCryst/UnitCell.cpp000066400000000000000000000505641430515525000211720ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * source file ObjCryst++ Crystal class * */ #include "ObjCryst/ObjCryst/UnitCell.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" namespace ObjCryst { const RefParType *gpRefParTypeUnitCell=0; const RefParType *gpRefParTypeUnitCellLength=0; const RefParType *gpRefParTypeUnitCellAngle=0; long NiftyStaticGlobalObjectsInitializer_UnitCell::mCount=0; UnitCell::UnitCell(): mCellDim(6), mBMatrix(3,3),mOrthMatrix(3,3),mOrthMatrixInvert(3,3) { VFN_DEBUG_MESSAGE("UnitCell::UnitCell()",10) this->InitOptions(); this->Init(10,11,12,M_PI/2+.1,M_PI/2+.2,M_PI/2+.3,"P 1",""); mClockMaster.AddChild(mClockLatticePar); mClockMaster.AddChild(this->GetSpaceGroup().GetClockSpaceGroup()); } UnitCell::UnitCell(const REAL a, const REAL b, const REAL c, const string &SpaceGroupId): mCellDim(6), mBMatrix(3,3),mOrthMatrix(3,3),mOrthMatrixInvert(3,3) { VFN_DEBUG_MESSAGE("UnitCell::UnitCell(a,b,c,Sg)",10) this->Init(a,b,c,M_PI/2,M_PI/2,M_PI/2,SpaceGroupId,""); this->InitOptions(); mClockMaster.AddChild(mClockLatticePar); mClockMaster.AddChild(this->GetSpaceGroup().GetClockSpaceGroup()); } UnitCell::UnitCell(const REAL a, const REAL b, const REAL c, const REAL alpha, const REAL beta, const REAL gamma,const string &SpaceGroupId): mCellDim(6), mBMatrix(3,3),mOrthMatrix(3,3),mOrthMatrixInvert(3,3) { VFN_DEBUG_MESSAGE("UnitCell::UnitCell(a,b,c,alpha,beta,gamma,Sg)",10) this->Init(a,b,c,alpha,beta,gamma,SpaceGroupId,""); this->InitOptions(); mClockMaster.AddChild(mClockLatticePar); mClockMaster.AddChild(this->GetSpaceGroup().GetClockSpaceGroup()); } UnitCell::UnitCell(const UnitCell &old): mCellDim(old.mCellDim),mSpaceGroup(old.GetSpaceGroup()), mBMatrix(3,3),mOrthMatrix(3,3),mOrthMatrixInvert(3,3) { VFN_DEBUG_MESSAGE("UnitCell::UnitCell(&oldUnitCell)",10) this ->InitRefParList(); mConstrainLatticeToSpaceGroup.SetChoice(old.mConstrainLatticeToSpaceGroup.GetChoice()); this->InitMatrices(); this->UpdateLatticePar(); mClockMaster.AddChild(mClockLatticePar); mClockMaster.AddChild(this->GetSpaceGroup().GetClockSpaceGroup()); } UnitCell::~UnitCell() { VFN_DEBUG_ENTRY("UnitCell::~UnitCell()",5) VFN_DEBUG_EXIT("UnitCell::~UnitCell()",5) } const string& UnitCell::GetClassName() const { const static string className="UnitCell"; return className; } CrystVector_REAL UnitCell::GetLatticePar() const { VFN_DEBUG_MESSAGE("UnitCell::GetLatticePar()",0) if(mClockLatticeParUpdate>mClockLatticePar) return mCellDim; else { //:NOTE: cannot use this->UpdateLatticePar() because it is not a const member function int num = mSpaceGroup.GetSpaceGroupNumber(); CrystVector_REAL cellDim=mCellDim; if((num <=2)||(mConstrainLatticeToSpaceGroup.GetChoice()!=0)) return cellDim; if((num <=15) && (0==mSpaceGroup.GetUniqueAxis())) { cellDim(4)=M_PI/2.; cellDim(5)=M_PI/2.; return cellDim; } if((num <=15) && (1==mSpaceGroup.GetUniqueAxis())) { cellDim(3)=M_PI/2.; cellDim(5)=M_PI/2.; return cellDim; } if((num <=15) && (2==mSpaceGroup.GetUniqueAxis())) { cellDim(3)=M_PI/2.; cellDim(4)=M_PI/2.; return cellDim; } if(num <=74) { cellDim(3)=M_PI/2.; cellDim(4)=M_PI/2.; cellDim(5)=M_PI/2.; return cellDim; } if(num <= 142) { cellDim(3)=M_PI/2.; cellDim(4)=M_PI/2.; cellDim(5)=M_PI/2.; cellDim(1) = mCellDim(0) ; return cellDim; } if(mSpaceGroup.GetExtension()=='R') { cellDim(4) = mCellDim(3); cellDim(5) = mCellDim(3); cellDim(1) = mCellDim(0); cellDim(2) = mCellDim(0); return cellDim; } if(num <= 194) // || (mSpaceGroup.GetExtension()=='H') //Hexagonal {//Hexagonal axes, for hexagonal and non-rhomboedral trigonal cells cellDim(3) = M_PI/2.; cellDim(4) = M_PI/2.; cellDim(5) = M_PI*2./3.; cellDim(1) = mCellDim(0) ; return cellDim; } cellDim(3)=M_PI/2.; cellDim(4)=M_PI/2.; cellDim(5)=M_PI/2.; cellDim(1) = mCellDim(0) ; cellDim(2) = mCellDim(0) ; return cellDim; } } REAL UnitCell::GetLatticePar(int whichPar)const { VFN_DEBUG_MESSAGE("UnitCell::LatticePar(i)",0) if( (whichPar<0) || (whichPar>5)) throw ObjCrystException("UnitCell::LatticePar(int) :trying to access parameter>5!"); if(mClockLatticeParUpdate>mClockLatticePar) return mCellDim(whichPar); else { const int num = mSpaceGroup.GetSpaceGroupNumber(); static CrystVector_REAL cellDim; cellDim=mCellDim; if((num <=2)||(mConstrainLatticeToSpaceGroup.GetChoice()!=0)) return cellDim(whichPar); if((num <=15) && (0==mSpaceGroup.GetUniqueAxis())) { cellDim(4)=M_PI/2.; cellDim(5)=M_PI/2.; return cellDim(whichPar); } if((num <=15) && (1==mSpaceGroup.GetUniqueAxis())) { cellDim(3)=M_PI/2.; cellDim(5)=M_PI/2.; return cellDim(whichPar); } if((num <=15) && (2==mSpaceGroup.GetUniqueAxis())) { cellDim(3)=M_PI/2.; cellDim(4)=M_PI/2.; return cellDim(whichPar); } if(num <=74) { cellDim(3)=M_PI/2.; cellDim(4)=M_PI/2.; cellDim(5)=M_PI/2.; return cellDim(whichPar); } if(num <= 142) { cellDim(3)=M_PI/2.; cellDim(4)=M_PI/2.; cellDim(5)=M_PI/2.; cellDim(1) = mCellDim(0) ; return cellDim(whichPar); } if(mSpaceGroup.GetExtension()=='R') { cellDim(4) = mCellDim(3); cellDim(5) = mCellDim(3); cellDim(1) = mCellDim(0); cellDim(2) = mCellDim(0); return cellDim(whichPar); } if(num <= 194) // ||(mSpaceGroup.GetExtension()=='H') {//Hexagonal axes, for hexagonal and non-rhomboedral trigonal cells cellDim(3) = M_PI/2.; cellDim(4) = M_PI/2.; cellDim(5) = M_PI*2./3.; cellDim(1) = mCellDim(0) ; return cellDim(whichPar); } cellDim(3)=M_PI/2.; cellDim(4)=M_PI/2.; cellDim(5)=M_PI/2.; cellDim(1) = mCellDim(0) ; cellDim(2) = mCellDim(0) ; return cellDim(whichPar); } } const CrystMatrix_REAL& UnitCell::GetBMatrix()const { VFN_DEBUG_MESSAGE("UnitCell::GetBMatrix()",0) this->InitMatrices(); return mBMatrix; } const CrystMatrix_REAL& UnitCell::GetOrthMatrix() const { VFN_DEBUG_MESSAGE("UnitCell::GetOrthMatrix()",0) this->InitMatrices(); return mOrthMatrix; } CrystVector_REAL UnitCell::GetOrthonormalCoords(const REAL x, const REAL y, const REAL z) const { this->InitMatrices(); CrystVector_REAL coords(3); coords(0)=mOrthMatrix(0,0)*x+mOrthMatrix(0,1)*y+mOrthMatrix(0,2)*z; coords(1)=mOrthMatrix(1,0)*x+mOrthMatrix(1,1)*y+mOrthMatrix(1,2)*z; coords(2)=mOrthMatrix(2,0)*x+mOrthMatrix(2,1)*y+mOrthMatrix(2,2)*z; return coords; } void UnitCell::FractionalToOrthonormalCoords(REAL &x,REAL &y,REAL &z) const { this->InitMatrices(); const REAL oldx=x; const REAL oldy=y; x=mOrthMatrix(0,0)*oldx+mOrthMatrix(0,1)*oldy+mOrthMatrix(0,2)*z; y=mOrthMatrix(1,0)*oldx+mOrthMatrix(1,1)*oldy+mOrthMatrix(1,2)*z; z=mOrthMatrix(2,0)*oldx+mOrthMatrix(2,1)*oldy+mOrthMatrix(2,2)*z; } void UnitCell::OrthonormalToFractionalCoords(REAL &x,REAL &y,REAL &z) const { //cout << x << " " << y << " " << z <InitMatrices(); const REAL oldx=x; const REAL oldy=y; x=mOrthMatrixInvert(0,0)*oldx+mOrthMatrixInvert(0,1)*oldy+mOrthMatrixInvert(0,2)*z; y=mOrthMatrixInvert(1,0)*oldx+mOrthMatrixInvert(1,1)*oldy+mOrthMatrixInvert(1,2)*z; z=mOrthMatrixInvert(2,0)*oldx+mOrthMatrixInvert(2,1)*oldy+mOrthMatrixInvert(2,2)*z; //cout << x << " " << y << " " << z <InitMatrices(); const REAL oldx=x; const REAL oldy=y; x=mBMatrix(0,0)*oldx+mBMatrix(0,1)*oldy+mBMatrix(0,2)*z; y=mBMatrix(1,0)*oldx+mBMatrix(1,1)*oldy+mBMatrix(1,2)*z; z=mBMatrix(2,0)*oldx+mBMatrix(2,1)*oldy+mBMatrix(2,2)*z; } void UnitCell::OrthonormalToMillerCoords(REAL &x,REAL &y,REAL &z) const { this->InitMatrices(); const REAL oldx=x; const REAL oldy=y; x=mBMatrixInvert(0,0)*oldx+mBMatrixInvert(0,1)*oldy+mBMatrixInvert(0,2)*z; y=mBMatrixInvert(1,0)*oldx+mBMatrixInvert(1,1)*oldy+mBMatrixInvert(1,2)*z; z=mBMatrixInvert(2,0)*oldx+mBMatrixInvert(2,1)*oldy+mBMatrixInvert(2,2)*z; } void UnitCell::Print(ostream &os)const { VFN_DEBUG_MESSAGE("UnitCell::Print()",5) this->InitMatrices(); int width =8 ; os << "UnitCell : " << mName <<"("<GetSpaceGroup().GetName()<<")"<< endl; os.width(width); os << " Cell dimensions : " << FormatFloat(this->GetLatticePar(0),8,5) << " " << FormatFloat(this->GetLatticePar(1),8,5) << " " << FormatFloat(this->GetLatticePar(2),8,5) << " " << FormatFloat(this->GetLatticePar(3)*RAD2DEG,8,5) << " " << FormatFloat(this->GetLatticePar(4)*RAD2DEG,8,5) << " " << FormatFloat(this->GetLatticePar(5)*RAD2DEG,8,5) << endl ; } const SpaceGroup & UnitCell::GetSpaceGroup() const {return mSpaceGroup;} SpaceGroup & UnitCell::GetSpaceGroup() {return mSpaceGroup;} const RefinableObjClock& UnitCell::GetClockLatticePar()const {return mClockLatticePar;} const RefinableObjClock& UnitCell::GetClockMetricMatrix()const {return mClockMetricMatrix;} REAL UnitCell::GetVolume()const { const REAL a=this->GetLatticePar(0); const REAL b=this->GetLatticePar(1); const REAL c=this->GetLatticePar(2); const REAL alpha=this->GetLatticePar(3); const REAL beta=this->GetLatticePar(4); const REAL gamma=this->GetLatticePar(5); return a*b*c*sqrt(1-cos(alpha)*cos(alpha)-cos(beta)*cos(beta)-cos(gamma)*cos(gamma) +2*cos(alpha)*cos(beta)*cos(gamma)); } void UnitCell::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) { VFN_DEBUG_ENTRY("UnitCell::Init(a,b,c,alpha,beta,gamma,Sg,name)",10) //mSpaceGroup.Print(); mSpaceGroup.ChangeSpaceGroup(SpaceGroupId); //mSpaceGroup.Print(); mCellDim(0)=a; mCellDim(1)=b; mCellDim(2)=c; mCellDim(3)=alpha; mCellDim(4)=beta; mCellDim(5)=gamma; mClockLatticePar.Click(); mClockMetricMatrix.Reset(); mClockLatticeParUpdate.Reset(); this->InitRefParList(); this->InitMatrices(); this->UpdateLatticePar(); this->SetName(name); VFN_DEBUG_EXIT("UnitCell::Init(a,b,c,alpha,beta,gamma,Sg,name):End",10) } void UnitCell::InitOptions() { VFN_DEBUG_ENTRY("UnitCell::InitOptions",10) static string ConstrainLatticeToSpaceGroupName; static string ConstrainLatticeToSpaceGroupChoices[2]; static bool needInitNames=true; if(true==needInitNames) { ConstrainLatticeToSpaceGroupName="Constrain Lattice to SpaceGroup Symmetry"; ConstrainLatticeToSpaceGroupChoices[0]="Yes (Default)"; ConstrainLatticeToSpaceGroupChoices[1]="No (Allow Crystallographic Pseudo-Symmetry)"; needInitNames=false;//Only once for the class } VFN_DEBUG_MESSAGE("UnitCell::Init(a,b,c,alpha,beta,gamma,Sg,name):Init options",5) mConstrainLatticeToSpaceGroup.Init(2,&ConstrainLatticeToSpaceGroupName, ConstrainLatticeToSpaceGroupChoices); mConstrainLatticeToSpaceGroup.SetChoice(0); this->AddOption(&mConstrainLatticeToSpaceGroup); VFN_DEBUG_EXIT("UnitCell::InitOptions",10) } void UnitCell::InitMatrices() const { //:NOTE: The Matrices must remain upper triangular, since this is assumed for //optimization purposes in some procedures. if(mClockMetricMatrix>mClockLatticePar) return;//no need to update //this->UpdateLatticePar(); we should be able to do this... VFN_DEBUG_MESSAGE("UnitCell::InitMatrices() for crystal : "+this->GetName(),5) //mClockMetricMatrix.Print(); //mClockLatticePar.Print(); REAL a,b,c,alpha,beta,gamma;//direct space parameters REAL aa,bb,cc,alphaa,betaa,gammaa;//reciprocal space parameters REAL v;//volume of the unit cell a=this->GetLatticePar(0); b=this->GetLatticePar(1); c=this->GetLatticePar(2); alpha=this->GetLatticePar(3); beta=this->GetLatticePar(4); gamma=this->GetLatticePar(5); //cout <mSpaceGroup.GetClockSpaceGroup()) &&(mClockLatticeParUpdate>mClockLatticePar)) return; VFN_DEBUG_ENTRY("UnitCell::UpdateLatticePar().",3) int num = mSpaceGroup.GetSpaceGroupNumber(); if((num <=2)||(mConstrainLatticeToSpaceGroup.GetChoice()!=0)) { mClockLatticeParUpdate.Click(); return; } if((num <=15) && (0==mSpaceGroup.GetUniqueAxis())) { mCellDim(4)=M_PI/2.; mCellDim(5)=M_PI/2.; mClockLatticeParUpdate.Click(); return; } if((num <=15) && (1==mSpaceGroup.GetUniqueAxis())) { mCellDim(3)=M_PI/2.; mCellDim(5)=M_PI/2.; mClockLatticeParUpdate.Click(); return; } if((num <=15) && (2==mSpaceGroup.GetUniqueAxis())) { mCellDim(3)=M_PI/2.; mCellDim(4)=M_PI/2.; mClockLatticeParUpdate.Click(); return; } if(num <=74) { mCellDim(3)=M_PI/2.; mCellDim(4)=M_PI/2.; mCellDim(5)=M_PI/2.; mClockLatticeParUpdate.Click(); return; } if(num <= 142) { mCellDim(3)=M_PI/2.; mCellDim(4)=M_PI/2.; mCellDim(5)=M_PI/2.; mCellDim(1) = mCellDim(0) ; mClockLatticeParUpdate.Click(); return; } if(mSpaceGroup.GetExtension()=='R') { mCellDim(4) = mCellDim(3); mCellDim(5) = mCellDim(3); mCellDim(1) = mCellDim(0); mCellDim(2) = mCellDim(0); mClockLatticeParUpdate.Click(); return; } if(num <= 194) //||(mSpaceGroup.GetExtension()=='H') {//Hexagonal axes, for hexagonal and non-rhomboedral trigonal cells mCellDim(3) = M_PI/2.; mCellDim(4) = M_PI/2.; mCellDim(5) = M_PI*2./3.; mCellDim(1) = mCellDim(0) ; mClockLatticeParUpdate.Click(); return; } mCellDim(3)=M_PI/2.; mCellDim(4)=M_PI/2.; mCellDim(5)=M_PI/2.; mCellDim(1) = mCellDim(0) ; mCellDim(2) = mCellDim(0) ; mClockLatticeParUpdate.Click(); VFN_DEBUG_EXIT("UnitCell::UpdateLatticePar().",3) return; } void UnitCell::InitRefParList() { VFN_DEBUG_ENTRY("UnitCell::InitRefParList()",5) //this->ResetParList(); int num = mSpaceGroup.GetSpaceGroupNumber(); bool a=true; bool b=true; bool c=true; bool alpha=true; bool beta=true; bool gamma=true; if(mConstrainLatticeToSpaceGroup.GetChoice()==0) { if(num <=2) { } else if((num <=15) && (0==mSpaceGroup.GetUniqueAxis())) { beta=false; gamma=false; } else if((num <=15) && (1==mSpaceGroup.GetUniqueAxis())) { alpha=false; gamma=false; } else if((num <=15) && (2==mSpaceGroup.GetUniqueAxis())) { alpha=false; beta=false; } else if(num <=74) { alpha=false; beta=false; gamma=false; } else if(num <= 142) { b=false; alpha=false; beta=false; gamma=false; } else if(mSpaceGroup.GetExtension()=='R') {//Rhombohedral b=false; c=false; alpha=true; beta=false; gamma=false; } else if(num <= 194) {//Hexagonal axes, for hexagonal and non-rhomboedral trigonal cells b=false; alpha=false; beta=false; gamma=false; } else { b=false; c=false; alpha=false; beta=false; gamma=false; } } REAL *pLatPar=mCellDim.data(); if(this->GetNbPar()==0) {//:KLUDGE: { RefinablePar tmp("a",pLatPar,1.,100., gpRefParTypeUnitCellLength,REFPAR_DERIV_STEP_ABSOLUTE, true,true,a,false,1.0); tmp.SetDerivStep(1e-4); tmp.AssignClock(mClockLatticePar); this->AddPar(tmp); } { RefinablePar tmp("b",pLatPar+1,1.,100., gpRefParTypeUnitCellLength,REFPAR_DERIV_STEP_ABSOLUTE, true,true,b,false,1.0); tmp.SetDerivStep(1e-4); tmp.AssignClock(mClockLatticePar); this->AddPar(tmp); } { RefinablePar tmp("c",pLatPar+2,1.,100., gpRefParTypeUnitCellLength,REFPAR_DERIV_STEP_ABSOLUTE, true,true,c,false,1.0); tmp.SetDerivStep(1e-4); tmp.AssignClock(mClockLatticePar); this->AddPar(tmp); } { RefinablePar tmp("alpha",pLatPar+3,.5,3., gpRefParTypeUnitCellAngle,REFPAR_DERIV_STEP_ABSOLUTE, true,true,alpha,false,RAD2DEG); tmp.SetDerivStep(1e-4); tmp.AssignClock(mClockLatticePar); this->AddPar(tmp); } { RefinablePar tmp("beta",pLatPar+4,.5,3., gpRefParTypeUnitCellAngle,REFPAR_DERIV_STEP_ABSOLUTE, true,true,beta,false,RAD2DEG); tmp.SetDerivStep(1e-4); tmp.AssignClock(mClockLatticePar); this->AddPar(tmp); } { RefinablePar tmp("gamma",pLatPar+5,.5,3., gpRefParTypeUnitCellAngle,REFPAR_DERIV_STEP_ABSOLUTE, true,true,gamma,false,RAD2DEG); tmp.SetDerivStep(1e-4); tmp.AssignClock(mClockLatticePar); this->AddPar(tmp); } } else {//Just Fix the 'used' status this->GetPar(pLatPar+0).SetIsUsed(a); this->GetPar(pLatPar+1).SetIsUsed(b); this->GetPar(pLatPar+2).SetIsUsed(c); this->GetPar(pLatPar+3).SetIsUsed(alpha); this->GetPar(pLatPar+4).SetIsUsed(beta); this->GetPar(pLatPar+5).SetIsUsed(gamma); } VFN_DEBUG_EXIT("UnitCell::InitRefParList():Finished",5) } } objcryst-2022.1/ObjCryst/ObjCryst/UnitCell.h000066400000000000000000000263211430515525000206310ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* UnitCell.h header file for the UnitCell object * */ #ifndef _OBJCRYST_UNITCELL_H_ #define _OBJCRYST_UNITCELL_H_ #include "ObjCryst/CrystVector/CrystVector.h" #include "ObjCryst/ObjCryst/General.h" #include "ObjCryst/RefinableObj/RefinableObj.h" #include "ObjCryst/ObjCryst/SpaceGroup.h" namespace ObjCryst { extern const RefParType *gpRefParTypeUnitCell; extern const RefParType *gpRefParTypeUnitCellLength; extern const RefParType *gpRefParTypeUnitCellAngle; class NiftyStaticGlobalObjectsInitializer_UnitCell { public: NiftyStaticGlobalObjectsInitializer_UnitCell() { if (mCount++ == 0) { gpRefParTypeUnitCell=new RefParType (gpRefParTypeObjCryst,"Unit Cell"); gpRefParTypeUnitCellLength=new RefParType (gpRefParTypeUnitCell,"Unit Cell Length"); gpRefParTypeUnitCellAngle=new RefParType (gpRefParTypeUnitCell,"Unit Cell Angle"); } } ~NiftyStaticGlobalObjectsInitializer_UnitCell() { if (--mCount == 0) { delete gpRefParTypeUnitCell; delete gpRefParTypeUnitCellLength; delete gpRefParTypeUnitCellAngle; gpRefParTypeUnitCell=0; gpRefParTypeUnitCellLength=0; gpRefParTypeUnitCellAngle=0; } } private: static long mCount; }; static NiftyStaticGlobalObjectsInitializer_UnitCell NiftyStaticGlobalObjectsInitializer_UnitCell_counter; //###################################################################### /** \brief Unit Cell class: Unit cell with spacegroup information. * */ //###################################################################### class UnitCell:public RefinableObj { public: /// Default Constructor UnitCell(); /** \brief UnitCell Constructor (orthorombic) * \param a,b,c : unit cell dimension, in angstroems * \param SpaceGroupId: space group symbol or number */ UnitCell(const REAL a, const REAL b, const REAL c, const string &SpaceGroupId); /** \brief UnitCell Constructor (triclinic) * \param a,b,c : unit cell dimension, in angstroems * \param alpha,beta,gamma : unit cell angles, in radians. * \param SpaceGroupId: space group symbol or number */ UnitCell(const REAL a, const REAL b, const REAL c, const REAL alpha, const REAL beta, const REAL gamma,const string &SpaceGroupId); /// UnitCell copy constructor UnitCell(const UnitCell &oldCryst); /// Destructor ~UnitCell(); virtual const string& GetClassName() const; /// Lattice parameters (a,b,c,alpha,beta,gamma) as a 6-element vector in Angstroems /// and radians. CrystVector_REAL GetLatticePar() const; /// Return one of the 6 Lattice parameters, 0<= whichPar <6 (a,b,c,alpha,beta,gamma), /// returned in Angstroems and radians. REAL GetLatticePar(const int whichPar)const; /// last time the Lattice parameters were changed const RefinableObjClock& GetClockLatticePar()const; /** \brief Get the 'B' matrix (UnitCell::mBMatrix)for the UnitCell (orthogonalization * matrix for the given lattice, in the reciprocal space) * * The convention is taken following Giacovazzo, "Fundamentals of Crystallography", p.69 * "e1 is chosen along a*, e2 in the (a*,b*) plane, then e3 is along c". */ const CrystMatrix_REAL& GetBMatrix() const; /** \brief Get the orthogonalization matrix (UnitCell::mOrthMatrix)for the UnitCell * in real space * */ const CrystMatrix_REAL& GetOrthMatrix() const; /// last time the metric matrices were changed const RefinableObjClock& GetClockMetricMatrix()const; /** \brief Get orthonormal cartesian coordinates for a set of (x,y,z) * fractional coordinates. * * Results are given in Angstroems. * The convention is taken following : * e1 is chosen along a, e2 in the (a,b) plane, then e3 is along c* */ CrystVector_REAL GetOrthonormalCoords(const REAL x,const REAL y,const REAL z) const; /** \brief Get orthonormal cartesian coordinates for a set of (x,y,z) * fractional coordinates. * * X,y and z input are changed to Amgstroems values * The convention is taken following : * e1 is chosen along a, e2 in the (a,b) plane, then e3 is along c* */ void FractionalToOrthonormalCoords(REAL &x,REAL &y,REAL &z) const; /** \brief Get fractional cartesian coordinates for a set of (x,y,z) * orthonormal coordinates. * * Result is stored into x,y and z * The convention is taken following : * e1 is chosen along a, e2 in the (a,b) plane, then e3 is along c* */ void OrthonormalToFractionalCoords(REAL &x,REAL &y,REAL &z) const; /** \brief Get Miller H,K, L indices from orthonormal coordinates * in reciprocal space. * * Result is stored into x,y and z */ void MillerToOrthonormalCoords(REAL &x,REAL &y,REAL &z) const; /** \brief Get orthonormal coordinates given a set of H,K, L indices * in reciprocal space. * * Result is stored into x,y and z */ void OrthonormalToMillerCoords(REAL &x,REAL &y,REAL &z) const; /** Prints some info about the UnitCell * * \param os the stream to which the information is outputed (default=cout) */ virtual void Print(ostream &os) const; // Avoid compiler warnings about hidden base class method. virtual void Print() const { this->Print(cout); } /// Access to the SpaceGroup object const SpaceGroup & GetSpaceGroup()const; /// Access to the SpaceGroup object. SpaceGroup & GetSpaceGroup(); // :TODO: ? //virtual void XMLOutput(ostream &os,int indent=0)const; //virtual void XMLInput(istream &is,const XMLCrystTag &tag); /// Volume of Unit Cell (in Angstroems) REAL GetVolume()const; protected: /** \brief Init all UnitCell parameters * \param a,b,c : unit cell dimension, in angstroems * \param alpha,beta,gamma : unit cell angles * \param SpcGroup: space group number (1..230) * \param name: name for the UnitCell, : '(TaSe4)2I' */ virtual 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); /** \brief Prepare the refinable parameters list * * This is called once when creating the UnitCell. */ void InitRefParList(); private: /** Init options. * * Need only be done once per UnitCell. */ virtual void InitOptions(); /// \internal.Init the (de)orthogonalization matrices. /// They are re-computed only if parameters have changed since last call. void InitMatrices() const; /// \internal /// Update cell parameters for tetragonal, trigonal, hexagonal, cubic lattices. /// Also set angular parameters for those group which need it. This is needed during /// Refinement, since for example in a quadratic spg, only a is refined and /// we need to have b=a... void UpdateLatticePar(); /// a,b and c in Angstroems, angles (stored) in radians /// For cubic, rhomboedric UnitCells, only the 'a' parameter is relevant. /// For quadratic and hexagonal UnitCells, only a and c parameters are relevant. /// The MUTABLE is temporary ! It should not be ! CrystVector_REAL mCellDim; /// The space group of the UnitCell SpaceGroup mSpaceGroup ; /** \brief B Matrix (Orthogonalization matrix for reciprocal space) * \f[ B= \left[ \begin {array}{ccc} a^* & b^*\cos(\gamma^*) & c^*\cos(\beta^*) \\ * 0 & b^*\sin(\gamma^*) & -c^*\sin(\beta^*)\cos(\alpha) \\ * 0 & 0 & \frac{1}{c}\end{array} \right]\f] *\f[ \left[ \begin{array}{c} k_x \\ k_y \\ k_z \end{array} \right]_{orthonormal} * = B \times \left[ \begin{array}{c} h \\ k \\ l \end{array}\right]_{integer} \f] * \note this matrix is and must remain upper triangular. this is assumed for * some optimizations. */ mutable CrystMatrix_REAL mBMatrix; /// inverse of B Matrix (i.e. inverse of orthogonalization matrix for direct space) mutable CrystMatrix_REAL mBMatrixInvert; /** \brief Eucl Matrix (Orthogonalization matrix for direct space) * \f[ M_{orth}= \left[ \begin {array}{ccc} a & b\cos(\gamma) & c\cos(\beta) \\ * 0 & b\sin(\gamma) & -c\sin(\beta)\cos(\alpha^*) \\ * 0 & 0 & \frac{1}{c^*}\end{array} \right]\f] * \f[ \left[ \begin{array}{c} x \\ y \\ z \end{array} \right]_{orthonormal} * = M_{orth} \times \left[ \begin{array}{c} x \\ y \\ z \end{array} * \right]_{fractional coords}\f] * \note this matrix is and must remain upper triangular. this is assumed for * some optimizations. */ mutable CrystMatrix_REAL mOrthMatrix; /// inverse of Eucl Matrix (i.e. inverse of de-orthogonalization matrix for direct space) mutable CrystMatrix_REAL mOrthMatrixInvert; /// Last time lattice parameters were changed RefinableObjClock mClockLatticePar; /// \internal Last time metric matrices were computed mutable RefinableObjClock mClockMetricMatrix; /// \internal Last time the lattice parameters whre updated mutable RefinableObjClock mClockLatticeParUpdate; /** Option to override lattice parameters constraints from spacegroup choice. * * \warning EXPERIMENTAL * * Normally lattice parameters are constrained by the space group choice * (e.g. a=b=c and angles =90° for cubic spacegroups). Using this option * allows you to override this, and choose any lattice parameter. THis works * as long as symmetry operations are applied to fractionnal coordinates. * * This is useful duting global optimization when searching the structure in a UnitCell * which has (or is expected to have) a known pseudo-crystallographic * symmetry, to reduce dramatically the number of parameters. Of course * for final refinement the 'real' symmetry should be imposed. */ RefObjOpt mConstrainLatticeToSpaceGroup; }; }// namespace #endif //_OBJCRYST_UNITCELL_H_ objcryst-2022.1/ObjCryst/ObjCryst/ZScatterer.cpp000066400000000000000000003374271430515525000215470ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Atom.h * header file for the Atom scatterer * */ #include #include #include #include //for sprintf() //#include "ObjCryst/ObjCryst/ScatteringPower.h" //#include "ObjCryst/ObjCryst/Scatterer.h" //#include "ObjCryst/ObjCryst/Atom.h" #include "ObjCryst/ObjCryst/ZScatterer.h" #include "ObjCryst/ObjCryst/ScatteringData.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" //simple formatting of integers, REALs.. #include "ObjCryst/Quirks/VFNDebug.h" #include #include #ifdef OBJCRYST_GL #ifdef __DARWIN__ #include #else #include #endif #endif #ifdef __WX__CRYST__ #include "ObjCryst/wxCryst/wxZScatterer.h" #undef GetClassName // Conflict from wxMSW headers ? (cygwin) #endif #ifdef _MSC_VER // MS VC++ predefined macros.... #undef min #undef max #endif namespace ObjCryst { //###################################################################### // // ZAtom // // //###################################################################### ZAtom::ZAtom(ZScatterer &scatt,const ScatteringPower *pow, const long atomBond, const REAL bondLength, const long atomAngle, const REAL bondAngle, const long atomDihedral, const REAL dihedralAngle, const REAL popu, const string &name): mpScattPow(pow), mAtomBond(atomBond),mAtomAngle(atomAngle),mAtomDihed(atomDihedral), mBondLength(bondLength),mAngle(bondAngle),mDihed(dihedralAngle), mOccupancy(popu),mName(name),mpScatt(&scatt) { VFN_DEBUG_MESSAGE("ZAtom::ZAtom():("<GetClockScatterer().Click();} void ZAtom::SetZAngle(const REAL angle) {mAngle=angle;mpScatt->GetClockScatterer().Click();} void ZAtom::SetZDihedralAngle(const REAL dihed) {mDihed=dihed;mpScatt->GetClockScatterer().Click();} void ZAtom::SetOccupancy(const REAL pop) {mOccupancy=pop;mpScatt->GetClockScatterer().Click();} void ZAtom::SetScatteringPower(const ScatteringPower* scatt) {mpScattPow=scatt;mpScatt->GetClockScatterer().Click();} #ifdef __WX__CRYST__ WXCrystObjBasic* ZAtom::WXCreate(wxWindow *parent) { VFN_DEBUG_ENTRY("ZAtom::WXCreate()",7) mpWXCrystObj=new WXZAtom (parent,this); VFN_DEBUG_EXIT("ZAtom::WXCreate()",7) return mpWXCrystObj; } WXCrystObjBasic* ZAtom::WXGet() { return mpWXCrystObj; } void ZAtom::WXDelete() { if(0!=mpWXCrystObj) { VFN_DEBUG_MESSAGE("ZAtom::WXDelete()",5) delete mpWXCrystObj; } mpWXCrystObj=0; } void ZAtom::WXNotifyDelete() { VFN_DEBUG_MESSAGE("ZAtom::WXNotifyDelete():"<GetXCoord().data(); const REAL *pY1=mpZScatt->GetYCoord().data(); const REAL *pZ1=mpZScatt->GetZCoord().data(); const REAL *pX0=mXCoord0.data(); const REAL *pY0=mYCoord0.data(); const REAL *pZ0=mZCoord0.data(); const REAL *pW=mAtomWeight.data(); REAL dist=0; //for(int i=mXCoord0.numElements()-1;i>=0;i--) // dist+= abs(*pX1++ - *pX0++) + abs(*pY1++ - *pY0++) + abs(*pZ1++ - *pZ0++); for(int i=mXCoord0.numElements()-1;i>=0;i--) { dist+= *pW++* ( (*pX1 - *pX0)*(*pX1 - *pX0) +(*pY1 - *pY0)*(*pY1 - *pY0) +(*pZ1 - *pZ0)*(*pZ1 - *pZ0)); pX1++;pY1++;pZ1++; pX0++;pY0++;pZ0++; } #if 0 const CrystVector_REAL *pXcoord=&(mpZScatt->GetXCoord()); const CrystVector_REAL *pYcoord=&(mpZScatt->GetYCoord()); const CrystVector_REAL *pZcoord=&(mpZScatt->GetZCoord()); REAL dist=0; for(int i=pXcoord->numElements()-1;i>=0;i--) { dist+=mAtomWeight(i)*( ((*pXcoord)(i)-mXCoord0(i))*((*pXcoord)(i)-mXCoord0(i)) +((*pYcoord)(i)-mYCoord0(i))*((*pYcoord)(i)-mYCoord0(i)) +((*pZcoord)(i)-mZCoord0(i))*((*pZcoord)(i)-mZCoord0(i))); } #endif return dist/mAtomWeight.sum(); } void ZMoveMinimizer::RecordConformation() { mXCoord0=mpZScatt->GetXCoord(); mYCoord0=mpZScatt->GetYCoord(); mZCoord0=mpZScatt->GetZCoord(); if(mAtomWeight.numElements() != mXCoord0.numElements()) { mAtomWeight.resize(mXCoord0.numElements()); mAtomWeight=1; } } void ZMoveMinimizer::SetZAtomWeight(const CrystVector_REAL weight) {mAtomWeight=weight;} void ZMoveMinimizer::MinimizeChange(long nbTrial) { if(mAtomWeight.max()<1e-3) return; mOptimObj.Optimize(nbTrial,true); } //###################################################################### // // ZScatterer // // //###################################################################### ZScatterer::ZScatterer(const string &name,Crystal &cryst, const REAL x,const REAL y,const REAL z, const REAL phi,const REAL chi, const REAL psi): mScattCompList(0),mNbAtom(0),mNbDummyAtom(0), mPhi(0),mChi(0),mPsi(0), mZAtomRegistry("List of ZAtoms"), mCenterAtomIndex(0), mPhiChiPsiMatrix(3,3), mUseGlobalScattPow(false),mpGlobalScattPow(0), mpZMoveMinimizer(0) { VFN_DEBUG_MESSAGE("ZScatterer::ZScatterer():("<SetCrystal(cryst); this->InitRefParList(); VFN_DEBUG_MESSAGE("ZScatterer::ZScatterer():("<SetCrystal(*(old.mpCryst)); this->InitRefParList(); VFN_DEBUG_MESSAGE("ZScatterer::ZScatterer(&old):Copying atoms",10) for(long i=0; iAddAtom(old.GetZAtomRegistry().GetObj(i).GetName(), old.GetZAtomRegistry().GetObj(i).GetScatteringPower(), old.GetZAtomRegistry().GetObj(i).GetZBondAtom(), old.GetZAtomRegistry().GetObj(i).GetZBondLength(), old.GetZAtomRegistry().GetObj(i).GetZAngleAtom(), old.GetZAtomRegistry().GetObj(i).GetZAngle(), old.GetZAtomRegistry().GetObj(i).GetZDihedralAngleAtom(), old.GetZAtomRegistry().GetObj(i).GetZDihedralAngle(), old.GetZAtomRegistry().GetObj(i).GetOccupancy()); this->SetUseGlobalScatteringPower(old.mUseGlobalScattPow); // Copy parameters attributes (limits, etc...) VFN_DEBUG_MESSAGE("ZScatterer::ZScatterer(&old):Copying param attributes",10) this->GetPar(mXYZ.data()). CopyAttributes(old.GetPar(old.mXYZ.data())); this->GetPar(mXYZ.data()+1).CopyAttributes(old.GetPar(old.mXYZ.data()+1)); this->GetPar(mXYZ.data()+2).CopyAttributes(old.GetPar(old.mXYZ.data()+2)); this->GetPar(&mOccupancy). CopyAttributes(old.GetPar(&(old.mOccupancy))); this->GetPar(&mPhi). CopyAttributes(old.GetPar(&(old.mPhi))); this->GetPar(&mChi). CopyAttributes(old.GetPar(&(old.mChi))); this->GetPar(&mPsi). CopyAttributes(old.GetPar(&(old.mPsi))); VFN_DEBUG_MESSAGE("ZScatterer::ZScatterer(&old):Copying atoms param attributes",10) for(long i=0; iGetPar(&(this->GetZAtomRegistry().GetObj(i).mBondLength)). CopyAttributes(old.GetPar(&(old.GetZAtomRegistry().GetObj(i).mBondLength))); this->GetPar(&(this->GetZAtomRegistry().GetObj(i).mAngle)). CopyAttributes(old.GetPar(&(old.GetZAtomRegistry().GetObj(i).mAngle))); this->GetPar(&(this->GetZAtomRegistry().GetObj(i).mDihed)). CopyAttributes(old.GetPar(&(old.GetZAtomRegistry().GetObj(i).mDihed))); this->GetPar(&(this->GetZAtomRegistry().GetObj(i).mOccupancy)). CopyAttributes(old.GetPar(&(old.GetZAtomRegistry().GetObj(i).mOccupancy))); } VFN_DEBUG_EXIT("ZScatterer::ZScatterer(&old):("<mBondLength), 1.,5., // bondLength*.9,bondLength*1.1, gpRefParTypeScattConformBondLength, REFPAR_DERIV_STEP_ABSOLUTE,true,false,usedBond,false,1.); tmp.AssignClock(mClockScatterer); this->AddPar(tmp); } { sprintf(buf,"%d-%d-%d",(int)mNbAtom,(int)atomBond,(int)atomAngle); RefinablePar tmp("Angle"+(string)buf,&(zatom->mAngle), 0,2*M_PI, // zatom->mAngle-.2,zatom->mAngle+.2, gpRefParTypeScattConformBondAngle, REFPAR_DERIV_STEP_ABSOLUTE,false,false,usedAngle,true,RAD2DEG,2*M_PI); tmp.AssignClock(mClockScatterer); this->AddPar(tmp); } { sprintf(buf,"%d-%d-%d-%d",(int)mNbAtom,(int)atomBond,(int)atomAngle,(int)atomDihedral); RefinablePar tmp("Dihed"+(string)buf,&(zatom->mDihed), 0,2*M_PI, // zatom->mDihed-.2,zatom->mDihed+.2, gpRefParTypeScattConformDihedAngle, REFPAR_DERIV_STEP_ABSOLUTE,false,false,usedDihed,true,RAD2DEG,2*M_PI); tmp.AssignClock(mClockScatterer); this->AddPar(tmp); } {//fixed by default sprintf(buf,"%d",(int)mNbAtom); RefinablePar tmp("Occupancy"+(string)buf, &(zatom->mOccupancy),0,1, gpRefParTypeScattOccup, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,1.,1.); tmp.AssignClock(mClockScatterer); this->AddPar(tmp); } //:NOTE: we *must* add it in the registry after declaring the parameters, // since it triggers the creation of the WXZAtom, which requires the parameters... VFN_DEBUG_MESSAGE("ZScatterer::AddAtom():Registering...",2) mZAtomRegistry.Register(*zatom); // Add an entry for this atom in the list of all components. The actual values are // written in Update().No entry for a dummy atom VFN_DEBUG_MESSAGE("ZScatterer::AddAtom():Adding to the ScattCompList...",2) if(0!=pow) { ++mScattCompList; mScattCompList(mNbAtom-mNbDummyAtom).mpScattPow=pow; mComponentIndex.resizeAndPreserve(mNbAtom-mNbDummyAtom+1); mComponentIndex(mNbAtom-mNbDummyAtom)=mNbAtom; } else mNbDummyAtom++; //Finish mNbAtom++; mClockScatterer.Click(); VFN_DEBUG_MESSAGE("ZScatterer::AddAtom():End",3) } int ZScatterer::GetNbComponent() const { if(true==mUseGlobalScattPow) return 1; return mNbAtom-mNbDummyAtom; } const ScatteringComponentList& ZScatterer::GetScatteringComponentList() const { this->UpdateScattCompList(); return mScattCompList; } string ZScatterer::GetComponentName(const int i) const { return mZAtomRegistry.GetObj(mComponentIndex(i)).GetName(); } void ZScatterer::Print() const { VFN_DEBUG_MESSAGE("ZScatterer::Print()",5) //:TODO: //this->UpdateScattCompList(); //for(int i=0;imNbAtom;i++) ??; } REAL ZScatterer::GetPhi() const {return mPhi;} REAL ZScatterer::GetChi() const {return mChi;} REAL ZScatterer::GetPsi() const {return mPsi;} void ZScatterer::SetPhi(const REAL x) { mClockScatterer.Click();mPhi=x;} void ZScatterer::SetChi(const REAL y) { mClockScatterer.Click();mChi=y;} void ZScatterer::SetPsi(const REAL z) { mClockScatterer.Click();mPsi=z;} REAL ZScatterer::GetZAtomX(const int i)const{this->UpdateCoordinates(); return mXCoord(i);} REAL ZScatterer::GetZAtomY(const int i)const{this->UpdateCoordinates(); return mYCoord(i);} REAL ZScatterer::GetZAtomZ(const int i)const{this->UpdateCoordinates(); return mZCoord(i);} long ZScatterer::GetZBondAtom(const int i)const {return mZAtomRegistry.GetObj(i).GetZBondAtom();} long ZScatterer::GetZAngleAtom(const int i)const {return mZAtomRegistry.GetObj(i).GetZAngleAtom();} long ZScatterer::GetZDihedralAngleAtom(const int i)const {return mZAtomRegistry.GetObj(i).GetZDihedralAngleAtom();} REAL ZScatterer::GetZBondLength(const int i)const {return mZAtomRegistry.GetObj(i).GetZBondLength();} REAL ZScatterer::GetZAngle(const int i)const {return mZAtomRegistry.GetObj(i).GetZAngle();} REAL ZScatterer::GetZDihedralAngle(const int i)const {return mZAtomRegistry.GetObj(i).GetZDihedralAngle();} void ZScatterer::SetZBondLength(const int i,const REAL a) {mClockScatterer.Click();mZAtomRegistry.GetObj(i).SetZBondLength(a);} void ZScatterer::SetZAngle(const int i,const REAL a) {mClockScatterer.Click();mZAtomRegistry.GetObj(i).SetZAngle(a);} void ZScatterer::SetZDihedralAngle(const int i,const REAL a) {mClockScatterer.Click();mZAtomRegistry.GetObj(i).SetZDihedralAngle(a);} const ObjRegistry& ZScatterer::GetZAtomRegistry()const {return mZAtomRegistry;} ostream& ZScatterer::POVRayDescription(ostream &os, const CrystalPOVRayOptions &options)const { VFN_DEBUG_MESSAGE("ZScatterer::POVRayDescription()",5) //throw ObjCrystException("ZScatterer::POVRayDescription() not implemented! "+this->GetName()); //:TODO: this->UpdateScattCompList(); //for(long i=0;iPOVRayDescription(os,onlyIndependentAtoms); os << "// Description of ZScatterer :" << this->GetName() <POVRayDescription(os,onlyIndependentAtoms); return os; } //Declare colours for(int i=0;iIsDummy()) continue; os <<" #declare colour_"<GetName()<<"="<Colour()<<";"<GetX(); y(i)=mpAtom[i]->GetY(); z(i)=mpAtom[i]->GetZ(); this->GetCrystal().FractionalToOrthonormalCoords(x(i),y(i),z(i)); } for(int i=0;iIsDummy()) { os << " // Skipping Dummy Atom :" << mpAtom[i]->GetName() <GetName() <," << mpAtom[i]->GetRadius()/3<GetName() <<" }" << endl; os << " }" <IsDummy()) || (i==0)) continue; os << " cylinder"<,"<,"< xyzCoords; for(int i=0;iGetCrystal().GetSpaceGroup().GetAllSymmetrics(mpAtom[i]->GetX(), mpAtom[i]->GetY(), mpAtom[i]->GetZ(), false,false,false)); const int nbSymmetrics=(vXYZCoords[0])->rows(); int symNum=0; CrystMatrix_int translate(27,3); translate= -1,-1,-1, -1,-1, 0, -1,-1, 1, -1, 0,-1, -1, 0, 0, -1, 0, 1, -1, 1,-1, -1, 1, 0, -1, 1, 1, 0,-1,-1, 0,-1, 0, 0,-1, 1, 0, 0,-1, 0, 0, 0, 0, 0, 1, 0, 1,-1, 0, 1, 0, 0, 1, 1, 1,-1,-1, 1,-1, 0, 1,-1, 1, 1, 0,-1, 1, 0, 0, 1, 0, 1, 1, 1,-1, 1, 1, 0, 1, 1, 1; REAL dx,dy,dz; CrystVector_REAL x(mNbAtom),y(mNbAtom),z(mNbAtom); CrystVector_REAL xSave,ySave,zSave; for(int i=0;i(-limit)) && (x(0)<(1+limit)) &&(y(0)>(-limit)) && (y(0)<(1+limit)) &&(z(0)>(-limit)) && (z(0)<(1+limit))) { for(int k=0;kGetCrystal().FractionalToOrthonormalCoords(x(k),y(k),z(k)); os << " // Symmetric&Translated #" << symNum++ <IsDummy()) { os << " // Skipping Dummy Atom :" << mpAtom[i]->GetName() <GetName() <," << mpAtom[i]->GetRadius()/3<GetName() <<" }" << endl; os << " }" <IsDummy()) || (i==0)) continue; os << " cylinder"<,"<,"<UpdateScattCompList(); if(true==mUseGlobalScattPow) { //mpAtom[mCenterAtomIndex]->GLInitDisplayList(onlyIndependentAtoms); return; } GLfloat colour_bond[]= { 0.5, .5, .5, 1.0 }; GLfloat colour_side[]= { 0.0, .0, .0, 1.0 }; const GLfloat colour0[] = {0.0f, 0.0f, 0.0f, 0.0f}; GLUquadricObj* pQuadric = gluNewQuadric(); if(true==onlyIndependentAtoms) { //cout << m3DDisplayIndex <0) { for(long k=0;kGetForwardScatteringFactor(RAD_XRAY)<1.5)) continue; glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mZAtomRegistry.GetObj(n1).GetScatteringPower()->GetColourRGB()); glPushMatrix(); glTranslatef(x(n1)*en, y(n1), z(n1)); gluSphere(pQuadric,mZAtomRegistry.GetObj(n1).GetScatteringPower() ->GetRadius()/3.,10,10); glPopMatrix(); } case 2: // Draw a bond { long n1,n2; n1=m3DDisplayIndex(k,1); n2=m3DDisplayIndex(k,2); if(hideHydrogens && (mZAtomRegistry.GetObj(n1).GetScatteringPower()->GetForwardScatteringFactor(RAD_XRAY)<1.5)) continue; if(hideHydrogens && (mZAtomRegistry.GetObj(n2).GetScatteringPower()->GetForwardScatteringFactor(RAD_XRAY)<1.5)) continue; glPushMatrix(); glTranslatef(x(n1)*en, y(n1), z(n1)); glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE,colour_bond); GLUquadricObj *quadobj = gluNewQuadric(); glColor3f(1.0f,1.0f,1.0f); const REAL height= sqrt( (x(n2)-x(n1))*(x(n2)-x(n1)) +(y(n2)-y(n1))*(y(n2)-y(n1)) +(z(n2)-z(n1))*(z(n2)-z(n1))); glRotatef(180,(x(n2)-x(n1))*en,y(n2)-y(n1),z(n2)-z(n1)+height);// ?!?!?! gluCylinder(quadobj,.1,.1,height,10,1 ); gluDeleteQuadric(quadobj); glPopMatrix(); } case 3: // Draw a triangular face { long n1,n2,n3; REAL x1,y1,z1,x2,y2,z2,xn,yn,zn,xc,yc,zc; n1=m3DDisplayIndex(k,1); n2=m3DDisplayIndex(k,2); n3=m3DDisplayIndex(k,3); x1=x(n1)-x(n2); y1=y(n1)-y(n2); z1=z(n1)-z(n2); x2=x(n1)-x(n3); y2=y(n1)-y(n3); z2=z(n1)-z(n3); xn=y1*z2-z1*y2; yn=z1*x2-x1*z2; zn=x1*y2-y1*x2; xc=(x(n1)+x(n2)+x(n3))/3.-x(mCenterAtomIndex); yc=(y(n1)+y(n2)+y(n3))/3.-y(mCenterAtomIndex); zc=(z(n1)+z(n2)+z(n3))/3.-z(mCenterAtomIndex); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mZAtomRegistry.GetObj(0).GetScatteringPower()->GetColourRGB()); //glColor3f(1.0f,1.0f,1.0f); // White glBegin(GL_TRIANGLES); // Bottom if((xn*xc+yn*yc+zn*zc)>0) glNormal3f(xn*en, yn, zn); else glNormal3f(-xn*en, -yn, -zn); glVertex3f(x(n1)*en,y(n1),z(n1)); glVertex3f(x(n2)*en,y(n2),z(n2)); glVertex3f(x(n3)*en,y(n3),z(n3)); glEnd(); glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE,colour_side); glBegin(GL_LINE_LOOP); glVertex3f(x(n1)*en,y(n1),z(n1)); glVertex3f(x(n2)*en,y(n2),z(n2)); glVertex3f(x(n3)*en,y(n3),z(n3)); glEnd(); } case 4: // Draw a quadric face { long n1,n2,n3,n4; REAL x1,y1,z1,x2,y2,z2,xn,yn,zn,xc,yc,zc; n1=m3DDisplayIndex(k,1); n2=m3DDisplayIndex(k,2); n3=m3DDisplayIndex(k,3); n4=m3DDisplayIndex(k,3); x1=x(n1)-x(n2); y1=y(n1)-y(n2); z1=z(n1)-z(n2); x2=x(n1)-x(n3); y2=y(n1)-y(n3); z2=z(n1)-z(n3); xn=y1*z2-z1*y2; yn=z1*x2-x1*z2; zn=x1*y2-y1*x2; xc=(x(n1)+x(n2)+x(n3)+x(n4))/4.-x(mCenterAtomIndex); yc=(y(n1)+y(n2)+y(n3)+y(n4))/4.-y(mCenterAtomIndex); zc=(z(n1)+z(n2)+z(n3)+z(n4))/4.-z(mCenterAtomIndex); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mZAtomRegistry.GetObj(0).GetScatteringPower()->GetColourRGB()); //glColor3f(1.0f,1.0f,1.0f); // White glBegin(GL_TRIANGLES); // Bottom if((xn*xc+yn*yc+zn*zc)>0) glNormal3f(xn*en, yn, zn); else glNormal3f(-xn*en, -yn, -zn); glVertex3f(x(n1)*en,y(n1),z(n1)); glVertex3f(x(n2)*en,y(n2),z(n2)); glVertex3f(x(n3)*en,y(n3),z(n3)); glVertex3f(x(n4)*en,y(n4),z(n4)); glEnd(); glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE,colour_side); glBegin(GL_LINE_LOOP); glVertex3f(x(n1)*en,y(n1),z(n1)); glVertex3f(x(n2)*en,y(n2),z(n2)); glVertex3f(x(n3)*en,y(n3),z(n3)); glVertex3f(x(n4)*en,y(n4),z(n4)); glEnd(); } } } } else { for(int k=0;kGetForwardScatteringFactor(RAD_XRAY)<1.5)) continue; const float r=mZAtomRegistry.GetObj(k).GetScatteringPower()->GetColourRGB()[0]; const float g=mZAtomRegistry.GetObj(k).GetScatteringPower()->GetColourRGB()[1]; const float b=mZAtomRegistry.GetObj(k).GetScatteringPower()->GetColourRGB()[2]; glPushMatrix(); glTranslatef(x(k)*en, y(k), z(k)); if(displayNames) { GLfloat colourChar [] = {1.0, 1.0, 1.0, 1.0}; if((r>0.8)&&(g>0.8)&&(b>0.8)) { colourChar[0] = 0.5; colourChar[1] = 0.5; colourChar[2] = 0.5; } glMaterialfv(GL_FRONT, GL_AMBIENT, colour0); glMaterialfv(GL_FRONT, GL_DIFFUSE, colour0); glMaterialfv(GL_FRONT, GL_SPECULAR, colour0); glMaterialfv(GL_FRONT, GL_EMISSION, colourChar); glMaterialfv(GL_FRONT, GL_SHININESS,colour0); glRasterPos3f(0.0f, 0.0f, 0.0f); crystGLPrint(mZAtomRegistry.GetObj(k).GetName()); } else { const GLfloat colourAtom [] = {r, g, b, 1.0}; glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE,colourAtom); glMaterialfv(GL_FRONT, GL_SPECULAR, colour0); glMaterialfv(GL_FRONT, GL_EMISSION, colour0); glMaterialfv(GL_FRONT, GL_SHININESS, colour0); glPolygonMode(GL_FRONT, GL_FILL); gluSphere(pQuadric, mZAtomRegistry.GetObj(k).GetScatteringPower()->GetRadius()/3.,10,10); //Draw the bond for this Atom,if it's not linked to a dummy int bond=this->GetZBondAtom(k); if((0!=mZAtomRegistry.GetObj(bond).GetScatteringPower()) && (k>0)) { glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,colour_bond); GLUquadricObj *quadobj = gluNewQuadric(); glColor3f(1.0f,1.0f,1.0f); const REAL height= sqrt( (x(bond)-x(k))*(x(bond)-x(k)) +(y(bond)-y(k))*(y(bond)-y(k)) +(z(bond)-z(k))*(z(bond)-z(k))); glRotatef(180,(x(bond)-x(k))*en,y(bond)-y(k),z(bond)-z(k)+height);// !!! gluCylinder(quadobj,.1,.1,height,10,1 ); gluDeleteQuadric(quadobj); } } glPopMatrix(); } }//Use triangle faces ? }//Only independent atoms ? else { VFN_DEBUG_ENTRY("ZScatterer::GLInitDisplayList():Show all symmetrics",3) vector vXYZCoords; { REAL x0,y0,z0; for(int i=0;iGetCrystal().OrthonormalToFractionalCoords(x0,y0,z0); vXYZCoords.push_back(this->GetCrystal().GetSpaceGroup(). GetAllSymmetrics(x0,y0,z0,false,false,false)); } } CrystMatrix_int translate(27,3); translate= -1,-1,-1, -1,-1, 0, -1,-1, 1, -1, 0,-1, -1, 0, 0, -1, 0, 1, -1, 1,-1, -1, 1, 0, -1, 1, 1, 0,-1,-1, 0,-1, 0, 0,-1, 1, 0, 0,-1, 0, 0, 0, 0, 0, 1, 0, 1,-1, 0, 1, 0, 0, 1, 1, 1,-1,-1, 1,-1, 0, 1,-1, 1, 1, 0,-1, 1, 0, 0, 1, 0, 1, 1, 1,-1, 1, 1, 0, 1, 1, 1; REAL dx,dy,dz; CrystVector_REAL x(mNbAtom),y(mNbAtom),z(mNbAtom); CrystVector_REAL xSave,ySave,zSave; const int nbSymmetrics=vXYZCoords[0].rows(); for(int i=0;ixMin) && (x(0)yMin) && (y(0)zMin) && (z(0)GetCrystal().FractionalToOrthonormalCoords(x(k),y(k),z(k)); //:NOTE: The code below is the same as without symmetrics if(m3DDisplayIndex.numElements()>0) { long n1,n2,n3; REAL x1,y1,z1,x2,y2,z2,xn,yn,zn,xc,yc,zc; for(long k=0;kGetColourRGB()); glBegin(GL_TRIANGLES); if((xn*xc+yn*yc+zn*zc)>0) glNormal3f( xn*en, yn, zn); else glNormal3f(-xn*en, -yn, -zn); glVertex3f(x(n1)*en,y(n1),z(n1)); glVertex3f(x(n2)*en,y(n2),z(n2)); glVertex3f(x(n3)*en,y(n3),z(n3)); glEnd(); glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE,colour_side); glBegin(GL_LINE_LOOP); glVertex3f(x(n1)*en,y(n1),z(n1)); glVertex3f(x(n2)*en,y(n2),z(n2)); glVertex3f(x(n3)*en,y(n3),z(n3)); glEnd(); } } else { for(int k=0;kGetForwardScatteringFactor(RAD_XRAY)<1.5)) continue; const float r=mZAtomRegistry.GetObj(k).GetScatteringPower()->GetColourRGB()[0]; const float g=mZAtomRegistry.GetObj(k).GetScatteringPower()->GetColourRGB()[1]; const float b=mZAtomRegistry.GetObj(k).GetScatteringPower()->GetColourRGB()[2]; glPushMatrix(); glTranslatef(x(k)*en, y(k), z(k)); if(displayNames) { GLfloat colourChar [] = {1.0, 1.0, 1.0, 1.0}; if((r>0.8)&&(g>0.8)&&(b>0.8)) { colourChar[0] = 0.5; colourChar[1] = 0.5; colourChar[2] = 0.5; } glMaterialfv(GL_FRONT, GL_AMBIENT, colour0); glMaterialfv(GL_FRONT, GL_DIFFUSE, colour0); glMaterialfv(GL_FRONT, GL_SPECULAR, colour0); glMaterialfv(GL_FRONT, GL_EMISSION, colourChar); glMaterialfv(GL_FRONT, GL_SHININESS,colour0); glRasterPos3f(0.0f, 0.0f, 0.0f); crystGLPrint(mZAtomRegistry.GetObj(k).GetName()); } else { const GLfloat colourAtom [] = {r, g, b, 1.0}; glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE,colourAtom); glMaterialfv(GL_FRONT, GL_SPECULAR, colour0); glMaterialfv(GL_FRONT, GL_EMISSION, colour0); glMaterialfv(GL_FRONT, GL_SHININESS, colour0); glPolygonMode(GL_FRONT, GL_FILL); gluSphere(pQuadric, mZAtomRegistry.GetObj(k).GetScatteringPower()->GetRadius()/3.,10,10); glRasterPos3f(0,0,0); //Draw the bond for this Atom,if it's not linked to a dummy int bond=this->GetZBondAtom(k); if((0!=mZAtomRegistry.GetObj(bond).GetScatteringPower()) && (k>0)) { glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,colour_bond); GLUquadricObj *quadobj = gluNewQuadric(); glColor3f(1.0f,1.0f,1.0f); const REAL height= sqrt( (x(bond)-x(k))*(x(bond)-x(k)) +(y(bond)-y(k))*(y(bond)-y(k)) +(z(bond)-z(k))*(z(bond)-z(k))); glRotatef(180,(x(bond)-x(k))*en,y(bond)-y(k),z(bond)-z(k)+height);// !!! gluCylinder(quadobj,.1,.1,height,10,1 ); gluDeleteQuadric(quadobj); } } glPopMatrix(); } }//Use triangle faces ? }//if in limits x=xSave; y=ySave; z=zSave; }//for translation VFN_DEBUG_EXIT("ZScatterer::GLInitDisplayList():Symmetric#"<GetName()<<":"<InitRefParList(); mClockScatterer.Click(); } //Just change the functions which return the component list } else { if(true==mUseGlobalScattPow) { delete mpGlobalScattPow; mpGlobalScattPow=0; mUseGlobalScattPow=false; mScattCompList.Reset(); for(long i=0;i<(mNbAtom-mNbDummyAtom);i++) ++mScattCompList; this->InitRefParList(); mClockScatterer.Click(); } } } void ZScatterer::GetGeneGroup(const RefinableObj &obj, CrystVector_uint & groupIndex, unsigned int &first) const { // One group for all translation parameters, another for orientation. // All conformation parameters (bond, angle,torsion) are in individual groups. unsigned int posIndex=0; unsigned int orientIndex=0; VFN_DEBUG_MESSAGE("ZScatterer::GetGeneGroup()",4) for(long i=0;iGetNbPar();j++) if(&(obj.GetPar(i)) == &(this->GetPar(j))) { if(this->GetPar(j).GetType()->IsDescendantFromOrSameAs(gpRefParTypeScattTransl)) { if(posIndex==0) posIndex=first++; groupIndex(i)=posIndex; } else if(this->GetPar(j).GetType()->IsDescendantFromOrSameAs(gpRefParTypeScattOrient)) { if(orientIndex==0) orientIndex=first++; groupIndex(i)=orientIndex; } else groupIndex(i)= first++; } } const CrystVector_REAL& ZScatterer::GetXCoord() const { this->UpdateCoordinates(); return mXCoord; } const CrystVector_REAL& ZScatterer::GetYCoord() const { this->UpdateCoordinates(); return mYCoord; } const CrystVector_REAL& ZScatterer::GetZCoord() const { this->UpdateCoordinates(); return mZCoord; } void ZScatterer::EndOptimization() { if(mOptimizationDepth==1) { if(0!=mpZMoveMinimizer) delete mpZMoveMinimizer; mpZMoveMinimizer=0; } this->RefinableObj::EndOptimization(); } std::vector SplitString(const std::string &s) { const string delim(" "); std::vector v; string str=s; unsigned int ct=0; int n=str.find_first_of(delim); while( n != (int) str.npos) { ct++; if(n>0) { v.push_back(str.substr(0,n)); } str= str.substr(n+1); n=str.find_first_of(delim); } if(str.length() > 0) v.push_back(str); //cout<<"SplitString: "< "; //for(std::vector::const_iterator pos=v.begin();pos!=v.end();++pos) cout << *pos <<" / "; //cout< v=SplitString(sbuf); if(nb==1) {//First atom "C 1" if(v.size()>0) symbol=v[0]; else symbol=string(buf).substr(0,2); return; } if(nb==2) {//Second atom "C 1 1.450" if(v.size()==3) { symbol=v[0]; n1=(unsigned int) atoi(v[1].c_str()); v1=string2floatC(v[2]); } else { symbol=string(buf).substr(0,2); n1=(int) atoi(string(buf).substr(2,3).c_str()); v1=string2floatC(string(buf).substr(5,6)); } cout<<"ReadFHLine():"< '9') ) { cout<<"ZScatterer::ImportFenskeHallZMatrix()" <<":getting rid of first line..."<> nbAtoms; char c; while(!isgraph(is.peek())) is.get(c); // go to end of line // 17 //C 1 //N 1 1.465 //C 2 1.366 1 119.987 //N 3 1.321 2 120.030 1 6.0 //C 4 1.355 3 119.982 2 6.8 //N 5 1.136 4 180.000 3 46.3 //N 3 1.366 2 120.022 1 186.0 //C 7 1.466 3 119.988 2 354.9 // ... string symbol, atomName,bondAtomName,angleAtomName,dihedAtomName,junk; int bondAtom=0,angleAtom=0,dihedAtom=0; float bond=0,angle=0,dihed=0; int scattPow; //first if(named) { is >> atomName >> symbol >> junk; VFN_DEBUG_MESSAGE("ZScatterer::ImportFenskeHallZMatrix():#"<<2<<",name:"<GetScatteringPowerRegistry().Find (symbol,"ScatteringPowerAtom",true); if(scattPow==-1) { cout<<"Scattering power"<AddScatteringPower(new ScatteringPowerAtom(symbol,symbol)); } scattPow=mpCryst->GetScatteringPowerRegistry().Find (symbol,"ScatteringPowerAtom"); if(named) this->AddAtom(atomName, &(mpCryst->GetScatteringPowerRegistry().GetObj(scattPow)), 0,0, 0,0, 0,0); else { sprintf(buf,"%d",1); this->AddAtom(symbol+(string)buf, &(mpCryst->GetScatteringPowerRegistry().GetObj(scattPow)), 0,0, 0,0, 0,0); } } //second if(named) { is >> atomName >> symbol >> bondAtomName >> bond; VFN_DEBUG_MESSAGE("ZScatterer::ImportFenskeHallZMatrix():#"<<2<<",name:"<GetScatteringPowerRegistry().Find (symbol,"ScatteringPowerAtom",true); if(scattPow==-1) { cout<<"Scattering power"<AddScatteringPower(new ScatteringPowerAtom(symbol,symbol)); } scattPow=mpCryst->GetScatteringPowerRegistry().Find (symbol,"ScatteringPowerAtom"); if(named) { bondAtom=mZAtomRegistry.Find(bondAtomName); if(bondAtom<0) throw ObjCrystException(string("ZScatterer::ImportFenskeHallZMatrix:") +string("when adding atom ")+atomName+string(": could not find atom: ") +bondAtomName); this->AddAtom(atomName, &(mpCryst->GetScatteringPowerRegistry().GetObj(scattPow)), bondAtom,bond, 0,0, 0,0); } else { sprintf(buf,"%d",2); this->AddAtom(symbol+(string)buf, &(mpCryst->GetScatteringPowerRegistry().GetObj(scattPow)), bondAtom-1,bond, 0,0, 0,0); } } //third if(named) { is >> atomName >> symbol >> bondAtomName >> bond >> angleAtomName >> angle; VFN_DEBUG_MESSAGE("ZScatterer::ImportFenskeHallZMatrix():#"<<2<<",name:"<GetScatteringPowerRegistry().Find (symbol,"ScatteringPowerAtom",true); if(scattPow==-1) { cout<<"Scattering power"<AddScatteringPower(new ScatteringPowerAtom(symbol,symbol)); } scattPow=mpCryst->GetScatteringPowerRegistry().Find (symbol,"ScatteringPowerAtom"); if(named) { VFN_DEBUG_MESSAGE("ZScatterer::ImportFenskeHallZMatrix():#"<<3<<",name:"<AddAtom(atomName, &(mpCryst->GetScatteringPowerRegistry().GetObj(scattPow)), bondAtom,bond, angleAtom,angle*DEG2RAD, 0,0); } else { sprintf(buf,"%d",3); this->AddAtom(symbol+(string)buf, &(mpCryst->GetScatteringPowerRegistry().GetObj(scattPow)), bondAtom-1,bond, angleAtom-1,angle*DEG2RAD, 0,0); } } for(int i=3;i> atomName >> symbol >> bondAtomName >> bond >> angleAtomName >> angle >> dihedAtomName >> dihed; VFN_DEBUG_MESSAGE("ZScatterer::ImportFenskeHallZMatrix():#"<GetScatteringPowerRegistry().Find (symbol,"ScatteringPowerAtom",true); if(scattPow==-1) { cout<<"Scattering power"<AddScatteringPower(new ScatteringPowerAtom(symbol,symbol)); } scattPow=mpCryst->GetScatteringPowerRegistry().Find (symbol,"ScatteringPowerAtom"); if(named) { bondAtom=mZAtomRegistry.Find(bondAtomName); angleAtom=mZAtomRegistry.Find(angleAtomName); dihedAtom=mZAtomRegistry.Find(dihedAtomName); VFN_DEBUG_MESSAGE("ZScatterer::ImportFenskeHallZMatrix():#"<AddAtom(atomName, &(mpCryst->GetScatteringPowerRegistry().GetObj(scattPow)), bondAtom,bond, angleAtom,angle*DEG2RAD, dihedAtom,dihed*DEG2RAD); } else { sprintf(buf,"%d",i+1); this->AddAtom(symbol+(string)buf, &(mpCryst->GetScatteringPowerRegistry().GetObj(scattPow)), bondAtom-1,bond, angleAtom-1,angle*DEG2RAD, dihedAtom-1,dihed*DEG2RAD); } } } this->SetLimitsRelative(gpRefParTypeScattConformBondLength,-.03,.03); this->SetLimitsRelative(gpRefParTypeScattConformBondAngle,-.01,.01); this->SetLimitsRelative(gpRefParTypeScattConformDihedAngle,-.01,.01); } void ZScatterer::ExportFenskeHallZMatrix(ostream &os) { if(mNbAtom<1) return; os << mNbAtom<GetZAtomRegistry().GetObj(0).mpScattPow->GetName() << " 1"<GetZAtomRegistry().GetObj(1).mpScattPow->GetName() << " "<GetZBondAtom(1)+1<< " "<GetZBondLength(1) <GetZAtomRegistry().GetObj(2).mpScattPow->GetName() << " "<GetZBondAtom(2)+1 << " "<GetZBondLength(2) << " "<GetZAngleAtom(2)+1<< " "<GetZAngle(2)*RAD2DEG <GetZAtomRegistry().GetObj(i).mpScattPow->GetName() << " "<GetZBondAtom(i)+1 << " "<GetZBondLength(i) << " "<GetZAngleAtom(i)+1<< " "<GetZAngle(i)*RAD2DEG << " "<GetZDihedralAngleAtom(i)+1<< " "<GetZDihedralAngle(i)*RAD2DEG <::const_iterator ZScatterer::begin() const { return mZAtomRegistry.begin(); } vector::const_iterator ZScatterer::end() const { return mZAtomRegistry.end(); } void ZScatterer::GlobalOptRandomMove(const REAL mutationAmplitude, const RefParType *type) { if(mRandomMoveIsDone) return; VFN_DEBUG_ENTRY("ZScatterer::GlobalOptRandomMove()",3) TAU_PROFILE("ZScatterer::GlobalOptRandomMove()","void ()",TAU_DEFAULT); // give a 2% chance of either moving a single atom, or move // all atoms before a given torsion angle. // Only try this if there are more than 10 atoms (else it's not worth the speed cost) if((mNbAtom>=10) && ((rand()/(REAL)RAND_MAX)<.02) && (gpRefParTypeScattConform->IsDescendantFromOrSameAs(type)))//.01 { TAU_PROFILE_TIMER(timer1,\ "ZScatterer::GlobalOptRandomMoveSmart1(prepare ref par & mutate)"\ ,"", TAU_FIELD); TAU_PROFILE_TIMER(timer2,\ "ZScatterer::GlobalOptRandomMoveSmart2(optimize if necessary)"\ ,"", TAU_FIELD); TAU_PROFILE_START(timer1); // Do we have *any* dihedral angle to really move ? CrystVector_long dihed(mNbAtom); dihed=0; int nbDihed=0; RefinablePar *par; dihed(nbDihed++)=2;//This is the Psi angle, in fact. Should Chi be added, too ? for(int i=3;iGetPar(&(mZAtomRegistry.GetObj(i).mDihed))); if( !(par->IsFixed()) ) //&& !(par->IsLimited()) dihed(nbDihed++)=i; } if(nbDihed<2) //Can't play :-( { mRandomMoveIsDone=false; this->RefinableObj::GlobalOptRandomMove(mutationAmplitude); TAU_PROFILE_STOP(timer1); VFN_DEBUG_EXIT("ZScatterer::GlobalOptRandomMove():End",3) return; } // Build mpZMoveMinimizer object if(0==mpZMoveMinimizer) { mpZMoveMinimizer=new ZMoveMinimizer(*this); // copy all parameters (and not reference them, we will change the fix status.. // we could remove all popu parameters... for(int i=0; iGetNbPar();i++) mpZMoveMinimizer->AddPar(this->GetPar(i)); } // Pick one to move and get the relevant parameter // (maybe we should random-move also the associated bond lengths an angles, // but for now we'll concentrate on dihedral (torsion) angles. const int atom=dihed((int) (rand()/((REAL)RAND_MAX+1)*nbDihed)); //cout<GetPar(&mPsi)); else par=&(this->GetPar(&(mZAtomRegistry.GetObj(atom).mDihed))); VFN_DEBUG_MESSAGE("ZScatterer::GlobalOptRandomMove(): initial value:"<GetHumanValue() ,3) // Record the current conformation mpZMoveMinimizer->RecordConformation(); // Set up const int moveType= rand()%3; mpZMoveMinimizer->FixAllPar(); REAL x0,y0,z0; //cout << " Move Type:"<GetZBondAtom(atom)) ||(i==this->GetZAngleAtom(atom)) ||(i==this->GetZDihedralAngleAtom(atom)) ||(atom==this->GetZBondAtom(i)) ||(atom==this->GetZAngleAtom(i)) ||(atom==this->GetZDihedralAngleAtom(i))) { if(!(this->GetPar(&(mZAtomRegistry.GetObj(i).mBondLength)).IsFixed())) mpZMoveMinimizer->GetPar(&(mZAtomRegistry.GetObj(i).mBondLength)).SetIsFixed(false); if(!(this->GetPar(&(mZAtomRegistry.GetObj(i).mAngle)).IsFixed())) mpZMoveMinimizer->GetPar(&(mZAtomRegistry.GetObj(i).mAngle)).SetIsFixed(false); if(!(this->GetPar(&(mZAtomRegistry.GetObj(i).mDihed)).IsFixed())) mpZMoveMinimizer->GetPar(&(mZAtomRegistry.GetObj(i).mDihed)).SetIsFixed(false); } if(!(this->GetPar(&mPhi).IsFixed())) mpZMoveMinimizer->GetPar(&mPhi).SetIsFixed(false); if(!(this->GetPar(&mChi).IsFixed())) mpZMoveMinimizer->GetPar(&mChi).SetIsFixed(false); if( !(this->GetPar(&mPsi).IsFixed()) && (atom!=2)) mpZMoveMinimizer->GetPar(&mPsi).SetIsFixed(false); if(!(this->GetPar(&mXYZ(0)).IsFixed())) mpZMoveMinimizer->GetPar(&mXYZ(0)).SetIsFixed(false); if(!(this->GetPar(&mXYZ(1)).IsFixed())) mpZMoveMinimizer->GetPar(&mXYZ(1)).SetIsFixed(false); if(!(this->GetPar(&mXYZ(2)).IsFixed())) mpZMoveMinimizer->GetPar(&mXYZ(2)).SetIsFixed(false); break; } case 1:// (1) Try to move the atoms *before* the rotated bond { VFN_DEBUG_MESSAGE("ZScatterer::GlobalOptRandomMove():Move before the rotated bond",3) const int atom1=this->GetZBondAtom(atom); const int atom2=this->GetZAngleAtom(atom); weight=0; weight(atom1)=1; for(int i=0;iGetZBondAtom(i))>.1) weight(i)=1; weight(atom2)=1; for(int i=0;iGetZAngleAtom(i)) &&(atom1 !=this->GetZBondAtom(i)) &&(i != atom) ) { if(!(this->GetPar(&(mZAtomRegistry.GetObj(i).mBondLength)).IsFixed())) mpZMoveMinimizer->GetPar(&(mZAtomRegistry.GetObj(i).mBondLength)).SetIsFixed(false); if(!(this->GetPar(&(mZAtomRegistry.GetObj(i).mAngle)).IsFixed())) mpZMoveMinimizer->GetPar(&(mZAtomRegistry.GetObj(i).mAngle)).SetIsFixed(false); if(!(this->GetPar(&(mZAtomRegistry.GetObj(i).mDihed)).IsFixed())) mpZMoveMinimizer->GetPar(&(mZAtomRegistry.GetObj(i).mDihed)).SetIsFixed(false); } if(!(this->GetPar(&mPhi).IsFixed())) mpZMoveMinimizer->GetPar(&mPhi).SetIsFixed(false); if(!(this->GetPar(&mChi).IsFixed())) mpZMoveMinimizer->GetPar(&mChi).SetIsFixed(false); if( !(this->GetPar(&mPsi).IsFixed()) && (atom!=2)) mpZMoveMinimizer->GetPar(&mPsi).SetIsFixed(false); if(!(this->GetPar(&mXYZ(0)).IsFixed())) mpZMoveMinimizer->GetPar(&mXYZ(0)).SetIsFixed(false); if(!(this->GetPar(&mXYZ(1)).IsFixed())) mpZMoveMinimizer->GetPar(&mXYZ(1)).SetIsFixed(false); if(!(this->GetPar(&mXYZ(2)).IsFixed())) mpZMoveMinimizer->GetPar(&mXYZ(2)).SetIsFixed(false); if(!(this->GetPar(&(mZAtomRegistry.GetObj(atom).mBondLength)).IsFixed())) mpZMoveMinimizer->GetPar(&(mZAtomRegistry.GetObj(atom).mBondLength)).SetIsFixed(false); if(!(this->GetPar(&(mZAtomRegistry.GetObj(atom).mAngle)).IsFixed())) mpZMoveMinimizer->GetPar(&(mZAtomRegistry.GetObj(atom).mAngle)).SetIsFixed(false); break; } case 2:// (2) Try to move the atoms *after* the rotated bond { if(mCenterAtomIndex>=atom) { VFN_DEBUG_MESSAGE("ZScatterer::GlobalOptRandomMove():Move after the bond (translate)",3) x0=this->GetXCoord()(0); y0=this->GetYCoord()(0); z0=this->GetZCoord()(0); } else { VFN_DEBUG_MESSAGE("ZScatterer::GlobalOptRandomMove():Move after the bond(nothing to do)",3) } break; } } // Move it, and with some probability use flipping to some // not-so-random angles., and then minimize the conformation change mpZMoveMinimizer->SetZAtomWeight(weight); REAL change; if( (rand()%5)==0) { switch(rand()%5) { case 0: change=-120*DEG2RAD;break; case 1: change= -90*DEG2RAD;break; case 2: change= 90*DEG2RAD;break; case 3: change= 120*DEG2RAD;break; default:change= 180*DEG2RAD;break; } } else { change= par->GetGlobalOptimStep() *2*(rand()/(REAL)RAND_MAX-0.5)*mutationAmplitude*16; } TAU_PROFILE_STOP(timer1); VFN_DEBUG_MESSAGE("ZScatterer::GlobalOptRandomMove(): mutation:"<Mutate(change); if(2==moveType) { if(mCenterAtomIndex>=atom) { this->UpdateCoordinates(); x0 -= this->GetXCoord()(0); y0 -= this->GetYCoord()(0); z0 -= this->GetZCoord()(0); mpCryst->OrthonormalToFractionalCoords(x0,y0,z0); this->GetPar(mXYZ.data()).Mutate(x0); this->GetPar(mXYZ.data()+1).Mutate(y0); this->GetPar(mXYZ.data()+2).Mutate(z0); } } else { const REAL tmp=mpZMoveMinimizer->GetLogLikelihood(); if(tmp>.05) { TAU_PROFILE_START(timer2); if(tmp<1) mpZMoveMinimizer->MinimizeChange(100); else if(tmp<5) mpZMoveMinimizer->MinimizeChange(200); else mpZMoveMinimizer->MinimizeChange(500); TAU_PROFILE_STOP(timer2); } } VFN_DEBUG_MESSAGE("ZScatterer::GlobalOptRandomMove(): final value:"<GetHumanValue(),3) // } #if 0 { // find unfixed, dihedral angles to play with //unlimited? CrystVector_long dihed(mNbAtom); dihed=0; int nbDihed=0; RefinablePar *par; dihed(nbDihed++)=2; for(int i=3;iGetPar(&(mZAtomRegistry.GetObj(i).mDihed))); if( !(par->IsFixed()) ) //&& !(par->IsLimited()) dihed(nbDihed++)=i; } if(nbDihed<2) //Can't play :-( this->RefinableObj::GlobalOptRandomMove(mutationAmplitude); // Pick one const int atom=dihed((int) (rand()/((REAL)RAND_MAX+1)*nbDihed)); VFN_DEBUG_MESSAGE("ZScatterer::GlobalOptRandomMove(): "<(dihed) ,10) VFN_DEBUG_MESSAGE("ZScatterer::GlobalOptRandomMove(): Changing atom #"<GetPar(&mPsi)); else par=&(this->GetPar(&(mZAtomRegistry.GetObj(atom).mDihed))); // Get the old value const REAL old=par->GetValue(); // Move it, with a max amplitude 8x greater than usual if( (rand()/(REAL)RAND_MAX)<.1) {// give some probability to use certain angles: -120,-90,90,120,180 switch(rand()%5) { case 0: par->Mutate(-120*!DEG2RAD);break; case 1: par->Mutate( -90*!DEG2RAD);break; case 2: par->Mutate( 90*!DEG2RAD);break; case 3: par->Mutate( 120*!DEG2RAD);break; default:par->Mutate( 180*!DEG2RAD);break; } } else par->Mutate( par->GetGlobalOptimStep() *2*(rand()/(REAL)RAND_MAX-0.5)*mutationAmplitude*8); const REAL change=mZAtomRegistry.GetObj(atom).GetZDihedralAngle()-old; // Now move all atoms using this changed bond as a reference //const int atom2= mZAtomRegistry.GetObj(atom).GetZAngleAtom(); for(int i=atom;iGetPar(&(mZAtomRegistry.GetObj(i).mDihed)).Mutate(-change); if(mZAtomRegistry.GetObj(i).GetZAngleAtom()==atom) this->GetPar(&(mZAtomRegistry.GetObj(i).mDihed)).Mutate(-change); //cout <<"ZScatterer::GlobalOptRandomMove:"<(dihed,4) // <RefinableObj::GlobalOptRandomMove(mutationAmplitude,type); } mRandomMoveIsDone=true; VFN_DEBUG_EXIT("ZScatterer::GlobalOptRandomMove():End",3) } void ZScatterer::UpdateCoordinates() const { if(mClockCoord>mClockScatterer) return; VFN_DEBUG_ENTRY("ZScatterer::UpdateCoordinates():"<GetName(),3) TAU_PROFILE("ZScatterer::UpdateCoordinates()","void ()",TAU_DEFAULT); //if(0==mNbAtom) throw ObjCrystException("ZScatterer::Update() No Atoms in Scatterer !"); if(0==mNbAtom) return; { CrystMatrix_REAL phiMatrix(3,3),chiMatrix(3,3),psiMatrix(3,3); phiMatrix= cos(mPhi) , -sin(mPhi) , 0, sin(mPhi) , cos(mPhi) , 0, 0 ,0 ,1; chiMatrix= cos(mChi) ,0 ,-sin(mChi), 0 ,1 ,0, sin(mChi) ,0 ,cos(mChi); psiMatrix= 1 , 0 , 0, 0 ,cos(mPsi) ,-sin(mPsi), 0 ,sin(mPsi) ,cos(mPsi); mPhiChiPsiMatrix=product(chiMatrix,product(phiMatrix,psiMatrix)); //cout << phiMatrix <Atom #0:"<1) {// Atom 1 mXCoord(1)=GetZBondLength(1); mYCoord(1)=0.; mZCoord(1)=0.; VFN_DEBUG_MESSAGE("->Atom #1:"<2) {// Atom 2 if(0==GetZBondAtom(2)) //Linked with Atom 1 mXCoord(2)=GetZBondLength(2)*cos(GetZAngle(2)); else //Linked with Atom 1 mXCoord(2)=mXCoord(1)-GetZBondLength(2)*cos(GetZAngle(2)); mYCoord(2)=GetZBondLength(2)*sin(GetZAngle(2)); mZCoord(2)=0.; VFN_DEBUG_MESSAGE("->Atom #2:"<3) { REAL xa,ya,za,xb,yb,zb,xd,yd,zd,cosph,sinph,costh,sinth,coskh,sinkh,cosa,sina; REAL xpd,ypd,zpd,xqd,yqd,zqd; REAL rbc,xyb,yza,tmp,xpa,ypa,zqa; int na,nb,nc; bool flag; REAL dist,angle,dihed; for(int i=3;i= 0.999999 ) { // Colinear mXCoord(i)=mXCoord(na)+cosa*dist*rbc*xb; mYCoord(i)=mYCoord(na)+cosa*dist*rbc*yb; mZCoord(i)=mZCoord(na)+cosa*dist*rbc*zb; VFN_DEBUG_MESSAGE("->Atom #"< 1e-5 ) { coskh = ypa/yza; sinkh = zqa/yza; ypd = coskh*yd - sinkh*zd; zpd = coskh*zd + sinkh*yd; } else { ypd = yd; zpd = zd; } xpd = cosph*xd - sinph*zpd; zqd = cosph*zpd + sinph*xd; xqd = costh*xpd - sinth*ypd; yqd = costh*ypd + sinth*xpd; if( true==flag ) { // Rotate about y-axis ? mXCoord(i)=mXCoord(na) - zqd; mYCoord(i)=mYCoord(na) + yqd; mZCoord(i)=mZCoord(na) + xqd; } else { mXCoord(i)=mXCoord(na) + xqd; mYCoord(i)=mYCoord(na) + yqd; mZCoord(i)=mZCoord(na) + zqd; } VFN_DEBUG_MESSAGE("->Atom #"<GetX(); y=this->GetY(); z=this->GetZ(); mpCryst->FractionalToOrthonormalCoords(x,y,z); const REAL x0=x-mXCoord(mCenterAtomIndex); const REAL y0=y-mYCoord(mCenterAtomIndex); const REAL z0=z-mZCoord(mCenterAtomIndex); for(int i=0;iGetName(),3) } void ZScatterer::UpdateScattCompList() const { VFN_DEBUG_ENTRY("ZScatterer::UpdateScattCompList()"<GetName(),3) this->UpdateCoordinates(); if( (mClockScattCompList>mClockCoord) &&(mClockScattCompList>mpCryst->GetClockLatticePar())) return; if(true==mUseGlobalScattPow) { mScattCompList(0).mX=mXYZ(0); mScattCompList(0).mY=mXYZ(1); mScattCompList(0).mZ=mXYZ(2); mScattCompList(0).mOccupancy=mOccupancy; mScattCompList(0).mpScattPow=mpGlobalScattPow; // Update central atom for Display. //mXCoord(mCenterAtomIndex)=this->GetX(); //mYCoord(mCenterAtomIndex)=this->GetY(); //mZCoord(mCenterAtomIndex)=this->GetZ(); //mpCryst->FractionalToOrthonormalCoords(mXCoord(mCenterAtomIndex), // mXCoord(mCenterAtomIndex), // mXCoord(mCenterAtomIndex)); mClockScattCompList.Click(); VFN_DEBUG_MESSAGE("ZScatterer::UpdateScattCompList()->Global Scatterer:End",3) return; } long j=0; REAL x,y,z; VFN_DEBUG_MESSAGE("ZScatterer::UpdateScattCompList(bool):Finishing"<OrthonormalToFractionalCoords(x,y,z); mScattCompList(j ).mX=x; mScattCompList(j ).mY=y; mScattCompList(j ).mZ=z; mScattCompList(j ).mpScattPow=mZAtomRegistry.GetObj(i).GetScatteringPower(); mScattCompList(j++).mOccupancy=mZAtomRegistry.GetObj(i).GetOccupancy()*mOccupancy; } } #ifdef __DEBUG__ if(gVFNDebugMessageLevel<3) mScattCompList.Print(); #endif mClockScattCompList.Click(); VFN_DEBUG_EXIT("ZScatterer::UpdateScattCompList()"<GetName(),3) } void ZScatterer::InitRefParList() { VFN_DEBUG_MESSAGE("ZScatterer::InitRefParList():"<GetName(),5) //throw ObjCrystException("ZScatterer::InitRefParList() not implemented! "+this->GetName()); //:TODO: this->ResetParList(); { RefinablePar tmp("x",&mXYZ(0),0.,1., gpRefParTypeScattTranslX, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,true,1.,1.); tmp.AssignClock(mClockScatterer); this->AddPar(tmp); } { RefinablePar tmp("y",&mXYZ(1),0,1, gpRefParTypeScattTranslY, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,true,1.,1.); tmp.AssignClock(mClockScatterer); this->AddPar(tmp); } { RefinablePar tmp("z",&mXYZ(2),0,1, gpRefParTypeScattTranslZ, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,true,1.,1.); tmp.AssignClock(mClockScatterer); this->AddPar(tmp); } { RefinablePar tmp("Occupancy",&mOccupancy,0,1, gpRefParTypeScattOccup, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,1.,1.); tmp.AssignClock(mClockScatterer); this->AddPar(tmp); } if(false==mUseGlobalScattPow) { { RefinablePar tmp("Phi",&mPhi,0,2*M_PI, gpRefParTypeScattOrient, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,true,RAD2DEG,2*M_PI); tmp.AssignClock(mClockScatterer); this->AddPar(tmp); } { RefinablePar tmp("Chi",&mChi,0,2*M_PI, gpRefParTypeScattOrient, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,true,RAD2DEG,2*M_PI); tmp.AssignClock(mClockScatterer); this->AddPar(tmp); } { RefinablePar tmp("Psi",&mPsi,0,2*M_PI, gpRefParTypeScattOrient, REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,true,RAD2DEG,2*M_PI); tmp.AssignClock(mClockScatterer); this->AddPar(tmp); } char buf [20]; for(long i=0;iAddPar(tmp); } { sprintf(buf,"%d-%d-%d",(int)i,(int)(mZAtomRegistry.GetObj(i).GetZBondAtom()), (int)(mZAtomRegistry.GetObj(i).GetZAngleAtom())); RefinablePar tmp("Angle"+(string)buf, &(mZAtomRegistry.GetObj(i).mAngle),0,2*M_PI, gpRefParTypeScattConformBondAngle, REFPAR_DERIV_STEP_ABSOLUTE,false,false,usedAngle,true,RAD2DEG,2*M_PI); tmp.AssignClock(mClockScatterer); this->AddPar(tmp); } { sprintf(buf,"%d-%d-%d-%d",(int)i,(int)(mZAtomRegistry.GetObj(i).GetZBondAtom()), (int)(mZAtomRegistry.GetObj(i).GetZAngleAtom()), (int)(mZAtomRegistry.GetObj(i).GetZDihedralAngleAtom())); RefinablePar tmp("Dihed"+(string)buf, &(mZAtomRegistry.GetObj(i).mDihed),0,2*M_PI, gpRefParTypeScattConformDihedAngle, REFPAR_DERIV_STEP_ABSOLUTE,false,false,usedDihed,true,RAD2DEG,2*M_PI); tmp.AssignClock(mClockScatterer); this->AddPar(tmp); } if(0!=mZAtomRegistry.GetObj(i).GetScatteringPower()) {//fixed by default sprintf(buf,"%d",(int)i); RefinablePar tmp("Occupancy"+(string)buf, &(mZAtomRegistry.GetObj(i).mOccupancy),0,1, gpRefParTypeScattOccup, REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,1.,1.); tmp.AssignClock(mClockScatterer); this->AddPar(tmp); } } }//if(false==mUseGlobalScatteringPower) } #ifdef __WX__CRYST__ WXCrystObjBasic* ZScatterer::WXCreate(wxWindow* parent) { //:TODO: Check mpWXCrystObj==0 mpWXCrystObj=new WXZScatterer(parent,this); return mpWXCrystObj; } #endif //###################################################################### // // ZPolyhedron // // //###################################################################### ZPolyhedron::ZPolyhedron( const RegularPolyhedraType type,Crystal &cryst, const REAL x, const REAL y, const REAL z, const string &name, const ScatteringPower *centralAtomSymbol, const ScatteringPower *periphAtomSymbol,const REAL centralPeriphDist, const REAL ligandPopu, const REAL phi, const REAL chi, const REAL psi): ZScatterer(name,cryst,x,y,z,phi,chi,psi),mPolyhedraType(type) { VFN_DEBUG_MESSAGE("ZPolyhedron::ZPolyhedron(..)",5) // Additioning string and char arrays takes a huge lot of mem (gcc 2.95.2) const string name_=name+"_"; const string name_central=name_+centralAtomSymbol->GetName(); const string name_periph=name_+periphAtomSymbol->GetName(); switch(mPolyhedraType) { case TETRAHEDRON : { REAL ang=2*asin(sqrt(2./3.)); this ->AddAtom (name_central, centralAtomSymbol, 0,0., 0,0., 0,0., 1.); this ->AddAtom (name_periph+"1",periphAtomSymbol, 0,centralPeriphDist, 0,0., 0,0., 1.); this ->AddAtom (name_periph+"2",periphAtomSymbol, 0,centralPeriphDist, 1,ang, 0,0., 1.); this ->AddAtom (name_periph+"3",periphAtomSymbol, 0,centralPeriphDist, 1,ang, 2, M_PI*2./3., 1.); this ->AddAtom (name_periph+"4",periphAtomSymbol, 0,centralPeriphDist, 1,ang, 2,-M_PI*2./3., 1.); m3DDisplayIndex.resize(4,3); m3DDisplayIndex= 1,2,3, 1,2,4, 1,3,4, 2,3,4; break; } case OCTAHEDRON: { this ->AddAtom (name_central, centralAtomSymbol, 0,0., 0,0., 0,0., 1.); this ->AddAtom (name_periph+"1",periphAtomSymbol, 0,centralPeriphDist, 0,0., 0,0., 1.); this ->AddAtom (name_periph+"2",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI/2, 0,0., 1.); this ->AddAtom (name_periph+"3",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI/2, 2,M_PI/2, 1.); this ->AddAtom (name_periph+"4",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI/2, 2,-M_PI/2, 1.); this ->AddAtom (name_periph+"5",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI/2, 2,M_PI, 1.); this ->AddAtom (name_periph+"6",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI, 2,0., 1.); m3DDisplayIndex.resize(8,3); m3DDisplayIndex= 1,2,3, 1,2,4, 1,5,3, 1,5,4, 6,2,3, 6,2,4, 6,5,3, 6,5,4; break; } case SQUARE_PLANE: { this ->AddAtom (name_central, centralAtomSymbol, 0,0., 0,0., 0,0., 1.); this ->AddAtom (name+"_X",0, //Dummy atom on top 0,1., 0,0., 0,0., 1.); this ->AddAtom (name_periph+"1",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI/2, 0,0., 1.); this ->AddAtom (name_periph+"2",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI/2, 2,M_PI/2, 1.); this ->AddAtom (name_periph+"3",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI/2, 2,M_PI, 1.); this ->AddAtom (name_periph+"4",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI/2, 2,-M_PI/2, 1.); //:TODO: GL Display with squares //m3DDisplayIndex.resize(2,3); //m3DDisplayIndex= 2,4,2, // 2,4,5; break; } case CUBE: { this ->AddAtom (name_central, centralAtomSymbol, 0,0., 0,0., 0,0., 1.); this ->AddAtom (name+"_X",0, //Dummy atom in middle of face 0,1., 0,0., 0,0., 1.); this ->AddAtom (name_periph+"1",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI/4., 0,0., 1.); this ->AddAtom (name_periph+"2",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI/4., 2,M_PI/2., 1.); this ->AddAtom (name_periph+"3",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI/4., 2,M_PI, 1.); this ->AddAtom (name_periph+"4",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI/4., 2,-M_PI/2., 1.); this ->AddAtom (name_periph+"5",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI*3./4., 0,0., 1.); this ->AddAtom (name_periph+"6",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI*3./4., 2,M_PI/2., 1.); this ->AddAtom (name_periph+"7",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI*3./4., 2,M_PI, 1.); this ->AddAtom (name_periph+"8",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI*3./4., 2,M_PI*3./2., 1.); break; } case ANTIPRISM_TETRAGONAL: { this ->AddAtom (name_central, centralAtomSymbol, 0,0., 0,0., 0,0., 1.); this ->AddAtom (name+"_X",0, //Dummy atom in middle of face 0,1., 0,0., 0,0., 1.); this ->AddAtom (name_periph+"1",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI/4., 0,0., 1.); this ->AddAtom (name_periph+"2",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI/4., 2,M_PI/2., 1.); this ->AddAtom (name_periph+"3",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI/4., 2,M_PI, 1.); this ->AddAtom (name_periph+"4",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI/4., 2,-M_PI/2., 1.); this ->AddAtom (name_periph+"5",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI*3./4., 0,M_PI/4., 1.); this ->AddAtom (name_periph+"6",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI*3./4., 2,M_PI*3./4., 1.); this ->AddAtom (name_periph+"7",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI*3./4., 2,M_PI*5./4., 1.); this ->AddAtom (name_periph+"8",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI*3./4., 2,M_PI*7./4., 1.); break; } case PRISM_TETRAGONAL_MONOCAP: { this ->AddAtom (name_central, centralAtomSymbol, 0,0., 0,0., 0,0., 1.); this ->AddAtom (name_periph+"0",periphAtomSymbol, 0,centralPeriphDist, 0,0., 0,0., 1.); this ->AddAtom (name_periph+"1",periphAtomSymbol, 0,centralPeriphDist, 1,70*DEG2RAD, 0,0., 1.); this ->AddAtom (name_periph+"2",periphAtomSymbol, 0,centralPeriphDist, 1,70*DEG2RAD, 2,M_PI/2., 1.); this ->AddAtom (name_periph+"3",periphAtomSymbol, 0,centralPeriphDist, 1,70*DEG2RAD, 2,M_PI, 1.); this ->AddAtom (name_periph+"4",periphAtomSymbol, 0,centralPeriphDist, 1,70*DEG2RAD, 2,-M_PI/2., 1.); this ->AddAtom (name_periph+"5",periphAtomSymbol, 0,centralPeriphDist, 1,145*DEG2RAD, 0,0., 1.); this ->AddAtom (name_periph+"6",periphAtomSymbol, 0,centralPeriphDist, 1,145*DEG2RAD, 2,M_PI/2., 1.); this ->AddAtom (name_periph+"7",periphAtomSymbol, 0,centralPeriphDist, 1,145*DEG2RAD, 2,M_PI, 1.); this ->AddAtom (name_periph+"8",periphAtomSymbol, 0,centralPeriphDist, 1,145*DEG2RAD, 2,M_PI*3./2., 1.); break; } case PRISM_TETRAGONAL_DICAP: { this ->AddAtom (name_central, centralAtomSymbol, 0,0., 0,0., 0,0., 1.); this ->AddAtom (name_periph+"0",periphAtomSymbol, 0,centralPeriphDist, 0,0., 0,0., 1.); this ->AddAtom (name_periph+"1",periphAtomSymbol, 0,centralPeriphDist, 1,60*DEG2RAD, 0,0., 1.); this ->AddAtom (name_periph+"2",periphAtomSymbol, 0,centralPeriphDist, 1,60*DEG2RAD, 2,M_PI/2., 1.); this ->AddAtom (name_periph+"3",periphAtomSymbol, 0,centralPeriphDist, 1,60*DEG2RAD, 2,M_PI, 1.); this ->AddAtom (name_periph+"4",periphAtomSymbol, 0,centralPeriphDist, 1,60*DEG2RAD, 2,-M_PI/2., 1.); this ->AddAtom (name_periph+"5",periphAtomSymbol, 0,centralPeriphDist, 1,120*DEG2RAD, 0,0., 1.); this ->AddAtom (name_periph+"6",periphAtomSymbol, 0,centralPeriphDist, 1,120*DEG2RAD, 2,M_PI/2., 1.); this ->AddAtom (name_periph+"7",periphAtomSymbol, 0,centralPeriphDist, 1,120*DEG2RAD, 2,M_PI, 1.); this ->AddAtom (name_periph+"8",periphAtomSymbol, 0,centralPeriphDist, 1,120*DEG2RAD, 2,M_PI*3./2., 1.); this ->AddAtom (name_periph+"8",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI, 2,0., 1.); break; } case PRISM_TRIGONAL: { const REAL ang=55.*DEG2RAD; const REAL ang2=120.*DEG2RAD; this ->AddAtom (name_central, centralAtomSymbol, 0,0., 0,0., 0,0., 1.); this ->AddAtom (name+"_X",0, //Dummy atom in middle of top face 0,1., 0,0., 0,0., 0.); this ->AddAtom (name_periph+"0",periphAtomSymbol, 0,centralPeriphDist, 1,ang, 0,0., 1.); this ->AddAtom (name_periph+"1",periphAtomSymbol, 0,centralPeriphDist, 1,ang, 2,ang2, 1.); this ->AddAtom (name_periph+"2",periphAtomSymbol, 0,centralPeriphDist, 1,ang, 2,-ang2, 1.); this ->AddAtom (name_periph+"3",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI-ang, 0,0., 1.); this ->AddAtom (name_periph+"4",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI-ang, 2,ang2, 1.); this ->AddAtom (name_periph+"5",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI-ang, 2,-ang2, 1.); break; } case PRISM_TRIGONAL_TRICAPPED: { const REAL ang=55.*DEG2RAD; const REAL ang2=120.*DEG2RAD; this ->AddAtom (name_central, centralAtomSymbol, 0,0., 0,0., 0,0., 1.); this ->AddAtom (name+"_X",0, //Dummy atom in middle of top face 0,1., 0,0., 0,0., 0.); this ->AddAtom (name_periph+"0",periphAtomSymbol, 0,centralPeriphDist, 1,ang, 0,0., 1.); this ->AddAtom (name_periph+"1",periphAtomSymbol, 0,centralPeriphDist, 1,ang, 2,ang2, 1.); this ->AddAtom (name_periph+"2",periphAtomSymbol, 0,centralPeriphDist, 1,ang, 2,-ang2, 1.); this ->AddAtom (name_periph+"3",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI-ang, 0,0., 1.); this ->AddAtom (name_periph+"4",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI-ang, 2,ang2, 1.); this ->AddAtom (name_periph+"5",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI-ang, 2,-ang2, 1.); this ->AddAtom (name_periph+"6",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI/2., 2,M_PI, 1.); this ->AddAtom (name_periph+"7",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI/2., 2,M_PI/3., 1.); this ->AddAtom (name_periph+"8",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI/2., 2,-M_PI/3., 1.); break; } case ICOSAHEDRON: { const REAL ang=acos(sqrt(.2)); const REAL ang2=M_PI*2./5.; this ->AddAtom (name_central, centralAtomSymbol, 0,0., 0,0., 0,0., 1.); this ->AddAtom (name_periph+"0",periphAtomSymbol, 0,centralPeriphDist, 0,0., 0,0., 1.); this ->AddAtom (name_periph+"1",periphAtomSymbol, 0,centralPeriphDist, 1,ang, 1,0., 1.); this ->AddAtom (name_periph+"2",periphAtomSymbol, 0,centralPeriphDist, 1,ang, 2,ang2, 1.); this ->AddAtom (name_periph+"3",periphAtomSymbol, 0,centralPeriphDist, 1,ang, 2,2*ang2, 1.); this ->AddAtom (name_periph+"4",periphAtomSymbol, 0,centralPeriphDist, 1,ang, 2,-2*ang2, 1.); this ->AddAtom (name_periph+"5",periphAtomSymbol, 0,centralPeriphDist, 1,ang, 2,-ang2, 1.); this ->AddAtom (name_periph+"6",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI, 0,0., 1.); this ->AddAtom (name_periph+"7",periphAtomSymbol, 0,centralPeriphDist, 7,ang, 3,M_PI, 1.); this ->AddAtom (name_periph+"8",periphAtomSymbol, 0,centralPeriphDist, 7,ang, 8,ang2, 1.); this ->AddAtom (name_periph+"9",periphAtomSymbol, 0,centralPeriphDist, 7,ang, 8,2*ang2, 1.); this ->AddAtom (name_periph+"10",periphAtomSymbol, 0,centralPeriphDist, 7,ang, 8,-2*ang2, 1.); this ->AddAtom (name_periph+"11",periphAtomSymbol, 0,centralPeriphDist, 7,ang, 8,-ang2, 1.); break; } case TRIANGLE_PLANE: { this ->AddAtom (name_central, centralAtomSymbol, 0,0., 0,0., 0,0., 1.); this ->AddAtom (name+"_X",0, //Dummy atom on top 0,1., 0,0., 0,0., 1.); this ->AddAtom (name_periph+"1",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI/2, 0,0., 1.); this ->AddAtom (name_periph+"2",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI/2, 2,2*M_PI/3, 1.); this ->AddAtom (name_periph+"3",periphAtomSymbol, 0,centralPeriphDist, 1,M_PI/2, 2,-2*M_PI/3, 1.); //:TODO: GL Display with squares //m3DDisplayIndex.resize(2,3); //m3DDisplayIndex= 2,4,2, // 2,4,5; break; } default : throw ObjCrystException("ZPolyhedron::ZPolyhedron():Unknown Polyhedra type !"); } //We want to keep an approximate geometry //this->RefinableObj::Print(); this->SetLimitsRelative(gpRefParTypeScattConformBondLength,-.2,.2); this->SetLimitsRelative(gpRefParTypeScattConformBondAngle ,-.2,.2); this->SetLimitsRelative(gpRefParTypeScattConformDihedAngle,-.2,.2); //this->RefinableObj::Print(); VFN_DEBUG_MESSAGE("ZPolyhedron::ZPolyhedron():End:"<Init(scatt); } GlobalScatteringPower::GlobalScatteringPower(const GlobalScatteringPower& old):mpZScatterer(0) { VFN_DEBUG_MESSAGE("GlobalScatteringPower::GlobalScatteringPower(&old):"<Init(*(old.mpZScatterer)); } GlobalScatteringPower::~GlobalScatteringPower() { VFN_DEBUG_MESSAGE("GlobalScatteringPower::~GlobalScatteringPower():"<SetName(scatt.GetName()+(string)"_Global"); VFN_DEBUG_MESSAGE("GlobalScatteringPower::Init(&Scatt):"<SetUseGlobalScatteringPower(false); mpZScatterer->SetName(scatt.GetName()+"_GlobalCopy"); //Set the DynPopCorrIndex to the sum of the DynPopCorrIndexs (eg the sum of atomic numbers) mDynPopCorrIndex=0; const ScatteringComponentList* tmp=&(mpZScatterer->GetScatteringComponentList()); for(long i=0;iGetNbComponent();i++) mDynPopCorrIndex += (*tmp)(i).mpScattPow->GetDynPopCorrIndex(); } CrystVector_REAL GlobalScatteringPower:: GetScatteringFactor(const ScatteringData &data, const int spgSymPosIndex) const { // Here comes the hard work VFN_DEBUG_MESSAGE("GlobalScatteringPower::GetScatteringFactor():"<SetCrystal(cryst); pData->SetName("GlobalScatteringPowerData!"); VFN_DEBUG_MESSAGE("GlobalScatteringPower::GetScatteringFactor():No DEBUG Messages",5) VFN_DEBUG_LOCAL_LEVEL(10) const long nbStep=4;//number of steps over 90 degrees for phi,chi psi REAL norm=0; for(int i=-nbStep;i<=nbStep;i++) { mpZScatterer->SetChi(i*M_PI/2/nbStep); for(int j=-nbStep;j<=nbStep;j++) { mpZScatterer->SetPhi(j*M_PI/2/nbStep); for(int k=-nbStep;k<=nbStep;k++) { //cout <SetPsi(k*M_PI/2/nbStep); rsf=pData->GetFhklCalcReal(); rsf*=rsf; isf=pData->GetFhklCalcImag(); isf*=isf; rsf+=isf; rsf=sqrt(rsf); //correct for the solid angle (dChi*dPhi) corresponding to this orientation rsf*= cos(mpZScatterer->GetPhi());//:TODO: needs checking !!! norm += cos(mpZScatterer->GetPhi()); sf += rsf; } } //cout << FormatHorizVector(sf) <GetScatteringComponentList()); for(int i=0;iGetNbComponent();i++) sf += (*pList)(i).mpScattPow->GetForwardScatteringFactor(type); return sf; } CrystVector_REAL GlobalScatteringPower:: GetTemperatureFactor(const ScatteringData &data, const int spgSymPosIndex) const { VFN_DEBUG_MESSAGE("GlobalScatteringPower::GetTemperatureFactor(data):"< namespace ObjCryst { class ZScatterer; //###################################################################### // // GLOBAL SCATTERING POWER /** * \brief Global Scattering Power. Used to approximate the scattering * power of a multi-atom ZScatterer (polyhedron,...) to an isotropic * scattering power. * * The scattering power will be (\b slowly) approximated to the average * scattering power of this ZScatterer take in all orientations. * The approximated scattering factor will include the temperature factor * and resonant scattering factors contributions. * * This is only used in ZScatterer, and maybe obsolete (?). */ //###################################################################### class GlobalScatteringPower:virtual public ScatteringPower { public: GlobalScatteringPower(); GlobalScatteringPower(const ZScatterer &scatt); GlobalScatteringPower(const GlobalScatteringPower& old); ~GlobalScatteringPower(); /// Re-initialize parameters (after using the default constructor). void Init(const ZScatterer &scatt); virtual CrystVector_REAL GetScatteringFactor(const ScatteringData &data, const int spgSymPosIndex=0) const; virtual REAL GetForwardScatteringFactor(const RadiationType) const; virtual CrystVector_REAL GetTemperatureFactor(const ScatteringData &data, const int spgSymPosIndex=0) const; virtual CrystMatrix_REAL GetResonantScattFactReal(const ScatteringData &data, const int spgSymPosIndex=0) const; virtual CrystMatrix_REAL GetResonantScattFactImag(const ScatteringData &data, const int spgSymPosIndex=0) const; virtual REAL GetRadius()const; protected: virtual void InitRefParList(); /// a copy of the ZScatterer associated to this object ZScatterer *mpZScatterer; private: // Avoid compiler warnings. Explicitly hide the base-class method. void Init(); }; //###################################################################### /// Class for individual atoms in a ZScatterer Object. This class /// is \e purely \e internal to ZScatterer, so should not be used /// for any other purpose... //###################################################################### class ZAtom { public: ZAtom(ZScatterer &scatt,const ScatteringPower *pow, const long atomBond=0, const REAL bondLength=1, const long atomAngle=0, const REAL bondAngle=M_PI, const long atomDihedral=0, const REAL dihedralAngle=M_PI, const REAL popu=1., const string &name=""); ~ZAtom(); const string& GetClassName()const; const string& GetName()const; void SetName(const string&); /// Get the ZScatterer associated to this ZAtom const ZScatterer& GetZScatterer()const; /// Get the ZScatterer associated to this ZAtom ZScatterer& GetZScatterer(); /// Index of the 1st atom used to define the atom in the Z-Matrix (the one from /// which the bondlength is calculated) long GetZBondAtom()const; /// Index of the 2nd atom used to define the atom in the Z-Matrix (the one from /// which the angle is calculated) long GetZAngleAtom()const; /// Index of the 3rd atom used to define the atom in the Z-Matrix (the one from /// which the dihedral angle is calculated) long GetZDihedralAngleAtom()const; ///Const access to bondlength parameter. const REAL& GetZBondLength()const; ///Const access to the angle parameter. const REAL& GetZAngle()const; ///Const access to the dihedral angle parameter. const REAL& GetZDihedralAngle()const; ///Const access to the ocupancy parameter. const REAL& GetOccupancy()const; ///ScatteringPower for this atom. const ScatteringPower* GetScatteringPower()const; ///Access to bondlength parameter. void SetZBondLength(const REAL); ///Access to the angle parameter. void SetZAngle(const REAL); ///Access to the dihedral angle parameter. void SetZDihedralAngle(const REAL); ///Access to the dihedral angle parameter. void SetOccupancy(const REAL); ///Set the ScatteringPower. void SetScatteringPower(const ScatteringPower*); void XMLOutput(ostream &os,int indent=0)const; void XMLInput(istream &is,const XMLCrystTag &tag); private: /// The ScatteringPower corresponding to this atom. const ScatteringPower *mpScattPow; /// The index (in the ZScatterer) of the atoms which are used to define the /// position of this atom. long mAtomBond,mAtomAngle,mAtomDihed; /// Bond length, angle and dihedral angle. REAL mBondLength,mAngle,mDihed,mOccupancy; /// Name for this atom string mName; /// the ZScatterer in which this atom is included. ZScatterer *mpScatt; friend class ZScatterer; //So that RefinablePar can be declared in ZScatterer #ifdef __WX__CRYST__ public: WXCrystObjBasic* WXCreate(wxWindow *parent); WXCrystObjBasic* WXGet(); void WXDelete(); void WXNotifyDelete(); private: WXCrystObjBasic *mpWXCrystObj; friend class WXZAtom; #endif }; //###################################################################### /** \brief Class to minimize conformation changes for random moves. Very * experimental !!! * \internal Only used within ZScatterer. */ //###################################################################### class ZMoveMinimizer:public RefinableObj { public: ZMoveMinimizer(ZScatterer &scatt); ~ZMoveMinimizer(); virtual REAL GetLogLikelihood()const; void RecordConformation(); void SetZAtomWeight(const CrystVector_REAL weight); void MinimizeChange(long nbTrial=10000); private: ZScatterer *mpZScatt; MonteCarloObj mOptimObj; CrystVector_REAL mXCoord0,mYCoord0,mZCoord0; CrystVector_REAL mAtomWeight; }; //###################################################################### /// ZScatterer: the basic type of complex scatterers, where atom positions /// are defined using a standard "Z-Matrix" description. This is used /// to describe inorganic polyhedras, as well as molecules. //###################################################################### class ZScatterer: public Scatterer { public: /** \brief ZScatterer constructor * * \param name: the name of the scatterer * \param cryst: the crystal in which the scatterer is (needed to convert * from cartesian to fractionnal coordinates). * \param x,y,z: fractionnal coordinates of the scatterer * \param phi,chi: angles defining the orientation of the scatterer */ ZScatterer(const string &name,Crystal &cryst, const REAL x=0.,const REAL y=0.,const REAL z=0., const REAL phi=0.,const REAL chi=0., const REAL psi=0.); /** \brief Copy constructor * */ ZScatterer(const ZScatterer &old); ~ZScatterer(); /// \internal so-called Virtual copy constructor, needed to make copies /// of arrays of Scatterers virtual ZScatterer* CreateCopy() const; virtual const string& GetClassName() const; /// Add an atom to the Zscatterer. If &ScatteringPower=0, then it is a 'dummy' /// atom and will be ignored for any scattering analysis. The 'name' supplied may /// not be respected, and can be replaced by 'ZScatterer_name'+'AtomNum'+'ScattPowName' void AddAtom(const string &name,const ScatteringPower *pow, const long atomBond, const REAL bondLength, const long atomAngle, const REAL bondAngle, const long atomDihedral, const REAL dihedralAngle, const REAL popu=1.); virtual int GetNbComponent() const; virtual const ScatteringComponentList& GetScatteringComponentList() const; virtual string GetComponentName(const int i) const; ///Print a single line of information about this scatterer void Print() const; ///Access to phi parameter (overall orientation of the scatterer) REAL GetPhi()const; ///Access to chi parameter (overall orientation of the scatterer) REAL GetChi()const; ///Access to psi parameter (overall orientation of the scatterer) REAL GetPsi()const; ///Access to phi parameter (overall orientation of the scatterer) void SetPhi(const REAL); ///Access to chi parameter (overall orientation of the scatterer) void SetChi(const REAL); ///Access to psi parameter (overall orientation of the scatterer) void SetPsi(const REAL); /// Get the X fractionnal coordinate of atom i REAL GetZAtomX(const int i)const; /// Get the Y fractionnal coordinate of atom i REAL GetZAtomY(const int i)const; /// Get the Z fractionnal coordinate of atom i REAL GetZAtomZ(const int i)const; /// Index of the 1st atom used to define the i-th atom in the Z-Matrix (the one from /// which the bondlength is calculated) long GetZBondAtom(const int i)const; /// Index of the 2nd atom used to define the i-th atom in the Z-Matrix (the one from /// which the angle is calculated) long GetZAngleAtom(const int i)const; /// Index of the 3rd atom used to define the i-th atom in the Z-Matrix (the one from /// which the dihedral angle is calculated) long GetZDihedralAngleAtom(const int i)const; ///Const access to bondlength parameter, for the i-th row in the Z-Matrix. REAL GetZBondLength(const int i)const; ///Const access to the angle parameter, for the i-th row in the Z-Matrix. REAL GetZAngle(const int i)const; ///Const access to the dihedral angle parameter, for the i-th row in the Z-Matrix. REAL GetZDihedralAngle(const int i)const; ///Access to bondlength parameter, for the i-th row in the Z-Matrix. void SetZBondLength(const int i,const REAL); ///Access to the angle parameter, for the i-th row in the Z-Matrix. void SetZAngle(const int i,const REAL); ///Access to the dihedral angle parameter, for the i-th row in the Z-Matrix. void SetZDihedralAngle(const int i,const REAL); ///Access to the registry of ZAtoms const ObjRegistry& GetZAtomRegistry()const; /// \warning Not implemented for ZScatterer virtual ostream& POVRayDescription(ostream &os, const CrystalPOVRayOptions &options)const; #ifdef OBJCRYST_GL virtual void GLInitDisplayList(const bool onlyIndependentAtoms=false, const REAL xMin=-.1,const REAL xMax=1.1, const REAL yMin=-.1,const REAL yMax=1.1, const REAL zMin=-.1,const REAL zMax=1.1, const bool displayEnantiomer=false, const bool displayNames=false, const bool hideHydrogens=false, const REAL fadeDistance=0, const bool fullMoleculeInLimits=false)const; #endif // OBJCRYST_GL /** \brief use a Global scattering power for this scatterer ? * * If true, then the overall scattering power of this ZScatterer will be * approximated to an isotropic scattering power computed for this scatterer. * Of course, only use this if the "isotropic" approximation is reasonable for * this scatterer (typically true for 'large' polyhedra). See GlobalScatteringPower. * * \warning EXPERIMENTAL */ virtual void SetUseGlobalScatteringPower(const bool useIt); virtual void XMLOutput(ostream &os,int indent=0)const; virtual void XMLInput(istream &is,const XMLCrystTag &tag); //virtual void XMLInputOld(istream &is,const IOCrystTag &tag); virtual void GetGeneGroup(const RefinableObj &obj, CrystVector_uint & groupIndex, unsigned int &firstGroup) const; virtual void GlobalOptRandomMove(const REAL mutationAmplitude, const RefParType *type=gpRefParTypeObjCryst); /// Get the list of all ZAtom cartesian x coordinates. const CrystVector_REAL& GetXCoord() const; /// Get the list of all ZAtom cartesian x coordinates. const CrystVector_REAL& GetYCoord() const; /// Get the list of all ZAtom cartesian x coordinates. const CrystVector_REAL& GetZCoord() const; virtual void EndOptimization(); /** Import "Fenske-Hall" ZMatrix file (fhz in the babel * program http://www.eyesopen.com/babel.html\ * example: use "./babel -ipdb foo.pdb -ofhz foo.fhz -d", * to convert a pdb file to a Z-Matrix file (the -d removes * hydrogen atoms) * * \param is: the input stream from which to read the z-matrix * \param names: if true, instead of reading a standard Fenske-Hall * z-matrix, the file will be read with names, i.e. with an added first * column with the names of the atoms, and the number used to reference * the bond, bond angle and dihedral angle atoms are replaced by the * names of the atoms. * * \warning: this should be called \e before any atom has been * added (if there are already atoms, they should be removed * but this has not been tested...) * * \note: this will search in the Crystal associated with this * ZScatterer the relevant ScatteringPowerAtom, which should have * the name of the corresponding symbol (eg 'H', 'C',...) * if these are not found then they will be added to the Crystal * with a default isotropic B-factor equal to 1. * \note: this also sets relative limits of +/-.03 Angstroems * for all bond distances, and +/-3.6 degress for bond and * dihedral angles. * \todo: identify which dihedral angles should \e not be limited, * by analysing a coordination table. */ void ImportFenskeHallZMatrix(istream &is,bool named=false); /** Export to Fenske-Hall ZMatrix file * * \todo USe more strict formatting than space-delimited. */ void ExportFenskeHallZMatrix(ostream &os); /// Set the index of the central atom (around which the rotation is made) void SetCenterAtomIndex(const unsigned int); /// Get the index of the central atom (around which the rotation is made) unsigned int GetCenterAtomIndex()const; /** STL access to registry of Zatom size */ std::size_t size() const; /** low-level access to the underlying vector of ZAtom begin(). * Const access as we do not want the number and order of objects to change, * but the objects themselves can be modified. */ vector::const_iterator begin() const; /** low-level access to the underlying vector of ZAtom end(). * Const access as we do not want the number and order of objects to change, * but the objects themselves can be modified. */ vector::const_iterator end() const; protected: /** Update the atom coordinates (in real units, in Angstroems). * * This takes into account the translation and global * rotation of the scatterer (ie this does not generate 'internal * coordinates). */ void UpdateCoordinates() const; /** Update the scattering component list, ie compute all atom * positions from the bonds/angles/dihedral angles, and convert * the coordinates to fractionnal coordinates of the Crystal. * * */ void UpdateScattCompList() const; /** For 3D display of the structure, bonds, triangular and quadric * faces can be displayed. This matrix determines what is drawn. * This is a 5-column matrix. The first column indicates the type of * drawing (0: : nothing, 1: display the atom (a sphere), 2: bond, * 3: triangular face, 4: quadric face) * the other columns indicate the index of the atoms involved in the * drawing (2 atoms for a bond, 3 for....) * * If the matrix is empty only the individual atoms are displayed. * * \todo This is still experimental. This is only used for the display * of ZPolyhedron, and should be more developped (and it should also * be saved in XML files !) */ CrystMatrix_long m3DDisplayIndex; /// The list of scattering components. mutable ScatteringComponentList mScattCompList; ///Total number of atoms in the structure long mNbAtom; private: ///Prepare refinable parameters for the scatterer object virtual void InitRefParList(); ///Number of "dummy" atoms in the structure long mNbDummyAtom; /// Index of atoms in the ScatteringComponentList. We need this list because /// Dummy atoms are not included in it. So this is an integer array with /// [ 0 1 2 4 5 6].. where the missing '3' marks a Dummy atom. Thus /// to get the name of component 'i' in the component list, you must /// take the mComponentIndex(i) atom in the ZAtom Registry. CrystVector_int mComponentIndex; /** \brief Angles giving the orientation of the ZScatterer (stored in radian) * * The position of any atom can be transformed from internal coordinates (orthonormal * coordinates derived from the ZMatrix, with first atom at (0,0,0), second * atom at (x,0,0), third atom at (x,y,0),...) to orthonormal coordinates in * the crystal reference frame (ie with orientation of the ZScatterer) using : * \f[ \left[ \begin{array}{c} x(i) \\ y(i) \\ z(i) \end{array} \right]_{orthonormal} = \left[ \begin{array}{ccc} \cos(\chi) & 0 & -\sin(\chi) \\ 0 & 1 & 0 \\ \sin(\chi) & 0 & \cos(\chi) \end{array} \right] \times \left[ \begin{array}{ccc} \cos(\phi) & -\sin(\phi) & 0 \\ \sin(\phi) & \cos(\phi) & 0 \\ 0 & 0 & 1 \end{array} \right] \times \left[ \begin{array}{ccc} 1 & 0 & 0 \\ 0 & \cos(\psi) & -\sin(\psi) \\ 0 & \sin(\psi) & \cos(\psi) \end{array} \right] \times \left[ \begin{array}{c} x_0(i) \\ y_0(i) \\ z_0(i) \end{array} \right] * \f] *, where x0(i), y0(i) and z0(i) describe the position for atom (i) in * internal coordinates, and x(i), y(i), z(i) are coordinates of the rotated ZScatterer. * * * The rotation is performed around a 'pivot' atom (see ZScatterer::mPivotAtom) */ REAL mPhi,mChi,mPsi; /// Registry for ZAtoms in this Scatterer. ObjRegistry mZAtomRegistry; /// Index of the atom used as a pivot (the scatterer is rotated around this atom). /// This should more or less be at the center of the Scatterer. long mCenterAtomIndex; /// Rotation matrix for the orientation of the scatterer mutable CrystMatrix_REAL mPhiChiPsiMatrix; /// Does the ZScatterer use a global scattering power ? /// \warning EXPERIMENTAL. bool mUseGlobalScattPow; /// the global scattering power used, if mUseGlobalScattPow=true /// \warning EXPERIMENTAL. GlobalScatteringPower* mpGlobalScattPow; /// Storage for Cartesian coordinates. The (0,0,0) is on the central atom. This /// includes Dummy atoms. mutable CrystVector_REAL mXCoord,mYCoord,mZCoord; /// Last time the cartesian coordinates were computed mutable RefinableObjClock mClockCoord; ZMoveMinimizer *mpZMoveMinimizer; #ifdef __WX__CRYST__ public: virtual WXCrystObjBasic* WXCreate(wxWindow*); friend class WXZScatterer; #endif }; //###################################################################### // // Different types of regular polyhedra // //###################################################################### enum RegularPolyhedraType { TETRAHEDRON, OCTAHEDRON, SQUARE_PLANE, CUBE, ANTIPRISM_TETRAGONAL, PRISM_TETRAGONAL_MONOCAP, PRISM_TETRAGONAL_DICAP, PRISM_TRIGONAL,PRISM_TRIGONAL_TRICAPPED, ICOSAHEDRON, TRIANGLE_PLANE}; //###################################################################### /// \class ZPolyhedron include.h ObjCryst/ZScatterer.h /// /// ZPolyhedron: a Scatterer to describe polyhedras such as octahedron, /// tetrahedron, square plane, etc... These are ZScatterer objects, so that /// even if they are initialized with constraints, these can be removed /// to make any configuration. //###################################################################### class ZPolyhedron: public ZScatterer { public: /** \brief ZPolyhedron constructor * \param type : OCTAHEDRON, TETRAHEDRON,... * \param cryst : a crystal is necessary to transform the orthornormal * coordinates (in which the relative atom positions are computed) to fractional ones. * \param x,y,z : \e fractional coordinates of the center of the polyhedra * \param name : name of the Polyhedra ('WO6','TaSe4_a', 'Tetra01'...). * The name can have \e any format but spaces should be avoided, since it * will generate problems when reading the names from a file. And there must \b not * be identical name for two scatterers in a given crystal object. * \param periphAtomPow,centralAtomPow: the ScatteringPower corresponding to the * central and peripheral atoms, respectively. * \param centralPeriphDist: the distance, in angstroems, from the central * to the peripheral atoms * \param ligandPopu : the relative population of ligand atoms, equal to 1/n if * ligand atoms are shared by n polyhedra. If you are using the 'Dynamical Polpulation * Correction', then keep this parameter to 1. * \param phi,chi,psi: initial angles for this polyhedron */ ZPolyhedron( const RegularPolyhedraType type, Crystal &cryst, const REAL x, const REAL y, const REAL z, const string &name, const ScatteringPower *centralAtomPow, const ScatteringPower *periphAtomPow,const REAL centralPeriphDist, const REAL ligandPopu=1, const REAL phi=0., const REAL chi=0., const REAL psi=0.); /// Copy Constructor ZPolyhedron(const ZPolyhedron&); /// \internal so-called Virtual copy constructor, needed to make copies ///of arrays of Scatterers virtual ZPolyhedron* CreateCopy() const; /* \brief Copy constructor * ZPolyhedron(const ZPolyhedron &old); */ protected: private: //Prepare refinable parameters for the scatterer object //virtual void InitRefParList(); /// RegularPolyhedraType mPolyhedraType; }; }//namespace #include "ObjCryst/ObjCryst/Crystal.h" #endif //_OBJCRYST_ZSCATTERER_H_ objcryst-2022.1/ObjCryst/ObjCryst/bc32.mak000066400000000000000000000023061430515525000201610ustar00rootroot00000000000000!include ..\rules.mak libcryst.lib : Indexing.obj CIF.obj ReflectionProfile.obj PowderPatternBackgroundBayesianMinimiser.obj Polyhedron.obj Molecule.obj ScatteringPowerSphere.obj ScatteringCorr.obj Spacegroup.obj Scatterer.obj Atom.obj ScatteringPower.obj ZScatterer.obj Crystal.obj ScatteringData.obj DiffractionDataSingleCrystal.obj PowderPattern.obj Exception.obj geomStructFactor.obj geomStructFactor_001.obj geomStructFactor_002.obj geomStructFactor_067.obj geomStructFactor_097.obj geomStructFactor_230.obj geomStructFactor_centro.obj IO.obj UnitCell.obj test.obj ${GL_OBJ} tlib "libcryst.lib" -+Indexing.obj -+CIF.obj -+ReflectionProfile.obj -+PowderPatternBackgroundBayesianMinimiser.obj -+Polyhedron.obj -+Molecule.obj -+ScatteringPowerSphere.obj -+ScatteringCorr.obj -+Spacegroup.obj -+Scatterer.obj -+Atom.obj -+ScatteringPower.obj -+ZScatterer.obj -+Crystal.obj -+ScatteringData.obj -+DiffractionDataSingleCrystal.obj -+PowderPattern.obj -+Exception.obj -+geomStructFactor.obj -+geomStructFactor_001.obj -+geomStructFactor_002.obj -+geomStructFactor_067.obj -+geomStructFactor_097.obj -+geomStructFactor_230.obj -+geomStructFactor_centro.obj -+IO.obj -+UnitCell.obj -+test.obj -+${GL_OBJ} lib: libcryst.lib objcryst-2022.1/ObjCryst/ObjCryst/geomStructFactor.cpp000066400000000000000000000043231430515525000227360ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ //:NOTE: It may be a good idea to use a static array to compute the structure //factor, so that less time be spent in the construction of the array. //For example by using mutable member (assuming h,k and l's are always CrystVector_REAL), //:NOTE: Or the result could be returned in an array given as a parameter //NOTA BENE : normally, the formatting of the equations is the same as in //the Int. Tables for X-Ray Crystallography (1969) : one line of equation //should correspond to one line in the table, for easier check. #include "ObjCryst/CrystVector/CrystVector.h" namespace ObjCryst { void RealGeomStructFactor (const REAL x, const REAL y, const REAL z, const CrystVector_REAL&h, const CrystVector_REAL&k, const CrystVector_REAL&l, CrystVector_REAL& rsf) { }; void ImagGeomStructFactor (const REAL x, const REAL y, const REAL z, const CrystVector_REAL&h, const CrystVector_REAL&k, const CrystVector_REAL&l, CrystVector_REAL& isf) { }; }//namespace objcryst-2022.1/ObjCryst/ObjCryst/geomStructFactor_001.cpp000066400000000000000000000052251430515525000233200ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ObjCryst/CrystVector/CrystVector.h" #ifdef __VFN_GEOM_STRUCT_FACTOR_USE_POINTERS #define H (*h) #define K (*k) #define L (*l) #define SF (*sf) #define __VFN_GEOM_STRUCT_FACTOR_POINTERS_INIT const REAL *h,*k,*l; REAL*sf;\ h=hh.data();k=kk.data();l=ll.data();sf=sfsf.data(); for(long i=0;i #include #include "ObjCryst/ObjCryst/test.h" #include "ObjCryst/ObjCryst/Crystal.h" #include "ObjCryst/ObjCryst/Atom.h" #include "ObjCryst/ObjCryst/DiffractionDataSingleCrystal.h" #include "ObjCryst/ObjCryst/PowderPattern.h" #include "ObjCryst/RefinableObj/GlobalOptimObj.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" namespace ObjCryst { SpeedTestReport SpeedTest(const unsigned int nbAtom, const int nbAtomType,const string spacegroup, const RadiationType radiation, const unsigned long nbReflections, const unsigned int dataType,const REAL time) { Crystal cryst(9,11,15,1.2,1.3,1.7,spacegroup); for(int i=0;iSetWavelength(0.25); pDataTmp->SetRadiationType(radiation); pDataTmp->SetMaxSinThetaOvLambda(100.); pDataTmp->SetCrystal(cryst); float maxtheta=0.1; for(;;) { pDataTmp->GenHKLFullSpace(maxtheta, true); if(pDataTmp->GetNbRefl()>(long)nbReflections) break; maxtheta*=1.5; if(maxtheta>=M_PI/2.) break; } CrystVector_REAL hh; hh=pDataTmp->GetH();hh.resizeAndPreserve(nbReflections);hh+=0.0001; CrystVector_REAL kk; kk=pDataTmp->GetK();kk.resizeAndPreserve(nbReflections);kk+=0.0001; CrystVector_REAL ll; ll=pDataTmp->GetL();ll.resizeAndPreserve(nbReflections);ll+=0.0001; CrystVector_long h(nbReflections); h=hh; CrystVector_long k(nbReflections); k=kk; CrystVector_long l(nbReflections); l=ll; CrystVector_REAL iobs(nbReflections); for(unsigned int i=0;iSetHklIobs (h, k, l, iobs, sigma); pDataTmp->SetWeightToInvSigma2(); pData=pDataTmp; break; } case 1: { PowderPattern *pDataTmp=new PowderPattern; pDataTmp->SetWavelength(0.25); pDataTmp->SetRadiationType(radiation); pDataTmp->SetPowderPatternPar(0.001,.001,3140); CrystVector_REAL iobs(3140); for(unsigned int i=0;i<3140;++i) iobs(i)=(REAL)rand()+1.; pDataTmp->SetPowderPatternObs(iobs); pDataTmp->SetMaxSinThetaOvLambda(100.); PowderPatternBackground *backgdData= new PowderPatternBackground; backgdData->SetName("PbSo4-background"); { CrystVector_REAL tth(2),backgd(2); tth(0)=0.;tth(1)=3.14; backgd(0)=1.;backgd(1)=9.; backgdData->SetInterpPoints(tth,backgd); } pDataTmp->AddPowderPatternComponent(*backgdData); PowderPatternDiffraction * diffData=new PowderPatternDiffraction; diffData->SetCrystal(cryst); pDataTmp->AddPowderPatternComponent(*diffData); diffData->SetName("Crystal phase"); diffData->SetReflectionProfilePar(PROFILE_PSEUDO_VOIGT, .03*DEG2RAD*DEG2RAD,0.,0.,0.3,0); { float maxtheta=0.1; for(;;) { diffData->ScatteringData::GenHKLFullSpace(maxtheta, true); if(diffData->GetNbRefl()>(long)nbReflections) break; maxtheta*=1.5; if(maxtheta>=M_PI/2.) break; } CrystVector_REAL hh; hh=diffData->GetH();hh.resizeAndPreserve(nbReflections); CrystVector_REAL kk; kk=diffData->GetK();kk.resizeAndPreserve(nbReflections); CrystVector_REAL ll; ll=diffData->GetL();ll.resizeAndPreserve(nbReflections); diffData->SetHKL (hh, kk, ll); } pData=pDataTmp; break; } } //Create the global optimization object MonteCarloObj *pGlobalOptObj=new MonteCarloObj; pGlobalOptObj->AddRefinableObj(*pData); pGlobalOptObj->AddRefinableObj(cryst); //Refine only positionnal parameters pGlobalOptObj->FixAllPar(); pGlobalOptObj->SetParIsFixed(gpRefParTypeScattTransl,false); pGlobalOptObj->SetParIsFixed(gpRefParTypeScattOrient,false); //Don't cheat ;-) pGlobalOptObj->RandomizeStartingConfig(); //Annealing parameters (schedule, Tmax, Tmin, displacement schedule, pGlobalOptObj->SetAlgorithmParallTempering(ANNEALING_SMART,1e8,1e-8, ANNEALING_EXPONENTIAL,8,.125); //Global Optimization //The real job-first test long nbTrial=50000000; pGlobalOptObj->Optimize(nbTrial,true,0,time); SpeedTestReport report; report.mNbAtom=nbAtom; report.mNbAtomType=nbAtomType; report.mSpacegroup=spacegroup; report.mRadiation=radiation; report.mNbReflections=nbReflections; report.mDataType=dataType; report.mBogoMRAPS=(REAL)nbAtom*cryst.GetSpaceGroup().GetNbSymmetrics()*(REAL)nbReflections *(50000000-nbTrial)/pGlobalOptObj->GetLastOptimElapsedTime()/1e6; report.mBogoMRAPS_reduced=(REAL)nbAtom*cryst.GetSpaceGroup().GetNbSymmetrics(true,true) *(REAL)nbReflections *(50000000-nbTrial)/pGlobalOptObj->GetLastOptimElapsedTime()/1e6; report.mBogoSPS=(50000000-nbTrial)/pGlobalOptObj->GetLastOptimElapsedTime(); delete pGlobalOptObj; delete pData; return report; } } objcryst-2022.1/ObjCryst/ObjCryst/test.h000066400000000000000000000053671430515525000201000ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* test.h * header file for test functions (speed, etc...) * */ #ifndef _OBJCRYST_TEST_H_ #define _OBJCRYST_TEST_H_ #include "ObjCryst/ObjCryst/General.h" namespace ObjCryst { /** Structure to hold the results of a speedtest (see ObjCryst::SpeedTest()) * * */ struct SpeedTestReport { /// Total number of unique atoms in the test structure. unsigned int mNbAtom; /// Total number of atom types in the test structure. int mNbAtomType; /// The symbol for the spacegroup string mSpacegroup; /// The type of radiation used RadiationType mRadiation; /// The total number of reflections used for the tests unsigned long mNbReflections; /// dataType: 0= single crystal, 1= powder pattern (1 background + 1 crystal phase) unsigned int mDataType; /// Million of Reflections-Atoms computed Per Second (considering all atoms in the unit cell) REAL mBogoMRAPS; /// Million of Reflections-Atoms computed Per Second (considering all atoms in the unit cell, /// except those deduced by a center of symmetry or a lattice translation) REAL mBogoMRAPS_reduced; /// Number of Structures evaluated Per Second REAL mBogoSPS; }; /** * * \param nbAtom: total number of unique atoms. * \param nbAtomType: total number of atom types. Must be smaller than nbAtom. * \param spacegroup: the symbol or spacegroup number for the spacegroup to be tested. * \param radiation: the type of radiation to do the test with (neutron, x-ray). * \param nbReflections: total number of reflections to use. * \param time: duration of the test (10s is usually enough). * \param dataType: 0= single crystal, 1= powder pattern (1 background + 1 crystal phase) */ SpeedTestReport SpeedTest(const unsigned int nbAtom, const int nbAtomType,const string spacegroup, const RadiationType radiation, const unsigned long nbReflections, const unsigned int dataType,const REAL time); } #endif objcryst-2022.1/ObjCryst/ObjCryst/vc.mak000066400000000000000000000021201430515525000200320ustar00rootroot00000000000000!include ..\rules.mak libcryst.lib : ReflectionProfile.obj PowderPatternBackgroundBayesianMinimiser.obj Polyhedron.obj Molecule.obj ScatteringPowerSphere.obj ScatteringCorr.obj Spacegroup.obj Scatterer.obj Atom.obj ScatteringPower.obj ZScatterer.obj Crystal.obj ScatteringData.obj DiffractionDataSingleCrystal.obj PowderPattern.obj Exception.obj geomStructFactor.obj geomStructFactor_001.obj geomStructFactor_002.obj geomStructFactor_067.obj geomStructFactor_097.obj geomStructFactor_230.obj geomStructFactor_centro.obj IO.obj UnitCell.obj test.obj lib -OUT:libcryst.lib ReflectionProfile.obj PowderPatternBackgroundBayesianMinimiser.obj Polyhedron.obj Molecule.obj ScatteringPowerSphere.obj ScatteringCorr.obj Spacegroup.obj Scatterer.obj Atom.obj ScatteringPower.obj ZScatterer.obj Crystal.obj ScatteringData.obj DiffractionDataSingleCrystal.obj PowderPattern.obj Exception.obj geomStructFactor.obj geomStructFactor_001.obj geomStructFactor_002.obj geomStructFactor_067.obj geomStructFactor_097.obj geomStructFactor_230.obj geomStructFactor_centro.obj IO.obj UnitCell.obj test.obj lib: libcryst.lib objcryst-2022.1/ObjCryst/Quirks/000077500000000000000000000000001430515525000164545ustar00rootroot00000000000000objcryst-2022.1/ObjCryst/Quirks/.cvsignore000066400000000000000000000001771430515525000204610ustar00rootroot00000000000000*.o *.exe *.out *.old *.dep *.a .directory .systemG.Desktop tags html latex *.oxy *.xml profile.0.0.0 *.pov Makefile rules.mak objcryst-2022.1/ObjCryst/Quirks/Chronometer.h000066400000000000000000000044551430515525000211220ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2007 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __VFN_CHRONOMETER__ #define __VFN_CHRONOMETER__ #include #include #include using namespace std; /** Simple chronometer class, with microsecond precision * * Reported time correspond to \e real time, i.e. not the time the program * has been running independently from other programs. */ class Chronometer { public: Chronometer(){this->start();}; ~Chronometer(){}; void start() {mPaused=false;mTime0=boost::posix_time::microsec_clock::local_time();} void pause() {mTime1=boost::posix_time::microsec_clock::local_time();mPaused=true;} void resume() { mTime0=boost::posix_time::microsec_clock::local_time()-(mTime1-mTime0); mPaused=false; } void print() { if(mPaused == false) mTime1=boost::posix_time::microsec_clock::local_time(); cout.setf(ios::fixed); int tmp=cout.precision(2); cout << "Elapsed time : " << this->seconds() << " s."< #include using namespace std; int gDebugMessageGlobalLevel=10; int gDebugMessageLevel=gDebugMessageLevel; unsigned int gVFNDebugMessageIndent=0; /* void LibCrystDebugMessage(const string &message, const int level=0) { if(level >= sDebugMessageLevel) cout << "DEBUG MSG:" << message < #endif /// Set the Global debug level for messages void LibCrystDebugGlobalLevel(const int level); /// Use this for a local modification of debug level messages. Call this at the /// beginning of the function, and call it without argument at the end of the function /// to revert to the default global debug level. void LibCrystDebugLocalLevel(const int level); extern int gVFNDebugMessageGlobalLevel; extern int gVFNDebugMessageLevel; extern unsigned int gVFNDebugMessageIndent; //Debug messages are printed only if __DEBUG__ is on, and if their level //is greater or equal to debugMessageGlobalLevel // 0 : messages from low-level routines, // 5 // 10 : messages from top LibCryst++ routines #ifdef _MSC_VER #define VFN_DEBUG_MESSAGE(message,level) \ if(level >= gVFNDebugMessageLevel) \ {\ stringstream ss;\ for(unsigned int iii=0;iii= gVFNDebugMessageLevel)\ {\ stringstream ss;\ ss << message;\ OutputDebugStringA(ss.str().c_str());\ } #define VFN_DEBUG_ENTRY(message,level) \ if(level >= gVFNDebugMessageLevel) \ {\ stringstream ss;\ for(unsigned int iii=0;iii= gVFNDebugMessageLevel) \ {\ stringstream ss;\ if(gVFNDebugMessageIndent>0) gVFNDebugMessageIndent--;\ for(unsigned int iii=0;iii (at " << __FILE__ << "," << __LINE__ << ")" <= gVFNDebugMessageLevel) \ {\ for(unsigned int iii=0;iii= gVFNDebugMessageLevel) cout << message; #define VFN_DEBUG_ENTRY(message,level) \ if(level >= gVFNDebugMessageLevel) \ {\ for(unsigned int iii=0;iii= gVFNDebugMessageLevel) \ {\ if(gVFNDebugMessageIndent>0) gVFNDebugMessageIndent--;\ for(unsigned int iii=0;iii (at " << __FILE__ << "," << __LINE__ << ")" < #include "ObjCryst/Quirks/VFNStreamFormat.h" #include "ObjCryst/Quirks/VFNDebug.h" using namespace std; //////////////////////////////////////////////////////////////////////// // // FormatInt // //////////////////////////////////////////////////////////////////////// FormatInt::FormatInt(const long num,const int width): mValue(num),mWidth(width) {} FormatInt::~FormatInt(){} ostream& operator<< (ostream& os, const FormatInt& fInt) { return os << setiosflags(ios::right) << setw(fInt.mWidth) << fInt.mValue << " "; } //////////////////////////////////////////////////////////////////////// // // FormatFloat // //////////////////////////////////////////////////////////////////////// FormatFloat::FormatFloat(const REAL num,const int width,const int precision) :mValue(num),mWidth(width),mPrecision(precision) { } FormatFloat::~FormatFloat(){} ostream& operator<< (ostream& os, const FormatFloat &fFloat) { std::istream::fmtflags old_flags=os.flags(); os.setf( std::istream::fixed | std::istream::right | std::istream::showpoint,std::istream::floatfield ); std::streamsize old_prec = os.precision(fFloat.mPrecision); std::streamsize old_width = os.width(fFloat.mWidth); os << fFloat.mValue; os.flags( old_flags ); os.precision( old_prec ); os.width(old_width); return os; } //////////////////////////////////////////////////////////////////////// // // FormatString // //////////////////////////////////////////////////////////////////////// FormatString::FormatString(const string &str,const unsigned int width): /*mString(str,1,width),*/mWidth(width) { mString=str; //:KLUDGE: if(mString.size() > mWidth) mString.resize(mWidth); else for(unsigned int i=mString.size();i FormatVertVector::FormatVertVector( const CrystVector &fVect, const int width, const int precision, const int nb): mWidth(width),mPrecision(precision),mNb(nb) { mvpVectors.push_back(&fVect); } template FormatVertVector::FormatVertVector( const CrystVector &fVect1, const CrystVector &fVect2, const int width, const int precision, const int nb): mWidth(width),mPrecision(precision),mNb(nb) { mvpVectors.push_back(&fVect1); mvpVectors.push_back(&fVect2); } template FormatVertVector::FormatVertVector( const CrystVector &fVect1, const CrystVector &fVect2, const CrystVector &fVect3, const int width, const int precision, const int nb): mWidth(width),mPrecision(precision),mNb(nb) { mvpVectors.push_back(&fVect1); mvpVectors.push_back(&fVect2); mvpVectors.push_back(&fVect3); } template FormatVertVector::FormatVertVector( const CrystVector &fVect1, const CrystVector &fVect2, const CrystVector &fVect3, const CrystVector &fVect4, const int width, const int precision, const int nb): mWidth(width),mPrecision(precision),mNb(nb) { mvpVectors.push_back(&fVect1); mvpVectors.push_back(&fVect2); mvpVectors.push_back(&fVect3); mvpVectors.push_back(&fVect4); } template FormatVertVector::FormatVertVector( const CrystVector &fVect1, const CrystVector &fVect2, const CrystVector &fVect3, const CrystVector &fVect4, const CrystVector &fVect5, const int width, const int precision, const int nb): mWidth(width),mPrecision(precision),mNb(nb) { mvpVectors.push_back(&fVect1); mvpVectors.push_back(&fVect2); mvpVectors.push_back(&fVect3); mvpVectors.push_back(&fVect4); mvpVectors.push_back(&fVect5); } template FormatVertVector::FormatVertVector( const CrystVector &fVect1, const CrystVector &fVect2, const CrystVector &fVect3, const CrystVector &fVect4, const CrystVector &fVect5, const CrystVector &fVect6, const int width, const int precision, const int nb): mWidth(width),mPrecision(precision),mNb(nb) { mvpVectors.push_back(&fVect1); mvpVectors.push_back(&fVect2); mvpVectors.push_back(&fVect3); mvpVectors.push_back(&fVect4); mvpVectors.push_back(&fVect5); mvpVectors.push_back(&fVect6); } template FormatVertVector::FormatVertVector( const CrystVector *pVect, const int nbVect, const int width, const int precision, const int nb): mWidth(width),mPrecision(precision),mNb(nb) { for(int i=0;i FormatVertVector::FormatVertVector( const CrystVector &fVect1, const CrystVector *pVect, const int nbVect, const int width, const int precision, const int nb): mWidth(width),mPrecision(precision),mNb(nb) { mvpVectors.push_back(&fVect1); for(int i=1;i FormatVertVector::FormatVertVector( vector *>& v, const int width, const int precision, const int nb): mWidth(width),mPrecision(precision),mNb(nb) { mvpVectors=v; } template FormatVertVector::~FormatVertVector() { } template ostream& operator<< (ostream &os, const FormatVertVector &fVect) { VFN_DEBUG_MESSAGE("ostream& operator<<(os,FormatVertVector)",3) long i; size_t j; std::istream::fmtflags old_flags=os.flags(); os.setf( std::istream::fixed | std::istream::right | std::istream::showpoint); std::streamsize old_prec = os.precision(fVect.mPrecision); std::streamsize old_width = os.width(); long nb=fVect.mNb; if(nb==0)nb=(fVect.mvpVectors[0])->numElements(); for(i=0;i):End",2) return os; } //////////////////////////////////////////////////////////////////////// // // FormatHorizVector // //////////////////////////////////////////////////////////////////////// template FormatHorizVector::FormatHorizVector( const CrystVector &fVect, const int width, const int precision): mWidth(width),mPrecision(precision) { mpVectors=&fVect; } template FormatHorizVector::~FormatHorizVector() {} template ostream& operator<< (ostream &os, const FormatHorizVector &fVect) { long i; std::istream::fmtflags old_flags=os.flags(); os.setf( std::istream::fixed | std::istream::right | std::istream::showpoint); std::streamsize old_prec = os.precision(fVect.mPrecision); std::streamsize old_width = os.width(); for(i=0;i<(*(fVect.mpVectors)).numElements();i++) { os < FormatVertVectorHKLFloats::FormatVertVectorHKLFloats( const CrystVector &h, const CrystVector &k, const CrystVector &l, const int width, const int precision, const int nb): mWidth(width),mPrecision(precision),mNb(nb) { mvpVectors.push_back(&h); mvpVectors.push_back(&k); mvpVectors.push_back(&l); } template FormatVertVectorHKLFloats::FormatVertVectorHKLFloats( const CrystVector &h, const CrystVector &k, const CrystVector &l, const CrystVector &m, const int width, const int precision, const int nb): mWidth(width),mPrecision(precision),mNb(nb) { mvpVectors.push_back(&h); mvpVectors.push_back(&k); mvpVectors.push_back(&l); mvpVectors.push_back(&m); } template FormatVertVectorHKLFloats::FormatVertVectorHKLFloats( const CrystVector &h, const CrystVector &k, const CrystVector &l, const CrystVector &m, const CrystVector &n, const int width, const int precision, const int nb): mWidth(width),mPrecision(precision),mNb(nb) { mvpVectors.push_back(&h); mvpVectors.push_back(&k); mvpVectors.push_back(&l); mvpVectors.push_back(&m); mvpVectors.push_back(&n); } template FormatVertVectorHKLFloats::FormatVertVectorHKLFloats( const CrystVector &h, const CrystVector &k, const CrystVector &l, const CrystVector &m, const CrystVector &n, const CrystVector &o, const int width, const int precision, const int nb): mWidth(width),mPrecision(precision),mNb(nb) { mvpVectors.push_back(&h); mvpVectors.push_back(&k); mvpVectors.push_back(&l); mvpVectors.push_back(&m); mvpVectors.push_back(&n); mvpVectors.push_back(&o); } template FormatVertVectorHKLFloats::FormatVertVectorHKLFloats( const CrystVector &h, const CrystVector &k, const CrystVector &l, const CrystVector &m, const CrystVector &n, const CrystVector &o, const CrystVector &p, const int width, const int precision, const int nb): mWidth(width),mPrecision(precision),mNb(nb) { mvpVectors.push_back(&h); mvpVectors.push_back(&k); mvpVectors.push_back(&l); mvpVectors.push_back(&m); mvpVectors.push_back(&n); mvpVectors.push_back(&o); mvpVectors.push_back(&p); } template FormatVertVectorHKLFloats::FormatVertVectorHKLFloats( const CrystVector &h, const CrystVector &k, const CrystVector &l, const CrystVector &m, const CrystVector &n, const CrystVector &o, const CrystVector &p, const CrystVector &q, const int width, const int precision, const int nb): mWidth(width),mPrecision(precision),mNb(nb) { mvpVectors.push_back(&h); mvpVectors.push_back(&k); mvpVectors.push_back(&l); mvpVectors.push_back(&m); mvpVectors.push_back(&n); mvpVectors.push_back(&o); mvpVectors.push_back(&p); mvpVectors.push_back(&q); } template FormatVertVectorHKLFloats::FormatVertVectorHKLFloats( const CrystVector &h, const CrystVector &k, const CrystVector &l, const CrystVector &m, const CrystVector &n, const CrystVector &o, const CrystVector &p, const CrystVector &q, const CrystVector &r, const int width, const int precision, const int nb): mWidth(width),mPrecision(precision),mNb(nb) { mvpVectors.push_back(&h); mvpVectors.push_back(&k); mvpVectors.push_back(&l); mvpVectors.push_back(&m); mvpVectors.push_back(&n); mvpVectors.push_back(&o); mvpVectors.push_back(&p); mvpVectors.push_back(&q); mvpVectors.push_back(&r); } template FormatVertVectorHKLFloats::FormatVertVectorHKLFloats( const CrystVector &h, const CrystVector &k, const CrystVector &l, const CrystVector &m, const CrystVector &n, const CrystVector &o, const CrystVector &p, const CrystVector &q, const CrystVector &r, const CrystVector &s, const int width, const int precision, const int nb): mWidth(width),mPrecision(precision),mNb(nb) { mvpVectors.push_back(&h); mvpVectors.push_back(&k); mvpVectors.push_back(&l); mvpVectors.push_back(&m); mvpVectors.push_back(&n); mvpVectors.push_back(&o); mvpVectors.push_back(&p); mvpVectors.push_back(&q); mvpVectors.push_back(&r); mvpVectors.push_back(&s); } template FormatVertVectorHKLFloats::FormatVertVectorHKLFloats( const CrystVector &h, const CrystVector &k, const CrystVector &l, const CrystVector &m, const CrystVector &n, const CrystVector &o, const CrystVector &p, const CrystVector &q, const CrystVector &r, const CrystVector &s, const CrystVector &t, const int width, const int precision, const int nb): mWidth(width),mPrecision(precision),mNb(nb) { mvpVectors.push_back(&h); mvpVectors.push_back(&k); mvpVectors.push_back(&l); mvpVectors.push_back(&m); mvpVectors.push_back(&n); mvpVectors.push_back(&o); mvpVectors.push_back(&p); mvpVectors.push_back(&q); mvpVectors.push_back(&r); mvpVectors.push_back(&s); mvpVectors.push_back(&t); } template FormatVertVectorHKLFloats::FormatVertVectorHKLFloats( const CrystVector &h, const CrystVector &k, const CrystVector &l, const CrystVector &m, const CrystVector &n, const CrystVector &o, const CrystVector &p, const CrystVector &q, const CrystVector &r, const CrystVector &s, const CrystVector &t, const CrystVector &u, const int width, const int precision, const int nb): mWidth(width),mPrecision(precision),mNb(nb) { mvpVectors.push_back(&h); mvpVectors.push_back(&k); mvpVectors.push_back(&l); mvpVectors.push_back(&m); mvpVectors.push_back(&n); mvpVectors.push_back(&o); mvpVectors.push_back(&p); mvpVectors.push_back(&q); mvpVectors.push_back(&r); mvpVectors.push_back(&s); mvpVectors.push_back(&t); mvpVectors.push_back(&u); } template FormatVertVectorHKLFloats::FormatVertVectorHKLFloats( vector *>& v, const int width, const int precision, const int nb): mWidth(width),mPrecision(precision),mNb(nb) { mvpVectors=v; } template FormatVertVectorHKLFloats::~FormatVertVectorHKLFloats() {} template ostream& operator<< (ostream& os, const FormatVertVectorHKLFloats &fVect) { long i; unsigned int j; std::istream::fmtflags old_flags=os.flags(); os.setf( std::istream::fixed | std::istream::right | std::istream::showpoint); std::streamsize old_prec = os.precision(fVect.mPrecision); std::streamsize old_width = os.width(); long nb=fVect.mNb; if(nb==0) nb=(fVect.mvpVectors[0])->numElements(); for(i=0;i; template ostream& operator<< (ostream&,const FormatVertVector&); template class FormatHorizVector; template ostream& operator<< (ostream&,const FormatHorizVector&); template class FormatVertVectorHKLFloats; template ostream& operator<< (ostream&,const FormatVertVectorHKLFloats&); template class FormatVertVector; template ostream& operator<< (ostream&,const FormatVertVector&); template class FormatHorizVector; template ostream& operator<< (ostream&,const FormatHorizVector&); template class FormatVertVectorHKLFloats; template ostream& operator<< (ostream&,const FormatVertVectorHKLFloats&); objcryst-2022.1/ObjCryst/Quirks/VFNStreamFormat.h000066400000000000000000000312061430515525000216050ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2005 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // This file includes some "effectors" used to format //strings, numbers, some arrays... #ifndef _VFN_STREAM_FORMAT_H_ #define _VFN_STREAM_FORMAT_H_ #include #include #include #include "ObjCryst/CrystVector/CrystVector.h" /** output a number as a formatted integer: * * \code os << FormatInt(mynumber,5);\endcode * * */ class FormatInt { public: FormatInt(const long num,const int width=5); ~FormatInt(); //private: const long mValue; const int mWidth; }; std::ostream& operator<< (std::ostream& os, const FormatInt& fInt); /** output a number as a formatted float: * *\code os << FormatFloat(mynumber,10,4); \endcode * * */ class FormatFloat { public: FormatFloat(const REAL num,const int width=10,const int precision=4); ~FormatFloat(); //private: const REAL mValue; const int mWidth; const int mPrecision; }; std::ostream& operator<< (std::ostream& os, const FormatFloat &fFloat); /** output a string with a fixed length (adding necessary space or removing * excess characters) : * * \code os << FormatString(myString,15);\endcode */ class FormatString { public: FormatString(const string &str,const unsigned int width=5); ~FormatString(); int length() const; //private: string mString; const unsigned int mWidth; }; std::ostream& operator<< (std::ostream& os, const FormatString& fStr); /** output one or several vectors as (a) column(s): * * \code * os << FormatVertVector(vect,8,3); * os << FormatVertVector(vect1,vect2,vetc3,12,6); * // For 7 vectors with width 12 and precision 4, * // pVect being a pointer to an array of 7 vectors: * os << FormatVertVector(pVect,7,12,4); * \endcode */ template class FormatVertVector { public: FormatVertVector( const CrystVector &fVect, const int width=10, const int precision=4, const int nb=0); FormatVertVector( const CrystVector &fVect1, const CrystVector &fVect2, const int width=10, const int precision=4, const int nb=0); FormatVertVector( const CrystVector &fVect1, const CrystVector &fVect2, const CrystVector &fVect3, const int width=10, const int precision=4, const int nb=0); FormatVertVector( const CrystVector &fVect1, const CrystVector &fVect2, const CrystVector &fVect3, const CrystVector &fVect4, const int width=10, const int precision=4, const int nb=0); FormatVertVector( const CrystVector &fVect1, const CrystVector &fVect2, const CrystVector &fVect3, const CrystVector &fVect4, const CrystVector &fVect5, const int width=10, const int precision=4, const int nb=0); FormatVertVector( const CrystVector &fVect1, const CrystVector &fVect2, const CrystVector &fVect3, const CrystVector &fVect4, const CrystVector &fVect5, const CrystVector &fVect6, const int width=10, const int precision=4, const int nb=0); FormatVertVector( const CrystVector *pVect, const int nbVect, const int width=10, const int precision=4, const int nb=0); FormatVertVector( const CrystVector &fVect1, const CrystVector *pVect, const int nbVect, const int width=10, const int precision=4, const int nb=0); FormatVertVector( std::vector *>& v, const int width=10, const int precision=4, const int nb=0); ~FormatVertVector(); //int length() const; //private: std::vector *>mvpVectors; const int mWidth; const int mPrecision; const int mNb; }; template std::ostream& operator<< (std::ostream &os, const FormatVertVector &fVect); /** Format vector as horiz array: * * \code os << FormatHorizVector(vect,8,3);\endcode */ template class FormatHorizVector { public: FormatHorizVector(const CrystVector &fVect, const int width=10, const int precision=4); ~FormatHorizVector(); //int length() const; //private: const CrystVector *mpVectors; const int mWidth; const int mPrecision; }; template ostream& operator<< (std::ostream &os, const FormatHorizVector &fVect); /** Output vectors as column arrays, with the first 3 columns printed as integers. * * \code cout << FormatVertVectorHKLFloats(vH,vK,vL,vIobs,vIcalc,vSigma,12,4);\endcode */ templateclass FormatVertVectorHKLFloats { public: FormatVertVectorHKLFloats( const CrystVector &h, const CrystVector &k, const CrystVector &l, const int width=10, const int precision=4, const int nb=0); FormatVertVectorHKLFloats( const CrystVector &h, const CrystVector &k, const CrystVector &l, const CrystVector &m, const int width=10, const int precision=4, const int nb=0); FormatVertVectorHKLFloats( const CrystVector &h, const CrystVector &k, const CrystVector &l, const CrystVector &m, const CrystVector &n, const int width=10, const int precision=4, const int nb=0); FormatVertVectorHKLFloats( const CrystVector &h, const CrystVector &k, const CrystVector &l, const CrystVector &m, const CrystVector &n, const CrystVector &o, const int width=10, const int precision=4, const int nb=0); FormatVertVectorHKLFloats( const CrystVector &h, const CrystVector &k, const CrystVector &l, const CrystVector &m, const CrystVector &n, const CrystVector &o, const CrystVector &p, const int width=10, const int precision=4, const int nb=0); FormatVertVectorHKLFloats( const CrystVector &h, const CrystVector &k, const CrystVector &l, const CrystVector &m, const CrystVector &n, const CrystVector &o, const CrystVector &p, const CrystVector &q, const int width=10, const int precision=4, const int nb=0); FormatVertVectorHKLFloats( const CrystVector &h, const CrystVector &k, const CrystVector &l, const CrystVector &m, const CrystVector &n, const CrystVector &o, const CrystVector &p, const CrystVector &q, const CrystVector &r, const int width=10, const int precision=4, const int nb=0); FormatVertVectorHKLFloats( const CrystVector &h, const CrystVector &k, const CrystVector &l, const CrystVector &m, const CrystVector &n, const CrystVector &o, const CrystVector &p, const CrystVector &q, const CrystVector &r, const CrystVector &s, const int width=10, const int precision=4, const int nb=0); FormatVertVectorHKLFloats( const CrystVector &h, const CrystVector &k, const CrystVector &l, const CrystVector &m, const CrystVector &n, const CrystVector &o, const CrystVector &p, const CrystVector &q, const CrystVector &r, const CrystVector &s, const CrystVector &t, const int width=10, const int precision=4, const int nb=0); FormatVertVectorHKLFloats( const CrystVector &h, const CrystVector &k, const CrystVector &l, const CrystVector &m, const CrystVector &n, const CrystVector &o, const CrystVector &p, const CrystVector &q, const CrystVector &r, const CrystVector &s, const CrystVector &t, const CrystVector &u, const int width=10, const int precision=4, const int nb=0); FormatVertVectorHKLFloats( std::vector *>& v, const int width=10, const int precision=4, const int nb=0); ~FormatVertVectorHKLFloats(); //int length() const; //private: std::vector *>mvpVectors; const int mWidth; const int mPrecision; const int mNb; }; template std::ostream& operator<< (std::ostream& os, const FormatVertVectorHKLFloats &fStr); #endif objcryst-2022.1/ObjCryst/Quirks/bc32.mak000066400000000000000000000003111430515525000176720ustar00rootroot00000000000000!include ../rules.mak libQuirks.lib : ci_string.obj VFNStreamFormat.obj VFNDebug.obj tlib "libQuirks.lib" -+ci_string.obj -+VFNStreamFormat -+VFNDebug.obj lib: libQuirks.lib default: lib all: lib objcryst-2022.1/ObjCryst/Quirks/ci_string.cpp000066400000000000000000000021411430515525000211370ustar00rootroot00000000000000#include "ci_string.h" /// Case-insensitive string class /// From: Guru of the Week #29 /// e.g.: http://gcc.gnu.org/onlinedocs/libstdc++/21_strings/gotw29a.txt /// /// Public domain. int strnicmp(const char *s1, const char *s2, int len) { unsigned char c1, c2; while (len) { c1 = *s1; c2 = *s2; s1++; s2++; if (!c1) return c2 ? -1 : 0; if (!c2) return 1; if (c1 != c2) { c1 = tolower(c1); c2 = tolower(c2); if (c1 != c2) return c1 < c2 ? -1 : 1; } len--; } return 0; } bool ci_char_traits::eq( char c1, char c2 ) {return tolower(c1) == tolower(c2);} bool ci_char_traits::ne( char c1, char c2 ) {return tolower(c1) != tolower(c2);} bool ci_char_traits::lt( char c1, char c2 ) {return tolower(c1) < tolower(c2);} int ci_char_traits::compare(const char* s1,const char* s2,size_t n ) { #ifdef _MSC_VER return _strnicmp(s1, s2, n); #else return strnicmp(s1, s2, n); #endif } const char* ci_char_traits::find( const char* s, int n, char a ) { while( n-- > 0 && tolower(*s) != tolower(a) ) ++s; return s; } objcryst-2022.1/ObjCryst/Quirks/ci_string.h000066400000000000000000000011221430515525000206020ustar00rootroot00000000000000#ifndef _CI_STRING_H #define _CI_STRING_H #include /// Case-insensitive string class /// From: Guru of the Week #29 /// e.g.: http://gcc.gnu.org/onlinedocs/libstdc++/21_strings/gotw29a.txt /// /// Public domain. struct ci_char_traits : public std::char_traits { static bool eq( char c1, char c2 ); static bool ne( char c1, char c2 ); static bool lt( char c1, char c2 ); static int compare(const char* s1,const char* s2,size_t n ); static const char* find( const char* s, int n, char a ); }; typedef std::basic_string ci_string; #endif objcryst-2022.1/ObjCryst/Quirks/gnu.mak000066400000000000000000000013511430515525000177370ustar00rootroot00000000000000BUILD_DIR=$(CURDIR)/../.. include $(BUILD_DIR)/ObjCryst/rules.mak OBJ= VFNStreamFormat.o VFNDebug.o ci_string.o ifeq ($(profile),2) %.o : %.cpp @rm -f $(*F).gcda $(*F).gcno @$(MAKEDEPEND) ${CXX} ${CPPFLAGS} ${CXXFLAGS} -c $< -o $@ else %.o : %.cpp @$(MAKEDEPEND) ${CXX} ${CPPFLAGS} ${CXXFLAGS} -c $< -o $@ endif -include $(OBJ:.o=.dep) # libVFNStreamFormat libQuirks.a : ${OBJ} @${RM} $@ ${AR} crs $@ ${filter-out %.a %.so, $^} lib: libQuirks.a default: lib dep: makedepend *.cpp -Y -I. -I../ -I../.. # target for removing all object files .PHONY : tidy tidy:: @${RM} *.o *.dep # target for removing all object files and libraries .PHONY : clean clean:: tidy @${RM} *.a *.exe cvsignore: cp -f ${DIR_CRYST}/.cvsignore ./ objcryst-2022.1/ObjCryst/Quirks/sse_mathfun.h000066400000000000000000000554631430515525000211560ustar00rootroot00000000000000/* SIMD (SSE1+MMX or SSE2) implementation of sin, cos, exp and log Inspired by Intel Approximate Math library, and based on the corresponding algorithms of the cephes math library The default is to use the SSE1 version. If you define USE_SSE2 the the SSE2 intrinsics will be used in place of the MMX intrinsics. Do not expect any significant performance improvement with SSE2. NOTE: - Original version available @: http://gruntthepeon.free.fr/ssemath/ - Modifications for inclusion in ObjCryst++ (http://objcryst.sf.net): - functions are now inline. */ /* Copyright (C) 2007 Julien Pommier This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. (this is the zlib license) */ #include /* yes I know, the top of this file is quite ugly */ #ifdef _MSC_VER /* visual c++ */ # define ALIGN16_BEG __declspec(align(16)) # define ALIGN16_END #else /* gcc or icc */ # define ALIGN16_BEG # define ALIGN16_END __attribute__((aligned(16))) #endif /* __m128 is ugly to write */ typedef __m128 v4sf; // vector of 4 float (sse1) #ifdef USE_SSE2 # include typedef __m128i v4si; // vector of 4 int (sse2) #else typedef __m64 v2si; // vector of 2 int (mmx) #endif /* declare some SSE constants -- why can't I figure a better way to do that? */ #define _PS_CONST(Name, Val) \ static const ALIGN16_BEG float _ps_##Name[4] ALIGN16_END = { Val, Val, Val, Val } #define _PI32_CONST(Name, Val) \ static const ALIGN16_BEG int _pi32_##Name[4] ALIGN16_END = { Val, Val, Val, Val } #define _PS_CONST_TYPE(Name, Type, Val) \ static const ALIGN16_BEG Type _ps_##Name[4] ALIGN16_END = { Val, Val, Val, Val } _PS_CONST(1 , 1.0f); _PS_CONST(0p5, 0.5f); /* the smallest non denormalized float number */ _PS_CONST_TYPE(min_norm_pos, int, 0x00800000); _PS_CONST_TYPE(mant_mask, int, 0x7f800000); _PS_CONST_TYPE(inv_mant_mask, int, ~0x7f800000); _PS_CONST_TYPE(sign_mask, unsigned int, 0x80000000); _PS_CONST_TYPE(inv_sign_mask, unsigned int, ~0x80000000); _PI32_CONST(1, 1); _PI32_CONST(inv1, ~1); _PI32_CONST(2, 2); _PI32_CONST(4, 4); _PI32_CONST(0x7f, 0x7f); _PS_CONST(cephes_SQRTHF, 0.707106781186547524); _PS_CONST(cephes_log_p0, 7.0376836292E-2); _PS_CONST(cephes_log_p1, - 1.1514610310E-1); _PS_CONST(cephes_log_p2, 1.1676998740E-1); _PS_CONST(cephes_log_p3, - 1.2420140846E-1); _PS_CONST(cephes_log_p4, + 1.4249322787E-1); _PS_CONST(cephes_log_p5, - 1.6668057665E-1); _PS_CONST(cephes_log_p6, + 2.0000714765E-1); _PS_CONST(cephes_log_p7, - 2.4999993993E-1); _PS_CONST(cephes_log_p8, + 3.3333331174E-1); _PS_CONST(cephes_log_q1, -2.12194440e-4); _PS_CONST(cephes_log_q2, 0.693359375); #if defined (__MINGW32__) /* the ugly part below: many versions of gcc used to be completely buggy with respect to some intrinsics The movehl_ps is fixed in mingw 3.4.5, but I found out that all the _mm_cmp* intrinsics were completely broken on my mingw gcc 3.4.5 ... Note that the bug on _mm_cmp* does occur only at -O0 optimization level */ inline __m128 my_movehl_ps(__m128 a, const __m128 b) { asm ( "movhlps %2,%0\n\t" : "=x" (a) : "0" (a), "x"(b) ); return a; } #warning "redefined _mm_movehl_ps (see gcc bug 21179)" #define _mm_movehl_ps my_movehl_ps inline __m128 my_cmplt_ps(__m128 a, const __m128 b) { asm ( "cmpltps %2,%0\n\t" : "=x" (a) : "0" (a), "x"(b) ); return a; } inline __m128 my_cmpgt_ps(__m128 a, const __m128 b) { asm ( "cmpnleps %2,%0\n\t" : "=x" (a) : "0" (a), "x"(b) ); return a; } inline __m128 my_cmpeq_ps(__m128 a, const __m128 b) { asm ( "cmpeqps %2,%0\n\t" : "=x" (a) : "0" (a), "x"(b) ); return a; } #warning "redefined _mm_cmpxx_ps functions..." #define _mm_cmplt_ps my_cmplt_ps #define _mm_cmpgt_ps my_cmpgt_ps #define _mm_cmpeq_ps my_cmpeq_ps #endif #ifndef USE_SSE2 typedef union xmm_mm_union { __m128 xmm; __m64 mm[2]; } xmm_mm_union; #define COPY_XMM_TO_MM(xmm_, mm0_, mm1_) { \ xmm_mm_union u; u.xmm = xmm_; \ mm0_ = u.mm[0]; \ mm1_ = u.mm[1]; \ } #define COPY_MM_TO_XMM(mm0_, mm1_, xmm_) { \ xmm_mm_union u; u.mm[0]=mm0_; u.mm[1]=mm1_; xmm_ = u.xmm; \ } #endif // USE_SSE2 /* natural logarithm computed for 4 simultaneous float return NaN for x <= 0 */ inline v4sf log_ps(v4sf x) { #ifdef USE_SSE2 v4si emm0; #else v2si mm0, mm1; #endif v4sf one = *(v4sf*)_ps_1; v4sf invalid_mask = _mm_cmple_ps(x, _mm_setzero_ps()); x = _mm_max_ps(x, *(v4sf*)_ps_min_norm_pos); /* cut off denormalized stuff */ #ifndef USE_SSE2 /* part 1: x = frexpf(x, &e); */ COPY_XMM_TO_MM(x, mm0, mm1); mm0 = _mm_srli_pi32(mm0, 23); mm1 = _mm_srli_pi32(mm1, 23); #else emm0 = _mm_srli_epi32(_mm_castps_si128(x), 23); #endif /* keep only the fractional part */ x = _mm_and_ps(x, *(v4sf*)_ps_inv_mant_mask); x = _mm_or_ps(x, *(v4sf*)_ps_0p5); #ifndef USE_SSE2 /* now e=mm0:mm1 contain the really base-2 exponent */ mm0 = _mm_sub_pi32(mm0, *(v2si*)_pi32_0x7f); mm1 = _mm_sub_pi32(mm1, *(v2si*)_pi32_0x7f); v4sf e = _mm_cvtpi32x2_ps(mm0, mm1); _mm_empty(); /* bye bye mmx */ #else emm0 = _mm_sub_epi32(emm0, *(v4si*)_pi32_0x7f); v4sf e = _mm_cvtepi32_ps(emm0); #endif e = _mm_add_ps(e, one); /* part2: if( x < SQRTHF ) { e -= 1; x = x + x - 1.0; } else { x = x - 1.0; } */ v4sf mask = _mm_cmplt_ps(x, *(v4sf*)_ps_cephes_SQRTHF); v4sf tmp = _mm_and_ps(x, mask); x = _mm_sub_ps(x, one); e = _mm_sub_ps(e, _mm_and_ps(one, mask)); x = _mm_add_ps(x, tmp); v4sf z = _mm_mul_ps(x,x); v4sf y = *(v4sf*)_ps_cephes_log_p0; y = _mm_mul_ps(y, x); y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p1); y = _mm_mul_ps(y, x); y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p2); y = _mm_mul_ps(y, x); y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p3); y = _mm_mul_ps(y, x); y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p4); y = _mm_mul_ps(y, x); y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p5); y = _mm_mul_ps(y, x); y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p6); y = _mm_mul_ps(y, x); y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p7); y = _mm_mul_ps(y, x); y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p8); y = _mm_mul_ps(y, x); y = _mm_mul_ps(y, z); tmp = _mm_mul_ps(e, *(v4sf*)_ps_cephes_log_q1); y = _mm_add_ps(y, tmp); tmp = _mm_mul_ps(z, *(v4sf*)_ps_0p5); y = _mm_sub_ps(y, tmp); tmp = _mm_mul_ps(e, *(v4sf*)_ps_cephes_log_q2); x = _mm_add_ps(x, y); x = _mm_add_ps(x, tmp); x = _mm_or_ps(x, invalid_mask); // negative arg will be NAN return x; } _PS_CONST(exp_hi, 88.3762626647949f); _PS_CONST(exp_lo, -88.3762626647949f); _PS_CONST(cephes_LOG2EF, 1.44269504088896341); _PS_CONST(cephes_exp_C1, 0.693359375); _PS_CONST(cephes_exp_C2, -2.12194440e-4); _PS_CONST(cephes_exp_p0, 1.9875691500E-4); _PS_CONST(cephes_exp_p1, 1.3981999507E-3); _PS_CONST(cephes_exp_p2, 8.3334519073E-3); _PS_CONST(cephes_exp_p3, 4.1665795894E-2); _PS_CONST(cephes_exp_p4, 1.6666665459E-1); _PS_CONST(cephes_exp_p5, 5.0000001201E-1); inline v4sf exp_ps(v4sf x) { v4sf tmp = _mm_setzero_ps(), fx; #ifdef USE_SSE2 v4si emm0; #else v2si mm0, mm1; #endif v4sf one = *(v4sf*)_ps_1; x = _mm_min_ps(x, *(v4sf*)_ps_exp_hi); x = _mm_max_ps(x, *(v4sf*)_ps_exp_lo); /* express exp(x) as exp(g + n*log(2)) */ fx = _mm_mul_ps(x, *(v4sf*)_ps_cephes_LOG2EF); fx = _mm_add_ps(fx, *(v4sf*)_ps_0p5); /* how to perform a floorf with SSE: just below */ #ifndef USE_SSE2 /* step 1 : cast to int */ tmp = _mm_movehl_ps(tmp, fx); mm0 = _mm_cvttps_pi32(fx); mm1 = _mm_cvttps_pi32(tmp); /* step 2 : cast back to float */ tmp = _mm_cvtpi32x2_ps(mm0, mm1); #else emm0 = _mm_cvttps_epi32(fx); tmp = _mm_cvtepi32_ps(emm0); #endif /* if greater, substract 1 */ v4sf mask = _mm_cmpgt_ps(tmp, fx); mask = _mm_and_ps(mask, one); fx = _mm_sub_ps(tmp, mask); tmp = _mm_mul_ps(fx, *(v4sf*)_ps_cephes_exp_C1); v4sf z = _mm_mul_ps(fx, *(v4sf*)_ps_cephes_exp_C2); x = _mm_sub_ps(x, tmp); x = _mm_sub_ps(x, z); z = _mm_mul_ps(x,x); v4sf y = *(v4sf*)_ps_cephes_exp_p0; y = _mm_mul_ps(y, x); y = _mm_add_ps(y, *(v4sf*)_ps_cephes_exp_p1); y = _mm_mul_ps(y, x); y = _mm_add_ps(y, *(v4sf*)_ps_cephes_exp_p2); y = _mm_mul_ps(y, x); y = _mm_add_ps(y, *(v4sf*)_ps_cephes_exp_p3); y = _mm_mul_ps(y, x); y = _mm_add_ps(y, *(v4sf*)_ps_cephes_exp_p4); y = _mm_mul_ps(y, x); y = _mm_add_ps(y, *(v4sf*)_ps_cephes_exp_p5); y = _mm_mul_ps(y, z); y = _mm_add_ps(y, x); y = _mm_add_ps(y, one); /* build 2^n */ #ifndef USE_SSE2 z = _mm_movehl_ps(z, fx); mm0 = _mm_cvttps_pi32(fx); mm1 = _mm_cvttps_pi32(z); mm0 = _mm_add_pi32(mm0, *(v2si*)_pi32_0x7f); mm1 = _mm_add_pi32(mm1, *(v2si*)_pi32_0x7f); mm0 = _mm_slli_pi32(mm0, 23); mm1 = _mm_slli_pi32(mm1, 23); v4sf pow2n; COPY_MM_TO_XMM(mm0, mm1, pow2n); _mm_empty(); #else emm0 = _mm_cvttps_epi32(fx); emm0 = _mm_add_epi32(emm0, *(v4si*)_pi32_0x7f); emm0 = _mm_slli_epi32(emm0, 23); v4sf pow2n = _mm_castsi128_ps(emm0); #endif y = _mm_mul_ps(y, pow2n); return y; } _PS_CONST(minus_cephes_DP1, -0.78515625); _PS_CONST(minus_cephes_DP2, -2.4187564849853515625e-4); _PS_CONST(minus_cephes_DP3, -3.77489497744594108e-8); _PS_CONST(sincof_p0, -1.9515295891E-4); _PS_CONST(sincof_p1, 8.3321608736E-3); _PS_CONST(sincof_p2, -1.6666654611E-1); _PS_CONST(coscof_p0, 2.443315711809948E-005); _PS_CONST(coscof_p1, -1.388731625493765E-003); _PS_CONST(coscof_p2, 4.166664568298827E-002); _PS_CONST(cephes_FOPI, 1.27323954473516); // 4 / M_PI /* evaluation of 4 sines at onces, using only SSE1+MMX intrinsics so it runs also on old athlons XPs and the pentium III of your grand mother. The code is the exact rewriting of the cephes sinf function. Precision is excellent as long as x < 8192 (I did not bother to take into account the special handling they have for greater values -- it does not return garbage for arguments over 8192, though, but the extra precision is missing). Note that it is such that sinf((float)M_PI) = 8.74e-8, which is the surprising but correct result. Performance is also surprisingly good, 1.33 times faster than the macos vsinf SSE2 function, and 1.5 times faster than the __vrs4_sinf of amd's ACML (which is only available in 64 bits). Not too bad for an SSE1 function (with no special tuning) ! However the latter libraries probably have a much better handling of NaN, Inf, denormalized and other special arguments.. On my core 1 duo, the execution of this function takes approximately 95 cycles. From what I have observed on the experiments with Intel AMath lib, switching to an SSE2 version would improve the perf by only 10%. Since it is based on SSE intrinsics, it has to be compiled at -O2 to deliver full speed. */ inline v4sf sin_ps(v4sf x) { // any x v4sf xmm1, xmm2 = _mm_setzero_ps(), xmm3, sign_bit, y; #ifdef USE_SSE2 v4si emm0, emm2; #else v2si mm0, mm1, mm2, mm3; #endif sign_bit = x; /* take the absolute value */ x = _mm_and_ps(x, *(v4sf*)_ps_inv_sign_mask); /* extract the sign bit (upper one) */ sign_bit = _mm_and_ps(sign_bit, *(v4sf*)_ps_sign_mask); /* scale by 4/Pi */ y = _mm_mul_ps(x, *(v4sf*)_ps_cephes_FOPI); //printf("plop:"); print4(y); #ifdef USE_SSE2 /* store the integer part of y in mm0 */ emm2 = _mm_cvttps_epi32(y); /* j=(j+1) & (~1) (see the cephes sources) */ emm2 = _mm_add_epi32(emm2, *(v4si*)_pi32_1); emm2 = _mm_and_si128(emm2, *(v4si*)_pi32_inv1); y = _mm_cvtepi32_ps(emm2); /* get the swap sign flag */ emm0 = _mm_and_si128(emm2, *(v4si*)_pi32_4); emm0 = _mm_slli_epi32(emm0, 29); /* get the polynom selection mask there is one polynom for 0 <= x <= Pi/4 and another one for Pi/4 #include "ObjCryst/RefinableObj/GlobalOptimObj.h" #include "ObjCryst/ObjCryst/Crystal.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" #include "ObjCryst/Quirks/VFNDebug.h" #include "ObjCryst/Quirks/Chronometer.h" #include "ObjCryst/ObjCryst/IO.h" #include "ObjCryst/RefinableObj/LSQNumObj.h" #include "ObjCryst/ObjCryst/Molecule.h" #ifdef __WX__CRYST__ #include "ObjCryst/wxCryst/wxRefinableObj.h" #undef GetClassName // Conflict from wxMSW headers ? (cygwin) #endif //For some reason, with wxWindows this must be placed after wx headers (Borland c++) #include #include #include #include namespace ObjCryst { void CompareWorlds(const CrystVector_long &idx,const CrystVector_long &swap, const RefinableObj &obj) { const long nb=swap.numElements(); const CrystVector_REAL *pv0=&(obj.GetParamSet(idx(swap(nb-1)))); for(long i=0;inumElements();++j) d += ((*pv0)(j)-(*pv1)(j))*((*pv0)(j)-(*pv1)(j)); cout<<"d("< gOptimizationObjRegistry("List of all Optimization objects"); OptimizationObj::OptimizationObj(): mName(""),mSaveFileName("GlobalOptim.save"), mNbTrialPerRun(10000000),mNbTrial(0),mRun(0),mBestCost(-1), mBestParSavedSetIndex(-1), mContext(0), mIsOptimizing(false),mStopAfterCycle(false), mRefinedObjList("OptimizationObj: "+mName+" RefinableObj registry"), mRecursiveRefinedObjList("OptimizationObj: "+mName+" recursive RefinableObj registry"), mLastOptimTime(0) { VFN_DEBUG_ENTRY("OptimizationObj::OptimizationObj()",5) // This must be done in a real class to avoid calling a pure virtual method // if a graphical representation is automatically called upon registration. // gOptimizationObjRegistry.Register(*this); static bool need_initRandomSeed=true; if(need_initRandomSeed==true) { srand(time(NULL)); need_initRandomSeed=false; } // We only copy parameters, so do not delete them ! mRefParList.SetDeleteRefParInDestructor(false); VFN_DEBUG_EXIT("OptimizationObj::OptimizationObj()",5) } OptimizationObj::OptimizationObj(const string name): mName(name),mSaveFileName("GlobalOptim.save"), mNbTrialPerRun(10000000),mNbTrial(0),mRun(0),mBestCost(-1), mBestParSavedSetIndex(-1), mContext(0), mIsOptimizing(false),mStopAfterCycle(false), mRefinedObjList("OptimizationObj: "+mName+" RefinableObj registry"), mRecursiveRefinedObjList("OptimizationObj: "+mName+" recursive RefinableObj registry"), mLastOptimTime(0) { VFN_DEBUG_ENTRY("OptimizationObj::OptimizationObj()",5) // This must be done in a real class to avoid calling a pure virtual method // if a graphical representation is automatically called upon registration. // gOptimizationObjRegistry.Register(*this); static bool need_initRandomSeed=true; if(need_initRandomSeed==true) { srand(time(NULL)); need_initRandomSeed=false; } // We only copy parameters, so do not delete them ! mRefParList.SetDeleteRefParInDestructor(false); VFN_DEBUG_EXIT("OptimizationObj::OptimizationObj()",5) } OptimizationObj::OptimizationObj(const OptimizationObj &old): mName(old.mName),mSaveFileName(old.mSaveFileName), mNbTrialPerRun(old.mNbTrialPerRun),mNbTrial(old.mNbTrial),mRun(old.mRun),mBestCost(old.mBestCost), mBestParSavedSetIndex(-1), mContext(0), mIsOptimizing(false),mStopAfterCycle(false), mRefinedObjList("OptimizationObj: "+mName+" RefinableObj registry"), mRecursiveRefinedObjList("OptimizationObj: "+mName+" recursive RefinableObj registry"), mLastOptimTime(0) { VFN_DEBUG_ENTRY("OptimizationObj::OptimizationObj(&old)",5) // This must be done in a real class to avoid calling a pure virtual method // if a graphical representation is automatically called upon registration. // gOptimizationObjRegistry.Register(*this); static bool need_initRandomSeed=true; if(need_initRandomSeed==true) { srand(time(NULL)); need_initRandomSeed=false; } // We only copy parameters, so do not delete them ! mRefParList.SetDeleteRefParInDestructor(false); for(unsigned int i=0;iAddRefinableObj(old.mRefinedObjList.GetObj(i)); VFN_DEBUG_EXIT("OptimizationObj::OptimizationObj(&old)",5) } OptimizationObj::~OptimizationObj() { VFN_DEBUG_ENTRY("OptimizationObj::~OptimizationObj()",5) gOptimizationObjRegistry.DeRegister(*this); VFN_DEBUG_EXIT("OptimizationObj::~OptimizationObj()",5) } void OptimizationObj::RandomizeStartingConfig() { VFN_DEBUG_ENTRY("OptimizationObj::RandomizeStartingConfig()",5) this->PrepareRefParList(); for(int j=0;jBuildRecursiveRefObjList(); for(int i=0;iBuildRecursiveRefObjList(); for(int i=0;iBuildRecursiveRefObjList(); for(int i=0;iBuildRecursiveRefObjList(); for(int i=0;iBuildRecursiveRefObjList(); for(int i=0;iBuildRecursiveRefObjList(); for(int i=0;iBuildRecursiveRefObjList(); for(int i=0;iBuildRecursiveRefObjList(); for(int i=0;iBuildRecursiveRefObjList(); for(int i=0;iBuildRecursiveRefObjList(); for(int i=0;imTotalLogLikelihood += tmp; st->mTotalLogLikelihoodDeltaSq += (tmp-st->mLastLogLikelihood)*(tmp-st->mLastLogLikelihood); st->mLastLogLikelihood=tmp; } cost += mvObjWeight[&(mRecursiveRefinedObjList.GetObj(i))].mWeight * tmp; } return cost; } void OptimizationObj::StopAfterCycle() { VFN_DEBUG_MESSAGE("OptimizationObj::StopAfterCycle()",5) if(mIsOptimizing) { #ifdef __WX__CRYST__ wxMutexLocker lock(mMutexStopAfterCycle); #endif mStopAfterCycle=true; } } void OptimizationObj::DisplayReport() { //:TODO: ask all objects to print their own report ? } void OptimizationObj::AddRefinableObj(RefinableObj &obj) { VFN_DEBUG_MESSAGE("OptimizationObj::AddRefinableObj():"<BuildRecursiveRefObjList(); mRefinedObjList.Register(obj); RefObjRegisterRecursive(obj,mRecursiveRefinedObjList); #ifdef __WX__CRYST__ if(0!=this->WXGet()) this->WXGet()->AddRefinedObject(obj); #endif } RefinableObj& OptimizationObj::GetFullRefinableObj(const bool rebuild) { if(rebuild) this->PrepareRefParList(); return mRefParList; } const string& OptimizationObj::GetName()const { return mName;} void OptimizationObj::SetName(const string& name) {mName=name;} const string OptimizationObj::GetClassName()const { return "OptimizationObj";} void OptimizationObj::Print()const {this->XMLOutput(cout);} void OptimizationObj::RestoreBestConfiguration() { //:TODO: check list of refinableObj has not changed, and the list of // RefPar has not changed in all sub-objects. if(mBestParSavedSetIndex>0) mRefParList.RestoreParamSet(mBestParSavedSetIndex); } bool OptimizationObj::IsOptimizing()const{return mIsOptimizing;} void OptimizationObj::TagNewBestConfig() { for(int i=0;i& OptimizationObj::GetOptionList() { return mOptionRegistry; } RefObjOpt& OptimizationObj::GetOption(const unsigned int i) { VFN_DEBUG_MESSAGE("RefinableObj::GetOption()"<Print(); throw ObjCrystException("OptimizationObj::GetOption(): cannot find option: "+name+" in object:"+this->GetName()); } return mOptionRegistry.GetObj(i); } const RefObjOpt& OptimizationObj::GetOption(const unsigned int i)const { VFN_DEBUG_MESSAGE("RefinableObj::GetOption()"<Print(); throw ObjCrystException("OptimizationObj::GetOption(): cannot find option: "+name+" in object:"+this->GetName()); } return mOptionRegistry.GetObj(i); } const ObjRegistry& OptimizationObj::GetRefinedObjList() const { return mRefinedObjList; } unsigned int OptimizationObj::GetNbParamSet() const { return mvSavedParamSet.size(); } long OptimizationObj::GetParamSetIndex(const unsigned int i) const { if(i>=mvSavedParamSet.size()) throw ObjCrystException("OptimizationObj::GetSavedParamSetIndex(i): i > nb saved param set"); return mvSavedParamSet[i].first; } long OptimizationObj::GetParamSetCost(const unsigned int i) const { if(i>=mvSavedParamSet.size()) throw ObjCrystException("OptimizationObj::GetSavedParamSetCost(i): i > nb saved param set"); return mvSavedParamSet[i].second; } void OptimizationObj::RestoreParamSet(const unsigned int i, const bool update_display) { mRefParList.RestoreParamSet(this->GetParamSetIndex(i)); if(update_display) this->UpdateDisplay(); } void OptimizationObj::PrepareRefParList() { VFN_DEBUG_ENTRY("OptimizationObj::PrepareRefParList()",6) this->BuildRecursiveRefObjList(); // As any parameter been added in the recursive list of objects ? // or has any object been added/removed ? RefinableObjClock clock; GetRefParListClockRecursive(mRecursiveRefinedObjList,clock); if( (clock>mRefParList.GetRefParListClock()) ||(mRecursiveRefinedObjList.GetRegistryClock()>mRefParList.GetRefParListClock()) ) { VFN_DEBUG_MESSAGE("OptimizationObj::PrepareRefParList():Rebuild list",6) mRefParList.ResetParList(); mRefParList.EraseAllParamSet(); for(int i=0;i (this->GetName()+"::Overall LogLikelihood",*this,fl)); for(long i=0;i (mRecursiveRefinedObjList.GetObj(i).GetName()+"::LogLikelihood",mRecursiveRefinedObjList.GetObj(i),fp)); if(mRecursiveRefinedObjList.GetObj(i).GetClassName()=="Crystal") { REAL (Crystal::*fc)() const; const Crystal *pCryst=dynamic_cast(&(mRecursiveRefinedObjList.GetObj(i))); fc=&Crystal::GetBumpMergeCost; mMainTracker.AddTracker(new TrackerObject (pCryst->GetName()+"::BumpMergeCost",*pCryst,fc)); fc=&Crystal::GetBondValenceCost; mMainTracker.AddTracker(new TrackerObject (pCryst->GetName()+"::BondValenceCost",*pCryst,fc)); } } } // Prepare for refinement, ie get the list of not fixed parameters, // and prepare the objects... mRefParList.PrepareForRefinement(); for(int i=0;iAddOption(&mXMLAutoSave); VFN_DEBUG_MESSAGE("OptimizationObj::InitOptions():End",5) } void OptimizationObj::UpdateDisplay() const { Chronometer chrono; for(int i=0;imRecursiveRefinedObjList.GetRegistryClock()) { VFN_DEBUG_ENTRY("OptimizationObj::BuildRecursiveRefObjList()",5) mRecursiveRefinedObjList.DeRegisterAll(); for(int i=0;iInitOptions(); mGlobalOptimType.SetChoice(GLOBAL_OPTIM_PARALLEL_TEMPERING); mAnnealingScheduleTemp.SetChoice(ANNEALING_SMART); mAnnealingScheduleMutation.SetChoice(ANNEALING_EXPONENTIAL); mXMLAutoSave.SetChoice(5);//Save after each Run mAutoLSQ.SetChoice(0); gOptimizationObjRegistry.Register(*this); VFN_DEBUG_EXIT("MonteCarloObj::MonteCarloObj()",5) } MonteCarloObj::MonteCarloObj(const string name): OptimizationObj(name), mCurrentCost(-1), mTemperatureMax(1e6),mTemperatureMin(.001),mTemperatureGamma(1.0), mMutationAmplitudeMax(8.),mMutationAmplitudeMin(.125),mMutationAmplitudeGamma(1.0), mNbTrialRetry(0),mMinCostRetry(0) #ifdef __WX__CRYST__ ,mpWXCrystObj(0) #endif { VFN_DEBUG_ENTRY("MonteCarloObj::MonteCarloObj()",5) this->InitOptions(); mGlobalOptimType.SetChoice(GLOBAL_OPTIM_PARALLEL_TEMPERING); mAnnealingScheduleTemp.SetChoice(ANNEALING_SMART); mAnnealingScheduleMutation.SetChoice(ANNEALING_EXPONENTIAL); mXMLAutoSave.SetChoice(5);//Save after each Run mAutoLSQ.SetChoice(0); gOptimizationObjRegistry.Register(*this); VFN_DEBUG_EXIT("MonteCarloObj::MonteCarloObj()",5) } MonteCarloObj::MonteCarloObj(const MonteCarloObj &old): OptimizationObj(old), mCurrentCost(old.mCurrentCost), mTemperatureMax(old.mTemperatureMax),mTemperatureMin(old.mTemperatureMin), mTemperatureGamma(old.mTemperatureGamma), mMutationAmplitudeMax(old.mMutationAmplitudeMax),mMutationAmplitudeMin(old.mMutationAmplitudeMin), mMutationAmplitudeGamma(old.mMutationAmplitudeGamma), mNbTrialRetry(old.mNbTrialRetry),mMinCostRetry(old.mMinCostRetry) #ifdef __WX__CRYST__ ,mpWXCrystObj(0) #endif { VFN_DEBUG_ENTRY("MonteCarloObj::MonteCarloObj(&old)",5) this->InitOptions(); for(unsigned int i=0;iGetNbOption();i++) this->GetOption(i).SetChoice(old.GetOption(i).GetChoice()); gOptimizationObjRegistry.Register(*this); VFN_DEBUG_EXIT("MonteCarloObj::MonteCarloObj(&old)",5) } MonteCarloObj::MonteCarloObj(const bool internalUseOnly): OptimizationObj(""), mCurrentCost(-1), mTemperatureMax(.03),mTemperatureMin(.003),mTemperatureGamma(1.0), mMutationAmplitudeMax(16.),mMutationAmplitudeMin(.125),mMutationAmplitudeGamma(1.0), mNbTrialRetry(0),mMinCostRetry(0) #ifdef __WX__CRYST__ ,mpWXCrystObj(0) #endif { VFN_DEBUG_ENTRY("MonteCarloObj::MonteCarloObj(bool)",5) this->InitOptions(); mGlobalOptimType.SetChoice(GLOBAL_OPTIM_PARALLEL_TEMPERING); mAnnealingScheduleTemp.SetChoice(ANNEALING_SMART); mAnnealingScheduleMutation.SetChoice(ANNEALING_EXPONENTIAL); mXMLAutoSave.SetChoice(5);//Save after each Run mAutoLSQ.SetChoice(0); if(false==internalUseOnly) gOptimizationObjRegistry.Register(*this); VFN_DEBUG_EXIT("MonteCarloObj::MonteCarloObj(bool)",5) } MonteCarloObj::~MonteCarloObj() { VFN_DEBUG_ENTRY("MonteCarloObj::~MonteCarloObj()",5) gOptimizationObjRegistry.DeRegister(*this); VFN_DEBUG_EXIT ("MonteCarloObj::~MonteCarloObj()",5) } void MonteCarloObj::SetAlgorithmSimulAnnealing(const AnnealingSchedule scheduleTemp, const REAL tMax, const REAL tMin, const AnnealingSchedule scheduleMutation, const REAL mutMax, const REAL mutMin, const long nbTrialRetry,const REAL minCostRetry) { VFN_DEBUG_MESSAGE("MonteCarloObj::SetAlgorithmSimulAnnealing()",5) mGlobalOptimType.SetChoice(GLOBAL_OPTIM_SIMULATED_ANNEALING); mTemperatureMax=tMax; mTemperatureMin=tMin; mAnnealingScheduleTemp.SetChoice(scheduleTemp); mMutationAmplitudeMax=mutMax; mMutationAmplitudeMin=mutMin; mAnnealingScheduleMutation.SetChoice(scheduleMutation); mNbTrialRetry=nbTrialRetry; mMinCostRetry=minCostRetry; VFN_DEBUG_MESSAGE("MonteCarloObj::SetAlgorithmSimulAnnealing():End",3) } void MonteCarloObj::SetAlgorithmParallTempering(const AnnealingSchedule scheduleTemp, const REAL tMax, const REAL tMin, const AnnealingSchedule scheduleMutation, const REAL mutMax, const REAL mutMin) { VFN_DEBUG_MESSAGE("MonteCarloObj::SetAlgorithmParallTempering()",5) mGlobalOptimType.SetChoice(GLOBAL_OPTIM_PARALLEL_TEMPERING); mTemperatureMax=tMax; mTemperatureMin=tMin; mAnnealingScheduleTemp.SetChoice(scheduleTemp); mMutationAmplitudeMax=mutMax; mMutationAmplitudeMin=mutMin; mAnnealingScheduleMutation.SetChoice(scheduleMutation); //mNbTrialRetry=nbTrialRetry; //mMinCostRetry=minCostRetry; VFN_DEBUG_MESSAGE("MonteCarloObj::SetAlgorithmParallTempering():End",3) } void MonteCarloObj::Optimize(long &nbStep,const bool silent,const REAL finalcost, const REAL maxTime) { //:TODO: Other algorithms ! TAU_PROFILE("MonteCarloObj::Optimize()","void (long)",TAU_DEFAULT); VFN_DEBUG_ENTRY("MonteCarloObj::Optimize()",5) this->BeginOptimization(true); this->PrepareRefParList(); this->InitLSQ(false); mIsOptimizing=true; if(mTemperatureGamma<0.1) mTemperatureGamma= 0.1; if(mTemperatureGamma>10.0)mTemperatureGamma=10.0; if(mMutationAmplitudeGamma<0.1) mMutationAmplitudeGamma= 0.1; if(mMutationAmplitudeGamma>10.0)mMutationAmplitudeGamma=10.0; // prepare all objects this->TagNewBestConfig(); mCurrentCost=this->GetLogLikelihood(); mBestCost=mCurrentCost; mvObjWeight.clear(); mMainTracker.ClearValues(); Chronometer chrono; chrono.start(); switch(mGlobalOptimType.GetChoice()) { case GLOBAL_OPTIM_SIMULATED_ANNEALING: { this->RunSimulatedAnnealing(nbStep,silent,finalcost,maxTime); break; }//case GLOBAL_OPTIM_SIMULATED_ANNEALING case GLOBAL_OPTIM_PARALLEL_TEMPERING: { this->RunParallelTempering(nbStep,silent,finalcost,maxTime); break; }//case GLOBAL_OPTIM_PARALLEL_TEMPERING case GLOBAL_OPTIM_RANDOM_LSQ: //:TODO: { long cycles = 1; this->RunRandomLSQMethod(cycles); break; }//case GLOBAL_OPTIM_GENETIC } mIsOptimizing=false; #ifdef __WX__CRYST__ mMutexStopAfterCycle.Lock(); #endif mStopAfterCycle=false; #ifdef __WX__CRYST__ mMutexStopAfterCycle.Unlock(); #endif mRefParList.RestoreParamSet(mBestParSavedSetIndex); this->EndOptimization(); (*fpObjCrystInformUser)((boost::format("Finished Optimization, final cost=%12.2f (dt=%.1fs)") % this->GetLogLikelihood() % chrono.seconds()).str()); if(mSaveTrackedData.GetChoice()==1) { ofstream outTracker; outTracker.imbue(std::locale::classic()); const string outTrackerName=this->GetName()+"-Tracker.dat"; outTracker.open(outTrackerName.c_str()); mMainTracker.SaveAll(outTracker); outTracker.close(); } for(vector >::iterator pos=mvSavedParamSet.begin();pos!=mvSavedParamSet.end();++pos) if(pos->first==mBestParSavedSetIndex) { if( (pos->second>mBestCost) ||(pos->second<0)) { pos->second=mBestCost; break; } } this->UpdateDisplay(); VFN_DEBUG_EXIT("MonteCarloObj::Optimize()",5) } void MonteCarloObj::MultiRunOptimize(long &nbCycle,long &nbStep,const bool silent, const REAL finalcost,const REAL maxTime) { //:TODO: Other algorithms ! TAU_PROFILE("MonteCarloObj::MultiRunOptimize()","void (long)",TAU_DEFAULT); VFN_DEBUG_ENTRY("MonteCarloObj::MultiRunOptimize()",5) //Keep a copy of the total number of steps, and decrement nbStep const long nbStep0=nbStep; this->BeginOptimization(true); this->PrepareRefParList(); this->InitLSQ(false); mIsOptimizing=true; if(mTemperatureGamma<0.1) mTemperatureGamma= 0.1; if(mTemperatureGamma>10.0)mTemperatureGamma=10.0; if(mMutationAmplitudeGamma<0.1) mMutationAmplitudeGamma= 0.1; if(mMutationAmplitudeGamma>10.0)mMutationAmplitudeGamma=10.0; // prepare all objects mCurrentCost=this->GetLogLikelihood(); mBestCost=mCurrentCost; this->TagNewBestConfig(); mvObjWeight.clear(); long nbTrialCumul=0; const long nbCycle0=nbCycle; Chronometer chrono; mRun = 0; while(nbCycle!=0) { if(!silent) cout <<"MonteCarloObj::MultiRunOptimize: Starting Run#"<RunSimulatedAnnealing(nbStep,silent,finalcost,maxTime);} catch(...){cout<<"Unhandled exception in MonteCarloObj::MultiRunOptimize() ?"<RunParallelTempering(nbStep,silent,finalcost,maxTime);} catch(...){cout<<"Unhandled exception in MonteCarloObj::MultiRunOptimize() ?"<RunRandomLSQMethod(nbCycle);} catch(...){cout<<"Unhandled exception in MonteCarloObj::RunRandomLSQMethod() ?"<1) (*fpObjCrystInformUser)((boost::format("Finished Run #%d, final cost=%12.2f, nbTrial=%d (dt=%.1fs), so far =%d") % (nbCycle0-nbCycle) % this->GetLogLikelihood() % (nbStep0-nbStep) % chrono.seconds() % (nbTrialCumul/(nbCycle0-nbCycle+1))).str()); else (*fpObjCrystInformUser)((boost::format("Finished Run #%d, final cost=%12.2f, nbTrial=%d (dt=%.1fs)") % (nbCycle0-nbCycle) % this->GetLogLikelihood() % (nbStep0-nbStep) % chrono.seconds()).str()); nbStep=nbStep0; if(false==mStopAfterCycle) this->UpdateDisplay(); stringstream s; s<<"Run #"<GetName(); time_t date=time(0); char strDate[40]; strftime(strDate,sizeof(strDate),"%Y-%m-%d_%H-%M-%S",localtime(&date));//%Y-%m-%dT%H:%M:%S%Z char costAsChar[30]; sprintf(costAsChar,"-Run#%ld-Cost-%f",abs(nbCycle),this->GetLogLikelihood()); saveFileName=saveFileName+(string)strDate+(string)costAsChar+(string)".xml"; XMLCrystFileSaveGlobal(saveFileName); } if(mSaveTrackedData.GetChoice()==1) { ofstream outTracker; outTracker.imbue(std::locale::classic()); char runNum[40]; sprintf(runNum,"-Tracker-Run#%ld.dat",abs(nbCycle)); const string outTrackerName=this->GetName()+runNum; outTracker.open(outTrackerName.c_str()); mMainTracker.SaveAll(outTracker); outTracker.close(); } nbCycle--; #ifdef __WX__CRYST__ mMutexStopAfterCycle.Lock(); #endif if(mStopAfterCycle) { #ifdef __WX__CRYST__ mMutexStopAfterCycle.Unlock(); #endif break; } #ifdef __WX__CRYST__ mMutexStopAfterCycle.Unlock(); #endif mRun++; } mIsOptimizing=false; mRefParList.RestoreParamSet(mBestParSavedSetIndex); for(vector >::iterator pos=mvSavedParamSet.begin();pos!=mvSavedParamSet.end();++pos) if(pos->first==mBestParSavedSetIndex) { if( (pos->second>mBestCost) ||(pos->second<0)) { pos->second=mBestCost; break; } } this->EndOptimization(); if(false==mStopAfterCycle) this->UpdateDisplay(); #ifdef __WX__CRYST__ mMutexStopAfterCycle.Lock(); #endif mStopAfterCycle=false; #ifdef __WX__CRYST__ mMutexStopAfterCycle.Unlock(); #endif if(finalcost>1) cout<="<DisplayReport(); REAL runBestCost; mCurrentCost=this->GetLogLikelihood(); runBestCost=mCurrentCost; const long lastParSavedSetIndex=mRefParList.CreateParamSet("MonteCarloObj:Last parameters (SA)"); const long runBestIndex=mRefParList.CreateParamSet("Best parameters for current run (SA)"); //Report each ... cycles const int nbTryReport=3000; // Keep record of the number of accepted moves long nbAcceptedMoves=0;//since last report long nbAcceptedMovesTemp=0;//since last temperature/mutation rate change // Number of tries since best configuration found long nbTriesSinceBest=0; // Change temperature (and mutation) every... const int nbTryPerTemp=300; mTemperature=sqrt(mTemperatureMin*mTemperatureMax); mMutationAmplitude=sqrt(mMutationAmplitudeMin*mMutationAmplitudeMax); // Do we need to update the display ? bool needUpdateDisplay=false; Chronometer chrono; chrono.start(); for(mNbTrial=1;mNbTrial<=nbSteps;) { if((mNbTrial % nbTryPerTemp) == 1) { VFN_DEBUG_MESSAGE("-> Updating temperature and mutation amplitude.",3) // Temperature & displacements amplitude switch(mAnnealingScheduleTemp.GetChoice()) { case ANNEALING_BOLTZMANN: mTemperature= mTemperatureMin*log((REAL)nbSteps)/log((REAL)(mNbTrial+1));break; case ANNEALING_CAUCHY: mTemperature=mTemperatureMin*nbSteps/mNbTrial;break; //case ANNEALING_QUENCHING: case ANNEALING_EXPONENTIAL: mTemperature=mTemperatureMax *pow(mTemperatureMin/mTemperatureMax, mNbTrial/(REAL)nbSteps);break; case ANNEALING_GAMMA: mTemperature=mTemperatureMax+(mTemperatureMin-mTemperatureMax) *pow(mNbTrial/(REAL)nbSteps,mTemperatureGamma);break; case ANNEALING_SMART: { if((nbAcceptedMovesTemp/(REAL)nbTryPerTemp)>0.30) mTemperature/=1.5; if((nbAcceptedMovesTemp/(REAL)nbTryPerTemp)<0.10) mTemperature*=1.5; if(mTemperature>mTemperatureMax) mTemperature=mTemperatureMax; if(mTemperature0.3) mMutationAmplitude*=2.; if((nbAcceptedMovesTemp/(REAL)nbTryPerTemp)<0.1) mMutationAmplitude/=2.; if(mMutationAmplitude>mMutationAmplitudeMax) mMutationAmplitude=mMutationAmplitudeMax; if(mMutationAmplitudeNewConfiguration(); accept=0; REAL cost=this->GetLogLikelihood(); if(costTagNewBestConfig(); needUpdateDisplay=true; mRefParList.SaveParamSet(runBestIndex); if(runBestCostUpdateDisplayNbTrial(); #endif } mNbTrial++;nbStep--; #ifdef __WX__CRYST__ mMutexStopAfterCycle.Lock(); #endif if((runBestCost0)&&(chrono.seconds()>maxTime))) { #ifdef __WX__CRYST__ mMutexStopAfterCycle.Unlock(); #endif if(!silent) cout << endl <86400)) ||((mXMLAutoSave.GetChoice()==2)&&((chrono.seconds()-secondsWhenAutoSave)>3600)) ||((mXMLAutoSave.GetChoice()==3)&&((chrono.seconds()-secondsWhenAutoSave)> 600)) ||((mXMLAutoSave.GetChoice()==4)&&(accept==2)) ) { secondsWhenAutoSave=(unsigned long)chrono.seconds(); string saveFileName=this->GetName(); time_t date=time(0); char strDate[40]; strftime(strDate,sizeof(strDate),"%Y-%m-%d_%H-%M-%S",localtime(&date));//%Y-%m-%dT%H:%M:%S%Z char costAsChar[30]; if(accept!=2) mRefParList.RestoreParamSet(mBestParSavedSetIndex); sprintf(costAsChar,"-Cost-%f",this->GetLogLikelihood()); saveFileName=saveFileName+(string)strDate+(string)costAsChar+(string)".xml"; XMLCrystFileSaveGlobal(saveFileName); if(accept!=2) mRefParList.RestoreParamSet(lastParSavedSetIndex); } if((mNbTrial%300==0)&&needUpdateDisplay) { this->UpdateDisplay(); needUpdateDisplay=false; mRefParList.RestoreParamSet(lastParSavedSetIndex); } } //cout<<"Beginning final LSQ refinement? ... "; if(mAutoLSQ.GetChoice()>0) {// LSQ if(!silent) cout<<"Beginning final LSQ refinement"<GetLogLikelihood(); try {mLSQ.Refine(-50,true,true,false,0.001);} catch(const ObjCrystException &except){}; if(!silent) cout<<"LSQ cost: "< "<GetLogLikelihood()<GetLogLikelihood(); if(costGetLogLikelihood(); if(!silent) this->DisplayReport(); if(!silent) chrono.print(); } /* void MonteCarloObj::RunNondestructiveLSQRefinement( int nbCycle,bool useLevenbergMarquardt, const bool silent, const bool callBeginEndOptimization, const float minChi2var ) { float bsigma=-1, bdelta=-1; float asigma=-1, adelta=-1; //set the sigma values lower - it makes the molecular model more stable for LSQ for(int i=0;i(&(mRefinedObjList.GetObj(i))); for(int s=0;sGetScattererRegistry().GetNb();s++) { Molecule *pMol=dynamic_cast(&(pCryst->GetScatt(s))); if(pMol==NULL) continue; // not a Molecule for(vector::iterator pos = pMol->GetBondList().begin(); pos != pMol->GetBondList().end();++pos) { bsigma = (*pos)->GetLengthSigma(); bdelta = (*pos)->GetLengthDelta(); (*pos)->SetLengthDelta(0.02); (*pos)->SetLengthSigma(0.001); } for(vector::iterator pos=pMol->GetBondAngleList().begin();pos != pMol->GetBondAngleList().end();++pos) { asigma = (*pos)->GetAngleSigma(); adelta = (*pos)->GetAngleDelta(); (*pos)->SetAngleDelta(0.2*DEG2RAD); (*pos)->SetAngleSigma(0.01*DEG2RAD); } } } catch (const std::bad_cast& e) { } } } for(int i=0;i(&(mRefinedObjList.GetObj(i))); for(int s=0;sGetScattererRegistry().GetNb();s++) { Molecule *pMol=dynamic_cast(&(pCryst->GetScatt(s))); if(pMol==NULL) continue; // not a Molecule for(vector::iterator pos = pMol->GetBondList().begin(); pos != pMol->GetBondList().end();++pos) { (*pos)->SetLengthDelta(bdelta); (*pos)->SetLengthSigma(bsigma); } for(vector::iterator pos=pMol->GetBondAngleList().begin();pos != pMol->GetBondAngleList().end();++pos) { (*pos)->SetAngleDelta(adelta); (*pos)->SetAngleSigma(asigma); } } } catch (const std::bad_cast& e) { } } } } */ void MonteCarloObj::RunRandomLSQMethod(long &nbCycle) { //perform random move mMutationAmplitude=mMutationAmplitudeMax; float bsigma=-1, bdelta=-1; float asigma=-1, adelta=-1; //set the delta and sigma values - low values are good for LSQ! for(int i=0;i(&(mRefinedObjList.GetObj(i))); for(int s=0;sGetScattererRegistry().GetNb();s++) { Molecule *pMol=dynamic_cast(&(pCryst->GetScatt(s))); if(pMol==NULL) continue; // not a Molecule for(vector::iterator pos = pMol->GetBondList().begin(); pos != pMol->GetBondList().end();++pos) { bsigma = (*pos)->GetLengthSigma(); bdelta = (*pos)->GetLengthDelta(); (*pos)->SetLengthDelta(0.02); (*pos)->SetLengthSigma(0.001); } for(vector::iterator pos=pMol->GetBondAngleList().begin();pos != pMol->GetBondAngleList().end();++pos) { asigma = (*pos)->GetAngleSigma(); adelta = (*pos)->GetAngleDelta(); (*pos)->SetAngleDelta(0.2*DEG2RAD); (*pos)->SetAngleSigma(0.01*DEG2RAD); } } } catch (const std::bad_cast& e){ } } } const long starting_point=mRefParList.CreateParamSet("MonteCarloObj:Last parameters (RANDOM-LSQ)"); mRefParList.SaveParamSet(starting_point); mRun = 0; while(nbCycle!=0) { nbCycle--; mRefParList.RestoreParamSet(starting_point); //this->NewConfiguration(); for(int i=0;iUpdateDisplay(); //perform LSQ for(int i=0;iGetLogLikelihood(); try { mLSQ.Refine(20,true,true,false,0.001); } catch(const ObjCrystException &except) { //cout<<"Something wrong?"< "<GetLogLikelihood()<GetLogLikelihood(); mCurrentCost = lsq_cost; //mRefParList.SaveParamSet(lsqtParSavedSetIndex); if(mCurrentCostUpdateDisplay(); //save it to the file string saveFileName=this->GetName(); time_t date=time(0); char strDate[40]; strftime(strDate,sizeof(strDate),"%Y-%m-%d_%H-%M-%S",localtime(&date));//%Y-%m-%dT%H:%M:%S%Z char costAsChar[30]; sprintf(costAsChar,"#Run%ld-Cost-%f",nbCycle, mCurrentCost); saveFileName=saveFileName+(string)strDate+(string)costAsChar+(string)".xml"; XMLCrystFileSaveGlobal(saveFileName); #ifdef __WX__CRYST__ mMutexStopAfterCycle.Lock(); #endif if(mStopAfterCycle) { #ifdef __WX__CRYST__ mMutexStopAfterCycle.Unlock(); #endif break; } #ifdef __WX__CRYST__ mMutexStopAfterCycle.Unlock(); #endif mRun++; } if(bsigma<0 || bdelta<0 || asigma<0 || adelta<0) return; //restore the delta and sigma values for(int i=0;i(&(mRefinedObjList.GetObj(i))); for(int s=0;sGetScattererRegistry().GetNb();s++) { Molecule *pMol=dynamic_cast(&(pCryst->GetScatt(s))); if(pMol==NULL) continue; // not a Molecule for(vector::iterator pos = pMol->GetBondList().begin(); pos != pMol->GetBondList().end();++pos) { (*pos)->SetLengthDelta(bdelta); (*pos)->SetLengthSigma(bsigma); } for(vector::iterator pos=pMol->GetBondAngleList().begin();pos != pMol->GetBondAngleList().end();++pos) { (*pos)->SetAngleDelta(adelta); (*pos)->SetAngleSigma(asigma); } } } catch (const std::bad_cast& e){ } } } } void MonteCarloObj::RunParallelTempering(long &nbStep,const bool silent, const REAL finalcost,const REAL maxTime) { TAU_PROFILE("MonteCarloObj::RunParallelTempering()","void ()",TAU_DEFAULT); TAU_PROFILE_TIMER(timer0a,"MonteCarloObj::RunParallelTempering() Begin 1","", TAU_FIELD); TAU_PROFILE_TIMER(timer0b,"MonteCarloObj::RunParallelTempering() Begin 2","", TAU_FIELD); TAU_PROFILE_TIMER(timer1,"MonteCarloObj::RunParallelTempering() New Config + LLK","", TAU_FIELD); TAU_PROFILE_TIMER(timerN,"MonteCarloObj::RunParallelTempering() Finish","", TAU_FIELD); TAU_PROFILE_START(timer0a); //Keep a copy of the total number of steps, and decrement nbStep const long nbSteps=nbStep; unsigned int accept;// 1 if last trial was accepted? 2 if new best config ? else 0 mNbTrial=0; // time (in seconds) when last autoSave was made (if enabled) unsigned long secondsWhenAutoSave=0; // Periodicity of the automatic LSQ refinements (if the option is set) const unsigned int autoLSQPeriod=150000; if(!silent) cout << "Starting Parallel Tempering Optimization"<GetLogLikelihood(); REAL runBestCost=mCurrentCost; CrystVector_REAL currentCost(nbWorld); currentCost=mCurrentCost; // Init the different temperatures CrystVector_REAL simAnnealTemp(nbWorld); for(int i=0;i=0;i--) { if((i!=(nbWorld-1))&&(i%2==0)) for(int j=0;jNewConfiguration(); accept=0; REAL cost=this->GetLogLikelihood(); TAU_PROFILE_STOP(timer1); //trialsDensity((long)(cost*100.),i+1)+=1; if(costTagNewBestConfig(); needUpdateDisplay=true; mRefParList.SaveParamSet(runBestIndex); if(runBestCostTrial :" << mNbTrial << " World="<< worldSwapIndex(i) << " Temp="<< mTemperature << " Mutation Ampl.: "<Trial :" << mNbTrial << " World="<< worldSwapIndex(i) << " Temp="<< mTemperature << " Mutation Ampl.: "<GetLogLikelihood()); saveFileName=saveFileName+(string)strDate+(string)costAsChar+(string)".xml"; XMLCrystFileSaveGlobal(saveFileName); //if(accept!=2) mRefParList.RestoreParamSet(lastParSavedSetIndex); } //if(accept==0) mRefParList.RestoreParamSet(lastParSavedSetIndex); mNbTrial++;nbStep--; if((mNbTrial%nbTrialsReport)==0) makeReport=true; }//nbTryPerWorld trials }//For each World if(mAutoLSQ.GetChoice()==2) if((mNbTrial%autoLSQPeriod)<(nbTryPerWorld*nbWorld)) {// Try a quick LSQ ? for(int i=0;i::iterator pos=mLSQ.GetRefinedObjMap().begin();pos!=mLSQ.GetRefinedObjMap().end();++pos) if(pos->first->GetNbLSQFunction()>0) { CrystVector_REAL tmp; tmp =pos->first->GetLSQCalc(pos->second); tmp-=pos->first->GetLSQObs (pos->second); tmp*=tmp; tmp*=pos->first->GetLSQWeight(pos->second); cout<first->GetClassName()<<":"<first->GetName()<<": GoF="<GetLogLikelihood();// cannot use currentCost(i), approximations changed... if(!silent) cout<<"LSQ: World="<first->GetName()<<": GoF="<GetLogLikelihood(); if(!silent) cout<<" -> "<GetLogLikelihood(); if(!silent) cout<<"LSQ2:"<"<TagNewBestConfig(); needUpdateDisplay=true; mRefParList.SaveParamSet(runBestIndex); if(runBestCostTrial :" << mNbTrial << " World="<< worldSwapIndex(i) << " LSQ2: NEW OVERALL Best Cost="<Trial :" << mNbTrial << " World="<< worldSwapIndex(i) << " LSQ2: NEW RUN Best Cost="<DisplayReport(); } // KLUDGE - after a successful LSQ, we will be close to a minimum, // which will make most successive global optimization trials to // be rejected, until the temperature is increased a lot - this // is a problem as the temperature increases so much that the // benefit of the LSQ is essentially negated. // So we need to use a higher recorded cost, so that successive trials // may be accepted #if 0 mMutationAmplitude=mutationAmplitude(i); for(unsigned int ii=0;ii<4;ii++) this->NewConfiguration(gpRefParTypeObjCryst,false); currentCost(i)=(this->GetLogLikelihood()+cost)/2; if(!silent) cout<<"LSQ3: #"<"<GetLogLikelihood()<GetLogLikelihood()-currentCost(i))/simAnnealTemp(i))) #endif { /* if(i>2) { cout <<"->Swapping Worlds :" << i <<"(cost="<GetLogLikelihood(); mRefParList.RestoreParamSet(worldCurrentSetIndex(i-1)); mMutationAmplitude=mutationAmplitude(i-1); currentCost(i-1)=this->GetLogLikelihood(); #endif } } #if 0 //Try mating worlds- NEW ! TAU_PROFILE_TIMER(timer1,\ "MonteCarloObj::Optimize (Try mating Worlds)"\ ,"", TAU_FIELD); TAU_PROFILE_START(timer1); if( (rand()/(REAL)RAND_MAX)<.1) for(int k=nbWorld-1;k>nbWorld/2;k--) for(int i=k-nbWorld/3;icrossoverPoint1)&&refParGeneGroupIndex(j)GetLogLikelihood(); //if(log((rand()+1)/(REAL)RAND_MAX) // < (-(cost-currentCost(k))/simAnnealTemp(k))) if(costTagNewBestConfig(); needUpdateDisplay=true; mRefParList.SaveParamSet(runBestIndex); if(costTrial :" << mNbTrial << " World="<< worldSwapIndex(k) << " Temp="<< simAnnealTemp(k) << " Mutation Ampl.: "<Trial :" << mNbTrial << " World="<< worldSwapIndex(k) << " Temp="<< simAnnealTemp(k) << " Mutation Ampl.: "<DisplayReport(); //for(int i=0;i ll,llvar; map::iterator pos; for(pos=mvContextObjStats[0].begin();pos!=mvContextObjStats[0].end();++pos) { ll [pos->first]=0.; llvar[pos->first]=0.; } for(int i=0;ifirst] += pos->second.mTotalLogLikelihood; llvar[pos->first] += pos->second.mTotalLogLikelihoodDeltaSq; } } for(pos=mvContextObjStats[0].begin();pos!=mvContextObjStats[0].end();++pos) { cout << pos->first->GetName() << " " << llvar[pos->first] << " " << mvObjWeight[pos->first].mWeight << " " << max<first] *= mvObjWeight[pos->first].mWeight; if(llvar[pos->first]>max) max=llvar[pos->first]; } map::iterator pos2; for(pos2=llvar.begin();pos2!=llvar.end();++pos2) { const REAL d=pos2->second; if(d<(max/mvObjWeight.size()/10.)) { if(d<1) continue; mvObjWeight[pos2->first].mWeight *=2; } } REAL ll1=0; REAL llt=0; for(pos2=ll.begin();pos2!=ll.end();++pos2) { llt += pos2->second; ll1 += pos2->second * mvObjWeight[pos2->first].mWeight; } map::iterator posw; for(posw=mvObjWeight.begin();posw!=mvObjWeight.end();++posw) { posw->second.mWeight *= llt/ll1; } } #endif //Experimental dynamical weighting #if 1 //def __DEBUG__ for(int i=0;i::iterator pos; for(pos=mvContextObjStats[i].begin();pos!=mvContextObjStats[i].end();++pos) { cout << pos->first->GetName() << "(LLK=" << pos->second.mLastLogLikelihood //<< "(=" //<< pos->second.mTotalLogLikelihood/nbTrialsReport //<< ", =" //<< pos->second.mTotalLogLikelihoodDeltaSq/nbTrialsReport << ", w="<first].mWeight <<") "; pos->second.mTotalLogLikelihood=0; pos->second.mTotalLogLikelihoodDeltaSq=0; } cout << endl; } #endif for(int i=0;i0.30) mutationAmplitude(i)*=2.; if((worldNbAcceptedMoves(i)/(REAL)nbTrialsReport)<0.10) mutationAmplitude(i)/=2.; if(mutationAmplitude(i)>mMutationAmplitudeMax) mutationAmplitude(i)=mMutationAmplitudeMax; if(mutationAmplitude(i)0.30) simAnnealTemp(i)/=1.5; if((worldNbAcceptedMoves(i)/(REAL)nbTrialsReport)>0.80) simAnnealTemp(i)/=1.5; if((worldNbAcceptedMoves(i)/(REAL)nbTrialsReport)>0.95) simAnnealTemp(i)/=1.5; if((worldNbAcceptedMoves(i)/(REAL)nbTrialsReport)<0.10) simAnnealTemp(i)*=1.5; if((worldNbAcceptedMoves(i)/(REAL)nbTrialsReport)<0.04) simAnnealTemp(i)*=1.5; //if((worldNbAcceptedMoves(i)/(REAL)nbTrialsReport)<0.01) // simAnnealTemp(i)*=1.5; //cout<<"World#"<mTemperatureMax) simAnnealTemp(i)=mTemperatureMax; //if(simAnnealTemp(i)DisplayReport(); #ifdef __WX__CRYST__ if(0!=mpWXCrystObj) mpWXCrystObj->UpdateDisplayNbTrial(); #endif } if( (needUpdateDisplay&&(lastUpdateDisplayTime<(chrono.seconds()-1)))||(lastUpdateDisplayTime<(chrono.seconds()-10))) { mRefParList.RestoreParamSet(runBestIndex); this->UpdateDisplay(); needUpdateDisplay=false; lastUpdateDisplayTime=chrono.seconds(); } #ifdef __WX__CRYST__ mMutexStopAfterCycle.Lock(); #endif if((runBestCost0)&&(chrono.seconds()>maxTime))) { #ifdef __WX__CRYST__ mMutexStopAfterCycle.Unlock(); #endif if(!silent) cout << endl <0) {// LSQ if(!silent) cout<<"Beginning final LSQ refinement"<GetLogLikelihood(); try {mLSQ.Refine(-50,true,true,false,0.001);} catch(const ObjCrystException &except){}; if(!silent) cout<<"LSQ cost: "< "<GetLogLikelihood()<GetLogLikelihood(); if(costDisplayReport(); mRefParList.RestoreParamSet(runBestIndex); //for(int i=0;iGetLogLikelihood(); if(!silent) cout<<"Run Best Cost:"<GetName(),5) for(int i=0;iGetName()); tag.AddAttribute("NbTrialPerRun",(boost::format("%d")%(this->NbTrialPerRun())).str()); os <GetName(),5) } void MonteCarloObj::XMLInput(istream &is,const XMLCrystTag &tagg) { VFN_DEBUG_ENTRY("MonteCarloObj::XMLInput():"<GetName(),5) for(unsigned int i=0;iSetName(tagg.GetAttributeValue(i)); if("NbTrialPerRun"==tagg.GetAttributeName(i)) { stringstream ss(tagg.GetAttributeValue(i)); long v; ss>>v; this->NbTrialPerRun()=v; } } while(true) { XMLCrystTag tag(is); if(("GlobalOptimObj"==tag.GetName())&&tag.IsEndTag()) { VFN_DEBUG_EXIT("MonteCarloObj::Exit():"<GetName(),5) this->UpdateDisplay(); return; } if("Option"==tag.GetName()) { for(unsigned int i=0;i>mTemperatureMax>> mTemperatureMin; if(false==tag.IsEmptyTag()) XMLCrystTag junk(is);//:KLUDGE: for first release continue; } if("MutationMaxMin"==tag.GetName()) { is>>mMutationAmplitudeMax>>mMutationAmplitudeMin; if(false==tag.IsEmptyTag()) XMLCrystTag junk(is);//:KLUDGE: for first release continue; } if("RefinedObject"==tag.GetName()) { string name,type; for(unsigned int i=0;iAddRefinableObj(*obj); continue; } } } const string MonteCarloObj::GetClassName()const { return "MonteCarloObj";} LSQNumObj& MonteCarloObj::GetLSQObj() {return mLSQ;} const LSQNumObj& MonteCarloObj::GetLSQObj() const{return mLSQ;} void MonteCarloObj::NewConfiguration(const RefParType *type) { TAU_PROFILE("MonteCarloObj::NewConfiguration()","void ()",TAU_DEFAULT); VFN_DEBUG_ENTRY("MonteCarloObj::NewConfiguration()",4) for(int i=0;iOptimizationObj::InitOptions(); static string GlobalOptimTypeName; static string GlobalOptimTypeChoices[2];//:TODO: Add Genetic Algorithm static string AnnealingScheduleChoices[6]; static string AnnealingScheduleTempName; static string AnnealingScheduleMutationName; static string runAutoLSQName; static string runAutoLSQChoices[3]; static string saveTrackedDataName; static string saveTrackedDataChoices[2]; static bool needInitNames=true; if(true==needInitNames) { GlobalOptimTypeName="Algorithm"; GlobalOptimTypeChoices[0]="Simulated Annealing"; GlobalOptimTypeChoices[1]="Parallel Tempering"; //GlobalOptimTypeChoices[2]="Random-LSQ"; AnnealingScheduleTempName="Temperature Schedule"; AnnealingScheduleMutationName="Displacement Amplitude Schedule"; AnnealingScheduleChoices[0]="Constant"; AnnealingScheduleChoices[1]="Boltzmann"; AnnealingScheduleChoices[2]="Cauchy"; AnnealingScheduleChoices[3]="Exponential"; AnnealingScheduleChoices[4]="Smart"; AnnealingScheduleChoices[5]="Gamma"; runAutoLSQName="Automatic Least Squares Refinement"; runAutoLSQChoices[0]="Never"; runAutoLSQChoices[1]="At the end of each run"; runAutoLSQChoices[2]="Every 150000 trials, and at the end of each run"; saveTrackedDataName="Save Tracked Data"; saveTrackedDataChoices[0]="No (recommended!)"; saveTrackedDataChoices[1]="Yes (for tests ONLY)"; needInitNames=false;//Only once for the class } mGlobalOptimType.Init(2,&GlobalOptimTypeName,GlobalOptimTypeChoices); mAnnealingScheduleTemp.Init(6,&AnnealingScheduleTempName,AnnealingScheduleChoices); mAnnealingScheduleMutation.Init(6,&AnnealingScheduleMutationName,AnnealingScheduleChoices); mSaveTrackedData.Init(2,&saveTrackedDataName,saveTrackedDataChoices); mAutoLSQ.Init(3,&runAutoLSQName,runAutoLSQChoices); this->AddOption(&mGlobalOptimType); this->AddOption(&mAnnealingScheduleTemp); this->AddOption(&mAnnealingScheduleMutation); this->AddOption(&mSaveTrackedData); this->AddOption(&mAutoLSQ); VFN_DEBUG_MESSAGE("MonteCarloObj::InitOptions():End",5) } void MonteCarloObj::InitLSQ(const bool useFullPowderPatternProfile) { mLSQ.SetRefinedObj(mRecursiveRefinedObjList.GetObj(0),0,true,true); for(unsigned int i=1;i::iterator pos=mLSQ.GetRefinedObjMap().begin();pos!=mLSQ.GetRefinedObjMap().end();++pos) if(pos->first->GetClassName()=="PowderPattern") pos->second=1; } // Only refine structural parameters (excepting parameters already fixed) and scale factor mLSQ.PrepareRefParList(true); // Intensity corrections can be refined std::list vIntCorrPar; for(int i=0; iIsDescendantFromOrSameAs(gpRefParTypeScattDataCorrInt) && mLSQ.GetCompiledRefinedObj().GetPar(i).IsFixed()==false) vIntCorrPar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar(i)); mLSQ.SetParIsFixed(gpRefParTypeScattData,true); mLSQ.SetParIsFixed(gpRefParTypeScattDataScale,false); for(std::list::iterator pos=vIntCorrPar.begin();pos!=vIntCorrPar.end();pos++) (*pos)->SetIsFixed(false); mLSQ.SetParIsFixed(gpRefParTypeUnitCell,true); mLSQ.SetParIsFixed(gpRefParTypeScattPow,true); mLSQ.SetParIsFixed(gpRefParTypeRadiation,true); } void MonteCarloObj::UpdateDisplay() const { Chronometer chrono; #ifdef __WX__CRYST__ if(0!=mpWXCrystObj) mpWXCrystObj->CrystUpdate(true,true); #endif this->OptimizationObj::UpdateDisplay(); } #ifdef __WX__CRYST__ WXCrystObjBasic* MonteCarloObj::WXCreate(wxWindow *parent) { mpWXCrystObj=new WXMonteCarloObj (parent,this); return mpWXCrystObj; } WXOptimizationObj* MonteCarloObj::WXGet() { return mpWXCrystObj; } void MonteCarloObj::WXDelete() { if(0!=mpWXCrystObj) delete mpWXCrystObj; mpWXCrystObj=0; } void MonteCarloObj::WXNotifyDelete() { mpWXCrystObj=0; } #endif }//namespace objcryst-2022.1/ObjCryst/RefinableObj/GlobalOptimObj.h000066400000000000000000000644051430515525000225460ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* OptimizationObj.h * header file for the Global Optimization object * */ #ifndef _GLOBALOPTIMOBJ_H #define _GLOBALOPTIMOBJ_H #include #include "ObjCryst/ObjCryst/General.h" namespace ObjCryst { class OptimizationObj; class MonteCarloObj; } #include "ObjCryst/RefinableObj/RefinableObj.h" #include "ObjCryst/RefinableObj/LSQNumObj.h" #include "ObjCryst/RefinableObj/IO.h" #include "ObjCryst/RefinableObj/Tracker.h" #include #include #ifdef __WX__CRYST__ //#undef GetClassName // Conflict from wxMSW headers ? (cygwin) #include "ObjCryst/wxCryst/wxGlobalOptimObj.h" #endif namespace ObjCryst { /** Annealing schedule type. Used to determine the variation of the * temperature and the mutation amplitude * * With A=Temperature or A=MutationAMplitude, and the corresponding , min and max values supplied (the latter is ignored for constant, * Cauchy and Boltzmann), with 'step' being the current step, and * NbStep the total number of steps. (In the Parallel Tempering * algorithm, a 'step' denotes one of the parallel refinement). * \f[ A_{constant} = A_{min}\f] * \f[ A_{Boltzmann} = A_{min} \frac{\ln(NbStep)}{\ln(step)} \f] * \f[ A_{Cauchy} = A_{min} \frac{NbStep}{step} \f] * \f[ A_{exponential} = A_{max} (\frac{T_{min}}{T_{max}})^{\frac{step}{NbStep}} \f] * \f[ A_{\gamma} = A_{max} +(A_{min}-A_{max}*(\frac{step}{NbStep})^{\gamma} \f] * * For the 'smart' schedule, it is only supported so far for the mutation amplitude: * it is modulated so that for each temperature between 30 and 70% of trial * configurations are accepted, within the limits for the mutation. */ enum AnnealingSchedule { ANNEALING_CONSTANT, ANNEALING_BOLTZMANN, ANNEALING_CAUCHY, // ANNEALING_QUENCHING, ANNEALING_EXPONENTIAL, ANNEALING_SMART, ANNEALING_GAMMA }; /** Global optimization type. Eventually it would be better to build * a base Global Optimization (or even Optimization) object, and to derive * it in different classes for Simulated Annealing, Parallel Tempering, * Genetic Algorithm,... */ enum GlobalOptimType { GLOBAL_OPTIM_SIMULATED_ANNEALING, GLOBAL_OPTIM_PARALLEL_TEMPERING, GLOBAL_OPTIM_RANDOM_LSQ, GLOBAL_OPTIM_SIMULATED_ANNEALING_MULTI, GLOBAL_OPTIM_PARALLEL_TEMPERING_MULTI, }; /** \brief Base object for Optimization methods. * * This is an abstract base class, derived for Monte-Cralo type algorithms * (Simulated Annealing & Parallel Tempering), and hopefully soon * for Genetic Algorithms. * * \remarks Instead of keeping a copy of the list of parameters here, * maybe it would be better to delegate all parameter handling to the refined * objects (they would also have to keep in memory the saved parameter sets, so * that could be difficult to administrate...). */ class OptimizationObj { public: /// Default constructor OptimizationObj(); /// Constructor OptimizationObj(const string name); /// Copy constructor OptimizationObj(const OptimizationObj &old); /// Destructor virtual ~OptimizationObj(); /** \brief Randomize starting configuration. Only affects limited and periodic parameters. */ virtual void RandomizeStartingConfig(); /// Launch optimization (a single run) for N steps /// \param nbSteps: the number of steps to go. This number is modified (decreases!) /// as the refinement goes on. /// \param silent : if true, absolutely no message should be printed (except debugging) /// \param finalcost: the optimization will stop if overall cost fallse below this value /// \param maxTime: the optimization will stop after the given number of seconds has /// been spent optimizing (ignored if <0). virtual void Optimize(long &nbSteps,const bool silent=false,const REAL finalcost=0, const REAL maxTime=-1)=0; /** Launch optimization for multiple runs of N steps * \param nbCycle: the number of runs (cycles) to perform. The structure is randomized * at the beginning of each cycle. If nbCycle==-1, this will run indefinitely. * The nbCycle parameter is decreased after each run. * \param nbSteps: the number of steps to go. This number is modified (decreases!) * as the refinement goes on. * \param silent : if true, absolutely no message should be printed (except debugging) * \param finalcost: the optimization will stop if overall cost fallse below this value * \param maxTime: the optimization will stop after the given number of seconds has * been spent optimizing (ignored if <0). */ virtual void MultiRunOptimize(long &nbCycle,long &nbSteps,const bool silent=false,const REAL finalcost=0, const REAL maxTime=-1)=0; //Set Refinable parameters status /// Fix all parameters void FixAllPar(); /// Fix one parameter void SetParIsFixed(const string& parName,const bool fix); /// Fix one family of parameters void SetParIsFixed(const RefParType *type,const bool fix); /// UnFix All parameters void UnFixAllPar(); /// Set a parameter to be used void SetParIsUsed(const string& parName,const bool use); /// Set a family of parameters to be used void SetParIsUsed(const RefParType *type,const bool use); /// Change the relative limits for a parameter from its name void SetLimitsRelative(const string &parName, const REAL min, const REAL max); /// Change the relative limits for a family of parameter void SetLimitsRelative(const RefParType *type, const REAL min, const REAL max); /// Change the absolute limits for a parameter from its name void SetLimitsAbsolute(const string &parName, const REAL min, const REAL max); /// Change the absolute limits for a family of parameter void SetLimitsAbsolute(const RefParType *type, const REAL min, const REAL max); /** \brief The optimized (minimized, actually) function. * * This function is the weighted sum of the chosen Cost Functions for * the refined objects. */ virtual REAL GetLogLikelihood()const; /// Stop after the current cycle. USed for interactive refinement. void StopAfterCycle(); /// Show report to the user during refinement. Used for GUI update. virtual void DisplayReport(); /// Add a refined object. All sub-objects are also added void AddRefinableObj(RefinableObj &); /// Get the RefinableObj with all the parameters from all refined objects. /// If rebuild=true, prepare again the list of objects/parameters. RefinableObj& GetFullRefinableObj(const bool rebuild=true); /** \brief Output a description of the object in XML format to a stream. * * This saves the list of refined object and the cost functions, as well as options * for the refinement. The refined objects are \b not saved, so this must be done * somewhere else (they must be reloaded before this object). */ virtual void XMLOutput(ostream &os,int indent=0)const=0; /** \brief Input in XML format from a stream, restoring the set of refined * objects and the associated cost functions. Note that the corresponding objects * must have been loaded in memory before, else shit happens. * */ virtual void XMLInput(istream &is,const XMLCrystTag &tag)=0; //virtual void XMLInputOld(istream &is,const IOCrystTag &tag); /// Get the name for this object const string& GetName()const; /// Set the name for this object void SetName(const string&); /// Get the name for this class type virtual const string GetClassName()const; /// Print some information about this object virtual void Print()const; /// Restore the Best configuration void RestoreBestConfiguration(); /// Are we busy optimizing ? bool IsOptimizing()const; /** During a global optimization, tell all objects that the current config is * the latest "best" config. */ void TagNewBestConfig(); /// Get the elapsed time (in seconds) during the last optimization REAL GetLastOptimElapsedTime()const; /// Get the MainTracker MainTracker& GetMainTracker(); /// Get the MainTracker const MainTracker& GetMainTracker()const; RefObjOpt& GetXMLAutoSaveOption(); const RefObjOpt& GetXMLAutoSaveOption()const; /// Access to current best cost const REAL& GetBestCost()const; /// Access to current best cost REAL& GetBestCost(); /// Begin optimization for all objects virtual void BeginOptimization(const bool allowApproximations=false, const bool enableRestraints=false); /// End optimization for all objects virtual void EndOptimization(); /// Number of trial per run virtual long& NbTrialPerRun(); /// Number of trial per run virtual const long& NbTrialPerRun() const; /// Current trial number (updated during a run) long GetTrial() const; /// Current run number (updated during a run) long GetRun() const; //Options /// Access to the options registry ObjRegistry& GetOptionList(); /// Number of Options for this object unsigned int GetNbOption()const; /// Access to the options RefObjOpt& GetOption(const unsigned int i); /// Access to the options by name RefObjOpt& GetOption(const string & name); /// const access to the options const RefObjOpt& GetOption(const unsigned int i)const; /// const access to the options by name const RefObjOpt& GetOption(const string & name)const; /// Access the list of refined object const ObjRegistry& GetRefinedObjList() const; /// Update Display (if any display is available), when a new 'relevant' configuration /// is reached. This calls all RefinableObj::UpdateDisplay() virtual void UpdateDisplay() const; /// Get the number of saved parameters set unsigned int GetNbParamSet() const; /// Get the index of a saved parameters set in the compiled RefinableObj. /// The parameters can then be accessed using GetRefinedObjList().GetParamSet(idx) long GetParamSetIndex(const unsigned int i) const; /// Get the cost (log-likelihood) of a saved parameters set long GetParamSetCost(const unsigned int i) const; /// Restore a given saved parameter set. /// This is equivalent to GetRefinedObjList().RestoreParamSet(GetSavedParamSetIndex(i)) /// \param i: the order of the saved parameter set void RestoreParamSet(const unsigned int i, const bool update_display=true); protected: /// \internal Prepare mRefParList for the refinement void PrepareRefParList(); /// Initialization of options. virtual void InitOptions(); /// (Re)build OptimizationObj::mRecursiveRefinedObjList, if an /// object has been added or modified. If no object has been /// added and no sub-object has been added/removed, then nothing is done. void BuildRecursiveRefObjList(); /// \internal Add an option for this parameter void AddOption(RefObjOpt *opt); /// The refinable par list used during refinement. Only a condensed version /// of all objects. This is useful to keep an history of modifications, and to /// restore previous values. /// \remarks maybe this should be completely delegated to the refined objetcs. mutable RefinableObj mRefParList; /// Name of the GlobalOptimization object string mName; /// File name where refinement info is saved (NOT USED so far...) string mSaveFileName; //Status of optimization /// Number of trial per run, to be saved/restored in XML output long mNbTrialPerRun; /// Current trial number long mNbTrial; /// Current run number (during multiple runs) long mRun; /// Best value of the cost function so far REAL mBestCost; /// Index of the 'best' saved parameter set long mBestParSavedSetIndex; /// The current 'context', in the case the optimization is run in different /// parallel contexts unsigned long mContext; /// Statistics about each object contributing to the overall Log(likelihood) struct LogLikelihoodStats { /// Previous log(likelihood) REAL mLastLogLikelihood; /// Total Log(Likelihood), to compute the average REAL mTotalLogLikelihood; /// total of (Delta(Log(Likelihood)))^2 between successive trials REAL mTotalLogLikelihoodDeltaSq; }; /// Statistics for each context /// (mutable for dynamic update during optimization) mutable map > mvContextObjStats; // Dynamic weights (EXPERIMENTAL!) struct DynamicObjWeight { DynamicObjWeight():mWeight(1.){}; REAL mWeight; }; /// Weights for each objects in each context /// (mutable for dynamic update during optimization) mutable map mvObjWeight; /// List of saved parameter sets. This is used to save possible /// solutions during the optimization, so that the user can check them /// afterwards. /// /// The first member of each pair is the \e index of the parameter set, /// and the second is the overall cost for that set. std::vector > mvSavedParamSet; /// True if a refinement is being done. For multi-threaded environment bool mIsOptimizing; /// If true, then stop at the end of the cycle. Used in multi-threaded environment bool mStopAfterCycle; // Refined objects /// The refined objects. This is mutable to allow a copy constructor for /// the OptimizationObj, and because the objects are not owned /// but rather referenced here. mutable ObjRegistry mRefinedObjList; /// The refined objects, recursively including all sub-objects. /// This is mutable, since it is a function of mRefinedObjList only. mutable ObjRegistry mRecursiveRefinedObjList; /// Periodic save of complete environment as an xml file RefObjOpt mXMLAutoSave; /// The time elapsed after the last optimization, in seconds REAL mLastOptimTime; /// MainTracker object to track the evolution of cost functions, likelihood, /// and individual parameters. MainTracker mMainTracker; /// List of options for this object. Note that these are just references, /// to options allocated by the object, to have a simple global access to /// all options ObjRegistry mOptionRegistry; private: #ifdef __WX__CRYST__ public: /// Create a WXCrystObj for this object. virtual WXCrystObjBasic* WXCreate(wxWindow*)=0; virtual WXOptimizationObj* WXGet()=0; virtual void WXDelete()=0; virtual void WXNotifyDelete()=0; protected: //:TODO: remove this ! friend class ObjCryst::WXOptimizationObj; //friend class ObjCryst::WXMonteCarloObj; //friend class ObjCryst::WXGeneticAlgorithm; /// Mutex used to protect mStopAfterCycle wxMutex mMutexStopAfterCycle; #endif }; /** \brief Base object for Monte-Carlo Global Optimization methods. * * The algorithm is quite simple, whith two type of optimizations, either * simulated Annealing or Parallel Tempering, the latter being recommanded * for most real-world optimizations. * */ class MonteCarloObj:public OptimizationObj { public: /// Default Constructor MonteCarloObj(); /// Constructor MonteCarloObj(const string name); /// Copy constructor MonteCarloObj(const MonteCarloObj &old); /// Constructor. Using internalUseOnly=true will avoid registering the /// the object to any registry, and thus (for example) no display will be created, /// nor will this object be automatically be saved. MonteCarloObj(const bool internalUseOnly); /// Destructor virtual ~MonteCarloObj(); /** \brief Set the refinement method to simulated Annealing. Note that * Parellel Tempering is more efficient to get out of local minima, so you sould * rather use that method. * * The refinement begins at max and finishes at min temperature. * *\param scheduleTemp: temperature schedule. See AnnealingSchedule. *\param tMax,tMin: Max and Min temperatures. *\param scheduleMutation: the mutation schedule. For each new configuration, the * variation of each refinable parameter is less than its RefinablePar::GlobalOptimStep(), * multiplied by the current mutation amplitude. By default this mutation is equal to 1., * but making bigger steps is a good idea at the beginning of the refinement * (for higher temperatures). See AnnealingSchedule. See AnnealingSchedule. *\param mutMax,mutMin: Max and Min mutation amplitudes. *\param minCostRetry, nbTrialRetry: if after nbTrialRetry, the cost function is still * above minCostRetry, then start again from a random configuration. No randomization is * made if nbTrialRetry <= 0. *\param maxNbTrialSinceBest: if more than maxNbTrialSinceBest trials have been made * since the best configuration was recorded, then revert to that configuration. This * should be large enough to have an ergodic search (the default is never to revert..) * * \warning do not use the 'smart' option for the temperature schedule, it is not yet * implemented. Later it will be used to set the temperatures as a function of * the amplitude schedule, so that we accept between 30% and 70% moves. * \note this will be removed when we separate the different algorithms in different * classes. */ void SetAlgorithmSimulAnnealing(const AnnealingSchedule scheduleTemp, const REAL tMax, const REAL tMin, const AnnealingSchedule scheduleMutation=ANNEALING_CONSTANT, const REAL mutMax=16., const REAL mutMin=.125, const long nbTrialRetry=0,const REAL minCostRetry=0.); /** \brief Set the refinement method to Parallel Tempering. * * The refinement begins at max and finishes at min temperature. * *\param scheduleTemp: temperature schedule *\param tMax,tMin: Max and Min temperatures. See AnnealingSchedule. *\param scheduleMutation: the mutation schedule. For each new configuration, the * variation of each refinable parameter is less than its RefinablePar::GlobalOptimStep(), * multiplied by the current mutation amplitude. By default this mutation is equal to 1., * but making bigger steps can be a good idea at the beginning of the refinement. Thus * you can choose a schedule for the amplitude, exactly like for the temperature. *\param mutMax,mutMin: Max and Min mutation amplitudes. * \warning do not use the 'smart' option for the temperature schedule, it is not yet * implemented. Later it will be used to set the temperatures as a function of * the amplitude schedule, so that we keep accepted move between 30% and 70%. * \note this will be removed when we separate the different algorithms in different * classes. */ void SetAlgorithmParallTempering(const AnnealingSchedule scheduleTemp, const REAL tMax, const REAL tMin, const AnnealingSchedule scheduleMutation=ANNEALING_CONSTANT, const REAL mutMax=16., const REAL mutMin=.125); virtual void Optimize(long &nbSteps,const bool silent=false,const REAL finalcost=0, const REAL maxTime=-1); virtual void MultiRunOptimize(long &nbCycle,long &nbSteps,const bool silent=false,const REAL finalcost=0, const REAL maxTime=-1); /** \internal Do a single simulated annealing run. This is called by Optimize(...) and * MultiRunOptimize(), which must also prepare the optimization (PrepareRefParList(), etc..). */ void RunSimulatedAnnealing(long &nbSteps,const bool silent=false,const REAL finalcost=0, const REAL maxTime=-1); /** \internal Do a single Parallel Tempering run. This is called by Optimize(...) and * MultiRunOptimize(), which must also prepare the optimization (PrepareRefParList(), etc..). */ void RunParallelTempering(long &nbSteps,const bool silent=false,const REAL finalcost=0, const REAL maxTime=-1); void RunRandomLSQMethod(long &nbCycle); //Parameter Access by name //RefinablePar& GetPar(const string& parName); // Print information about the current state of optimization (parameters value, // characteristic figures...) //virtual ostream& operator<<(ostream& os)const; virtual void XMLOutput(ostream &os,int indent=0)const; virtual void XMLInput(istream &is,const XMLCrystTag &tag); //virtual void XMLInputOld(istream &is,const IOCrystTag &tag); virtual const string GetClassName()const; /// Access to the builtin LSQ optimization object LSQNumObj & GetLSQObj(); /// Access to the builtin LSQ optimization object const LSQNumObj & GetLSQObj() const; /** Prepare mLSQ for least-squares refinement during the global optimization * * \param useFullPowderPatternProfile: if true, the refinement will use the full * profile version of powder patterns, otherwise only the integrated powder pattern * will be used (faster). */ virtual void InitLSQ(const bool useFullPowderPatternProfile=true); /// Update Display (if any display is available), when a new 'relevant' configuration /// is reached. This calls all RefinableObj::UpdateDisplay() virtual void UpdateDisplay() const; protected: /** \brief Make a random change in the configuration. * * \internal * This just generates a new configuration with random changes (according * to current parameters). The new configuration is \e not tested \e in \e this \e function * vs temperature: this should be done in the OptimizationObj::Optimize() function, * which also chooses whether to revert to the previous configuration. * * Random moves are made by the objects and not by this function, * because the new configuration can be specific * (like, for example, permutations between some of the parameters (atoms)). * * \param type: can be used to restrict the move to a given category of parameters. */ virtual void NewConfiguration(const RefParType *type=gpRefParTypeObjCryst); virtual void InitOptions(); /// Method used for the global optimization. Should be removed when we switch /// to using several classes for different algorithms. RefObjOpt mGlobalOptimType; //Status of optimization /// Current value of the cost function REAL mCurrentCost; // History, for experimental purposes only ! /// Option to save the evolution of tracked data (cost functions, /// likelihhod, individual parameters,...) RefObjOpt mSaveTrackedData; // Annealing parameters /// Current temperature for annealing REAL mTemperature; /// Beginning temperature for annealing REAL mTemperatureMax; /// Lower temperature REAL mTemperatureMin; /// Schedule for the annealing RefObjOpt mAnnealingScheduleTemp; /// Gamma for the 'gamma' temperature schedule REAL mTemperatureGamma; //Parameters to create new configurations /// Mutation amplitude. From .25 to 64. Random moves will have a maximum amplitude /// equal to this amplitude multiplied by the Global optimization step defined /// for each RefinablePar. Large amplitude should be used at the beginning of the /// refinement (high temeratures). REAL mMutationAmplitude; /// Mutation amplitude at the beginning of the optimization. REAL mMutationAmplitudeMax; /// Mutation amplitude at the end of the optimization. REAL mMutationAmplitudeMin; /// Schedule for the annealing RefObjOpt mAnnealingScheduleMutation; /// Gamma for the 'gamma' Mutation amplitude schedule REAL mMutationAmplitudeGamma; //Automatic retry /// Number of trials before testing if we are below the given minimum cost. /// If <=0, this will be ignored. long mNbTrialRetry; /// Cost to reach unless an automatic randomization and retry is done REAL mMinCostRetry; /// Least squares object LSQNumObj mLSQ; /// Option to run automatic least-squares refinements RefObjOpt mAutoLSQ; private: #ifdef __WX__CRYST__ public: virtual WXCrystObjBasic* WXCreate(wxWindow*); virtual WXOptimizationObj* WXGet(); virtual void WXDelete(); virtual void WXNotifyDelete(); protected: WXMonteCarloObj* mpWXCrystObj; friend class ObjCryst::WXMonteCarloObj; #endif }; /// Global Registry for all OptimizationObj extern ObjRegistry gOptimizationObjRegistry; }// namespace #endif //_GLOBALOPTIMOBJ_H objcryst-2022.1/ObjCryst/RefinableObj/IO.cpp000066400000000000000000000335061430515525000205420ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * source file for generic XMLInput/XMLOutput in * */ #include #include "ObjCryst/RefinableObj/RefinableObj.h" #include "ObjCryst/RefinableObj/IO.h" namespace ObjCryst { //////////////////////////////////////////////////////////////////////// // // XMLCrystTag // //////////////////////////////////////////////////////////////////////// XMLCrystTag::XMLCrystTag(): mIsEndTag(false),mIsEmptyTag(false) {} XMLCrystTag::XMLCrystTag(istream &is) { is >> *this; } XMLCrystTag::XMLCrystTag(const string &tagName, const bool isEndTag, const bool isEmptyTag): mName(tagName),mIsEndTag(isEndTag),mIsEmptyTag(isEmptyTag) {} XMLCrystTag::~XMLCrystTag(){} const string& XMLCrystTag::GetName()const{return mName;} const string& XMLCrystTag::GetClassName()const{static string str="XMLCrystTag";return str;} unsigned int XMLCrystTag::GetNbAttribute()const{return mvAttribute.size();} void XMLCrystTag::AddAttribute(const string &attName,const string &attValue) { VFN_DEBUG_ENTRY("XMLCrystTag::AddAttribute():"<GetName(),4) mvAttribute.push_back(make_pair(attName,attValue)); VFN_DEBUG_EXIT("XMLCrystTag::AddAttribute():"<GetName(),4) } void XMLCrystTag::GetAttribute(const int attNum,string &attName,string &attValue) { attName=mvAttribute[attNum].first; attValue=mvAttribute[attNum].second; } const string& XMLCrystTag::GetAttributeName(const int attNum)const {return mvAttribute[attNum].first;} const string& XMLCrystTag::GetAttributeValue(const int attNum)const {return mvAttribute[attNum].second;} void XMLCrystTag::SetIsEndTag(const bool isEndTag){mIsEndTag=isEndTag;} bool XMLCrystTag::IsEndTag()const{return mIsEndTag;} void XMLCrystTag::SetIsEmptyTag(const bool isEmptyTag){mIsEmptyTag=isEmptyTag;} bool XMLCrystTag::IsEmptyTag()const{return mIsEmptyTag;} void XMLCrystTag::Print()const{cout<<*this;} #ifdef __WX__CRYST__ WXCrystObj* XMLCrystTag::WXCreate(wxWindow *parent) { //:TODO: //mpWXXMLCrystTag=new WXXMLCrystTag (parent,this); return mpWXXMLCrystTag; } WXCrystObj* XMLCrystTag::WXGet() { return mpWXXMLCrystTag; } void XMLCrystTag::WXDelete() { if(0!=mpWXXMLCrystTag) delete mpWXXMLCrystTag; mpWXXMLCrystTag=0; } void XMLCrystTag::WXNotifyDelete() { mpWXXMLCrystTag=0; } #endif ostream& operator<< (ostream& os, const XMLCrystTag&tag) { if(true==tag.mIsEndTag) { os <<""; return os; } os <<"<"<"; else os <<">"; return os; } istream& operator>> (istream& is, XMLCrystTag &tag) { ios::fmtflags f=is.flags(); is.unsetf(ios::skipws);//skip whitespaces tag.mIsEmptyTag=false; tag.mIsEndTag=false; char tmp; is>>tmp; while ((tmp!='<') && !(is.eof()) && !(is.fail()) )is>>tmp; if(is.eof()) return is; if(is.fail()) {cout<<"throw:"<<__FILE__<<":"<<__LINE__<<":"<> failed input");} while ((tmp==' ')||(tmp=='<'))is>>tmp; if('/'==tmp) { tag.mIsEndTag=true; while ((tmp==' ')||(tmp=='/'))is>>tmp; } string str=""; do { str+=tmp; is>>tmp; VFN_DEBUG_MESSAGE(str,1); if(is.fail()) {cout<<"throw:"<<__FILE__<<":"<<__LINE__<<":"<> failed input");} } while ((tmp!=' ')&&(tmp!='>')&&(tmp!='/')); tag.mName=str; string str2; while(true) { while(tmp==' ')is>>tmp; if(tmp=='>') { is.setf(f); return is; } if(tmp=='/') { is>>tmp; //if(tmp!='>') ; :TODO: tag.mIsEmptyTag=true; is.setf(f); return is; } str=""; do {str+=tmp;is>>tmp;VFN_DEBUG_MESSAGE(str,1)} while ((tmp!=' ')&&(tmp!='=')); while(tmp!='"')is>>tmp; str2=""; is>>tmp; if(tmp!='"') do {str2+=tmp;is>>tmp;VFN_DEBUG_MESSAGE(str2,1)} while (tmp!='"'); is>>tmp; tag.AddAttribute(str,str2); } is.setf(f); return is; } //////////////////////////////////////////////////////////////////////// // // I/O RefinablePar // //////////////////////////////////////////////////////////////////////// void RefinablePar::XMLOutput(ostream &os,const string &name,int indent)const { VFN_DEBUG_ENTRY("RefinablePar::XMLOutput():"<GetName(),5) XMLCrystTag tag("Par"); { stringstream ss; ss <IsFixed()); tag.AddAttribute("Refined",ss.str()); } { stringstream ss; ss <IsLimited(); tag.AddAttribute("Limited",ss.str()); } { stringstream ss; ss <GetHumanMin(); tag.AddAttribute("Min",ss.str()); } { stringstream ss; ss <GetHumanMax(); tag.AddAttribute("Max",ss.str()); } #if 0 {//Useless. Periodicity cannot be changed for a given parameter stringstream ss; ss <IsPeriodic(); tag.AddAttribute("Periodic",ss.str()); } #endif //the name of the parameter is saved last to enhance readability of saved files tag.AddAttribute("Name",name); for(int i=0;iGetHumanValue()<GetName(),5) } void RefinablePar::XMLOutput(ostream &os,int indent)const { this->XMLOutput(os,mName,indent); } void RefinablePar::XMLInput(istream &is,const XMLCrystTag &tag) { VFN_DEBUG_ENTRY("RefinablePar::XMLInput():"<GetName(),5) for(unsigned int i=0;i>b; this->SetIsFixed(!b); continue; } if("Limited"==tag.GetAttributeName(i)) { bool b; stringstream ss(tag.GetAttributeValue(i)); ss.imbue(std::locale::classic()); ss >>b; this->SetIsLimited(b); continue; } if("Min"==tag.GetAttributeName(i)) { REAL f; stringstream ss(tag.GetAttributeValue(i)); ss.imbue(std::locale::classic()); ss >>f; this->SetHumanMin(f); continue; } if("Max"==tag.GetAttributeName(i)) { REAL f; stringstream ss(tag.GetAttributeValue(i)); ss.imbue(std::locale::classic()); ss >>f; this->SetHumanMax(f); continue; } if("Periodic"==tag.GetAttributeName(i)) { bool b; stringstream ss(tag.GetAttributeValue(i)); ss.imbue(std::locale::classic()); ss >>b; this->SetIsPeriodic(b); continue; } } VFN_DEBUG_MESSAGE(tag, 10) REAL f=InputFloat(is,'<'); if(ISNAN_OR_INF(f)) f=1.0; this->SetHumanValue(f); XMLCrystTag junk(is);//read end tag VFN_DEBUG_MESSAGE(tag, 10) VFN_DEBUG_EXIT("RefinablePar::XMLInput():"<GetName(),5) } //////////////////////////////////////////////////////////////////////// // // I/O RefObjOpt // //////////////////////////////////////////////////////////////////////// void RefObjOpt::XMLOutput(ostream &os,int indent)const { VFN_DEBUG_ENTRY("RefObjOpt::XMLOutput():"<GetName(),5) XMLCrystTag tag("Option",false,true); tag.AddAttribute("Name",this->GetName()); { stringstream ss; ss <GetChoice(); tag.AddAttribute("Choice",ss.str()); } tag.AddAttribute("ChoiceName",this->GetChoiceName(this->GetChoice())); for(int i=0;iGetName(),5) } void RefObjOpt::XMLInput(istream &is,const XMLCrystTag &tag) { VFN_DEBUG_ENTRY("RefObjOpt::XMLInput():"<GetName(),5) for(unsigned int i=0;i>b; this->SetChoice(b); continue; } } VFN_DEBUG_EXIT("RefObjOpt::XMLInput():"<GetName(),5) } //////////////////////////////////////////////////////////////////////// // // I/O RefinableObj // Does nothing ! Should be purely virtual... // //////////////////////////////////////////////////////////////////////// void RefinableObj::XMLOutput(ostream &os,int indent)const { VFN_DEBUG_MESSAGE("RefinableObj::XMLOutput():"<GetName(),5) } void RefinableObj::XMLInput(istream &is,const XMLCrystTag &tag) { VFN_DEBUG_MESSAGE("RefinableObj::XMLInput():"<GetName(),5) } #if 0 void RefinableObj::XMLInputOld(istream &is,const IOCrystTag &tag) { VFN_DEBUG_MESSAGE("RefinableObj::XMLInput():"<GetName(),5) } #endif //////////////////////////////////////////////////////////////////////// // // OLD Functions & objects // //////////////////////////////////////////////////////////////////////// #if 0 void IOCrystExtractNameSpace(istream &is,string &str) { ios::fmtflags f=is.flags(); is.unsetf(ios::skipws);//skip whitespaces char tmp; do {is>>tmp;} while (tmp==' '); str=""; do {str+=tmp;is>>tmp;VFN_DEBUG_MESSAGE(str,1)} while ((tmp!=' ')&&(tmp!='>')); if(tmp=='>') is.putback(tmp); is.setf(f); } void IOCrystExtractNameLine(istream &is,string &str) { ios::fmtflags f=is.flags(); is.setf(ios::skipws);//skip leading whitespaces getline(is,str); is.setf(f); } void IOCrystExtractNameQuoted(istream &is,string &str) { char tmp; do {is>>tmp;} while ((tmp!='\'')&&(tmp!='\"')); str=""; is>>tmp; if((tmp=='\'')||(tmp=='\"')) return; ios::fmtflags f=is.flags(); is.unsetf(ios::skipws);//do not skip whitespaces do {str+=tmp;is>>tmp;VFN_DEBUG_MESSAGE(str,1)} while ((tmp!='\'')&&(tmp!='\"')); is.setf(f); } void IOCrystXMLOutputNameQuoted(ostream &os,const string &str) { os << '\"' << str << '\"'; } //////////////////////////////////////////////////////////////////////// // // IOCrystTag // //////////////////////////////////////////////////////////////////////// IOCrystTag::IOCrystTag(const string& type,const string& name, const unsigned long version): mTagType(type),mTagName(name),mTagVersion(version),mIsClosingTag(false) {} IOCrystTag::IOCrystTag(istream &is) { VFN_DEBUG_MESSAGE("IOCrystTag::IOCrystTag(istream &is)",2) char tmp; do { is>>tmp; if(true==is.eof()) { mTagVersion=0;//closing tag mTagName=""; mTagType=""; mIsClosingTag=true; return; } } while (tmp!='<'); IOCrystExtractNameSpace(is,mTagType); VFN_DEBUG_MESSAGE("IOCrystTag::IOCrystTag(istream &is):TagType:"<> mTagVersion; mIsClosingTag=false; } do {is>>tmp;} while (tmp!='>'); VFN_DEBUG_MESSAGE("IOCrystTag::IOCrystTag(istream &is):End",2) } IOCrystTag::~IOCrystTag(){} bool IOCrystTag::operator==(const IOCrystTag& rhs)const { if( (rhs.GetType()==this->GetType()) && (rhs.GetName()==this->GetName())) return true; return false; } void IOCrystTag::XMLInput(istream &is) { VFN_DEBUG_MESSAGE("IOCrystTag::XMLInput(istream &is)",2) char tmp; do {is>>tmp;} while ((tmp!='<') && (!is.eof()) ); if(is.eof()) return; IOCrystExtractNameSpace(is,mTagType); VFN_DEBUG_MESSAGE("IOCrystTag::XMLInput(istream &is):TagType:"<> mTagVersion; mIsClosingTag=false; } do {is>>tmp;} while (tmp!='>'); VFN_DEBUG_MESSAGE("IOCrystTag::XMLInput(istream &is):End",2) } const string &IOCrystTag::GetType() const{return mTagType;} const string &IOCrystTag::GetName() const{return mTagName;} unsigned long IOCrystTag::GetVersion()const{return mTagVersion;} bool IOCrystTag::IsClosingTag()const{return mIsClosingTag;} void IOCrystTag::Print() const { if(mIsClosingTag==true) cout <<"<"<"<"< #include #include using namespace std; #include "ObjCryst/ObjCryst/General.h" namespace ObjCryst { class XMLCrystTag; } #ifdef __WX__CRYST__ #include "ObjCryst/wxCryst/wxCryst.h" #endif namespace ObjCryst { /** Safely read a floating-point value from a stream. * * \param endchar: the character ending the input. On return, the stream will be placed * at this character (i.e. it will be the next to be read). Note that the input will * stop when encoutering a space character, even if the endchar has not been found. * \return: the value - NaN will be returned as NaN, but probably only if the value * was written on the same platform */ float InputFloat(istream &is, const char endchar=' '); /// Test if the value is a NaN bool ISNAN_OR_INF(REAL r); #ifdef __WX__CRYST__ /** \brief wxWindows representation of a XMLCrystTag (not implemented yet !) * * This will be used to choose objects to import from a save file. */ class WXXMLCrystTag: public WXCrystObj { public: WXXMLCrystTag(wxWindow *parent, XMLCrystTag*); virtual void CrystUpdate(); virtual void SetObjName(const string&); virtual string GetObjName()const; virtual bool Show(const bool); private: XMLCrystTag* mpTag; }; #endif /** \brief class to input or output a well-formatted xml beginning or ending tag. * */ class XMLCrystTag { public: XMLCrystTag(); XMLCrystTag(istream &is); XMLCrystTag(const string &tagName,const bool isEndTag=false, const bool isEmptyTag=false); ~XMLCrystTag(); const string& GetName()const; const string& GetClassName()const; unsigned int GetNbAttribute()const; void AddAttribute(const string &attName,const string &attValue); void GetAttribute(const int attNum,string &attName,string &attValue); const string& GetAttributeName(const int attNum)const; const string& GetAttributeValue(const int attNum)const; void SetIsEndTag(const bool isEndTag); bool IsEndTag()const; void SetIsEmptyTag(const bool isEmptyTag); bool IsEmptyTag()const; void Print()const; private: string mName; bool mIsEndTag; bool mIsEmptyTag; vector > mvAttribute; friend ostream& operator<< (ostream&, const XMLCrystTag&); friend istream& operator>> (istream&, XMLCrystTag&); #ifdef __WX__CRYST__ public: /// Create a WXCrystObj for this object. (not implemented yet) WXCrystObj* WXCreate(wxWindow*); WXCrystObj* WXGet(); void WXDelete(); void WXNotifyDelete(); protected: WXXMLCrystTag *mpWXXMLCrystTag; #endif }; /// Output an XMLCrystTag to a stream ostream& operator<< (ostream&, const XMLCrystTag&); /// Input an XMLCrystTag from a stream istream& operator>> (istream&, XMLCrystTag&); #if 0 //OLD void IOCrystExtractNameSpace(istream &is,string &str); void IOCrystExtractNameLine(istream &is,string &str); void IOCrystExtractNameQuoted(istream &is,string &str); void IOCrystXMLOutputNameQuoted(ostream &os,const string &str); #ifdef __WX__CRYST__ class IOCrystTag; class WXIOCrystTag: public WXCrystObj { public: WXIOCrystTag(wxWindow *parent, IOCrystTag*); virtual void CrystUpdate(); virtual void SetObjName(const string&); virtual string GetObjName()const; virtual bool Show(const bool); private: IOCrystTag* mpTag; }; #endif /// OLD /// \internal Tag used to delimitate objects (example: "") /// This includes the name of the corresponding ObjCryst class, as well /// as a version number for the description. class IOCrystTag { public: IOCrystTag(const string& type,const string& name, const unsigned long version=0); IOCrystTag(istream &is); virtual ~IOCrystTag(); void XMLInput(istream &is); bool operator==(const IOCrystTag&)const; const string &GetType()const; const string &GetName()const; unsigned long GetVersion()const; bool IsClosingTag()const; void Print()const; /// This is the same as GetType(), but allows using a registry const string &GetClassName()const; private: string mTagType; string mTagName; unsigned long mTagVersion; bool mIsClosingTag; #ifdef __WX__CRYST__ public: /// Create a WXCrystObj for this object. virtual WXCrystObj* WXCreate(wxWindow*); WXCrystObj* WXGet(); void WXDelete(); void WXNotifyDelete(); protected: WXIOCrystTag *mpWXIOCrystTag; #endif }; #endif }//namespace ObjCryst #endif //_REFOBJ_IO_H_ objcryst-2022.1/ObjCryst/RefinableObj/LSQNumObj.cpp000066400000000000000000001150411430515525000220000ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ObjCryst/Quirks/VFNStreamFormat.h" #include "ObjCryst/RefinableObj/LSQNumObj.h" #ifdef __WX__CRYST__ #include "ObjCryst/wxCryst/wxLSQ.h" #endif #include "newmat/newmatap.h" //for SVD decomposition #include "newmat/newmatio.h" #ifdef use_namespace using namespace NEWMAT; #endif using namespace std; #include #define POSSIBLY_UNUSED(expr) (void)(expr) namespace ObjCryst { LSQNumObj::LSQNumObj(string objName) #ifdef __WX__CRYST__ :mpWXCrystObj(0) #endif { mDampingFactor=1.; mSaveReportOnEachCycle=false; mName=objName; mSaveFileName="LSQrefinement.save"; mR=0; mRw=0; mChiSq=0; mStopAfterCycle=false; } LSQNumObj::~LSQNumObj() { #ifdef __WX__CRYST__ this->WXDelete(); #endif } void LSQNumObj::SetParIsFixed(const string& parName,const bool fix) { if(mRefParList.GetNbPar()==0) this->PrepareRefParList(); mRefParList.SetParIsFixed(parName,fix); } void LSQNumObj::SetParIsFixed(const RefParType *type,const bool fix) { if(mRefParList.GetNbPar()==0) this->PrepareRefParList(); mRefParList.SetParIsFixed(type,fix); } void LSQNumObj::SetParIsFixed(RefinablePar &par,const bool fix) { if(mRefParList.GetNbPar()==0) this->PrepareRefParList(); mRefParList.GetPar(par.GetPointer()).SetIsFixed(fix); } void LSQNumObj::SetParIsFixed(RefinableObj &obj,const bool fix) { if(mRefParList.GetNbPar()==0) this->PrepareRefParList(); for(unsigned int i=0;iSetParIsFixed(obj.GetPar(i),fix); } void LSQNumObj::UnFixAllPar() { if(mRefParList.GetNbPar()==0) this->PrepareRefParList(); mRefParList.UnFixAllPar(); } void LSQNumObj::SetParIsUsed(const string& parName,const bool use) { if(mRefParList.GetNbPar()==0) this->PrepareRefParList(); mRefParList.SetParIsUsed(parName,use); } void LSQNumObj::SetParIsUsed(const RefParType *type,const bool use) { if(mRefParList.GetNbPar()==0) this->PrepareRefParList(); mRefParList.SetParIsUsed(type,use); } void LSQNumObj::Refine (int nbCycle,bool useLevenbergMarquardt, const bool silent, const bool callBeginEndOptimization, const float minChi2var) { TAU_PROFILE("LSQNumObj::Refine()","void ()",TAU_USER); TAU_PROFILE_TIMER(timer1,"LSQNumObj::Refine() 1 - Init","", TAU_FIELD); TAU_PROFILE_TIMER(timer2,"LSQNumObj::Refine() 2 - LSQ Deriv","", TAU_FIELD); TAU_PROFILE_TIMER(timer3,"LSQNumObj::Refine() 3 - LSQ MB","", TAU_FIELD); TAU_PROFILE_TIMER(timer4,"LSQNumObj::Refine() 4 - LSQ Singular Values","", TAU_FIELD); TAU_PROFILE_TIMER(timer5,"LSQNumObj::Refine() 5 - LSQ Newmat, eigenvalues...","", TAU_FIELD); TAU_PROFILE_TIMER(timer6,"LSQNumObj::Refine() 6 - LSQ Apply","", TAU_FIELD); TAU_PROFILE_TIMER(timer7,"LSQNumObj::Refine() 7 - LSQ Finish","", TAU_FIELD); TAU_PROFILE_START(timer1); if(callBeginEndOptimization) this->BeginOptimization(); mObs=this->GetLSQObs(); mWeight=this->GetLSQWeight(); bool terminateOnDeltaChi2=false; if(nbCycle<0) { nbCycle=-nbCycle; terminateOnDeltaChi2=true; } if(!silent) cout << "LSQNumObj::Refine():Beginning "<PrepareRefParList(); mRefParList.PrepareForRefinement(); //if(!silent) mRefParList.Print(); if(mRefParList.GetNbPar()==0) throw ObjCrystException("LSQNumObj::Refine():no parameter to refine !"); //variables long nbVar=mRefParList.GetNbParNotFixed(); const long nbObs=mObs.numElements(); CrystVector_REAL calc,calc0,calc1,tmpV1,tmpV2; CrystMatrix_REAL M(nbVar,nbVar); CrystMatrix_REAL N(nbVar,nbVar); CrystVector_REAL B(nbVar); CrystMatrix_REAL designMatrix(nbVar,nbObs); CrystVector_REAL deltaVar(nbVar); long i,j,k; REAL R_ini,Rw_ini; POSSIBLY_UNUSED(R_ini); REAL *pTmp1,*pTmp2; REAL marquardt=1e-2; const REAL marquardtMult=4.; //initial Chi^2, needed for Levenberg-Marquardt this->CalcChiSquare(); //store old values mIndexValuesSetInitial=mRefParList.CreateParamSet("LSQ Refinement-Initial Values"); mIndexValuesSetLast=mRefParList.CreateParamSet("LSQ Refinement-Last Cycle Values"); TAU_PROFILE_STOP(timer1); //refine for(int cycle=1 ; cycle <=nbCycle;cycle++) { TAU_PROFILE_START(timer2); const REAL ChisSqPreviousCycle=mChiSq; mRefParList.SaveParamSet(mIndexValuesSetLast);// end of last cycle if(!silent) cout << "LSQNumObj::Refine():Cycle#"<< cycle <GetLSQCalc(); //R tmpV1 = mObs; tmpV1 -= calc0; tmpV1 *= tmpV1; tmpV2 = mObs; tmpV2 *= mObs; R_ini=sqrt(tmpV1.sum()/tmpV2.sum()); //Rw tmpV1 *= mWeight; tmpV2 *= mWeight; Rw_ini=sqrt(tmpV1.sum()/tmpV2.sum()); //derivatives //designMatrix=0.; pTmp2=designMatrix.data(); //cout <<"obs:"<(calc0,10,8); //cout <<"calc:"<(mObs,10,8); //cout <<"weight:"<(mWeight,10,8); #if 1 for(i=0;iGetLSQDeriv(mRefParList.GetParNotFixed(i)); pTmp1=tmpV1.data(); //cout <<"deriv#"<(tmpV1,10,8); for(j=0;jGetLSQ_FullDeriv(); for(i=0;i=(nbVar-2)) cout<<__FILE__<<":"<<__LINE__<<":"<<(mRefParList.GetParNotFixed(i)).GetName()<<"size="<GetLSQDeriv(mRefParList.GetParNotFixed(i)); cout <<"deriv#"<(tmpV1,10,8); } } */ if(!silent) cout << "LSQNumObj::Refine(): Automatically fixing parameter"; if(!silent) cout << " and re-start cycle.."; if(!silent) cout << endl; mRefParList.GetParNotFixed(i).SetIsFixed(true); mRefParList.PrepareForRefinement(); nbVar=mRefParList.GetNbParNotFixed(); if(nbVar<=1) { mRefParList.RestoreParamSet(mIndexValuesSetInitial); if(callBeginEndOptimization) this->EndOptimization(); if(!silent) mRefParList.Print(); throw ObjCrystException("LSQNumObj::Refine(): not enough (1) parameters after fixing one..."); } N.resize(nbVar,nbVar); deltaVar.resize(nbVar); //Just remove the ith line in the design matrix REAL *p1=designMatrix.data(); const REAL *p2=designMatrix.data(); p1 += i*nbObs; p2 += i*nbObs+nbObs; for(long j=i*nbObs+nbObs;j=i) && (j minAllowedValue) newmatInvW(i+1,i+1) = 1./newmatW(i+1,i+1); else { cout << "LSQNumObj::Refine():SVD: fixing singular value "<< i < minAllowedValue) newmatInvW(i+1,i+1)= 1./newmatW(i+1,i+1); else { if(!silent) cout << "LSQNumObj::Refine():fixing ill-cond EigenValue "<< i < max ) { max = fabs(newmatW(j+1)*newmatV(j+1,i+1)*newmatV(j+1,i+1)); maxIndex=j; } cout << FormatFloat(newmatW(i+1,i+1),36,2) << " " ; cout << FormatFloat(max,36,2); cout << FormatFloat(newmatW(maxIndex+1,maxIndex+1),36,2) << " " ; cout << FormatFloat(newmatV(i+1,maxIndex+1)*100,8,2) ; //cout << endl; if(newmatW(i+1,i+1) > (max*minRatio)) { newmatInvW(i+1,i+1) = 1./newmatW(i+1,i+1); cout << endl; } else { cout << "LSQNumObj::Refine():fixing ill-cond EigenValue "<< i < minAllowedValue) newmatInvW(i+1,i+1) = 1./newmatW(i+1,i+1); else { cout << "LSQNumObj::Refine():SVD: fixing ill-cond value "<< i <GetLSQCalc(); //Chi^2 { REAL oldChiSq=mChiSq; tmpV1 = mObs; tmpV1 -= calc; tmpV1 *= tmpV1; tmpV1 *= mWeight; mChiSq=tmpV1.sum(); if(true==useLevenbergMarquardt) { if(mChiSq > (oldChiSq*1.0001)) { mRefParList.RestoreParamSet(mIndexValuesSetLast); increaseMarquardt=true; if(!silent) { cout << "LSQNumObj::Refine(Chi^2="<"<Increasing Levenberg-Marquardt factor :" << FormatFloat(marquardt*marquardtMult,18,14) <1e4) { // :TODO: Revert to previous parameters. Or initial ? mRefParList.RestoreParamSet(mIndexValuesSetLast); if(callBeginEndOptimization) this->EndOptimization(); //if(!silent) mRefParList.Print(); return; //throw ObjCrystException("LSQNumObj::Refine():Levenberg-Marquardt diverging !"); } TAU_PROFILE_STOP(timer6); goto LSQNumObj_Refine_RestartMarquardt; } else { if(!silent && (marquardt>1e-2)) { cout << "LSQNumObj::Refine(Chi^2="<"<Decreasing Levenberg-Marquardt factor :" << FormatFloat(marquardt/marquardtMult,18,14) <"<"<WriteReportToFile(); if(!silent) this->PrintRefResults(); TAU_PROFILE_STOP(timer7); if( terminateOnDeltaChi2 && (minChi2var>( (ChisSqPreviousCycle-mChiSq)/abs(ChisSqPreviousCycle+1e-6) ) ) ) break; } if(callBeginEndOptimization) this->EndOptimization(); } bool LSQNumObj::SafeRefine(std::list vnewpar, std::list vnewpartype, REAL maxChi2factor, int nbCycle, bool useLevenbergMarquardt, const bool silent, const bool callBeginEndOptimization, const float minChi2var) { if(callBeginEndOptimization) this->BeginOptimization(); // :TODO: update mObs and mWeight in a centralized way... Not in BeginOptimization() (not always called) mObs=this->GetLSQObs(); mWeight=this->GetLSQWeight(); //Prepare for refinement (get non-fixed parameters) if(mRefParList.GetNbPar()==0) this->PrepareRefParList(); mRefParList.PrepareForRefinement(); if(mRefParList.GetNbPar()==0) throw ObjCrystException("LSQNumObj::SafeRefine():no parameter to refine !"); this->CalcChiSquare(); const REAL chi2_0 = mChiSq; for(std::list::iterator pos=vnewpar.begin(); pos!=vnewpar.end(); pos++) { this->SetParIsFixed(**pos, false); } for(std::list::iterator pos=vnewpartype.begin(); pos!=vnewpartype.end(); pos++) { this->SetParIsFixed(*pos, false); } bool diverged = false; try { this->Refine(nbCycle, useLevenbergMarquardt, silent, false, minChi2var); } catch(const ObjCrystException &except) { diverged = true; if(!silent) cout << "Refinement did not converge !"; } const REAL deltachi2 = (mChiSq-chi2_0)/(chi2_0+1e-6); if(callBeginEndOptimization) this->EndOptimization(); if(deltachi2>maxChi2factor) { if(!silent) cout << "Refinement did not converge ! Chi2 increase("<"<::iterator pos=vnewpar.begin(); pos!=vnewpar.end(); pos++) { this->SetParIsFixed(**pos, true); } for(std::list::iterator pos=vnewpartype.begin(); pos!=vnewpartype.end(); pos++) { this->SetParIsFixed(*pos, true); } this->CalcRfactor(); this->CalcRwFactor(); this->CalcChiSquare(); if(!silent) cout <<"=> REVERTING to initial parameters values and fixing new parameters"<GetLSQCalc(); tmpV1 = this->GetLSQObs(); tmpV1 -= calc; tmpV1 *= tmpV1; tmpV2 = this->GetLSQObs(); tmpV2 *= tmpV2; mR=sqrt(tmpV1.sum()/tmpV2.sum()); } REAL LSQNumObj::Rfactor()const{return mR;}; void LSQNumObj::CalcRwFactor()const { CrystVector_REAL calc, tmpV1, tmpV2; calc=this->GetLSQCalc(); tmpV1 = this->GetLSQObs(); tmpV1 -= calc; tmpV1 *= tmpV1; tmpV2 = this->GetLSQObs(); tmpV2 *= tmpV2; tmpV1 *= mWeight; tmpV2 *= mWeight; mRw=sqrt(tmpV1.sum()/tmpV2.sum()); } REAL LSQNumObj::RwFactor()const{return mRw;}; void LSQNumObj::CalcChiSquare()const { CrystVector_REAL calc, tmpV1; calc=this->GetLSQCalc(); tmpV1 = mObs; tmpV1 -= calc; tmpV1 *= tmpV1; tmpV1 *= mWeight; mChiSq=tmpV1.sum(); } REAL LSQNumObj::ChiSquare()const{return mChiSq;}; void RecursiveMapFunc(RefinableObj &obj,map &themap, const unsigned int value) { themap[&obj]=value; ObjRegistry *pObjReg=&(obj.GetSubObjRegistry()); for(int i=0;iGetNb();i++) RecursiveMapFunc(pObjReg->GetObj(i),themap,value); return; } void LSQNumObj::SetRefinedObj(RefinableObj &obj, const unsigned int LSQFuncIndex, const bool init, const bool recursive) { if(init) { mvRefinedObjMap.clear(); } if(recursive) RecursiveMapFunc(obj,mvRefinedObjMap,LSQFuncIndex); else mvRefinedObjMap[&obj]=LSQFuncIndex; } //ObjRegistry &LSQNumObj::GetRefinedObjList(){return mRecursiveRefinedObjList;} const map& LSQNumObj::GetRefinedObjMap() const { return mvRefinedObjMap; } map& LSQNumObj::GetRefinedObjMap() { return mvRefinedObjMap; } RefinableObj& LSQNumObj::GetCompiledRefinedObj(){return mRefParList;} const RefinableObj& LSQNumObj::GetCompiledRefinedObj()const{return mRefParList;} void LSQNumObj::SetUseSaveFileOnEachCycle(bool yesOrNo) { mSaveReportOnEachCycle=yesOrNo; } void LSQNumObj::SetSaveFile(string fileName) { mSaveFileName=fileName; } void LSQNumObj::PrintRefResults() const { //:TODO: //this->PrepareRefParList(); activate this when PrepareRefParList() will be more savy cout << "Results after last refinement :(" ; cout << mRefParList.GetNbParNotFixed()<< " non-fixed parameters)"<GetLSQWeight().numElements()<,REAL > & LSQNumObj::GetVarianceCovarianceMap()const { return mvVarCovar;} void LSQNumObj::PrepareRefParList(const bool copy_param) { mRefParList.ResetParList(); for(map::iterator pos=mvRefinedObjMap.begin();pos!=mvRefinedObjMap.end();++pos) { VFN_DEBUG_MESSAGE("LSQNumObj::PrepareRefParList():"<first->GetName(),4); //mRecursiveRefinedObjList.GetObj(i).Print(); mRefParList.AddPar(*(pos->first),copy_param); } //mRefParList.Print(); if(copy_param) mRefParList.SetDeleteRefParInDestructor(true); else mRefParList.SetDeleteRefParInDestructor(false); } const CrystVector_REAL& LSQNumObj::GetLSQCalc() const { const CrystVector_REAL *pV; long nb=0; for(map::const_iterator pos=mvRefinedObjMap.begin();pos!=mvRefinedObjMap.end();++pos) { if(pos->first->GetNbLSQFunction()==0) continue; pV=&(pos->first->GetLSQCalc(pos->second)); const long n2 = pV->numElements(); if((nb+n2)>mLSQCalc.numElements()) mLSQCalc.resizeAndPreserve(nb+pV->numElements()); const REAL *p1=pV->data(); REAL *p2=mLSQCalc.data()+nb; for(long j = 0; j < n2; ++j) *p2++ = *p1++; nb+=n2; } if(mLSQCalc.numElements()>nb) mLSQCalc.resizeAndPreserve(nb); return mLSQCalc; } const CrystVector_REAL& LSQNumObj::GetLSQObs() const { const CrystVector_REAL *pV; long nb=0; for(map::const_iterator pos=mvRefinedObjMap.begin();pos!=mvRefinedObjMap.end();++pos) { if(pos->first->GetNbLSQFunction()==0) continue; pV=&(pos->first->GetLSQObs(pos->second)); const long n2 = pV->numElements(); mvRefinedObjLSQSize[pos->first]=n2; if((nb+n2)>mLSQObs.numElements()) mLSQObs.resizeAndPreserve(nb+pV->numElements()); const REAL *p1=pV->data(); REAL *p2=mLSQObs.data()+nb; for(long j = 0; j < n2; ++j) *p2++ = *p1++; nb+=n2; } if(mLSQObs.numElements()>nb) mLSQObs.resizeAndPreserve(nb); return mLSQObs; } const CrystVector_REAL& LSQNumObj::GetLSQWeight() const { const CrystVector_REAL *pV; long nb=0; for(map::const_iterator pos=mvRefinedObjMap.begin();pos!=mvRefinedObjMap.end();++pos) { if(pos->first->GetNbLSQFunction()==0) continue; pV=&(pos->first->GetLSQWeight(pos->second)); const long n2 = pV->numElements(); if((nb+n2)>mLSQWeight.numElements()) mLSQWeight.resizeAndPreserve(nb+pV->numElements()); const REAL *p1=pV->data(); REAL *p2=mLSQWeight.data()+nb; for(long j = 0; j < n2; ++j) *p2++ = *p1++; nb+=n2; } if(mLSQWeight.numElements()>nb) mLSQWeight.resizeAndPreserve(nb); return mLSQWeight; } const CrystVector_REAL& LSQNumObj::GetLSQDeriv(RefinablePar&par) { const CrystVector_REAL *pV; long nb=0; for(map::iterator pos=mvRefinedObjMap.begin();pos!=mvRefinedObjMap.end();++pos) { if(pos->first->GetNbLSQFunction()==0) continue; pV=&(pos->first->GetLSQDeriv(pos->second,par)); const long n2 = pV->numElements(); if((nb+n2)>mLSQDeriv.numElements()) mLSQDeriv.resizeAndPreserve(nb+pV->numElements()); const REAL *p1=pV->data(); REAL *p2=mLSQDeriv.data()+nb; for(long j = 0; j < n2; ++j) *p2++ = *p1++; nb+=n2; } if(mLSQDeriv.numElements()>nb) mLSQDeriv.resizeAndPreserve(nb); return mLSQDeriv; } const std::map& LSQNumObj::GetLSQ_FullDeriv() { long nbVar=mRefParList.GetNbParNotFixed(); std::set vPar; for(unsigned int i=0;i::iterator pos=mvRefinedObjMap.begin();pos!=mvRefinedObjMap.end();++pos) { if(pos->first->GetNbLSQFunction()==0) continue; const unsigned long n2=mvRefinedObjLSQSize[pos->first]; if(n2==0) continue;//this object does not have an LSQ function const std::map *pvV=&(pos->first->GetLSQ_FullDeriv(pos->second,vPar)); for(std::map::const_iterator d=pvV->begin();d!=pvV->end();d++) { if(mLSQ_FullDeriv[d->first].size()==0) mLSQ_FullDeriv[d->first].resize(mLSQObs.size()); REAL *p2=mLSQ_FullDeriv[d->first].data()+nb; if(d->second.size()==0) { //derivative can be null and then the vector missing // But we must still fill in zeros cout<<__FILE__<<":"<<__LINE__<<":"<first->GetClassName()<<":"<first->GetName()<<":"<first->GetName()<<" (all deriv=0)"<second.data(); for(unsigned long j=0;j::iterator pos=mvRefinedObjMap.begin();pos!=mvRefinedObjMap.end();++pos) pos->first->BeginOptimization(allowApproximations, enableRestraints); } void LSQNumObj::EndOptimization() { for(map::iterator pos=mvRefinedObjMap.begin();pos!=mvRefinedObjMap.end();++pos) pos->first->EndOptimization(); } #ifdef __WX__CRYST__ WXCrystObjBasic* LSQNumObj::WXCreate(wxWindow* parent) { this->WXDelete(); mpWXCrystObj=new WXLSQ(parent,this); return mpWXCrystObj; } WXCrystObjBasic* LSQNumObj::WXGet() { return mpWXCrystObj; } void LSQNumObj::WXDelete() { if(0!=mpWXCrystObj) { VFN_DEBUG_MESSAGE("LSQNumObj::WXDelete()",5) delete mpWXCrystObj; } mpWXCrystObj=0; } void LSQNumObj::WXNotifyDelete() { VFN_DEBUG_MESSAGE("LSQNumObj::WXNotifyDelete():"< #include #include namespace ObjCryst { /** \brief (Quick & dirty) Least-Squares Refinement Object with Numerical derivatives * * This is still highly experimental ! */ class LSQNumObj { public: LSQNumObj(std::string objName="Unnamed LSQ object"); ~LSQNumObj(); /// Fix one parameter. /// /// LSQNumObj::PrepareRefParList() must be called first! void SetParIsFixed(const std::string& parName,const bool fix); /// Fix one family of parameters /// /// LSQNumObj::PrepareRefParList() must be called first! void SetParIsFixed(const RefParType *type,const bool fix); /** Fix one parameter * * Note that this will fix the copied parameter, not the one * in the original object. The supplied RefinablePar * may be either the copied one or the original. * * LSQNumObj::PrepareRefParList() must be called first! **/ void SetParIsFixed(RefinablePar &par,const bool fix); /** Fix all parameters within an object * * Note that this will fix the copied parameters, not the one * in the original objects. * * LSQNumObj::PrepareRefParList() must be called first! **/ void SetParIsFixed(RefinableObj &obj,const bool fix); /// UnFix All parameters /// /// LSQNumObj::PrepareRefParList() must be called first! void UnFixAllPar(); /// Set a parameter to be used /// /// LSQNumObj::PrepareRefParList() must be called first! void SetParIsUsed(const std::string& parName,const bool use); /// Set a family of parameters to be used /// /// LSQNumObj::PrepareRefParList() must be called first! void SetParIsUsed(const RefParType *type,const bool use); /** Do the refinement * * \param nbCycle: number of LSQ cycles - if negative, the algorithm will continue * until it reaches (-nbcycle) or until the relative variation in Chi2 is less * than minChi2var * \param useLevenbergMarquardt: enable Levenberg-Marquardt algorithm * to ensure that a decrease of Chi^2 will be obtained (actually a 1% * increase is allowed) * \param callBeginEndOptimization: if true, will call RefinableObj::BeginOptimization(true,...) * and RefinableObj::EndOptimization(). You may not want this if the LSQ is done during another * (e.g. monte-carlo) optimization - but then the calling function \b must ensure * that approximations are disabled (using RefinableObj::SetApproximationFlag) * for objects where that would render derivative calculations imprecise. * \param minChi2var: used for termination of the refinement if the relative variation * of Chi2 between two successive cyles is less than minChi2var */ void Refine (int nbCycle=1,bool useLevenbergMarquardt=false, const bool silent=false, const bool callBeginEndOptimization=true, const float minChi2var=0.01); /** Run a refinement in a 'safe' way: if the Chi2 value increases by more that a given factor * the parameters are reverted to their initial values. Moreover, the listed 'new' parameters * or parameter types are then fixed. * \param vnewpar: list of parameters added for this optimization, which will be unfixed at the * beginning, and will be fixed at the end if Chi2 increases. This can be empty. * \param vnewpartype: list of parameter types, which will be unfixed at the * beginning, and will be fixed at the end if Chi2 increases. This can be empty. * \param maxChi2factor: if Chi2_end> maxChi2factor * Chi2_begin, parameters are reverted to their * initial value, and new parameters are fixed. * All the other parameters are the same as in LSQNumObj::Refine. * \return: true if the minimization was succesful, false otherwise. */ bool SafeRefine(std::list vnewpar, std::list vnewpartype, REAL maxChi2factor=1.01, int nbCycle=1, bool useLevenbergMarquardt=false, const bool silent=false, const bool callBeginEndOptimization=true, const float minChi2var=0.01); CrystVector_REAL Sigma()const; CrystMatrix_REAL CorrelMatrix()const; void CalcRfactor()const; REAL Rfactor()const; void CalcRwFactor()const; REAL RwFactor()const; void CalcChiSquare() const; REAL ChiSquare()const; //uses the weight if specified /** Choose the object to refine. The minimization will be done * against its LSQ function and its parameters, as well as the LSQ functions * and parameters of its sub-objects (if recursive==true) * * \param LSQFuncIndex: one object can have a choice of several LSQ * functions to minimize- this allows to choose which one to minimize. * * \param init: if true, the list of refined objects is first cleared. otherwise * the new object (and its sub-objects) is just added to the list. * * \param recursive: if false, only the supplied object is added, and not its sub-objects */ void SetRefinedObj(RefinableObj &obj, const unsigned int LSQFuncIndex=0, const bool init=true, const bool recursive=false); // Access to the full list of refined objects. The list is initially built // recursively from one object. This function allows to modify the list // of sub-objects before refinement (such as for removing certain types // of objects). //ObjRegistry &GetRefinedObjList(); /** Get the map of refined objects - this is a recursive list of all the objects * that are taken into account for the refinement. The key is a pointer to the * object and the value is the LSQ function index for that object. */ const std::map& GetRefinedObjMap() const; /** Get the map of refined objects - this is a recursive list of all the objects * that are taken into account for the refinement. The key is a pointer to the * object and the value is the LSQ function index for that object. */ std::map& GetRefinedObjMap(); /** Access to the RefinableObj which is the compilation of all parameters * from the object supplied for optimization and its sub-objects. * * Since this compilation is only updated from the suplied refinableobj and * its sub-objects when SetRefinedObj() and PrepareRefParList() are called, * it is possible to alter the fixed/limited status of parameters * here without affecting the parameters in the refined objects. */ RefinableObj& GetCompiledRefinedObj(); /** Access to the RefinableObj which is the compilation of all parameters * from the object supplied for optimization and its sub-objects. * * Since this compilation is only updated from the suplied refinableobj and * its sub-objects when SetRefinedObj() and PrepareRefParList() are called, * it is possible to alter the fixed/limited status of parameters * here without affecting the parameters in the refined objects. */ const RefinableObj& GetCompiledRefinedObj()const; void SetUseSaveFileOnEachCycle(bool yesOrNo=true); void SetSaveFile(std::string fileName="refine.save"); void PrintRefResults()const; void SetDampingFactor(const REAL newDampFact); void PurgeSaveFile(); void WriteReportToFile()const; void OptimizeDerivativeSteps(); const std::map,REAL > &GetVarianceCovarianceMap()const; /** Prepare the full parameter list for the refinement * \param copy_param: if false (the default), then the lsq algorithm will work directly * on the parameters of the refined object and sub-object. So that any modification * to the fixed/used/limited status applies permanently to the parameters. * if true, then the parameters are copied and therefore only the value of the * parameter is changed (and the clocks are ticked). * * \note: if copy_param==true, then any modification to the parameters (fixed, limited, used * status) only affects the copy and not the original. Also, calling again PrepareRefParList * cancels any such modification. * * \note This will be called automatically before starting the refinement only if * the parameter list is empty. Otherwise it should be called before refinement. */ void PrepareRefParList(const bool copy_param=false); /// Get the LSQ calc vector (using either only the top or the hierarchy of object) const CrystVector_REAL& GetLSQCalc() const; /// Get the LSQ obs vector (using either only the top or the hierarchy of object) const CrystVector_REAL& GetLSQObs() const; /// Get the LSQ weight vector (using either only the top or the hierarchy of object) const CrystVector_REAL& GetLSQWeight() const; /// Get the LSQ deriv vector (using either only the top or the hierarchy of object) const CrystVector_REAL& GetLSQDeriv(RefinablePar&par); const std::map& GetLSQ_FullDeriv(); /** Tell all refined object that the refinement is beginning */ void BeginOptimization(const bool allowApproximations=false, const bool enableRestraints=false); /** Tell all refined object that the refinement is finished */ void EndOptimization(); protected: private: // Refined object /// The recursive list of all refined sub-objects ObjRegistry mRecursiveRefinedObjList; /** The refinable par list used during refinement. It is only a compilation * of the parameters in RefinableObj and its sub-objects * * This list is only updated from the suplied refinableobj and * its sub-objects when SetRefinedObj() and PrepareRefParList() are called, * so it is possible to alter the fixed/limited status of parameters * here without affecting the parameters in the refined objects. */ mutable RefinableObj mRefParList; /// Damping factor for the refinement (unused yet...) REAL mDampingFactor; ///Save result to file after each cycle ? bool mSaveReportOnEachCycle; /// Name of the refined object std::string mName; /// File name where refinement info is saved std::string mSaveFileName; mutable REAL mR,mRw,mChiSq; /// Correlation matrix between all refined parameters. CrystMatrix_REAL mCorrelMatrix; ///Variance-Covariance matrix, as a std::map std::map,REAL > mvVarCovar; /// Observed values. CrystVector_REAL mObs; /// Weight corresponding to all observed values. CrystVector_REAL mWeight; /// Index of the set of saved values for all refinable parameters, before refinement /// and before the last cycle. int mIndexValuesSetInitial, mIndexValuesSetLast; /// If true, then stop at the end of the cycle. Used in multi-threading environment bool mStopAfterCycle; // The optimized object //RefinableObj *mpRefinedObj; // The index of the LSQ function in the refined object (if there are several...) //unsigned int mLSQFuncIndex; /** Map of the recursive list of the objects to be refined. The key is the pointer * to the object and the value the LSQ function index * * Individual LSQ functions can be changed using GetRefinedObjMap(). */ std::map mvRefinedObjMap; /// Size of each object LSQ data. This is initialized in LSQNumObj::GetLSQObs() mutable std::map mvRefinedObjLSQSize; /// If true, then parameters to be refined will be copied instead of referenced. /// Therefore only their values and the parameter's clocks are affected when /// working on the copy. bool mCopyRefPar; /// Temporary arrays for LSQ functions evaluation - used when /// using recursive LSQ function mutable CrystVector_REAL mLSQObs,mLSQCalc,mLSQWeight,mLSQDeriv; mutable std::map mLSQ_FullDeriv; #ifdef __WX__CRYST__ public: virtual WXCrystObjBasic* WXCreate(wxWindow* parent); WXCrystObjBasic* WXGet(); void WXDelete(); void WXNotifyDelete(); protected: WXCrystObjBasic *mpWXCrystObj; #endif }; }//namespace #endif //_LSQOBJNUM_H objcryst-2022.1/ObjCryst/RefinableObj/RefinableObj.cpp000066400000000000000000002035741430515525000225610ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * source file for the RefinablePar and RefinableObj classes * */ #include #include #include "ObjCryst/RefinableObj/RefinableObj.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" #include "ObjCryst/Quirks/VFNDebug.h" #ifdef __WX__CRYST__ #include "ObjCryst/wxCryst/wxRefinableObj.h" #undef GetClassName // Conflict from wxMSW headers ? (cygwin) #endif #include #define POSSIBLY_UNUSED(expr) (void)(expr) namespace ObjCryst { //###################################################################### // // RefParType // //###################################################################### RefParType::RefParType(const string &name): mpParent(0),mName(name),mId(0) { this->InitId(); } RefParType::RefParType(const RefParType *parent,const string &name): mpParent(parent),mName(name),mId(0) { this->InitId(); } RefParType::~RefParType(){}; bool RefParType::IsDescendantFromOrSameAs(const RefParType *type) const { VFN_DEBUG_MESSAGE("RefParType::IsDescendantFromOrSameAs(RefParType*): "<mId==mId) return true; if(0==mpParent) return false; return mpParent->IsDescendantFromOrSameAs(type); } bool RefParType::operator==(const RefParType *type) const { if(this==type) return true; return false; } const string& RefParType::GetName() const{ return mName;} void RefParType::InitId() { static unsigned long nbRefParType=0; mId=nbRefParType++; } const RefParType *gpRefParTypeObjCryst=0; long NiftyStaticGlobalObjectsInitializer_RefinableObj::mCount=0; //###################################################################### // // // //###################################################################### unsigned long RefinableObjClock::msTick0=0; unsigned long RefinableObjClock::msTick1=0; RefinableObjClock::RefinableObjClock() { //this->Click(); mTick0=0; mTick1=0; } RefinableObjClock::~RefinableObjClock() { // first copy & clear sets to avoid possible loops in RemoveChild() set vChild=mvChild; set vParent=mvParent; mvChild.clear(); mvParent.clear(); for(std::set::iterator pos=vChild.begin(); pos!=vChild.end();++pos) (*pos)->RemoveParent(*this); for(std::set::iterator pos=vParent.begin(); pos!=vParent.end();++pos) (*pos)->RemoveChild(*this); } bool RefinableObjClock::operator< (const RefinableObjClock &rhs)const { if(mTick1 (const RefinableObjClock &rhs)const { if(mTick1>rhs.mTick1) return true; if(mTick1==rhs.mTick1) if(mTick0>rhs.mTick0) return true; return false; } bool RefinableObjClock::operator>=(const RefinableObjClock &rhs)const { if(mTick1>rhs.mTick1) return true; if(mTick1==rhs.mTick1) if(mTick0>=rhs.mTick0) return true; return false; } void RefinableObjClock::Click() { //return; if(++msTick0==0) ++msTick1;//Update ObjCryst++ static event counter mTick0=msTick0; mTick1=msTick1; for(std::set::iterator pos=mvParent.begin(); pos!=mvParent.end();++pos) (*pos)->Click(); VFN_DEBUG_MESSAGE("RefinableObjClock::Click():"<Print(); } void RefinableObjClock::Reset() { mTick0=0; mTick1=0; } void RefinableObjClock::Print()const { cout <<"Clock():"<Click();} void RefinableObjClock::RemoveChild(const RefinableObjClock &clock) { const unsigned int i = mvChild.erase(&clock); POSSIBLY_UNUSED(i); VFN_DEBUG_MESSAGE("RefinableObjClock::RemoveChild():"<Click(); } void RefinableObjClock::AddParent(RefinableObjClock &clock)const { // First check for loop if(&clock==this) throw ObjCrystException("RefinableObjClock::AddParent(..) child == Parent !!"); if(clock.HasParent(*this)==true) throw ObjCrystException("RefinableObjClock::AddParent(..) Loop in clock tree !!"); mvParent.insert(&clock); } void RefinableObjClock::RemoveParent(RefinableObjClock &clock)const { // avoid warnings about unused i when not debugging. const unsigned int i = mvParent.erase(&clock); POSSIBLY_UNUSED(i); VFN_DEBUG_MESSAGE("RefinableObjClock::RemoveParent():"<::iterator pos=mvParent.begin(); pos!=mvParent.end();++pos) if( (*this) > (**pos) ) **pos = *this; } bool RefinableObjClock::HasParent(const RefinableObjClock &clock) const { for(std::set::iterator pos=mvParent.begin(); pos!=mvParent.end();++pos) { if((*pos)==&clock) return true; if((*pos)->HasParent(clock)) return true; } return false; } //###################################################################### // Restraint //###################################################################### Restraint::Restraint(): mpRefParType(gpRefParTypeObjCryst) {} Restraint::Restraint(const RefParType *type): mpRefParType(type) {} Restraint::~Restraint() {} const RefParType* Restraint::GetType()const{return mpRefParType;} void Restraint::SetType(const RefParType *type){mpRefParType=type;} REAL Restraint::GetLogLikelihood()const{return 0.;} //###################################################################### // RefinablePar //###################################################################### RefinablePar::RefinablePar(): Restraint(), mName(""),mpValue(0),mMin(0),mMax(0), mHasLimits(false),mIsFixed(true),mIsUsed(true),mIsPeriodic(false), mPeriod(0.),mGlobalOptimStep(1.),mDerivStep(1e-5),mRefParDerivStepModel(REFPAR_DERIV_STEP_ABSOLUTE), mSigma(0.),mHumanScale(1.),mHasAssignedClock(false),mpClock(0) #ifdef __WX__CRYST__ ,mpWXFieldRefPar(0) #endif {} RefinablePar::RefinablePar( const string &name, REAL *refPar, const REAL min, const REAL max, const RefParType *type, RefParDerivStepModel derivMode, const bool hasLimits, const bool isFixed, const bool isUsed, const bool isPeriodic, const REAL humanScale, REAL period): Restraint(type), mName(name),mpValue(refPar),mMin(min),mMax(max), mHasLimits(hasLimits),mIsFixed(isFixed),mIsUsed(isUsed),mIsPeriodic(isPeriodic),mPeriod(period), mGlobalOptimStep((max-min)/100.),mDerivStep(1e-5),mRefParDerivStepModel(derivMode), mSigma(0.),mHumanScale(humanScale), #if 0 mUseEquation(false),mEquationNbRefPar(0),mEquationCoeff(0), #endif mHasAssignedClock(false),mpClock(0) #ifdef __WX__CRYST__ ,mpWXFieldRefPar(0) #endif {} RefinablePar::~RefinablePar() { #ifdef __WX__CRYST__ this->WXDelete(); #endif } void RefinablePar::Init(const string &name, REAL *refPar, const REAL min, const REAL max, const RefParType *type, RefParDerivStepModel derivMode, const bool hasLimits, const bool isFixed, const bool isUsed, const bool isPeriodic, const REAL humanScale, REAL period) { mName=name; mpValue=refPar; mMin=min; mMax=max; Restraint::SetType(type); mHasLimits=hasLimits; mIsFixed=isFixed; mIsUsed=isUsed; mIsPeriodic=isPeriodic; mPeriod=period; mGlobalOptimStep=(max-min)/100.; mDerivStep=1e-5; mRefParDerivStepModel=derivMode; mSigma=0.; mHumanScale=humanScale; #if 0 mUseEquation=false; mEquationNbRefPar=0; mEquationCoeff=0; #endif mHasAssignedClock=false; mpClock=0; } RefinablePar::RefinablePar(const RefinablePar &old): Restraint(old) { mpValue=old.mpValue; #ifdef __WX__CRYST__ mpWXFieldRefPar=0; #endif this->CopyAttributes(old); mHasAssignedClock=old.mHasAssignedClock; mpClock=old.mpClock; } void RefinablePar::CopyAttributes(const RefinablePar&old) { mName=old.mName; mMin=old.GetMin(); mMax=old.GetMax(); mHasLimits=old.mHasLimits; mIsFixed=old.mIsFixed; mIsUsed=old.mIsUsed; mIsPeriodic=old.mIsPeriodic; mPeriod=old.mPeriod; mGlobalOptimStep=old.mGlobalOptimStep; mDerivStep=old.mDerivStep; mRefParDerivStepModel=old.mRefParDerivStepModel; mSigma=old.mSigma; mHumanScale=old.mHumanScale; #if 0 mUseEquation=old.mUseEquation; mEquationNbRefPar=old.mEquationNbRefPar; mEquationCoeff=old.mEquationCoeff; #endif } REAL RefinablePar::GetValue()const { #if 0 if(true==mUseEquation) { VFN_DEBUG_MESSAGE("RefinablePar::Value():Evaluating Equation",0) REAL tmp=mEquationCoeff(0); for(int i=0;iGetValue(); *mpValue = tmp; } #endif return *mpValue; } const REAL* RefinablePar::GetPointer()const { return mpValue; } void RefinablePar::SetValue(const REAL value) { if(*mpValue == value) return; this->Click(); VFN_DEBUG_MESSAGE("RefinablePar::SetValue()",2) #if 0 if(true==mUseEquation) { cout << "RefinablePar::SetValue(): this parameter is defined by an equation !!" <IsLimited() ==true) { if(true==this->IsPeriodic()) { if(*mpValue > this->GetMax()) *mpValue -= this->GetMax()-this->GetMin(); if(*mpValue < this->GetMin()) *mpValue += this->GetMax()-this->GetMin(); } else { if(*mpValue > this->GetMax()) *mpValue=this->GetMax(); if(*mpValue < this->GetMin()) *mpValue=this->GetMin(); } } */ if(this->IsLimited() ==true) { if(*mpValue > this->GetMax()) *mpValue=this->GetMax(); if(*mpValue < this->GetMin()) *mpValue=this->GetMin(); } else if(true==this->IsPeriodic()) { if(*mpValue > mPeriod) *mpValue -= mPeriod; if(*mpValue < 0) *mpValue += mPeriod; } } const REAL& RefinablePar::GetHumanValue() const { static REAL val; val = *mpValue * mHumanScale; return val; } void RefinablePar::SetHumanValue(const REAL &value) { if(*mpValue == (value/mHumanScale)) return; this->Click(); VFN_DEBUG_MESSAGE("RefinablePar::SetHumanValue()",2) #if 0 if(true==mUseEquation) { cout << "RefinablePar::SetValue(): this parameter is defined by an equation !!" <IsLimited() ==true) { if(true==this->IsPeriodic()) { if(*mpValue > this->GetMax()) *mpValue -= this->GetMax()-this->GetMin(); if(*mpValue < this->GetMin()) *mpValue += this->GetMax()-this->GetMin(); } else { if(*mpValue > this->GetMax()) *mpValue=this->GetMax(); if(*mpValue < this->GetMin()) *mpValue=this->GetMin(); } } */ if(this->IsLimited() ==true) { if(*mpValue > this->GetMax()) *mpValue=this->GetMax(); if(*mpValue < this->GetMin()) *mpValue=this->GetMin(); } else if(true==this->IsPeriodic()) { if(*mpValue > mPeriod) *mpValue -= mPeriod; if(*mpValue < 0) *mpValue += mPeriod; } } void RefinablePar::Mutate(const REAL mutateValue) { if(0==mutateValue) return; VFN_DEBUG_MESSAGE("RefinablePar::Mutate():"<GetName(),1) if(true==mIsFixed) return; this->Click(); #if 0 if(true==mUseEquation) { cout << "RefinablePar::Mutate(): this parameter is defined by an equation !!" <IsLimited() ==true) { if(true==this->IsPeriodic()) { if(*mpValue > this->GetMax()) *mpValue -= this->GetMax()-this->GetMin(); if(*mpValue < this->GetMin()) *mpValue += this->GetMax()-this->GetMin(); } else { if(*mpValue > this->GetMax()) *mpValue=this->GetMax(); if(*mpValue < this->GetMin()) *mpValue=this->GetMin(); } } */ if(this->IsLimited() ==true) { if(*mpValue > this->GetMax()) *mpValue=this->GetMax(); if(*mpValue < this->GetMin()) *mpValue=this->GetMin(); } else if(true==this->IsPeriodic()) { //if(*mpValue > mPeriod) *mpValue -= mPeriod; *mpValue=fmod((REAL)*mpValue,(REAL)mPeriod); if(*mpValue < 0) *mpValue += mPeriod; } VFN_DEBUG_MESSAGE("RefinablePar::Mutate():End",0) } void RefinablePar::MutateTo(const REAL mutateValue) { VFN_DEBUG_MESSAGE("RefinablePar::MutateTo()",2) if(true==mIsFixed) return; if(*mpValue == mutateValue)return; this->Click(); #if 0 if(true==mUseEquation) { cout << "RefinablePar::Mutate(): this parameter is defined by an equation !!" <IsLimited() ==true) { if(true==this->IsPeriodic()) { if(*mpValue > this->GetMax()) *mpValue -= this->GetMax()-this->GetMin(); if(*mpValue < this->GetMin()) *mpValue += this->GetMax()-this->GetMin(); } else { if(*mpValue > this->GetMax()) *mpValue=this->GetMax(); if(*mpValue < this->GetMin()) *mpValue=this->GetMin(); } } */ if(this->IsLimited() ==true) { if(*mpValue > this->GetMax()) *mpValue=this->GetMax(); if(*mpValue < this->GetMin()) *mpValue=this->GetMin(); } else if(true==this->IsPeriodic()) { if(*mpValue > mPeriod) *mpValue -= mPeriod; if(*mpValue < 0) *mpValue += mPeriod; } } REAL RefinablePar::GetSigma()const {return mSigma;} REAL RefinablePar::GetHumanSigma()const {return mSigma*mHumanScale;} void RefinablePar::SetSigma(const REAL sigma) {mSigma=sigma; this->Click();} void RefinablePar::Print() const { cout << this->GetName() << " : " << this->GetHumanValue() << " Fixed:"<< mIsFixed <<" Periodic:"<GetHumanMin() << " Max:" << this->GetHumanMax() << " Step:" <GetName(),1) mIsFixed=b; } bool RefinablePar::IsLimited()const {return mHasLimits;} void RefinablePar::SetIsLimited(const bool b) {mHasLimits=b;this->Click();} bool RefinablePar::IsUsed()const {return mIsUsed;} void RefinablePar::SetIsUsed(const bool b) {mIsUsed=b;this->Click();} bool RefinablePar::IsPeriodic()const {return mIsPeriodic;} void RefinablePar::SetIsPeriodic(const bool b,REAL period) {mIsPeriodic=b;mPeriod=period;this->Click();} REAL RefinablePar::GetMin()const {return mMin;} void RefinablePar::SetMin(const REAL min) { mMin=min;this->Click();} REAL RefinablePar::GetHumanMin()const {return mMin * mHumanScale;} void RefinablePar::SetHumanMin(const REAL min) { mMin=min/mHumanScale;this->Click();} REAL RefinablePar::GetMax()const {return mMax;} void RefinablePar::SetMax(const REAL max) { mMax=max;this->Click();} REAL RefinablePar::GetHumanMax()const {return mMax * mHumanScale;} void RefinablePar::SetHumanMax(const REAL max) { mMax=max/mHumanScale;this->Click();} REAL RefinablePar::GetPeriod()const {return mPeriod;} void RefinablePar::SetPeriod(const REAL period) { mPeriod=period;this->Click();} REAL RefinablePar::GetDerivStep()const { if(REFPAR_DERIV_STEP_ABSOLUTE==mRefParDerivStepModel) return mDerivStep; REAL d=mDerivStep* (*mpValue); //:KLUDGE: Parameter will probably has a singular value, so it should not matter.. if(d == 0.) return 1e-8; return d; } void RefinablePar::SetDerivStep(const REAL step) { this->Click(); mDerivStep = step; } REAL RefinablePar::GetGlobalOptimStep()const {return mGlobalOptimStep;} void RefinablePar::SetGlobalOptimStep(const REAL step) {mGlobalOptimStep=step;} REAL RefinablePar::GetHumanScale()const {return mHumanScale;} void RefinablePar::SetHumanScale(const REAL scale) {mHumanScale=scale;} #if 0 void RefinablePar::SetUseEquation(const bool useItOrNot,const REAL c0) { this->Click(); mUseEquation=useItOrNot; if(true==mUseEquation) { mEquationCoeff.resize(mEquationMaxRefPar); mEquationCoeff(0)=c0; } } void RefinablePar::SetUseEquation(const bool useItOrNot,const REAL c0, const REAL c1, const RefinablePar &refpar1) { this->Click(); mUseEquation=useItOrNot; if(true==mUseEquation) { mEquationCoeff.resize(mEquationMaxRefPar); mEquationCoeff(0)=c0; mEquationCoeff(1)=c1; mEquationRefPar[0]=&refpar1; } } void RefinablePar::SetUseEquation(const bool useItOrNot,const REAL c0, const REAL c1, const RefinablePar &refpar1, const REAL c2, const RefinablePar &refpar2) { this->Click(); mUseEquation=useItOrNot; if(true==mUseEquation) { mEquationCoeff.resize(mEquationMaxRefPar); mEquationCoeff(0)=c0; mEquationCoeff(1)=c1; mEquationCoeff(2)=c2; mEquationRefPar[0]=&refpar1; mEquationRefPar[1]=&refpar2; } } void RefinablePar::SetUseEquation(const bool useItOrNot,const REAL c0, const REAL c1, const RefinablePar &refpar1, const REAL c2, const RefinablePar &refpar2, const REAL c3, const RefinablePar &refpar3) { this->Click(); mUseEquation=useItOrNot; if(true==mUseEquation) { mEquationCoeff.resize(mEquationMaxRefPar); mEquationCoeff(0)=c0; mEquationCoeff(1)=c1; mEquationCoeff(2)=c2; mEquationCoeff(3)=c2; mEquationRefPar[0]=&refpar1; mEquationRefPar[1]=&refpar2; mEquationRefPar[2]=&refpar2; } } #endif void RefinablePar::AssignClock(RefinableObjClock &clock) { VFN_DEBUG_MESSAGE("RefinablePar::AssignClock() for "<GetName()<< "at "<<&clock,4) mpClock=&clock; mHasAssignedClock=true; } void RefinablePar::Click() { if(false==mHasAssignedClock) return; VFN_DEBUG_MESSAGE("RefinablePar::Click():"<GetName(),1) mpClock->Click(); //mpClock->Print(); //VFN_DEBUG_MESSAGE("RefinablePar::Click():End",2) } void RefinablePar::SetLimitsAbsolute(const REAL min, const REAL max) { //:TODO: check limits mMin=min; mMax=max; mHasLimits=true; } void RefinablePar::SetLimitsRelative(const REAL min, const REAL max) { VFN_DEBUG_MESSAGE("RefinablePar::SetLimitsRelative():"<GetName(),1) //:TODO: check limits mMin=this->GetValue()+min; mMax=this->GetValue()+max; this->SetIsLimited(true); } void RefinablePar::SetLimitsProportional(const REAL min, const REAL max) { //:TODO: check limits mMin=this->GetValue()*min; mMax=this->GetValue()*max; this->SetIsLimited(true); } #ifdef __WX__CRYST__ WXCrystObjBasic* RefinablePar::WXCreate(wxWindow *parent) { VFN_DEBUG_MESSAGE("RefinablePar::WXCreate()",8) if(mpWXFieldRefPar!=0) { throw ObjCrystException((string)"RefinablePar::WXCreate():"+this->GetName()+(string)" WXFieldRefPar already exists !"); } mpWXFieldRefPar=new WXFieldRefPar (parent,this->GetName(),this); return (WXCrystObjBasic*) mpWXFieldRefPar; } WXCrystObjBasic* RefinablePar::WXGet() { return (WXCrystObjBasic*) mpWXFieldRefPar; } void RefinablePar::WXDelete() { if(0!=mpWXFieldRefPar) { VFN_DEBUG_MESSAGE("RefinablePar::WXDelete():"<GetName()<< \ " to "<GetChoiceName(choice),5) mChoice=choice; mClock.Click(); } void RefObjOpt::SetChoice(const string &choiceName) { int choice; for(choice=0;choiceSetChoice(choice); } const string& RefObjOpt::GetName()const { return *mpName; } const string& RefObjOpt::GetClassName()const { static string className="Option"; return className; } const string& RefObjOpt::GetChoiceName(const int i)const { return *(mpChoiceName+i); } const RefinableObjClock& RefObjOpt::GetClock()const{return mClock;} #ifdef __WX__CRYST__ WXCrystObjBasic* RefObjOpt::WXCreate(wxWindow *parent) { VFN_DEBUG_MESSAGE("RefObjOpt::WXCreate()",8) mpWXFieldOption=new WXFieldOption (parent,-1,this); return mpWXFieldOption; } WXCrystObjBasic* RefObjOpt::WXGet() { return mpWXFieldOption; } void RefObjOpt::WXDelete() { if(0!=mpWXFieldOption) { VFN_DEBUG_MESSAGE("RefObjOpt::WXDelete()",5) delete mpWXFieldOption; } mpWXFieldOption=0; } void RefObjOpt::WXNotifyDelete() { VFN_DEBUG_MESSAGE("RefObjOpt::WXNotifyDelete()",5) mpWXFieldOption=0; } #endif //###################################################################### // RefObjOption //###################################################################### template RefObjOption::RefObjOption(T* obj): mpObj(obj) {} template RefObjOption::~RefObjOption() {} template void RefObjOption::SetChoice(const int choice) { if(mChoice==choice)return; VFN_DEBUG_MESSAGE("RefObjOption::SetChoice()"<GetName()<< \ " to "<GetChoiceName(choice),5) mChoice=choice; mClock.Click(); if(mfpSetNewValue !=0) (mpObj->*mfpSetNewValue)(choice); } template void RefObjOption::Init(const int nbChoice, const string *name, const string *choiceNames, void (T::*fp)(const int)) { this->RefObjOpt::Init(nbChoice,name,choiceNames); mfpSetNewValue=fp; } //###################################################################### // ObjRegistry //###################################################################### #ifdef __WX__CRYST__ bool operator==(const wxString&wx,const string&str) { return wx==str.c_str(); } bool operator==(const string&str,const wxString&wx) { return wx==str.c_str(); } #endif template ObjRegistry::ObjRegistry(): mName(""),mAutoUpdateUI(true) #ifdef __WX__CRYST__ ,mpWXRegistry(0) #endif { VFN_DEBUG_MESSAGE("ObjRegistry::ObjRegistry()",5) } template ObjRegistry::ObjRegistry(const string &name): mName(name),mAutoUpdateUI(true) #ifdef __WX__CRYST__ ,mpWXRegistry(0) #endif { VFN_DEBUG_MESSAGE("ObjRegistry::ObjRegistry(name):"< ObjRegistry::~ObjRegistry() { VFN_DEBUG_MESSAGE("ObjRegistry::~ObjRegistry():"<WXDelete(); #endif } template void ObjRegistry::Register(T &obj) { VFN_DEBUG_ENTRY("ObjRegistry("<::iterator pos=find(mvpRegistry.begin(),mvpRegistry.end(),&obj); if(pos!=mvpRegistry.end()) { VFN_DEBUG_EXIT("ObjRegistry("<Add(obj.WXCreate(mpWXRegistry)); #endif //this->Print(); VFN_DEBUG_EXIT("ObjRegistry("< void ObjRegistry::DeRegister(T &obj) { VFN_DEBUG_ENTRY("ObjRegistry("<Print(); typename vector::iterator pos=find(mvpRegistry.begin(),mvpRegistry.end(),&obj); if(pos==mvpRegistry.end()) { VFN_DEBUG_EXIT("ObjRegistry("<Remove(obj.WXGet()); #endif mvpRegistry.erase(pos); typename list::iterator pos2=find(mvpRegistryList.begin(),mvpRegistryList.end(),&obj); mvpRegistryList.erase(pos2); mListClock.Click(); VFN_DEBUG_EXIT("ObjRegistry("< void ObjRegistry::DeRegister(const string &objName) { VFN_DEBUG_ENTRY("ObjRegistry("<Find(objName); if(-1==i) { VFN_DEBUG_EXIT("ObjRegistry("<::iterator pos=find(mvpRegistry.begin(),mvpRegistry.end(),mvpRegistry[i]); #ifdef __WX__CRYST__ if(0!=mpWXRegistry) mpWXRegistry->Remove((*pos)->WXGet()); #endif mvpRegistry.erase(pos); typename list::iterator pos2=find(mvpRegistryList.begin(),mvpRegistryList.end(),mvpRegistry[i]); mvpRegistryList.erase(pos2); mListClock.Click(); VFN_DEBUG_EXIT("ObjRegistry("< void ObjRegistry::DeRegisterAll() { VFN_DEBUG_ENTRY("ObjRegistry("<::iterator pos; for(pos=mvpRegistry.begin();pos!=mvpRegistry.end();++pos) mpWXRegistry->Remove((*pos)->WXGet()); } #endif mvpRegistry.clear(); mvpRegistryList.clear(); mListClock.Click(); VFN_DEBUG_EXIT("ObjRegistry("< void ObjRegistry::DeleteAll() { VFN_DEBUG_ENTRY("ObjRegistry("< reg=mvpRegistry;//mvpRegistry will be modified as objects are deleted, so use a copy typename vector::iterator pos; for(pos=reg.begin();pos!=reg.end();++pos) delete *pos; mvpRegistry.clear(); mvpRegistryList.clear(); mListClock.Click(); VFN_DEBUG_EXIT("ObjRegistry("< T& ObjRegistry::GetObj(const unsigned int i) { if(i>=this->GetNb()) throw ObjCrystException("ObjRegistry::GetObj(i): i >= nb!"); return *(mvpRegistry[i]); } template const T& ObjRegistry::GetObj(const unsigned int i) const { if(i>=this->GetNb()) throw ObjCrystException("ObjRegistry::GetObj(i): i >= nb!"); return *(mvpRegistry[i]); } template T& ObjRegistry::GetObj(const string &objName) { const long i=this->Find(objName); return *(mvpRegistry[i]); } template const T& ObjRegistry::GetObj(const string &objName) const { const long i=this->Find(objName); return *(mvpRegistry[i]); } template T& ObjRegistry::GetObj(const string &objName, const string& className) { const long i=this->Find(objName,className); return *(mvpRegistry[i]); } template const T& ObjRegistry::GetObj(const string &objName, const string& className) const { const long i=this->Find(objName,className); return *(mvpRegistry[i]); } template long ObjRegistry::GetNb()const{return (long)mvpRegistry.size();} template void ObjRegistry::Print()const { VFN_DEBUG_MESSAGE("ObjRegistry::Print():",2) cout <GetNb()<<" object registered:" <GetNb();++i) cout << boost::format("#%3d:%s(%s)") %i %this->GetObj(i).GetClassName() %this->GetObj(i).GetName()< void ObjRegistry::SetName(const string &name){ mName=name;} template const string& ObjRegistry::GetName()const { return mName;} template long ObjRegistry::Find(const string &objName) const { VFN_DEBUG_MESSAGE("ObjRegistry::Find(objName)",2) long index=-1; //bool error=false; for(long i=this->GetNb()-1;i>=0;i--) if( mvpRegistry[i]->GetName() == objName) return i; // if(-1 != index) error=true ;else index=i; //if(true == error) //{ // cout << "ObjRegistry::Find(name) : "; // cout << "found duplicate name ! This *cannot* be !!" ; // cout << objName <Print(); // throw 0; //} cout << "ObjRegistry::Find("<Print(); throw ObjCrystException("ObjRegistry::Find("+objName+"): Not found !!"); return index; } template long ObjRegistry::Find(const string &objName, const string &className, const bool nothrow) const { VFN_DEBUG_MESSAGE("ObjRegistry::Find(objName,className)",2) long index=-1; //bool error=false; for(long i=this->GetNb()-1;i>=0;i--) if( mvpRegistry[i]->GetName() == objName) if(className==mvpRegistry[i]->GetClassName()) return i; // if(-1 != index) error=true ;else index=i; //if(true == error) //{ // cout << "ObjRegistry::Find(name) : "; // cout << "found duplicate name ! This *cannot* be !!" ; // cout << objName <Print(); // throw 0; //} cout << "ObjRegistry::Find("<Print(); if(nothrow==false) throw ObjCrystException("ObjRegistry::Find("+objName+","+className+"): Not found !!"); return index; } template long ObjRegistry::Find(const T &obj) const { VFN_DEBUG_MESSAGE("ObjRegistry::Find(&obj)",2) for(long i=this->GetNb()-1;i>=0;i--) if( mvpRegistry[i]== &obj) return i; //:TODO: throw something return -1; } template long ObjRegistry::Find(const T *pobj) const { VFN_DEBUG_MESSAGE("ObjRegistry::Find(&obj)",2) for(long i=this->GetNb()-1;i>=0;i--) if( mvpRegistry[i]== pobj) return i; //:TODO: throw something return -1; } template const RefinableObjClock& ObjRegistry::GetRegistryClock()const{return mListClock;} template void ObjRegistry::AutoUpdateUI(const bool autoup) { mAutoUpdateUI=autoup; } template void ObjRegistry::UpdateUI() { #ifdef __WX__CRYST__ for(unsigned int i=0;iGetNb();i++) { if((this->GetObj(i).WXGet()==NULL) && (0!=mpWXRegistry)) mpWXRegistry->Add(this->GetObj(i).WXCreate(mpWXRegistry)); } #endif } template std::size_t ObjRegistry::size() const { return (std::size_t) mvpRegistry.size(); } template typename vector::const_iterator ObjRegistry::begin() const { return mvpRegistry.begin(); } template typename vector::const_iterator ObjRegistry::end() const { return mvpRegistry.end(); } template typename list::const_iterator ObjRegistry::list_begin() const { return mvpRegistryList.begin(); } template typename list::const_iterator ObjRegistry::list_end() const { return mvpRegistryList.end(); } #ifdef __WX__CRYST__ template WXRegistry* ObjRegistry::WXCreate(wxWindow *parent) { VFN_DEBUG_MESSAGE("ObjRegistry::WXCreate()",2) mpWXRegistry=new WXRegistry (parent,this); for(int i=0;iGetNb();i++) mpWXRegistry->Add(this->GetObj(i).WXCreate(mpWXRegistry)); return mpWXRegistry; } template void ObjRegistry::WXDelete() { if(0!=mpWXRegistry) { VFN_DEBUG_MESSAGE("ObjRegistry::WXDelete()",2) delete mpWXRegistry; } mpWXRegistry=0; } template void ObjRegistry::WXNotifyDelete() { VFN_DEBUG_MESSAGE("ObjRegistry::WXNotifyDelete()",2) mpWXRegistry=0; } #endif //###################################################################### // function RefObjRegisterRecursive //###################################################################### template void RefObjRegisterRecursive(T &obj,ObjRegistry ®) { VFN_DEBUG_MESSAGE("RefObjRegisterRecursive()",3) reg.Register(obj); ObjRegistry *pObjReg=&(obj.GetSubObjRegistry()); for(int i=0;iGetNb();i++) RefObjRegisterRecursive(pObjReg->GetObj(i),reg); return; } //###################################################################### // function RefObjRegisterRecursive //###################################################################### void GetSubRefObjListClockRecursive(ObjRegistry ®,RefinableObjClock &clock) { if(reg.GetRegistryClock()>clock) clock=reg.GetRegistryClock(); for(int i=0;i gRefinableObjRegistry("Global RefinableObj registry"); ObjRegistry gTopRefinableObjRegistry("Global Top RefinableObj registry"); RefinableObj::RefinableObj(): mName(""), mNbRefParNotFixed(-1),mOptimizationDepth(0),mDeleteRefParInDestructor(true) #ifdef __WX__CRYST__ ,mpWXCrystObj(0) #endif { VFN_DEBUG_MESSAGE("RefinableObj::RefinableObj()",3) gRefinableObjRegistry.Register(*this); mSubObjRegistry.SetName("Registry for sub-objects"); mClientObjRegistry.SetName("Registry for Clients"); VFN_DEBUG_MESSAGE("RefinableObj::RefinableObj():End",2) } RefinableObj::RefinableObj(const bool internalUseOnly): mName(""), mNbRefParNotFixed(-1),mOptimizationDepth(0),mDeleteRefParInDestructor(true) #ifdef __WX__CRYST__ ,mpWXCrystObj(0) #endif { VFN_DEBUG_MESSAGE("RefinableObj::RefinableObj(bool)",3) if(false==internalUseOnly) gRefinableObjRegistry.Register(*this); mSubObjRegistry.SetName("Registry for sub-objects"); mClientObjRegistry.SetName("Registry for Clients"); VFN_DEBUG_MESSAGE("RefinableObj::RefinableObj(bool):End",2) } RefinableObj::RefinableObj(const RefinableObj &old) {} /* RefinableObj::RefinableObj(const RefinableObj &old): mName(old.mName),mMaxNbRefPar(old.mMaxNbRefPar),mSavedValuesSetIsUsed(mMaxNbSavedSets), mOptimizationDepth(0),mDeleteRefParInDestructor(true) #ifdef __WX__CRYST__ ,mpWXCrystObj(0) #endif { VFN_DEBUG_MESSAGE("RefinableObj::RefinableObj(RefinableObj&)",3) mpRefPar = new RefinablePar*[mMaxNbRefPar]; mpSavedValuesSet = new CrystVector_REAL* [mMaxNbSavedSets]; mpSavedValuesSetName = new string* [mMaxNbSavedSets]; mSavedValuesSetIsUsed=false; *this=old; mSubObjRegistry.SetName("Registry for sub-objects of "+mName); mClientObjRegistry.SetName("Registry for Clients of "+mName); gRefinableObjRegistry.Register(*this); } */ RefinableObj::~RefinableObj() { VFN_DEBUG_MESSAGE("RefinableObj::~RefinableObj():"<GetName(),5) if(mvpRefPar.size()>0) { if(true==mDeleteRefParInDestructor) { vector::iterator pos; for(pos=mvpRefPar.begin();pos!=mvpRefPar.end();pos++) delete *pos; } } gRefinableObjRegistry.DeRegister(*this); for(int i=0;iWXDelete(); #endif } const string& RefinableObj::GetClassName() const { const static string className="RefinableObj"; return className; } const string& RefinableObj::GetName() const {return mName;} void RefinableObj::SetName(const string &name) { VFN_DEBUG_MESSAGE("RefinableObj::SetName()to :"<ResetParList(); //this->AddPar(old); // Do not copy old saved sets //... but erase any that may be stored for(long i=0;iGetNbPar()); for(long i=0;iGetNbPar();i++) if ( (this->GetPar(i).IsFixed() == false) && (this->GetPar(i).IsUsed() == true)) { mRefparNotFixedIndex(mNbRefParNotFixed) = i; mNbRefParNotFixed++; } //this->Print(); VFN_DEBUG_MESSAGE("RefinableObj::PrepareForRefinement():End",5) } void RefinableObj::FixAllPar() { VFN_DEBUG_ENTRY("RefinableObj("<GetClassName()<<":" <GetName()<<")::FixAllPar()",4) for(long i=0;iGetNbPar();i++) this->GetPar(i).SetIsFixed(true); for(int i=0;iGetSubObjRegistry().GetNb();i++) this->GetSubObjRegistry().GetObj(i).FixAllPar(); VFN_DEBUG_EXIT("RefinableObj("<GetName()<<")::FixAllPar()",4) } void RefinableObj::UnFixAllPar() { for(long i=0;iGetNbPar();i++) this->GetPar(i).SetIsFixed(false); for(int i=0;iGetSubObjRegistry().GetNb();i++) this->GetSubObjRegistry().GetObj(i).UnFixAllPar(); } void RefinableObj::SetParIsFixed(const long parIndex,const bool fix) { this->GetPar(parIndex).SetIsFixed(fix); } void RefinableObj::SetParIsFixed(const string& name,const bool fix) { for(long i=this->GetNbPar()-1;i>=0;i--) if( this->GetPar(i).GetName() == name) this->GetPar(i).SetIsFixed(fix); } void RefinableObj::SetParIsFixed(const RefParType *type,const bool fix) { for(long i=0;iGetNbPar();i++) if( this->GetPar(i).GetType()->IsDescendantFromOrSameAs(type)) { //cout << " Fixing ..." << this->GetPar(i).Name()<GetPar(i).SetIsFixed(fix); } for(int i=0;iGetSubObjRegistry().GetNb();i++) this->GetSubObjRegistry().GetObj(i).SetParIsFixed(type,fix); } void RefinableObj::SetParIsUsed(const string& name,const bool use) { for(long i=this->GetNbPar()-1;i>=0;i--) if( this->GetPar(i).GetName() == name) this->GetPar(i).SetIsUsed(use); } void RefinableObj::SetParIsUsed(const RefParType *type,const bool use) { for(long i=0;iGetNbPar();i++) if( this->GetPar(i).GetType()->IsDescendantFromOrSameAs(type)) { //cout << " Now used (Waow!) : ..." << this->GetPar(i).Name()<GetPar(i).SetIsUsed(use); } for(int i=0;iGetSubObjRegistry().GetNb();i++) this->GetSubObjRegistry().GetObj(i).SetParIsUsed(type,use); } long RefinableObj::GetNbPar()const { return mvpRefPar.size();} long RefinableObj::GetNbParNotFixed()const {return mNbRefParNotFixed;} RefinablePar& RefinableObj::GetPar(const long i) { return *(mvpRefPar[i]); } const RefinablePar& RefinableObj::GetPar(const long i) const { return *(mvpRefPar[i]); } RefinablePar& RefinableObj::GetPar(const string & name) { const long i=this->FindPar(name); if(-1==i) { this->Print(); throw ObjCrystException("RefinableObj::GetPar(): cannot find parameter: "+name+" in object:"+this->GetName()); } return *(mvpRefPar[i]); } const RefinablePar& RefinableObj::GetPar(const string & name) const { const long i=this->FindPar(name); if(-1==i) { this->Print(); throw ObjCrystException("RefinableObj::GetPar(): cannot find parameter: "+name+" in object:"+this->GetName()); } return *(mvpRefPar[i]); } RefinablePar& RefinableObj::GetPar(const REAL *p) { const long i=this->FindPar(p); if(-1==i) { this->Print(); throw ObjCrystException("RefinableObj::GetPar(*p): cannot find parameter in object:"+this->GetName()); } return *(mvpRefPar[i]); } const RefinablePar& RefinableObj::GetPar(const REAL *p) const { const long i=this->FindPar(p); if(-1==i) { this->Print(); throw ObjCrystException("RefinableObj::GetPar(*p): cannot find parameter in object:"+this->GetName()); } return *(mvpRefPar[i]); } RefinablePar& RefinableObj::GetParNotFixed(const long i) { return *(mvpRefPar[mRefparNotFixedIndex(i)]); } const RefinablePar& RefinableObj::GetParNotFixed(const long i) const { return *(mvpRefPar[mRefparNotFixedIndex(i)]); } void RefinableObj::AddPar(const RefinablePar &newRefPar) { VFN_DEBUG_MESSAGE("RefinableObj::AddPar(RefPar&)",2) string name=newRefPar.GetName(); long ct=0; if(this->FindPar(name)>=0) while(this->FindPar(name)!=-1) {// KLUDGE ? Extend name if another parameter already exists with the same name VFN_DEBUG_MESSAGE("RefinableObj::AddPar(): need to change name ?! -> "<FindPar(name),10) name += "~"; if(++ct==100) break;// KLUDGE, let go and hope for the best... } mvpRefPar.push_back(new RefinablePar(newRefPar)); mvpRefPar.back()->SetName(name); mRefParListClock.Click(); } void RefinableObj::AddPar(RefinablePar *newRefPar) { VFN_DEBUG_MESSAGE("RefinableObj::AddPar(RefPar&)",2) string name=newRefPar->GetName(); long ct=0; if(this->FindPar(name)>=0) while(this->FindPar(name)!=-1) {// KLUDGE ? Extend name if another parameter already exists with the same name VFN_DEBUG_MESSAGE("RefinableObj::AddPar(): need to change name ?! -> "<FindPar(name),10) name += "~"; if(++ct==100) break;// KLUDGE, let go and hope for the best... } mvpRefPar.push_back(newRefPar); mvpRefPar.back()->SetName(name); mRefParListClock.Click(); } void RefinableObj::AddPar(RefinableObj &newRefParList,const bool copyParam) { VFN_DEBUG_MESSAGE("RefinableObj::AddPar(RefParList&)" <AddPar(p); } } vector::iterator RefinableObj::RemovePar(RefinablePar *refPar) { VFN_DEBUG_MESSAGE("RefinableObj::RemovePar(RefPar&)",2) vector::iterator pos=find(mvpRefPar.begin(),mvpRefPar.end(),refPar); if(pos==mvpRefPar.end()) { throw ObjCrystException("RefinableObj::RemovePar():"+refPar->GetName() +"is not in this object:"+this->GetName()); } return mvpRefPar.erase(pos); } void RefinableObj::Print() const { VFN_DEBUG_ENTRY("RefinableObj::Print()",2) cout << "Refinable Object:"<GetName() <<", with " << this->GetNbPar() << " parameters" <GetNbPar();i++) { if(this->GetPar(i).IsUsed() == false) continue; cout << "#"<GetPar(i).GetName() << ": " ; cout << FormatFloat(this->GetPar(i).GetHumanValue(),18,12) << " "; if(true == this->GetPar(i).IsFixed()) cout << "Fixed"; else if(true == this->GetPar(i).IsLimited()) { cout << "Limited (" << this->GetPar(i).GetHumanMin()<<"," <GetPar(i).GetHumanMax()<<")"; if(true == this->GetPar(i).IsPeriodic()) cout << ",Periodic" ; } VFN_DEBUG_MESSAGE_SHORT(" (at "<GetPar(i).mpValue<<")",5) if(true == this->GetPar(i).mHasAssignedClock) { VFN_DEBUG_MESSAGE_SHORT(" (Clock at "<GetPar(i).mpClock<<")",5) } cout << endl; } VFN_DEBUG_EXIT("RefinableObj::Print()",2) } unsigned long RefinableObj::CreateParamSet(const string name) const { VFN_DEBUG_ENTRY("RefinableObj::CreateParamSet()",3) unsigned long id; for(id=0;id<=mvpSavedValuesSet.size();id++) if(mvpSavedValuesSet.end()==mvpSavedValuesSet.find(id)) break; pair< CrystVector_REAL ,string> p; p.second=name; mvpSavedValuesSet.insert(make_pair(id,p)); this->SaveParamSet(id); VFN_DEBUG_MESSAGE("RefinableObj::CreateParamSet(): new parameter set with id="<FindParamSet(id)); VFN_DEBUG_EXIT("RefinableObj::ClearParamSet()",2) } void RefinableObj::SaveParamSet(const unsigned long id)const { VFN_DEBUG_MESSAGE("RefinableObj::SaveRefParSet()",2) map >::iterator pos=this->FindParamSet(id); pos->second.first.resize(mvpRefPar.size()); REAL *p=pos->second.first.data(); for(long i=0;iGetNbPar();i++) *p++ = this->GetPar(i).GetValue(); } void RefinableObj::RestoreParamSet(const unsigned long id) { VFN_DEBUG_MESSAGE("RefinableObj::RestoreRefParSet()",2) map >::iterator pos=this->FindParamSet(id); REAL *p=pos->second.first.data(); for(long i=0;iGetNbPar();i++) { //if( !this->GetPar(i).IsFixed() && this->GetPar(i).IsUsed()) if(this->GetPar(i).IsUsed()) this->GetPar(i).SetValue(*p); p++; } } const CrystVector_REAL & RefinableObj::GetParamSet(const unsigned long id)const { VFN_DEBUG_MESSAGE("RefinableObj::GetParamSet() const",2) map >::const_iterator pos=this->FindParamSet(id); return pos->second.first; } CrystVector_REAL & RefinableObj::GetParamSet(const unsigned long id) { VFN_DEBUG_MESSAGE("RefinableObj::GetParamSet()",2) map >::iterator pos=this->FindParamSet(id); return pos->second.first; } REAL RefinableObj::GetParamSet_ParNotFixedHumanValue(const unsigned long id, const long par)const { VFN_DEBUG_MESSAGE("RefinableObj::RefParSetNotFixedHumanValue()",0) map >::iterator pos=this->FindParamSet(id); return pos->second.first(mRefparNotFixedIndex(par)); } const void RefinableObj::EraseAllParamSet() { mvpSavedValuesSet.clear(); } const string& RefinableObj::GetParamSetName(const unsigned long id)const { VFN_DEBUG_MESSAGE("RefinableObj::GetParamSetName()",2) map >::const_iterator pos=this->FindParamSet(id); return pos->second.second; } void RefinableObj::SetLimitsAbsolute(const string &name,const REAL min,const REAL max) { for(long i=this->GetNbPar()-1;i>=0;i--) if( this->GetPar(i).GetName() == name) this->GetPar(i).SetLimitsAbsolute(min,max); } void RefinableObj::SetLimitsAbsolute(const RefParType *type, const REAL min,const REAL max) { for(long i=0;iGetNbPar();i++) if(this->GetPar(i).GetType()->IsDescendantFromOrSameAs(type)) this->GetPar(i).SetLimitsAbsolute(min,max); for(int i=0;iGetSubObjRegistry().GetNb();i++) this->GetSubObjRegistry().GetObj(i).SetLimitsAbsolute(type,min,max); } void RefinableObj::SetLimitsRelative(const string &name, const REAL min, const REAL max) { for(long i=this->GetNbPar()-1;i>=0;i--) if( this->GetPar(i).GetName() == name) this->GetPar(i).SetLimitsRelative(min,max); } void RefinableObj::SetLimitsRelative(const RefParType *type, const REAL min, const REAL max) { VFN_DEBUG_MESSAGE("RefinableObj::SetLimitsRelative(RefParType*):"<GetName(),2) for(long i=0;iGetNbPar();i++) { VFN_DEBUG_MESSAGE("RefinableObj::SetLimitsRelative(RefParType*):par #"<GetPar(i).GetType()->IsDescendantFromOrSameAs(type)) this->GetPar(i).SetLimitsRelative(min,max); } for(int i=0;iGetSubObjRegistry().GetNb();i++) this->GetSubObjRegistry().GetObj(i).SetLimitsRelative(type,min,max); } void RefinableObj::SetLimitsProportional(const string &name,const REAL min,const REAL max) { for(long i=this->GetNbPar()-1;i>=0;i--) if( this->GetPar(i).GetName() == name) this->GetPar(i).SetLimitsProportional(min,max); } void RefinableObj::SetLimitsProportional(const RefParType *type, const REAL min, const REAL max) { for(long i=0;iGetNbPar();i++) if(this->GetPar(i).GetType()->IsDescendantFromOrSameAs(type)) this->GetPar(i).SetLimitsProportional(min,max); for(int i=0;iGetSubObjRegistry().GetNb();i++) this->GetSubObjRegistry().GetObj(i).SetLimitsProportional(type,min,max); } void RefinableObj::SetGlobalOptimStep(const RefParType *type, const REAL step) { for(long i=0;iGetNbPar();i++) if(this->GetPar(i).GetType()->IsDescendantFromOrSameAs(type)) this->GetPar(i).SetGlobalOptimStep(step); for(int i=0;iGetSubObjRegistry().GetNb();i++) this->GetSubObjRegistry().GetObj(i).SetGlobalOptimStep(type,step); } ObjRegistry& RefinableObj::GetSubObjRegistry() {return mSubObjRegistry;} const ObjRegistry& RefinableObj::GetSubObjRegistry()const {return mSubObjRegistry;} void RefinableObj::RegisterClient(RefinableObj &obj)const {mClientObjRegistry.Register(obj);} void RefinableObj::DeRegisterClient(RefinableObj &obj)const {mClientObjRegistry.DeRegister(obj);} const ObjRegistry& RefinableObj::GetClientRegistry()const{return mClientObjRegistry;} ObjRegistry& RefinableObj::GetClientRegistry() {return mClientObjRegistry;} bool RefinableObj::IsBeingRefined()const {return mOptimizationDepth>0;} extern const long ID_WXOBJ_ENABLE; //These are defined in wxCryst/wxCryst.cpp extern const long ID_WXOBJ_DISABLE; void RefinableObj::BeginOptimization(const bool allowApproximations, const bool enableRestraints) { mOptimizationDepth++; if(mOptimizationDepth>1) return; this->Prepare(); for(int i=0;iEnable(false); else { wxUpdateUIEvent event(ID_WXOBJ_DISABLE); wxPostEvent(mpWXCrystObj,event); } } #endif } void RefinableObj::EndOptimization() { mOptimizationDepth--; if(mOptimizationDepth<0) throw ObjCrystException("RefinableObj::EndOptimization(): mOptimizationDepth<0 !!"); if(mOptimizationDepth>0) return; for(int i=0;iEnable(true); else { wxUpdateUIEvent event(ID_WXOBJ_ENABLE); wxPostEvent(mpWXCrystObj,event); } } #endif } void RefinableObj::SetApproximationFlag(const bool allow) { for(int i=0;iPrepareForRefinement(); for(int j=0;jGetNbParNotFixed();j++) { if(true==this->GetParNotFixed(j).IsLimited()) { const REAL min=this->GetParNotFixed(j).GetMin(); const REAL max=this->GetParNotFixed(j).GetMax(); this->GetParNotFixed(j).MutateTo(min+(max-min)*(rand()/(REAL)RAND_MAX) ); } else if(true==this->GetParNotFixed(j).IsPeriodic()) { this->GetParNotFixed(j).MutateTo((rand()/(REAL)RAND_MAX) * this->GetParNotFixed(j).GetPeriod()); } } for(int i=0;iGetSubObjRegistry().GetNb();i++) this->GetSubObjRegistry().GetObj(i).RandomizeConfiguration(); VFN_DEBUG_EXIT("RefinableObj::RandomizeConfiguration():Finished",5) } void RefinableObj::GlobalOptRandomMove(const REAL mutationAmplitude, const RefParType *type) { if(mRandomMoveIsDone) return; VFN_DEBUG_ENTRY("RefinableObj::GlobalOptRandomMove()",2) for(int j=0;jGetNbParNotFixed();j++) { if(this->GetParNotFixed(j).GetType()->IsDescendantFromOrSameAs(type)) this->GetParNotFixed(j).Mutate( this->GetParNotFixed(j).GetGlobalOptimStep() *2*(rand()/(REAL)RAND_MAX-0.5)*mutationAmplitude); } for(int i=0;i::const_iterator pos; for(pos=mvpRestraint.begin();pos!=mvpRestraint.end();pos++) { VFN_DEBUG_MESSAGE("RefinableObj::GetLogLikelihood()Restraint: "<<*pos,2) loglike+= (*pos)->GetLogLikelihood(); } VFN_DEBUG_EXIT("RefinableObj::GetLogLikelihood()="<& RefinableObj::GetLogLikelihood_FullDeriv(std::set &vPar) // { // //TODO // return mLogLikelihood_FullDeriv; // } const CrystVector_REAL& RefinableObj::GetLSQCalc(const unsigned int) const { throw ObjCrystException("Error: called RefinableObj::GetLSQCalc()"); CrystVector_REAL *noWarning=new CrystVector_REAL; return *noWarning; } const CrystVector_REAL& RefinableObj::GetLSQObs(const unsigned int) const { throw ObjCrystException("Error: called RefinableObj::GetLSQObs()"); CrystVector_REAL *noWarning=new CrystVector_REAL; return *noWarning; } const CrystVector_REAL& RefinableObj::GetLSQWeight(const unsigned int) const { throw ObjCrystException("Error: called RefinableObj::GetLSQWeight()"); CrystVector_REAL *noWarning=new CrystVector_REAL; return *noWarning; } const CrystVector_REAL& RefinableObj::GetLSQDeriv(const unsigned int n, RefinablePar&par) { // By default, use numerical derivatives const REAL step=par.GetDerivStep(); par.Mutate(step); mLSQDeriv =this->GetLSQCalc(n); par.Mutate(-2*step); mLSQDeriv -=this->GetLSQCalc(n); par.Mutate(step); mLSQDeriv /= step*2; return mLSQDeriv; } std::map & RefinableObj::GetLSQ_FullDeriv(const unsigned int n,std::set &vPar) { mLSQ_FullDeriv[n].clear(); mLSQ_FullDeriv[n][(RefinablePar*)0]=this->GetLSQCalc(n); for(std::set::const_iterator pos=vPar.begin();pos!=vPar.end();pos++) mLSQ_FullDeriv[n][*pos]=this->GetLSQDeriv(n,**pos); return mLSQ_FullDeriv[n]; } void RefinableObj::ResetParList() { VFN_DEBUG_MESSAGE("RefinableObj::ResetParList()",3) if(mvpRefPar.size()>0) { if(true==mDeleteRefParInDestructor) { vector::iterator pos; for(pos=mvpRefPar.begin();pos!=mvpRefPar.end();pos++) delete *pos; } mvpRefPar.clear(); } mNbRefParNotFixed=-1; VFN_DEBUG_MESSAGE("RefinableObj::ResetParList():Deleting Saved Sets....",2) this->EraseAllParamSet(); mRefParListClock.Click(); VFN_DEBUG_MESSAGE("RefinableObj::ResetParList():End.",3) } ObjRegistry& RefinableObj::GetOptionList() { return mOptionRegistry; } unsigned int RefinableObj::GetNbOption()const { return mOptionRegistry.GetNb(); } RefObjOpt& RefinableObj::GetOption(const unsigned int i) { VFN_DEBUG_MESSAGE("RefinableObj::GetOption()"<Print(); throw ObjCrystException("RefinableObj::GetOption(): cannot find option: "+name+" in object:"+this->GetName()); } return mOptionRegistry.GetObj(i); } const RefObjOpt& RefinableObj::GetOption(const unsigned int i)const { //:TODO: Check return mOptionRegistry.GetObj(i); } const RefObjOpt& RefinableObj::GetOption(const string & name)const { VFN_DEBUG_MESSAGE("RefinableObj::GetOption()"<Print(); throw ObjCrystException("RefinableObj::GetOption(): cannot find option: "+name+" in object:"+this->GetName()); } return mOptionRegistry.GetObj(i); } void RefinableObj::GetGeneGroup(const RefinableObj &obj, CrystVector_uint & groupIndex, unsigned int &first) const { VFN_DEBUG_MESSAGE("RefinableObj::GetGeneGroup()",4) for(long i=0;iGetNbPar();j++) if(&(obj.GetPar(i)) == &(this->GetPar(j))) groupIndex(i)= first++; } void RefinableObj::SetDeleteRefParInDestructor(const bool b) {mDeleteRefParInDestructor=b;} const RefinableObjClock& RefinableObj::GetRefParListClock()const{return mRefParListClock;} REAL RefinableObj::GetRestraintCost()const { vector::const_iterator pos; REAL cost(0); for(pos=mvpRestraint.begin();pos != mvpRestraint.end();++pos) cost += (*pos)->GetLogLikelihood(); return 0; } void RefinableObj::AddRestraint(Restraint *pNewRestraint) { VFN_DEBUG_MESSAGE("RefinableObj::AddRestraint(Restraint*)",2) mvpRestraint.push_back(pNewRestraint); } vector::iterator RefinableObj::RemoveRestraint(Restraint *pRestraint) { VFN_DEBUG_MESSAGE("RefinableObj::RemoveRestraint(Restraint*)",2) vector::iterator pos=find(mvpRestraint.begin(),mvpRestraint.end(),pRestraint); if(mvpRestraint.end() != pos) { return mvpRestraint.erase(pos); } else { cout <<"RefinableObj::RemoveRestraint(..)" <<" Whoops... tried to remove a Restraint which does not exist..."<CrystUpdate(true,true); VFN_DEBUG_EXIT("RefinableObj::UpdateDisplay()",3) #endif } long RefinableObj::FindPar(const string &name) const { long index=-1; bool warning=false; for(long i=this->GetNbPar()-1;i>=0;i--) if( this->GetPar(i).GetName() == name) { if(-1 != index) warning=true ;else index=i; } if(true == warning) { throw ObjCrystException("RefinableObj::FindPar("+name+"): found duplicate refinable variable name in object:"+this->GetName()); } return index; } long RefinableObj::FindPar(const REAL *p) const { long index=-1; bool warning=false; for(long i=this->GetNbPar()-1;i>=0;i--) if( p == mvpRefPar[i]->mpValue ) //&(this->GetPar(i).GetValue()) { if(-1 != index) warning=true ;else index=i; } if(true == warning) { throw ObjCrystException("RefinableObj::FindPar(*p): Found duplicate parameter in object:"+this->GetName()); } return index; } void RefinableObj::AddSubRefObj(RefinableObj &obj) { VFN_DEBUG_MESSAGE("RefinableObj::AddSubRefObj()",3) mSubObjRegistry.Register(obj); mClockMaster.AddChild(obj.GetClockMaster()); } void RefinableObj::RemoveSubRefObj(RefinableObj &obj) { VFN_DEBUG_MESSAGE("RefinableObj::RemoveSubRefObj()",3) mSubObjRegistry.DeRegister(obj); mClockMaster.RemoveChild(obj.GetClockMaster()); } void RefinableObj::AddOption(RefObjOpt *opt) { VFN_DEBUG_MESSAGE("RefinableObj::AddOption()",5) //:TODO: automagically resize the option array if necessary mOptionRegistry.Register(*opt); mClockMaster.AddChild(opt->GetClock()); VFN_DEBUG_MESSAGE("RefinableObj::AddOption():End",5) } void RefinableObj::Prepare() { VFN_DEBUG_MESSAGE("RefinableObj::Prepare()",5) for(int i=0;iGetSubObjRegistry().GetNb();i++) this->GetSubObjRegistry().GetObj(i).Prepare(); } map >::iterator RefinableObj:: FindParamSet(const unsigned long id)const { VFN_DEBUG_ENTRY("RefinableObj::FindParamSet()",2) map >::iterator pos; pos=mvpSavedValuesSet.find(id); if(mvpSavedValuesSet.end() == pos) {//throw up throw ObjCrystException("RefinableObj::FindParamSet(long): Unknown saved set ! In object:"+this->GetName()); } VFN_DEBUG_EXIT("RefinableObj::FindParamSet()",2) return pos; } #ifdef __WX__CRYST__ WXCrystObjBasic* RefinableObj::WXCreate(wxWindow *parent) { VFN_DEBUG_MESSAGE("RefinableObj::WXCreate()",8) mpWXCrystObj=new WXRefinableObj (parent,this); return mpWXCrystObj; } WXCrystObjBasic* RefinableObj::WXGet() { return mpWXCrystObj; } void RefinableObj::WXDelete() { if(0!=mpWXCrystObj) { VFN_DEBUG_MESSAGE("RefinableObj::WXDelete()",5) delete mpWXCrystObj; } mpWXCrystObj=0; } void RefinableObj::WXNotifyDelete() { VFN_DEBUG_MESSAGE("RefinableObj::WXNotifyDelete():"< ®,RefinableObjClock &clock) { for(int i=0;iclock) clock=reg.GetObj(i).GetRefParListClock(); GetRefParListClockRecursive(reg.GetObj(i).GetSubObjRegistry(),clock); } } //***********EXPLICIT INSTANTIATION*******************// template void RefObjRegisterRecursive(RefinableObj &obj,ObjRegistry ®); }//namespace #include "ObjCryst/ObjCryst/Crystal.h" #include "ObjCryst/ObjCryst/Scatterer.h" #include "ObjCryst/ObjCryst/ScatteringPower.h" #include "ObjCryst/ObjCryst/ZScatterer.h" #include "ObjCryst/ObjCryst/PowderPattern.h" #include "ObjCryst/ObjCryst/DiffractionDataSingleCrystal.h" #include "ObjCryst/ObjCryst/ScatteringCorr.h" #include "ObjCryst/RefinableObj/GlobalOptimObj.h" #include "ObjCryst/RefinableObj/IO.h" #include "ObjCryst/ObjCryst/ReflectionProfile.h" namespace ObjCryst { template class ObjRegistry; template class ObjRegistry; template class ObjRegistry; template class ObjRegistry; template class ObjRegistry; template class ObjRegistry; template class ObjRegistry; template class ObjRegistry; template class ObjRegistry; template class ObjRegistry; //template class ObjRegistry;//to be removed template class ObjRegistry; template class ObjRegistry; template class ObjRegistry; template class ObjRegistry; template class ObjRegistry; template class RefObjOption; template class RefObjOption; template class RefObjOption; template class RefObjOption; template class RefObjOption; template class RefObjOption; template class RefObjOption; template class RefObjOption; template class RefObjOption; template class RefObjOption; template class RefObjOption; //template class RefObjOption; //template class RefObjOption; } // namespace ObjCryst objcryst-2022.1/ObjCryst/RefinableObj/RefinableObj.h000066400000000000000000001702451430515525000222240ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * header file for the RefinablePar and RefinableObj classes * * */ #ifndef _VFN_REFINABLE_OBJ_H_ #define _VFN_REFINABLE_OBJ_H_ #include #include #include #include #include #include #include "ObjCryst/CrystVector/CrystVector.h" #include "ObjCryst/ObjCryst/General.h" #include "ObjCryst/RefinableObj/IO.h" #ifdef __WX__CRYST__ class wxWindow; namespace ObjCryst { template class ObjRegistry; class RefObjOpt; template class RefObjOption; class RefinableObj; } #include "ObjCryst/wxCryst/wxRefinableObj.h" #endif namespace ObjCryst { /// How do we compute steps h for numerical derivative calculation : d=f(x+h)-f(x-h)/h/2 /// either h is fixed (absolute), or relative h=x*derivFactor enum RefParDerivStepModel { REFPAR_DERIV_STEP_ABSOLUTE, REFPAR_DERIV_STEP_RELATIVE }; /** \brief class of refinable parameter types. * * This is used to categorize all parameters, to be able to modify * a complete category of parameters (fix/unfix, set limits,...). * The types are organized as a tree. * * Parameters should be allocated globally in the heap, so we only use * pointers in the interface. * * \note when modifying (fixing, changing limits) for a given RefParType (ie a 'family' * of parameters), it affects all RefinablePar of this type \e and the parameters * belonging to the children of this RefParType. eg fixing for the type "gpRefParTypeScatt" * will fix all the derived postionnal, orientationnal, and population parameters * for the scatterers. * * \remarks In the future, why not use a tree with multiple inheritance ?? It would * be easy to allow multiple parents... But beware of loops... */ class RefParType { public: /// Create a \e top parameter type. (in ObjCryst, there is /// only one, the "ObjCryst" category. RefParType(const string &name); /// create a children type. RefParType(const RefParType *parent,const string &name); ///Destructor ~RefParType(); /// Returns true if the parameter is a descendant of 'type' bool IsDescendantFromOrSameAs(const RefParType *type) const; /// returns true if the two types are the same. bool operator==(const RefParType *parent) const; /// Get the name for this parameter const string& GetName() const; private: /// Get a Unique id (RefParType::mId) void InitId(); /// the parent for this RefParType (we could easily allow several...) const RefParType* mpParent; /// The name/description for this parameter type const string mName; /// The unique number identifying this type unsigned long mId; }; /// Top RefParType for the ObjCryst++ library. extern const RefParType *gpRefParTypeObjCryst; class NiftyStaticGlobalObjectsInitializer_RefinableObj { public: NiftyStaticGlobalObjectsInitializer_RefinableObj() { if (mCount++ == 0) { gpRefParTypeObjCryst=new RefParType("ObjCryst++"); } } ~NiftyStaticGlobalObjectsInitializer_RefinableObj() { if (--mCount == 0) { delete gpRefParTypeObjCryst; gpRefParTypeObjCryst=0; } } private: static long mCount; }; static NiftyStaticGlobalObjectsInitializer_RefinableObj NiftyStaticGlobalObjectsInitializer_RefinableObj_counter; /// We need to record exactly when refinable objects /// have been modified for the last time (to avoid re-computation), /// and to do that we need a precise time. Since the clock() function is not /// precise enough (and is architecture-dependant), we use a custom time, /// which records the number of events in the program which uses the library. /// This is purely internal, so don't worry about it... /// /// The clock values have nothing to do with 'time' as any normal person undertands it. class RefinableObjClock { public: RefinableObjClock(); ~RefinableObjClock(); bool operator< (const RefinableObjClock &rhs)const; bool operator<=(const RefinableObjClock &rhs)const; bool operator> (const RefinableObjClock &rhs)const; bool operator>=(const RefinableObjClock &rhs)const; /// Record an event for this clock (generally, the 'time' /// an object has been modified, or some computation has been made) void Click(); /// Reset a Clock to 0, to force an update void Reset(); /// Print clock value. Only for debugging purposes. void Print()const; /// Print current general clock value. Only for debugging purposes. void PrintStatic()const; /// Add a 'child' clock. Whenever a child clock is clicked, it will also click its parent. /// This function takes care of adding itself to the list of parent in the children clock. void AddChild(const RefinableObjClock &); /// remove a child clock. This also tells the child clock to remove the parent. void RemoveChild(const RefinableObjClock &); /// Add a 'parent' clock. Whenever a clock is clicked, all parent clocks /// also are. void AddParent(RefinableObjClock &)const; /// remove a parent clock void RemoveParent(RefinableObjClock &)const; /// This will (i) set the clock to the same values as the rhs clock, but will not change /// the list of children and parent clocks. This will afterwards Click() the clock /// to notify parents. void operator=(const RefinableObjClock &rhs); private: bool HasParent(const RefinableObjClock &) const; unsigned long mTick0, mTick1; static unsigned long msTick0,msTick1; /// List of 'child' clocks, which will click this clock whenever they are clicked. std::set mvChild; /// List of parent clocks, which will be clicked whenever this one is. This /// is a mutable list since reporting to parent clocks does not change /// the vlaue of the clock. mutable std::set mvParent; }; /** Restraint: generic class for a restraint of a given model. This * defines only the category (RefParType) of restraint, and the function * to access the log(likelihood) associated to this restraint and the current model. * * By default: -log(likelihood)=0, and the function must be overloaded * for "real" restraints. * *\note the log(likelihood) \e must always include the normalization term, * so that variances can also optimized during the maximum likelihood * optimization. e.g.: * - \f$ P=\frac{1}{\sqrt{2\pi\sigma^2}}e^{\frac{-(calc-expected)^2}{\sigma^2}}\f$ * - \f$ -\log(P)= \log\left(\sqrt{2\pi\sigma^2}\right) * + \left(\frac{calc-expected}{\sigma} \right)^2\f$ * * forgetting the normalization term would result in making the optimization diverge towards * infinite variances. */ class Restraint { public: /// Default constructor, sets RefParType to gpRefParTypeObjCryst Restraint(); ///constructor specifying the type Restraint(const RefParType *type); virtual ~Restraint(); virtual const RefParType* GetType()const; virtual void SetType(const RefParType *type); /// Get -ln(likelihood) for this restraint virtual REAL GetLogLikelihood()const; private: const RefParType *mpRefParType; }; /** Generic class for parameters of refinable objects. * These must be continuous. * * \todo: define parameters using equations between parameters. * \todo: for complex objects with lots of parameters, give the * possibility to define vectors of parameters, all with the same * properties, to reduce memory usage. */ class RefinablePar:public Restraint { public: /// \name Destructor & Constructors //@{ /** Default Constructor */ RefinablePar(); /** \brief Constructor *\par name: the name of the parameter *\par refPar: the address of the refined parameter *\par min,max: the minimum & maximum value for this parameter. Only used * if the parameter is limited. *\par type: the type (category) of refinable parameter. This is used to (de)activate * groups of parameters. *\par derivMode: to compute numerical (partial) derivatives, the step used is either * an absolute (fixed) value, or it can be proportionnal to the current value of the * parameter. *\par hasLimits: if true, then the parameter cannot exceed its limits. *\par isFixed: if true, the parameter cannot be refined. *\par isUsed: if false, then the parameter does not affect in any way the refined object, * and thus is simply ignored and should never appear to the user. *\par isPeriodic: if true, then when the parameter exceeds one of its limits, it is * shifted by the period (=max-min), in order to be back to the allowed [min,max] range. *\par humanScale:this is the scale which should be used to display the value to the * end program user. This is mostly used for angles: the values are stored in radians, so * that a scale equal to 180/pi must be used for a 'human-understandable' value. Use * the RefinablePar::HumanValue() in order to get this value. By default it * is equal to 1.0 (no scaling required). */ RefinablePar( const string &name, REAL *refPar, const REAL min, const REAL max, const RefParType *type, RefParDerivStepModel derivMode=REFPAR_DERIV_STEP_RELATIVE, const bool hasLimits=true, const bool isFixed=false, const bool isUsed=true, const bool isPeriodic=false, const REAL humanScale=1., REAL period=1.); /** Copy Constructor */ RefinablePar(const RefinablePar &ref); ~RefinablePar(); /** \brief Constructor *\par name: the name of the parameter *\par refPar: the address of the refined parameter *\par min,max: the minimum & maximum value for this parameter. Only used * if the parameter is limited. *\par type: the type (category) of refinable parameter. This is used to (de)activate * groups of parameters. *\par derivMode: to compute numerical (partial) derivatives, the step used is either * an absolute (fixed) value, or it can be proportionnal to the current value of the * parameter. *\par hasLimits: if true, then the parameter cannot exceed its limits. *\par isFixed: if true, the parameter cannot be refined. *\par isUsed: if false, then the parameter does not affect in any way the refined object, * and thus is simply ignored and should never appear to the user. *\par isPeriodic: if true, then when the parameter exceeds one of its limits, it is * shifted by the period (=max-min), in order to be back to the allowed [min,max] range. *\par humanScale:this is the scale which should be used to display the value to the * end program user. This is mostly used for angles: the values are stored in radians, so * that a scale equal to 180/pi must be used for a 'human-understandable' value. Use * the RefinablePar::HumanValue() in order to get this value. By default it * is equal to 1.0 (no scaling required). */ void Init( const string &name, REAL *refPar, const REAL min, const REAL max, const RefParType *type, RefParDerivStepModel derivMode=REFPAR_DERIV_STEP_RELATIVE, const bool hasLimits=true, const bool isFixed=false, const bool isUsed=true, const bool isPeriodic=false, const REAL humanScale=1., REAL period=1.); /// Copy all attributes (limits, flags, etc...) from another RefinablePar object. /// This is useful in RefinableObj copy constructors. Everything is copied but the /// pointer to the value refined, and the pointer to the clock. void CopyAttributes(const RefinablePar&); //@} /// \name Access & change the current value of the parameter //@{ /** of the parameter. Use the The Mutate() and MutateTo() function * to change this value. */ REAL GetValue()const; /** Access to a const pointer to the refined value * * This can be used to identify the parameter */ const REAL* GetPointer()const; /** of the parameter. Use the The Mutate() and MutateTo() function * to change this value. */ void SetValue(const REAL value); /** \brief Current value of parameter, scaled if necessary (for angles) to a * human-understandable value. */ const REAL& GetHumanValue() const; /** \brief Current value of parameter, scaled if necessary (for angles) to a * human-understandable value. */ void SetHumanValue(const REAL&) ; /** \brief Add the given amount to the parameter current value. * * If limit is hit, set to limit. * If the limit is hit \e and the parameter is periodic, shift by period to bring * back to allowed values. *\warning Will throw an exception if the parameter is defined by an equation. */ void Mutate(const REAL mutateValue); /**Change the current value to the given one. * * If the limit is hit, then set to the limit (unless the pameter is periodic, * then shift by the period amount back to allowed values). *\warning Will throw an exception if the parameter is defined by an equation. */ void MutateTo(const REAL newValue); REAL GetSigma()const; REAL GetHumanSigma()const; void SetSigma(const REAL); //@} /// \name General info //@{ /// Get the parameter's name string GetName()const; /// Set the name of the parameter. It should be unique in the RefinableObj. void SetName(const string&); void Print() const; bool IsFixed()const; void SetIsFixed(const bool); bool IsLimited()const; void SetIsLimited(const bool); /// Is the parameter used (if not, it is simply irrelevant in the model) ? bool IsUsed()const; /// Is the parameter used (if not, it is simply irrelevant in the model) ? void SetIsUsed(const bool); bool IsPeriodic()const; void SetIsPeriodic(const bool,REAL period=1); /// Human scale for this parameter : for angles, this is equal to 180/pi. REAL GetHumanScale()const; /// Human scale for this parameter : for angles, this is equal to 180/pi. void SetHumanScale(const REAL); //@} /// \name Min, max values //@{ /// Minimum value allowed (if limited or periodic) REAL GetMin()const; /// Set the Minimum value allowed (if limited) void SetMin(const REAL); ///Get the minimum value allowed (if limited) REAL GetHumanMin()const; ///Set the minimum value allowed (if limited) void SetHumanMin(const REAL); ///Get the maximum value allowed (if limited) REAL GetMax()const; ///Get the maximum value allowed (if limited) void SetMax(const REAL); ///Get the maximum value allowed (if limited) REAL GetHumanMax()const; ///Get the maximum value allowed (if limited) void SetHumanMax(const REAL); ///Get the period (if periodic) REAL GetPeriod()const; ///Set the period value (if periodic) void SetPeriod(const REAL); //@} /// \name Steps during refinement //@{ ///Fixed step to use to compute numerical derivative REAL GetDerivStep()const; ///Fixed step to use to compute numerical derivative void SetDerivStep(const REAL); ///Maximum step to use during Global Optimization algorithms REAL GetGlobalOptimStep()const; ///Maximum step to use during Global Optimization algorithms void SetGlobalOptimStep(const REAL); //@} #if 0 /// \name Equations-In development ! ->do not use or even look. //@{ void SetUseEquation(const bool useItOrNot,const REAL c0=0.); void SetUseEquation(const bool useItOrNot,const REAL c0, const REAL c1, const RefinablePar &refpar1); void SetUseEquation(const bool useItOrNot,const REAL c0, const REAL c1, const RefinablePar &refpar1, const REAL c2, const RefinablePar &refpar2); void SetUseEquation(const bool useItOrNot,const REAL c0, const REAL c1, const RefinablePar &refpar1, const REAL c2, const RefinablePar &refpar2, const REAL c3, const RefinablePar &refpar3); //@} #endif /// \name Parameter's Clock //@{ /// \internal /// Assign a clock to this parameter. Any time this parameter is modified, /// the clock will be ticked ! void AssignClock(RefinableObjClock &clock); //@} /// \name Change Limits //@{ /// Change the limits for this object, giving absolute new limits void SetLimitsAbsolute(const REAL min, const REAL max); /// Change the limits for this object, giving relative new limits (eg giving -.1 /// and +.1 will set new limits at the current value + min and current value + max) /// Thus min should logically be <0 and max >0. void SetLimitsRelative(const REAL min, const REAL max); /// Change the limits for this object, proportionnaly to the current value. /// min should be < 1. and max > 1. void SetLimitsProportional(const REAL min, const REAL max); //@} /** \brief XMLOutput to stream in well-formed XML * * this will save the fixed & limited flags, as well as limits * \param name the name to use instead of the RefPar name. */ void XMLOutput(ostream &os,const string &name,int indent=0)const; /** \brief XMLOutput to stream in well-formed XML. * * this will save the fixed & limited flags, as well as limits. * In this function the name used is that of the RefPar. */ void XMLOutput(ostream &os,int indent=0)const; /** \brief XMLInput From stream * */ void XMLInput(istream &is,const XMLCrystTag &tag); private: /// Click the Clock ! to telle the RefinableObj it has been modified. void Click(); ///name of the refinable parameter string mName; /// Pointer to the refinable value REAL *mpValue; /// Hard lower and upper limits. REAL mMin,mMax; /// Does the refinable parameter need limits (min and max) ? bool mHasLimits; /// is the parameter currently fixed ? bool mIsFixed; /// Is the parameter currently used ? bool mIsUsed; /// Is the parameter periodic ? If this is the case, then when using the /// RefinablePar::Mutate() function, if the parameter goes beyond its limits, /// it will be shifted by the value of its period. bool mIsPeriodic; /// Period value (if relevant) REAL mPeriod; /// Step to use for global method search (simulated annealing,...) REAL mGlobalOptimStep; /// Step to use for numerical derivative calculation REAL mDerivStep; /// Model followed for derivation RefParDerivStepModel mRefParDerivStepModel; /// Calculated sigma on value REAL mSigma; /// Scale to be used to display 'human' value. This is for angular parameters: the computer /// stores values in radians, whil the user only understands degrees. So a scale /// factor of 180/pi is necessary. REAL mHumanScale; #if 0 // Parameter defined by equations ? :TODO: ///Is this parameter deined by an equation ? eg: mValue= c0 +c1*par1.Value+... bool mUseEquation; /// Max number of other ref. parameters involved in the equation evaluation static const int mEquationMaxRefPar=10; /// number of other ref. parameters involved in the equation evaluation int mEquationNbRefPar; /// Coefficient Ci used in equation: Value= C0 + C1 * RefPar1 + C2 * RefPar2 +... CrystVector_REAL mEquationCoeff; /// Array of pointers to the RefinablePar used in the equation const RefinablePar *mEquationRefPar[10]; #endif /// Is there a clock associated with this parameter ? If yes, then it must Click() it /// each time it is modified bool mHasAssignedClock; RefinableObjClock* mpClock; #ifdef __WX__CRYST__ public: /// Create a WXFieldRefPar representation of the parameter. WXCrystObjBasic* WXCreate(wxWindow *parent); WXCrystObjBasic* WXGet(); void WXDelete(); void WXNotifyDelete(); private: WXFieldRefPar * mpWXFieldRefPar; #endif friend class RefinableObj; }; /** Base class for options * */ class RefObjOpt { public: /** Constructor for the option * \param obj: the */ RefObjOpt(); virtual ~RefObjOpt(); void Init(const int nbChoice,const string *name, const string *choiceNames); int GetNbChoice()const; int GetChoice()const; virtual void SetChoice(const int choice); void SetChoice(const string &choiceName); const string& GetName()const; const string& GetClassName()const; const string& GetChoiceName(const int i)const; const RefinableObjClock& GetClock()const; /** \brief XMLOutput to stream in well-formed XML. * * In this function the name used is that of the Option. */ void XMLOutput(ostream &os,int indent=0)const; /** \brief XMLInput From stream * */ void XMLInput(istream &is,const XMLCrystTag &tag); protected: /// Number of different choice possible for this option int mNbChoice; /// Current value int mChoice; /// (short) Name for this option. Should be statically stored in the class /// using the option const string* mpName; /// Names corresponding to each possible value of this option (Human-understandable). /// Should be statically stored in the class using the option. const string* mpChoiceName; /// The clock associated to this option RefinableObjClock mClock; #ifdef __WX__CRYST__ public: WXCrystObjBasic* WXCreate(wxWindow *parent); WXCrystObjBasic* WXGet(); void WXDelete(); void WXNotifyDelete(); private: WXFieldOption * mpWXFieldOption; #endif }; /** * Class for options of RefinableObj, templated so that we can warn * the object that something has been changed. NOT USED SO FAR. */ template class RefObjOption:public RefObjOpt { public: /** Constructor for the option * \param obj: the */ RefObjOption(T* obj); ~RefObjOption(); void Init(const int nbChoice,const string *name, const string *choiceNames, void (T::*fp)(const int)); virtual void SetChoice(const int choice); protected: private: /// The object which uses this option T* mpObj; /// The pointer to the member function to be used when the choice is changed, to notify /// immediately the object. If null, the value is just recorded and no notification /// is done. void (T::*mfpSetNewValue)(const int); }; /** Object Registry * * This class is used to keep a list of all object of a given class at the global * level, or inside another object. This is primarily aimed for the derivative * of the RefinableObj class but it * can be used for \e any class that has GetName() and GetClassName() function. * This class now uses a vector<> approach from the STL. * * \warning the order of the objects in the registry can change (every time an object * is de-registered). * * \todo (?) create two derived classes with the same interface, one which is a const * registry (the 'client' registry for RefinableObj), and one which has a non-const * access to the registered objects (the 'sub-objects' in RefinableObj). */ template class ObjRegistry { public: ObjRegistry(); ObjRegistry(const string &name); ~ObjRegistry(); /// Register a new object. Already registered objects are skipped. void Register(T &obj); /// De-register an object. void DeRegister(T &obj); /// De-register an object from its name. void DeRegister(const string &objName); /// De-register \e all objects from the list. void DeRegisterAll(); /// Delete all objects in the registry.. Use with caution !! void DeleteAll(); /** Get object #i in the registry. * \internal * Use with caution. The order of the objects * changes as objects are added and removed. */ T& GetObj(const unsigned int i); /** Get object #i in the registry. * \internal * Use with caution. The order of the objects * changes as objects are added and removed. */ const T& GetObj(const unsigned int i)const; /// Get an object from its name in the registry. /// The search starts at the *end* of the registry. T& GetObj(const string &objName); /// Get an object from its name in the registry. /// The search starts at the *end* of the registry. const T& GetObj(const string &objName)const; /// Get an object from its name in the registry. /// The search starts at the *end* of the registry. /// Also check the class of the object. T& GetObj(const string &objName, const string& className); /// Get an object from its name in the registry. /// The search starts at the *end* of the registry. /// Also check the class of the object. const T& GetObj(const string &objName, const string& className)const; /// Get the index of an object in the registry, from its name /// Warning: it can change if an object is removed from the registry long GetNb()const; void Print()const; void SetName(const string &); const string& GetName()const; /// Find the number of an object in the registry from its name (slow !) /// The search starts at the *end* of the registry. long Find(const string &objName)const; /// Find the number of an object in the registry from its name (slow !) /// The search starts at the *end* of the registry. /// Also check the class of the object (inheritance...). /// use nothrow=true to avoid having an exception thrown if no object /// is found (instead the index returned will be -1) long Find(const string &objName, const string& className, const bool nothrow=false)const; /// Find the number of an object in the registry /// The search starts at the *end* of the registry. long Find(const T &obj)const; /// Find the number of an object in the registry /// The search starts at the *end* of the registry. long Find(const T *pobj)const; /// Last time an object was added or removed from the registry const RefinableObjClock& GetRegistryClock()const; /** Enable the UI automatic update, so that objects in the registry are * automatically added to the UI. */ void AutoUpdateUI(const bool autoup=true); /** Manually update the UI, making sure all objects in the registry are displayed * This is useful when the automatic adding of objects has been disabled. * */ void UpdateUI(); /** STL access to object size */ std::size_t size() const; /** low-level access to the underlying vector begin(). * Const access as we do not want the number and order of objects to change, * but the objects themselves can be modified. * \warning: the iterator can be invalidated if the registry is modified */ typename vector::const_iterator begin() const; /** low-level access to the underlying vector end(). * Const access as we do not want the number and order of objects to change, * but the objects themselves can be modified. * \warning: the iterator can be invalidated if the registry is modified */ typename vector::const_iterator end() const; /** low-level access to the underlying list begin(). * Const access as we do not want the number and order of objects to change, * but the objects themselves can be modified. * This iterator should remain valid even if an object is removed. */ typename std::list::const_iterator list_begin() const; /** low-level access to the underlying list end(). * Const access as we do not want the number and order of objects to change, * but the objects themselves can be modified. * This iterator should remain valid even if an object is removed. */ typename std::list::const_iterator list_end() const; private: /// The registry of objects vector mvpRegistry; /// Another view of the registry of objects - this time as a std::list, which /// will not be invalidated if one object is deleted std::list mvpRegistryList; /// Name of this registry string mName; /// Last time an object was added or removed RefinableObjClock mListClock; /** Enable the user interface update. * If true, any time an object is added, it will be added to the user interface (wx...). * If objects have not been added to the user interface, this can be done asynchronously * using UpdateUI() which will go through the list of objects and add those not yet displayed. * * This does not affect the removal of objects. */ bool mAutoUpdateUI; #ifdef __WX__CRYST__ public: WXRegistry* WXCreate(wxWindow *parent); void WXDelete(); void WXNotifyDelete(); private: WXRegistry * mpWXRegistry; #endif }; /** \brief Generic Refinable Object * * This is basically a list of refinable parameters, with other basic common properties * such as a name,. etc... * This allows optimization/refinement algorithms to access the parameters without * knowing what the object really is. * * \todo Define more clearly which operations are recursive (ie also modify sub-objects). */ class RefinableObj { public: /// Constructor RefinableObj(); /// Constructor. Using internalUseOnly=true will avoid registering the /// the object to any registry, and thus (for example) no display will be created, /// nor will this object be automatically be saved. RefinableObj(const bool internalUseOnly); /// Defined not implemented... Should never be called /// (copying the refinable parameters would allow you to modify the /// input object). /// Use the default constructor and RefinableObj::AddPar(RefinableObj&) instead. RefinableObj(const RefinableObj &old); /// Destructor virtual ~RefinableObj(); /// Name for this class ("RefinableObj", "Crystal",...). This is only useful /// to distinguish different classes when picking up objects from the /// RefinableObj Global Registry virtual const string& GetClassName() const; /// Name of the object virtual const string& GetName() const; /// Name of the object virtual void SetName(const string &name); /** Defined not implemented... Should never be called */ void operator=(const RefinableObj &old); /// Find which parameters are used and \b not fixed, for a refinement /optimization. /// This \b must be called before any refinement... void PrepareForRefinement() const; /// Fix All parameters void FixAllPar(); /// UnFix All parameters void UnFixAllPar(); /// Fix/un-fix one parameter from its #. void SetParIsFixed(const long parIndex,const bool fix); /// Fix/un-fix one parameter from its name. void SetParIsFixed(const string& parName,const bool fix); /// Fix/un-fix one family of parameters void SetParIsFixed(const RefParType *type,const bool fix); /// Set whether a parameter is used void SetParIsUsed(const string& parName,const bool use); /// Set whether a family of parameters is used void SetParIsUsed(const RefParType *type,const bool use); /// Total number of refinable parameter in the object. Note that some /// may be actually fixed or even not used !! /// For refinement use PrepareForRefinement(), NbRefParNotFixed(), and /// ParNotFixed(i) long GetNbPar()const; /// Total number of non-fixed parameters. Is initialized by PrepareForRefinement() long GetNbParNotFixed()const; /// Access all parameters in the order they were inputted RefinablePar& GetPar(const long i); /// Access all parameters in the order they were inputted const RefinablePar& GetPar(const long i) const; /// Access all parameters from their name RefinablePar& GetPar(const string & name); ///Access all parameters from their name const RefinablePar& GetPar(const string & name) const; /// Access parameter from its adress RefinablePar& GetPar(const REAL*); /// Access parameter from its adress const RefinablePar& GetPar(const REAL*) const; /// Access all parameters in the order they were inputted, /// skipping fixed parameters. Must call PrepareForRefinement() before ! RefinablePar& GetParNotFixed(const long i); /// Access all parameters in the order they were inputed, /// skipping fixed parameters. Must call PrepareForRefinement() before ! const RefinablePar& GetParNotFixed(const long i)const; /** Add a refinable parameter. The parameter is copied, so * it need only be allocated temporarily. * * \deprecated Use the next function, which supplies the parameter as * a pointer, and avoids a useless copy. * \note: if a parameter is added and its name is already used by another, * its name will be automatically appended with an ~ */ void AddPar(const RefinablePar &newRefPar); /** Add a refinable parameter. The parameter is \e not copied, so * it should be allocated in the heap. * * \note: if a parameter is added and its name is already used by another, * its name will be automatically appended with an ~ */ void AddPar(RefinablePar *newRefPar); /** Add all the parameters in another RefinableObj. Parameters * are \not copied, so they should be allocated in the heap. * * \warning If a copy of another RefinableObj parameter list is made, * such as in the OptimizationObj class, make sure that upon deletion * of this object the parameters will not be destroyed. To do this * use RefinableObj::SetDeleteRefParInDestructor(false). * * \param copyParam: if false (default), then parameters are not copied * from the object but just referenced. Use RefinableObj::SetDeleteRefParInDestructor(false) * accordingly. If true, then the parameters are copied, so that any * modification to the fixed/limited/used attributes do not affect * the original parameter. Only the value and the parameter's clock * can then be modified by the copied parameter * * \note: if a parameter is added and its name is already used by another, * its name will be automatically appended with an ~ */ void AddPar(RefinableObj &newRefParList, const bool copyParam=false); /** Remove a refinable parameter. * * This returns an iterator to the next parameter in the vector. */ vector::iterator RemovePar(RefinablePar *refPar); virtual void Print() const; /** \brief Save the current set of refined values in a new set. * * \param name : the name associated to this set of values. Names should be unique. * \return an number identifying the set of saved values. * * \warning: there is no limit to the number of parameters sets, so try to * release them when you don't need them. */ unsigned long CreateParamSet(const string name="") const; /** \brief Erase the param set with the given id, releasing memory. */ void ClearParamSet(const unsigned long id)const; /** \brief Save the current set of refined values over a previously-created set *of saved values. * \param id the number identifying the set of saved values. */ void SaveParamSet(const unsigned long id)const; /** \brief Restore a saved set of values. * * \param id : the number identifying the set. * \warning this only affects parameters which are used. Others * remain unchanged. Parameters which are fixed are also restored, * although generally they will not be altered. */ void RestoreParamSet(const unsigned long id); /** \brief Access one save refpar set * * \param setId : the number identifying the set. */ const CrystVector_REAL& GetParamSet(const unsigned long setId)const; /** \brief Access one save refpar set * * \param setId : the number identifying the set. */ CrystVector_REAL& GetParamSet(const unsigned long setId); /** \brief Access the (human) value of one refined parameter in a saved set of parameters * * \internal * \param setId : the number identifying the set. * \param parNumber : the number identifying the parameter in the list of refined * parameters * \return if parNumber=5 and setId=37, then the returned value will be the value (scaled *if it is an angle) value of the 5th not-fixed parameter in the saved set #37. */ REAL GetParamSet_ParNotFixedHumanValue(const unsigned long setId,const long parNumber)const; /** \brief Erase all saved refpar sets * */ const void EraseAllParamSet(); /** \brief Get the name associated to a refpar set * * \param setId : the number identifying the set. */ const string& GetParamSetName(const unsigned long setId)const; /// Change the limits for a given parameter, giving absolute new limits void SetLimitsAbsolute(const string &parName, const REAL min, const REAL max); /// Change the limits for a category of parameters, giving absolute new limits void SetLimitsAbsolute(const RefParType *type, const REAL min, const REAL max); /// Change the limits for a given parameter, giving relative new limits (eg giving -.1 /// and +.1 will set new limits at the current value + min and current value + max) /// Thus min should logically be <0 and max >0. void SetLimitsRelative(const string &parName, const REAL min, const REAL max); /// Change the limits for a category of parameters, giving relative new limits /// (eg giving -.1 and +.1 will set new limits at the current value + min and /// current value + max). Thus min should logically be <0 and max >0. void SetLimitsRelative(const RefParType *type, const REAL min, const REAL max); /// Change the limits for a given parameter, proportionnaly to the current value. /// min should be < 1. and max > 1. void SetLimitsProportional(const string &parName, const REAL min, const REAL max); /// Change the limits for a category of parameters, proportionnaly to their current value. /// min should be < 1. and max > 1. void SetLimitsProportional(const RefParType *type, const REAL min, const REAL max); ///Change the maximum step to use during Global Optimization algorithms void SetGlobalOptimStep(const RefParType *type, const REAL step); /// Access to the registry of RefinableObj used by this object ObjRegistry& GetSubObjRegistry(); /// Access to the registry of RefinableObj used by this object const ObjRegistry& GetSubObjRegistry()const; /// Register a new object using this object /// \todo : the clients should be const, but are not... This need to be fixed... virtual void RegisterClient(RefinableObj &)const; /// Deregister an object (which not any more) using this object virtual void DeRegisterClient(RefinableObj &)const; /// Get the list of clients virtual const ObjRegistry& GetClientRegistry()const; /// Get the list of clients virtual ObjRegistry& GetClientRegistry(); /// Is the object being refined ? (Can be refined by one algorithm at a time only.) bool IsBeingRefined()const; /** This should be called by any optimization class at the begining of an optimization * * This will also check that everything is ready, eg call the RefinableObj::Prepare() * function. This also affects all sub-objects. * \note this may be called several time for some objects which are used by several * other objects, or for nested optimizations (e.g. least-squares optimizations * inside a global one). * * \note EndOptimization() must be called at the end of the optimization, the same * number of time BeginOptimization() was called ! * * \param allowApproximations: if true, then the object can use faster * but less precise functions during the optimization. This is useful for * global optimization not using derivatives. * \param enableRestraints: \deprecated if true, then restrained parameters will be allowed * to go beyond theur hard limits. This implies that the algorithm will take * into account the cost (penalty) related to the restraints. Objects which do not * use restraints will simply ignore this. WARNING: this parameter may be removed * with the new likelihood scheme. */ virtual void BeginOptimization(const bool allowApproximations=false, const bool enableRestraints=false); /** This should be called by any optimization class at the end of an optimization * * This also affects all sub-objects. * \note this may be called several time for some objects which are used by several * other objects. */ virtual void EndOptimization(); /** Enable or disable numerical approximations. This can be used for global optimization * to get faster calculations. Depending on the type of object, this may do something * or not (it does not do anything in a base RefinableObj, except calling this function * for all sub-objects). * * \note Currently there is no mApproximationFlag in the base class, but maybe there should... * * Also see: */ virtual void SetApproximationFlag(const bool allow); /// Randomize Configuration (before a global optimization). This /// Affects only parameters which are limited and not fixed. /// The randomization also affects all sub-objects (recursive). virtual void RandomizeConfiguration(); /** Make a random move of the current configuration. * * This is for global optimization algorithms. the moves for each * parameter are less than their global optimization step, multiplied * by the mutation amplitude. * * \warning: this makes a random move for the parameter declared * for this object, and it is the duty of the object to decide whether * the included objects should be moved and how. (eg an algorithm should * only call for a move with the top object, and this object decides how * he and his sub-objects moves). By default (RefinableObj implementation) * all included objects are moved recursively. * * RefinableObj:: * \param mutationAmplitude: multiplier for the maximum move amplitude, * for all parameters * \param type: restrain the change exclusively to parameters of a given * type (same type or descendant from this RefParType). */ virtual void GlobalOptRandomMove(const REAL mutationAmplitude, const RefParType *type=gpRefParTypeObjCryst); /** Raise a flag, to be sure not to make a random change more than once * in each RefinableObj. This calls recursively all sub-objects. * * This is necessary since one object may be included in several others. * This must be called before making a random configuration change on * a list of objects. */ void BeginGlobalOptRandomMove(); // Likelihood /** Get -log(likelihood) of the current configuration for the object. * * * By default (no likelihood evaluation available), this is equal to 0. * * This call should not be recursive, it is the task of the algorithm to * get the sum of likelihoods for all objects invlolved. * * \note contrary to the old "Cost Function" approach, with log(Likelihood) * there is no 'choice' of cost function, so that it is the task of the * object to give the optimized likelihood (possibly with user options). */ virtual REAL GetLogLikelihood()const; /* Get log(likelihood) and all its first derivative versus a list of parameters. * * \return: a map, with a RefinablePar pointer as key, and as value the corresponding * derivative. Note that the value of the map for the NULL key is the current value * for the log(likelihood), which is also returned. The map will include derivatives * only for parameters which have been supplied in vPar - but if a parameter * is listed in vPar and has a null derivative, it may be missing in the returned map. * * \warning: currently in development, to provide faster, analytic derivatives * * \note:ideally, this function should be const - but since numerical derivatives * may be used before all analytical formulas are entered, a non-const version is * required. * \todo */ //virtual std::map& GetLogLikelihood_FullDeriv(std::set &vPar); //LSQ functions /// Number of LSQ functions virtual unsigned int GetNbLSQFunction()const; // Get a Cost function name from its id#. //virtual const string& GetLSQFunctionName(const unsigned int)const; // Get the (short) description of a cost function //virtual const string& GetLSQFunctionDescription(const unsigned int)const; /// Get the current calculated value for the LSQ function virtual const CrystVector_REAL& GetLSQCalc(const unsigned int) const; /// Get the observed values for the LSQ function virtual const CrystVector_REAL& GetLSQObs(const unsigned int) const; /// Get the weight values for the LSQ function virtual const CrystVector_REAL& GetLSQWeight(const unsigned int) const; /** Get the first derivative values for the LSQ function, for a given * parameter. Note that the default method in the base RefinableObj * class is to use numerical derivatives, so it should be * overridden for better precision. * * \todo This should be a const method, and the given RefPar should be const too... */ virtual const CrystVector_REAL& GetLSQDeriv(const unsigned int, RefinablePar&); /** Get the first derivative for the LSQ function for each parameter supplied * in a list. * * \return: a map, with a RefinablePar pointer as key, and as value the corresponding * derivative vector. Note that the value of the map for the NULL key is the current value * for the LSQ function, which is also returned. The map will include derivatives * only for parameters which have been supplied in vPar - but if a parameter * is listed in vPar and has a null derivative, the returned vecor will be empty. * * \warning: currently in development, to provide faster, analytic derivatives * * \note:ideally, this function should be const - but since numerical derivatives * may be used before all analytical formulas are entered, a non-const version is * required. * \todo */ virtual std::map & GetLSQ_FullDeriv(const unsigned int,std::set &vPar); /// Re-init the list of refinable parameters, removing all parameters. /// This does \e not delete the RefinablePar if /// RefinableObj::mDeleteRefParInDestructor is false void ResetParList(); /** \brief Output to stream in well-formed XML * * \todo Use inheritance.. as for XMLInputTag()... */ virtual void XMLOutput(ostream &os,int indent=0)const; /** \brief Input From stream * * \todo Add an bool XMLInputTag(is,tag) function to recognize all the tags * from the stream. So that each inherited class can use the XMLInputTag function * from its parent (ie take advantage of inheritance). The children class * would first try to interpret the tag, then if unsuccessful would pass it to * its parent (thus allowing overloading), etc... */ virtual void XMLInput(istream &is,const XMLCrystTag &tag); //virtual void XMLInputOld(istream &is,const IOCrystTag &tag); /// If there is an interface, this should be automatically be called each /// time there is a 'new, significant' configuration to report. virtual void UpdateDisplay()const; //Options /// Access to the options list ObjRegistry& GetOptionList(); /// Number of Options for this object unsigned int GetNbOption()const; /// Access to the options RefObjOpt& GetOption(const unsigned int i); /// Access to the options by name RefObjOpt& GetOption(const string & name); /// const access to the options const RefObjOpt& GetOption(const unsigned int i)const; /// const access to the options by name const RefObjOpt& GetOption(const string & name)const; // Genetic /** \brief Get the gene group assigned to each parameter. * * Each parameter (a \e gene in terms of genetic algorithms) * can be assigned to a gene group. Thus when mating two configurations, * genes will be exchanged by groups. By default (in the base RefinabeObj class), * each parameter is alone in its group. Derived classes can group genes * for a better s** life. * * The number identifying a gene group only has a meaning in a given * object. It can also change on subsequent calls, and thus is not unique. * * \param obj the \RefinableObj, supplied by an algorithm class (OptimizationObj,..), * which contains a list of parameters, some of which (but possibly all or none) * are parameters belonging to this object. * \param groupIndex a vector of unsigned integers, one for each parameter in the * input object, giving an unsigned integer value as gene group index. * At the beginning this vector should contain only zeros (no group assigned). * \param firstGroup this is the number of groups which have already been assigned, * plus one. The gene groups returned by this object will start from this * value, and increment \b firstGroup for each gene group used, so that * different RefinableObj cannot share a gene group. * \note this function is not optimized, and should only be called at the beginning * of a refinement. */ virtual void GetGeneGroup(const RefinableObj &obj, CrystVector_uint & groupIndex, unsigned int &firstGroup) const; /** Set this object not to delete its list of parameters when destroyed. * * This is used for the RefinableObj in algorithms objects (OptimizationObj), * which only hold copies of parameters from the refined objects. */ void SetDeleteRefParInDestructor(const bool b); /** What was the last time a RefinablePar was added/removed ? * */ const RefinableObjClock& GetRefParListClock()const; // Restraints /** Get the restraint cost (overall penalty of all restraints) * * By default this returns 0, so this \e must be overloaded by any * object which actually uses restraint. * \note Instead, we could return by default the sum of the restraints, * but this is dangerous since we \e want to have derived objects fully * responsible for handling restraints. */ virtual REAL GetRestraintCost()const; /** Add a new restraint * * This returns an iterator pointing to the next Restraint in the vector. */ void AddRestraint(Restraint *pNewRestraint); /** Remove a restraint from the list of known restraints. This does not * delete the Restraint object. */ vector::iterator RemoveRestraint(Restraint *pRestraint); /** During a global optimization, tells the object that the current config is * the latest "best" config. * * This can be used by the object to make more intellingent random moves (use with * caution: highly experimental !). */ virtual void TagNewBestConfig()const; /// This clocks records _any_ change in the object. See refinableObj::mClockMaster const RefinableObjClock& GetClockMaster()const; /// Access to the integer address of this object, for unique identification from python size_t int_ptr() const; protected: /// Find a refinable parameter with a given name long FindPar(const string &name) const; /// Find a refinable parameter from the adress of its value long FindPar(const REAL*) const; /// \internal Add an object in the registry of used objects. void AddSubRefObj(RefinableObj &); /// \internal Remove an object in the registry of used objects. void RemoveSubRefObj(RefinableObj &); /// \internal Add an option for this parameter void AddOption(RefObjOpt *opt); /// \internal Prepare everything (if necessary) for an optimization/calculation. virtual void Prepare(); /// Find a parameter set with a given id (and check if it is there) map >::iterator FindParamSet(unsigned long id)const; ///Name for this RefinableObject. Should be unique, at least in the same scope.+ string mName; // Parameters /// Vector of pointers to the refinable parameters vector mvpRefPar; // Restraints /// Vector of pointers to the restraints for this object. This excludes /// all RefinablePar declared in RefinableObj::mpRefPar, which also /// are Restraint. vector mvpRestraint; //Saved sets of parameters /// Map of (index,pointers to arrays) used to save sets of values for all parameters. /// Currently there is no limit to the number of saved sets. /// /// This is mutable since creating/storing a param set does not affect the /// 'real' part of the object. mutable map > mvpSavedValuesSet; // Used during refinements, initialized by PrepareForRefinement() /// Total of not-fixed parameters mutable long mNbRefParNotFixed; /// Index of not-fixed parameters mutable CrystVector_long mRefparNotFixedIndex; /// Is the object being refined or optimized ? /// if mOptimizationDepth=0, no optimization is taking place. /// mOptimizationDepth>0 indicates the object is being optimized. Values /// larger than 1 indicate that several level of optimizations are taking place, /// e.g. one least-square optimization during a global optimization, etc... int mOptimizationDepth; /// Registry of RefinableObject needed for this object (owned by this object or not) ObjRegistry mSubObjRegistry; /// Registry of RefinableObject using this object. /// This is mutable so that client can modify it (kludge?) mutable ObjRegistry mClientObjRegistry; // Options for this object /// List of options for this object. Note that these are just references, /// to options allocated by the object, to have a simple global access to /// all options ObjRegistry mOptionRegistry; /// If true (the default), then all RefinablePar will be deleted when the /// the object is deleted. The opposite option (false) should only be used /// in RefinableObj holding 'copies' of other objects, such as in algorithms. bool mDeleteRefParInDestructor; /// Last time the RefinableParList was modified (a parameter added or removed). RefinableObjClock mRefParListClock; /// \internal This true is false if RefinableObj::GlobalOptRandomMove() has been called /// since RefinableObj::BeginGlobalOptRandomMove() was called. bool mRandomMoveIsDone; /// Temporary array used to return derivative values of the LSQ function for given /// parameters. mutable CrystVector_REAL mLSQDeriv; /// Temporary map to return the derivative of the LSQ function versus a list of parameters /// /// Several LSQ functions can be stored. /// /// \todo In development mutable std::map< unsigned int,std::map > mLSQ_FullDeriv; // Temporary map to return the derivative of log(likelihood) versus a list of parameters // // \todo In development //mutable std::map mLogLikelihood_FullDeriv; /// Master clock, which is changed whenever the object has been altered. /// It should be parent to all clocks recording changes in derived classes. RefinableObjClock mClockMaster; #ifdef __WX__CRYST__ public: /// Create a WXCrystObj for this object. Only a generic WXCrystObj pointer is kept. virtual WXCrystObjBasic* WXCreate(wxWindow*); WXCrystObjBasic* WXGet(); void WXDelete(); void WXNotifyDelete(); protected: WXCrystObjBasic *mpWXCrystObj; #endif }; /// Get the last time any RefinablePar was added in a recursive list of objects. void GetRefParListClockRecursive(ObjRegistry ®,RefinableObjClock &clock); /// Register a new object in a registry, and recursively /// include all included (sub)objects. template void RefObjRegisterRecursive(T &obj,ObjRegistry ®); /// Get the last time any object was added in the recursive list of objects. void GetSubRefObjListClockRecursive(ObjRegistry ®,RefinableObjClock &clock); /// Global Registry for all RefinableObj extern ObjRegistry gRefinableObjRegistry; /// This is a special registry for 'top' object for an optimization. In /// the ObjCryst++ class, this currently includes Crystal, PowderPattern and /// DiffractionDataSingleCrystal. extern ObjRegistry gTopRefinableObjRegistry; }//namespace #endif// _VFN_REFINABLE_OBJ_H_ objcryst-2022.1/ObjCryst/RefinableObj/Simplex.cpp000066400000000000000000000157361430515525000216610ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Simplex.cpp * source file for Conjugate Gradient Algorithm object * */ #include "ObjCryst/RefinableObj/Simplex.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" namespace ObjCryst { SimplexObj::SimplexObj(const string name): OptimizationObj(name) { } void SimplexObj::Optimize(long &nbSteps,const bool silent,const REAL finalcost, const REAL maxTime) { VFN_DEBUG_ENTRY("SimplexObj::Optimize()",10) for(int i=0;iPrepareRefParList(); const unsigned long n=mRefParList.GetNbParNotFixed(); // Create the n+1 set of parameters (n+1 vertices for the initial simplex) // To obtain the n new vertices we just move from the starting point // by the amount of the declared global optimization step. CrystVector_long vIndex(n+1); vIndex(0)=mRefParList.CreateParamSet(); CrystVector_REAL vLLK(n+1); vLLK(0)=this->GetLogLikelihood(); for(unsigned long i=0;iGetLogLikelihood(); mRefParList.RestoreParamSet(vIndex(0)); } unsigned long best=0,worst=0,nextworst=0; for(;nbSteps>=0;--nbSteps) { // determine best, worst and next worst points if(vLLK(0)>vLLK(1)){worst=0;nextworst=1;} else{worst=1;nextworst=0;} for(unsigned long i=1;i<=n;i++) { if(vLLK(i)<=vLLK(best)) best =i; if(vLLK(i)>vLLK(worst)) { nextworst=worst; worst=i; } else if((vLLK(i)>vLLK(nextworst)) && (i!=worst)) nextworst=i; } { CrystVector_REAL center(n); center = 0.0; for(unsigned long i=0;i<=n;i++) { if(i==worst) continue; center += mRefParList.GetParamSet(vIndex(i)); } center /= (REAL)n; CrystVector_REAL worstdiff; worstdiff=mRefParList.GetParamSet(vIndex(worst)); worstdiff-=center; for(unsigned long i=0;iOptimize(nbSteps,silent,finalcost,maxTime); if(!silent) cout <<"SimplexObj::MultiRunOptimize: Finished Run#"<GetLogLikelihood(); //cout<<"New,f="<ReadValue();} void Tracker::Clear() { mvValues.clear(); } const std::map& Tracker::GetValues()const{return mvValues;} std::map& Tracker::GetValues(){return mvValues;} //////////////////////////////////////////////////////////////////////// // // MainTracker // //////////////////////////////////////////////////////////////////////// MainTracker::MainTracker() { #ifdef __WX__CRYST__ mpWXTrackerGraph=0; #endif } MainTracker::~MainTracker() { #ifdef __WX__CRYST__ this->WXDelete(); #endif this->ClearTrackers(); } void MainTracker::AddTracker(Tracker *t) { mvpTracker.insert(t); mClockTrackerList.Click(); this->UpdateDisplay(); } void MainTracker::AppendValues(const long nb) { for(std::set::iterator pos=mvpTracker.begin(); pos!=mvpTracker.end();++pos) (*pos)->AppendValue(nb); mClockValues.Click(); } void MainTracker::ClearTrackers() { std::set::iterator pos; for(pos=mvpTracker.begin();pos!=mvpTracker.end();++pos) delete *pos; mvpTracker.clear(); mClockTrackerList.Click(); this->UpdateDisplay(); } void MainTracker::ClearValues() { std::set::iterator pos; for(pos=mvpTracker.begin();pos!=mvpTracker.end();++pos) (*pos)->Clear(); mClockValues.Click(); this->UpdateDisplay(); } void MainTracker::SaveAll(std::ostream &os)const { std::set::const_iterator posT,posT0; os<<"#Trial "; for(posT=mvpTracker.begin();posT!=mvpTracker.end();++posT) os<<(*posT)->GetName()<<" "; os<::const_iterator pos0,pos; for(pos0=(*posT0)->GetValues().begin();pos0!=(*posT0)->GetValues().end();++pos0) { const long k=pos0->first; os<GetValues().find(k); if(pos==(*posT)->GetValues().end()) os << -1.0 <<" "; else os << pos->second <<" "; } os< &MainTracker::GetTrackerList()const { return mvpTracker; } void MainTracker::UpdateDisplay()const { #ifdef __WX__CRYST__ if(0!=mpWXTrackerGraph)mpWXTrackerGraph->UpdateDisplay(); #endif } const RefinableObjClock& MainTracker::GetClockTrackerList()const{return mClockTrackerList;} const RefinableObjClock& MainTracker::GetClockValues()const{ return mClockValues;} #ifdef __WX__CRYST__ WXTrackerGraph* MainTracker::WXCreate(wxFrame *frame) { if(0==mpWXTrackerGraph) mpWXTrackerGraph=new WXTrackerGraph(frame,this); return mpWXTrackerGraph; } WXTrackerGraph* MainTracker::WXGet(){return mpWXTrackerGraph;} void MainTracker::WXDelete() { if(0!=mpWXTrackerGraph) { delete mpWXTrackerGraph; mpWXTrackerGraph=0; } } void MainTracker::WXNotifyDelete() { mpWXTrackerGraph=0; } #endif }//namespace objcryst-2022.1/ObjCryst/RefinableObj/Tracker.h000066400000000000000000000066031430515525000212710ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2005- Vincent Favre-Nicolin vincefn@users.sourceforge.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * header file ObjCryst++ Tracker class * */ #ifndef _REFINABLEOBJ_TRACKER_H_ #define _REFINABLEOBJ_TRACKER_H_ #include #include #include #include "ObjCryst/RefinableObj/RefinableObj.h" #ifdef __WX__CRYST__ namespace ObjCryst { class MainTracker; class Tracker; } #include "ObjCryst/wxCryst/wxTrackerGraph.h" #endif namespace ObjCryst { /** A class to track the variation of parameters as a function * of a number of cycles/trials. * * This is an abstract base class. */ class Tracker { public: Tracker(const std::string &name); virtual ~Tracker(); const std::string& GetName()const; void AppendValue(const long trial); /// Removes all stored values void Clear(); const std::map& GetValues() const; std::map& GetValues(); protected: virtual REAL ReadValue()=0; std::map mvValues; std::string mName; }; /** A class to hold all trackers * * All trackers need not have the same */ class MainTracker { public: MainTracker(); ~MainTracker(); void AddTracker(Tracker *t); void AppendValues(const long trial); /// Removes all Trackers void ClearTrackers(); /// Removes all stored values void ClearValues(); /// Will save to a single file if all recorded trial numbers are the same /// Otherwise ? void SaveAll(std::ostream &out)const; const std::set &GetTrackerList()const; /// Update display, if any void UpdateDisplay()const; /// Get last time a tracker was added const RefinableObjClock& GetClockTrackerList()const; /// Get last time values were whanged const RefinableObjClock& GetClockValues()const; private: std::set mvpTracker; /// Last time a tracker was added RefinableObjClock mClockTrackerList; /// Last time values were whanged RefinableObjClock mClockValues; #ifdef __WX__CRYST__ public: WXTrackerGraph* WXCreate(wxFrame*); WXTrackerGraph* WXGet(); void WXDelete(); void WXNotifyDelete(); protected: WXTrackerGraph *mpWXTrackerGraph; #endif }; /** Tracker for objects (RefinableObj, Crystal, PowderPattern, RefPar,...) * */ template class TrackerObject:public Tracker { public: TrackerObject(const std::string &name, const T&obj, REAL (T::*f)() const): Tracker(name),mpObj(&obj),mfp(f) {} private: const T *mpObj; REAL (T::*mfp)() const; REAL ReadValue(){return (mpObj->*mfp)();} }; }//namespace #endif objcryst-2022.1/ObjCryst/RefinableObj/bc32.mak000066400000000000000000000004331430515525000207430ustar00rootroot00000000000000!include ../rules.mak libRefinableObj.lib : Tracker.obj Simplex.obj RefinableObj.obj LSQNumObj.obj GlobalOptimObj.obj IO.obj tlib "libRefinableObj.lib" -+Tracker.obj -+Simplex.obj -+RefinableObj.obj -+LSQNumObj.obj -+GlobalOptimObj.obj -+IO.obj lib: libRefinableObj.lib all: lib objcryst-2022.1/ObjCryst/RefinableObj/gnu.mak000066400000000000000000000014171430515525000210060ustar00rootroot00000000000000BUILD_DIR=$(CURDIR)/../.. include $(BUILD_DIR)/ObjCryst/rules.mak # GeneticAlgorithm.o Powell.o ConjugateGradient.o OBJ= Tracker.o Simplex.o RefinableObj.o GlobalOptimObj.o IO.o LSQNumObj.o ifeq ($(profile),2) %.o : %.cpp @rm -f $(*F).gcda $(*F).gcno @$(MAKEDEPEND) ${CXX} ${CPPFLAGS} ${CXXFLAGS} -c $< -o $@ else %.o : %.cpp @$(MAKEDEPEND) ${CXX} ${CPPFLAGS} ${CXXFLAGS} -c $< -o $@ endif libRefinableObj.a : ${OBJ} @${RM} $@ ${AR} crs $@ ${filter-out %.a %.so, $^} -include $(OBJ:.o=.dep) lib: libRefinableObj.a default: lib all: lib # target for removing all object files .PHONY : tidy tidy:: @${RM} core *.o *.dep # target for removing all object files and libraries .PHONY : clean clean:: tidy @${RM} *.a *.exe cvsignore: cp -f ${DIR_CRYST}/.cvsignore ./ objcryst-2022.1/ObjCryst/RefinableObj/vc.mak000066400000000000000000000004211430515525000206170ustar00rootroot00000000000000!include ../rules.mak libRefinableObj.lib : Tracker.obj Simplex.obj RefinableObj.obj LSQNumObj.obj GlobalOptimObj.obj IO.obj lib -OUT:libRefinableObj.lib Tracker.obj Simplex.obj RefinableObj.obj LSQNumObj.obj GlobalOptimObj.obj IO.obj lib: libRefinableObj.lib all: lib objcryst-2022.1/ObjCryst/doc/000077500000000000000000000000001430515525000157435ustar00rootroot00000000000000objcryst-2022.1/ObjCryst/doc/.cvsignore000066400000000000000000000001771430515525000177500ustar00rootroot00000000000000*.o *.exe *.out *.old *.dep *.a .directory .systemG.Desktop tags html latex *.oxy *.xml profile.0.0.0 *.pov Makefile rules.mak objcryst-2022.1/ObjCryst/doc/Doxyfile000066400000000000000000000224231430515525000174540ustar00rootroot00000000000000# Doxyfile 1.5.5 #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = FOX/ObjCryst++ PROJECT_NUMBER = "1.8.X (development)" OUTPUT_DIRECTORY = . CREATE_SUBDIRS = NO OUTPUT_LANGUAGE = English BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = YES ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the ALWAYS_DETAILED_SEC = NO INLINE_INHERITED_MEMB = NO FULL_PATH_NAMES = NO STRIP_FROM_PATH = STRIP_FROM_INC_PATH = SHORT_NAMES = YES JAVADOC_AUTOBRIEF = YES QT_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO DETAILS_AT_TOP = NO INHERIT_DOCS = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 3 ALIASES = OPTIMIZE_OUTPUT_FOR_C = NO OPTIMIZE_OUTPUT_JAVA = NO OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_OUTPUT_VHDL = NO BUILTIN_STL_SUPPORT = NO CPP_CLI_SUPPORT = NO SIP_SUPPORT = NO DISTRIBUTE_GROUP_DOC = NO SUBGROUPING = YES TYPEDEF_HIDES_STRUCT = NO #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- EXTRACT_ALL = NO EXTRACT_PRIVATE = YES EXTRACT_STATIC = YES EXTRACT_LOCAL_CLASSES = NO EXTRACT_LOCAL_METHODS = NO EXTRACT_ANON_NSPACES = NO HIDE_UNDOC_MEMBERS = NO HIDE_UNDOC_CLASSES = NO HIDE_FRIEND_COMPOUNDS = NO HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = YES CASE_SENSE_NAMES = NO HIDE_SCOPE_NAMES = NO SHOW_INCLUDE_FILES = NO INLINE_INFO = NO SORT_MEMBER_DOCS = YES SORT_BRIEF_DOCS = NO SORT_GROUP_NAMES = NO SORT_BY_SCOPE_NAME = NO GENERATE_TODOLIST = YES GENERATE_TESTLIST = NO GENERATE_BUGLIST = YES GENERATE_DEPRECATEDLIST= YES ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES SHOW_DIRECTORIES = NO FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- QUIET = YES WARNINGS = YES WARN_IF_UNDOCUMENTED = NO WARN_IF_DOC_ERROR = YES WARN_NO_PARAMDOC = NO WARN_FORMAT = "$file:$line: $text" WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- INPUT = ../doc/ \ ../ObjCryst/ \ ../CrystVector/ \ ../RefinableObj/ \ ../Quirks/ \ ../wxCryst/ INPUT_ENCODING = UTF-8 FILE_PATTERNS = *.h \ *.cpp RECURSIVE = NO EXCLUDE = EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = PDF* EXCLUDE_SYMBOLS = EXAMPLE_PATH = EXAMPLE_PATTERNS = EXAMPLE_RECURSIVE = NO IMAGE_PATH = INPUT_FILTER = FILTER_PATTERNS = FILTER_SOURCE_FILES = YES #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- SOURCE_BROWSER = YES INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES REFERENCED_BY_RELATION = NO REFERENCES_RELATION = NO REFERENCES_LINK_SOURCE = NO USE_HTAGS = NO VERBATIM_HEADERS = NO #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- ALPHABETICAL_INDEX = YES COLS_IN_ALPHA_INDEX = 4 IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_HTML = YES HTML_OUTPUT = html HTML_FILE_EXTENSION = .html HTML_HEADER = HTML_FOOTER = HTML_STYLESHEET = HTML_ALIGN_MEMBERS = YES GENERATE_HTMLHELP = NO GENERATE_DOCSET = NO DOCSET_FEEDNAME = "Doxygen generated docs" DOCSET_BUNDLE_ID = org.doxygen.Project HTML_DYNAMIC_SECTIONS = YES CHM_FILE = HHC_LOCATION = GENERATE_CHI = NO BINARY_TOC = NO TOC_EXPAND = NO DISABLE_INDEX = NO ENUM_VALUES_PER_LINE = 4 GENERATE_TREEVIEW = YES TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- GENERATE_LATEX = YES LATEX_OUTPUT = latex LATEX_CMD_NAME = latex MAKEINDEX_CMD_NAME = makeindex COMPACT_LATEX = YES PAPER_TYPE = a4wide EXTRA_PACKAGES = LATEX_HEADER = PDF_HYPERLINKS = NO USE_PDFLATEX = YES LATEX_BATCHMODE = YES LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- GENERATE_RTF = NO RTF_OUTPUT = rtf COMPACT_RTF = NO RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- GENERATE_MAN = NO MAN_OUTPUT = man MAN_EXTENSION = .3 MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- GENERATE_XML = NO XML_OUTPUT = xml XML_SCHEMA = XML_DTD = XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- GENERATE_PERLMOD = NO PERLMOD_LATEX = NO PERLMOD_PRETTY = YES PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- ENABLE_PREPROCESSING = YES MACRO_EXPANSION = NO EXPAND_ONLY_PREDEF = NO SEARCH_INCLUDES = YES INCLUDE_PATH = INCLUDE_FILE_PATTERNS = PREDEFINED = DOXYGEN_SKIP_THIS \ __WXCRYST__ EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- TAGFILES = GENERATE_TAGFILE = ALLEXTERNALS = NO EXTERNAL_GROUPS = YES PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- CLASS_DIAGRAMS = YES MSCGEN_PATH = HIDE_UNDOC_RELATIONS = YES HAVE_DOT = YES CLASS_GRAPH = YES COLLABORATION_GRAPH = YES GROUP_GRAPHS = NO UML_LOOK = NO TEMPLATE_RELATIONS = YES INCLUDE_GRAPH = YES INCLUDED_BY_GRAPH = YES CALL_GRAPH = NO CALLER_GRAPH = NO GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = NO DOT_IMAGE_FORMAT = png DOT_PATH = DOTFILE_DIRS = DOT_GRAPH_MAX_NODES = 20 MAX_DOT_GRAPH_DEPTH = 3 DOT_TRANSPARENT = YES DOT_MULTI_TARGETS = YES GENERATE_LEGEND = YES DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- SEARCHENGINE = NO objcryst-2022.1/ObjCryst/doc/doc-install.h000066400000000000000000000164621430515525000203360ustar00rootroot00000000000000/*! \page page_install ObjCryst++ Download & Installation Notes * * This project is still in active development, even if I left the Lab of Crystallography * in Geneva to the ESRF. If you encounter some problem * with the library, please contact me at vincefn@users.sourceforge.net * and I'll try to help. * * Also note that if you want to develop something using ObjCryst++, I recommend * to contact me so that I can help you and avoid possible conflicts. * There are numerous things I want to implement, so an incompatibility is always * possible when I had something... * * Yuu should also subscribe to the mailing-lists at: http://sourceforge.net/mail/?group_id=27546 * and most especially the "objcryst-devel" and "objcryst-announce". * *\section download Download * You can download the ObjCryst library from the * ObjCryst project page * on SourceForge, * or from the mirrors: * - CCP14 (UK) * - CCP14 (Ca) * - CCP14 (USA) * - University of Geneva * * You will need to download the ObjCryst tar.bz2 (.zip for windows), as well as * the 'external libraries' tar.gz (.zip) archives (the latter include libraries which are * used by this project: currently atominfo,sglite and newmat). Simply uncompress both archives * in the same directory. This will create the atominfo, sglite and newmat directories, * as well as the ObjCryst directory. This documentation is in ObjCryst/doc/html/ * * If you want to use the Graphical Interface part of the library (wxCryst), e.g. * if you want to compile Fox, you will also need to download wxWindows * from http://www.wxwindows.org. Depending on your OS, you will need wxGTK-2.2.7 * (for Linux), or wxMSW-2.2.7 (for Windows). * *\section cvs CVS Repository * The cutting-edge version of the library can always be obtained through its CVS repository. * Under linux, to download the first time the ObjCryst++ directory, first * login in the CVS repository (give a blank password when asked) and then * download the ObjCryst source:\code * cvs -d:pserver:anonymous@cvs.objcryst.sourceforge.net:/cvsroot/objcryst login * cvs -d:pserver:anonymous@cvs.objcryst.sourceforge.net:/cvsroot/objcryst checkout ObjCryst * \endcode * once you have done this once, you can update to the current version by typing:\code * cvs update \endcode (with a blank password) at the root of the ObjCryst directory. * * For further questions about cvs (doing this under windows, etc...): http://www.cvshome.org/ * *\section compile Compiling * *\par ANSI C++ Compliance * The ObjCryst++ library makes use of some (relatively) recent C++ features, such as * templates, exceptions, mutable members. This implies that you need a compiler with * reasonable C++ compliance in order to use this library. Currently tested are the * GNU Compiler gcc on Linux and the Free Borland C++ compiler v5.5 under Windows * Metrowerks Codewarrior Pro 6 on MacOS should work, too, but has not been * tested recently. *\par Makefiles * Under linux (resp. windows), copy the rules-gnu.mak (resp. rules-bc32.mak) * to rules.mak at the root of the ObjCryst directory. You can edit this file * to check the paths and (for Windows) some compiling options. * *\section platform Platforms *\par Linux * The library is developped on a Linux computer, using the * GNU compiler gcc , version 2.95.3 (release) or more recent (not tested yet on * gcc 3.0+). *\par Windows * The library has been tested under windows (NT,98) using the * * free Borland C++ compiler 5.5. As for the cygwin gcc port, I encountered a few * problems with the standard library packaged with it so it does not work now. *\par Macintosh * The library can also be compiled on MacOS, using * Metrowerks Codewarrior Pro 6 (version 5 should work, too). Note that no tests have * been made recently on the macintosh... and absolutely no tests on the * wxWindows part on the Macintosh (ie so far console only on the Mac). * *\section wxwindows Compiling wxWindows * To use the graphical part of ObjCryst++ (wxCryst), you must first compile * wxWindows. To do this under Linux, in the wxWindows directory:\code * ./configure --with-opengl --disable-shared * make FINAL=1 * \endcode (this will take some time) * * Under windows, follow the compile instruction for Borland C++ 5.5 * in the wxWindows documentation, and make sure * you (i) activate opengl support and (ii) deactivate debug-context in setup.h. * You can leave all other options at default values. * *\section example Example * There is a short example in the ObjCryst/example/pbso4 directory. *\par Linux * Under linux, change to the ObjCryst/example/pbso4 directoryand simply type:\code * make -f gnu.mak wxcryst=1 opengl=1 debug=0 all \endcode * * (use wxCryst=0 if you do not want the Graphical interface, and debug=1 for * faster compiling and debugging messages. Not that anytime you change one of * these options, you need to clean up all directories: type "make -f gnu.mak clean" * at the root of the ObjCryst directory) * * That should compile all necessary libraries and programs. * You can try the different example programs, running on PbSO4, on neutron * and X-Ray powder diffraction, as well as X-Ray single crystal * (in fact, extracted intensities) *\par Windows * Under Windows (a DOS command prompt), change to the ObjCryst/example/pbso4 and do:\code * make -f bc32.mak all \endcode * * \subsection example_result * On a 500 Mhz linux box, pbso4-xray2 (using only the first 80 reflections and no * dynamical occupancy correction), * 50000 trials are done in less than 30 s (for 5 independent atoms, each with 4 * symetrics (not counting the center of symmetry): that's * 80*50000*5*4/27.2 = 2.9 10^6 reflection.atom per second). * For pbso4-xray and pbso4-neutron, it takes 2 to 3 more time, using only the first * 90 degrees of the powder pattern (about 80 reflections again), because a full * powder spectrum is generated (applying profiles is slow), and dynamical occupancy * correction is used to take special positions into account (computing distances * takes a lot of time). On the final structure output, note that the population consists * of two factor, the first (1.0 here) is the 'real' occupancy of the site, and the * second is the dynamical correction due to the fact that several identical atoms * overlap (For PbSo4, all atoms should be at 0.5 dyn corr). * *\section fox Fox * To compile Fox, simply go to the ObjCryst/wxCryst directory and do: * - under Linux : \code make -f gnu.mak wxcryst=1 opengl=1 debug=0 all \endcode * - under windows: \code make -f bc32.mak all \endcode * * For both, you will of course need to have compiled wxWindows beforehand. */ objcryst-2022.1/ObjCryst/doc/doc-main.h000066400000000000000000000332651430515525000176140ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* doc-main.h * This file includes only documentation, to be formatted automatically by doxygen. */ /*! \mainpage %ObjCryst++ Object-Oriented Crystallographic Library * *\section warning Warning- General documentation outdated * Most of the general text in this documentation (status, etc...) is really * outdated, but should be helpful to understand the general use about the * library. The detailed class documentation, however, is always up-to-date * (it can be incomplete, though). * *\section index Index * \li ObjCryst++ Homepage * \li Project page on SourceForge * \li \ref page_install * \li \ref page_status * \li \ref page_wishlist * \li \ref page_legal * \li \ref page_oop * \li \ref page_design * *\section news News * The new version of ObjCryst++ has been added to Sourceforge. Note that there could remain * missing points in the documentation, especially for the graphical interface part (wxCryst). * * The new version includes major changes for several classes (ScatteringPower, PowderPattern), * and includes the graphical classes associated with all objects using * wxWindows, and saving all objects using a new, * more expandable XML-based format. * *\section intro Introduction *\par Overview of the project * * The aim of this project is to provide object-oriented tools for Crystallography. The * focus of these tools is the analysis of diffraction data, with an emphasis * on speed optimization for repetitive calculations (for global refinement methods such * as simulated annealing, for example). * *\par * To have an overview of all available libraries, go to the Class Hierarchy. *\par * Even if we intend to use this library mainly for the development of a global optimization * program from powder diffraction, this library is programmed in a general way so that * other applications can make use of it. * The library was designed to be reusable, by adding new kind of experiments, new algorithms, * new Scatterer type, new ScatteringPower,... See \ref page_design to learn more about * the object-oriented design of this library and why it is good for its expandability. * *\par Contributors * Design & implementation: Vincent Favre-Nicolin (http://v.favrenicolin.free.fr/), * vincefn@users.sourceforge.net *\par * This project was initiated in the laboratory of Crystallography of the University * of Geneva (http://www.unige.ch/crystal/), and is part of the development of a global * optimization program with Radovan Cerny (http://www.unige.ch/crystal/cerny/rcerny.htm). * \par * This project has been supported by the Swiss * National Science Foundation (#21-53847.98). * *\par * This project also makes use of some other programs or libraries. Most notable in this * project are the spacegroup (SgLite) and atominfo packages from * R. Grosse-Kunstleve * (see \ref page_legal). * *\par * This page & project is hosted on * SourceForge Logo * */ /*! \page page_legal License Information *\par Copyright * The ObjCryst++ library is copyright (2000-2002) * Vincent FAVRE-NICOLIN * and (2000-2001) The University of Geneva (Switzerland) *\par License * This is free software, * but not public domain. By using it, you agree to the terms of the * GPL license (General Public License), * which you can find in the top directory of the ObjCryst++ package. * Should you wish to use this library in a closed-source project, * please contact the author for possible conditions. *\par Included libraries * Software libraries distributed with this package (but not written by V. Favre-Nicolin) * do not fall under the terms of the above copyright and license: * these are the atominfo, sglite and newmat package. You should * refer to the documentation and legal notes included in their respective directories: *\par * The newmat matrix library (Robert B Davies). * This library is only used * for matrix SVD decomposition and inversion in Least Squares methods (Least Squares * method was written only for tests purposes... Don't expect anything from it...). *\par * The atominfo library(Ralf Grosse-Kunstleve). * This library is used to * determine the atomic scattering factors for X-Ray, neutrons, as well as anomalous * scattering factors and the atomic number. *\par * The SgLite library(Ralf Grosse-Kunstleve). * Note that this package * is part of the PyMOL Molecular * Graphics System (used with permission), * and is not free software. It is used to derive symmetry operations from a given * spacegroup symbol or number. * *\par * The Blitz++ array library (Todd Veldhuizen). * This library * is used for data storage and calculation in arrays and vectors. (Currently it * is \e not used because of the huge memory requirements when compiling blitz++ expressions * using the gcc compiler. Instead the CrystVector and CrystMatrix are used, emulating * the blitz interface, but without the smart handling of mathematical expressions.) Support * for the Blitz++ should come back some time... */ /*! \page page_oop Why is Object Oriented Programming good for Crystallographic Computing ? *\par Reusability * The \b encapsulation of data and \b inheritance * (and other features such as templates) allows a much better * reusability of the code: adding new procedures does not require to understand how other * function works, since these are only accessed through the object interface. * And inheritance allows to create new object types (say new diffraction experiments) while * re-using computing code from the base object: for example all diffraction analysis involves * the computing of geometrical structure factors ( geometrical meaning before taking * scattering power into account), so that different diffraction ( X-Ray, neutron, electron, * single crystal or powder) can re-use this code. See \ref page_design for examples * on how to use inheritance to create new classes using inheritance. * * \par Philosophy * Re-usability in Object-oriented programming can be achieved by designing a base * class interface which can be re-used for all derived classes using inheritance. It * is much better than having isolated functions or small classes, since not only * old code can be re-used, but the new code is compatible with the old because it has * a common interface.. (of course the base interface must be well written and that * is delicate to achieve... Hope I did not do too bad a job of it...). * *\par Performance * Although it has long been considered that the price of OOP was a slower * execution speed, modern scientific & computing libraries have made that wrong, and c++ * is now widely used for large-scale computations. A short explanation is that c++ * is both a high-level language (object-oriented), and low-level since it uses * pointers and thus programming can be very close to assembly. This latter point is a boon * for numerically-intensive programs. *\par * For good examples of numerically intensive calculations using c++, you take a look at: *\par * -> The home page for Scientific Computing in Object-Oriented Languages: * http://www.oonumerics.org/ *\par * -> \b POOMA (http://www.acl.lanl.gov/pooma/)Parallel Object-Oriented Methods and Applications *\par * -> \b Blitz++ home page (http://www.oonumerics.org/blitz/): * a 'smart' array computing library which yields performance on par * with that of fortran. */ /*! \page page_design The Design of ObjCryst++ * If you have any comment or suggestion about this you can * drop me an email. * * Also read \ref page_oop. * * \section overview Overview of the Library (Crystallographic classes) * \par Scatterer * A Scatterer is the common denominator for any scattering object: all it includes * is a function which gives a list of positions in fractional coordinates, with a * scattering power associated to each position (Scatterer::GetScatteringComponentList()). * It also includes a few functions for the display (3D) of the object. * \par * All Scatterer can be derived from such a class: Atom, ZScatterer. The advantage of using * inheritance is that all derived classes \b must re-use the functions declared in the base * class, so that \e any function which knows what a generic 'Scatterer' object (but does not * know what an Atom or ZScatterer is) can still use any derived class. * \par * \e Further \e development \e example: currently there is no 'rigid body' object: if any * developper wants to create such an object, he just needs to make sure he rewrites the function * GetScatteringComponentList(). Thus without any modification, the Crystal and ScatteringData * classes will automatically be able to use this new object... since this RigidBody object * is derived from the Scatterer class (which Crystal and ScatteringData know). * * \par ScatteringPower * This class can compute the scattering, resonant and thermic factor for any ScatteringData * object (eg a list of reflections with some metric information). The three member function * GetScatteringFactor(), GetTemperatureFactor(),GetResonantScattFactReal(), and * GetResonantScattFactImag() can be used to get the corresponding factors for a list * of reflections (and wavelengths for resonant terms) in a ScatteringData object. * \par * The base class is designed to handle anisotropic factors: for this the index of * the symetric position in the Spacegroup must be given. * \par * \e Further \e development \e example: currently only the interface to handle anisotropy * has been written, but no code or derived class. But no matter what kind of anisotropy * is added, it will always work with the base class interface. * \par * \e Note: why always use a ScatteringData object as input (to compute scattering factors, * for example), rather than, say, a list of HKL or a list of sin(theta/lambda) ? The * first reason is that from a ScatteringData you can extract all these * hkl's and sin(theta)/lambda. The second reason is that with such an approach, no matter * how complex the derived classes are, you can always use the same interface * (for isotropic thermic factors as well as anharmonic !), so that any function * written with only the knowledge of the base class can use any derived class. * * \par Crystal * a Crystal is a unit cell with an associated SpaceGroup with a list of Scatterer. * * \par ScatteringData * The ScatteringData is a base class which is basically a list of reflections with the * ability to compute structure factors. The DiffractionDataSingleCrystal and * PowderPatternDiffraction classes are derived from it. * * \section optim Optimization design * \par RefinableObj * The RefinableObj is the base class for almost all objects in the library. The advantage * of such a design (see the inheritance tree on the ObjCryst::RefinableObj page) is that * when you design an algorithm, you do not need to know what kind of object is refined. All * you need to know is (i) how many parameters there are (ii) how to move these parameters * (iii) how to access one or several 'cost function' for the optimized object (to * characterize 'how good' the current configuration is). Indeed, the global optimization * class (for simulated annealing and parallel tempering) does not include any of the * crystallographic headers, and yet it can refine the crystal structures... * \par * This design does not mean that only 'stupid' algorithms can be handled. Since the * 'random moves' are handled by the refined objects, this 'random moves' can be very * non-random (for example in the Crystal object, permutation of Scatterers is made from * time to time...). * \par * What if you are \e not interested in the RefinableObj functionnality ? You can simply * ignore it, it will not do any harm. You can do other crystallographic work by 'forgetting' * that a Crystal, PowderPattern, Atom is a RefinableObj. Even new derived objects do not * have to declare their parameters as 'RefinablePar', if you want to save some memory. * \par * what is currently lacking in RefinableObj is (i) a way to set constraints/restraints * (currently there are only limits for individual parameters), the ability to have * arrays of RefinablePar (to handle large structure without a significant memory penalty), * and a design for analytical derivatives (well I've got a few ideas about this but * this is not a priority yet...). */ objcryst-2022.1/ObjCryst/doc/doc-status.h000066400000000000000000000226021430515525000202040ustar00rootroot00000000000000/*! \page page_status Current status and development history of ObjCryst++ * * If you have a question you can * drop me an email * * *\section history History *\par 1.1 * \li INCOMPATIBLE CHANGES:GlobalOptimObj has been replaced by MonteCarloObj, * RefinableObj::GetClassName now returns a "const string&", and * RefinableObj::BeginOptimization has two parameters, to enable * approximations and restraints * \li now one can choose either float or double for precision. The default * is float for global optimization. * \li Changed RefinableObj::BeginOptimization to pass two flags to enable * approximations (faster) and restraints before beginning an optimization. * \li ZScatterer: worked on ZScatterer::GlobalOptimRandomMove(), * to give the possibility of making 'smart' moves, especially for * molecules. * \li Scatterer: removed the ZScatterer::Update() function from the base * Scatterer class, as previously scheduled. * \li OptimizationObj: Forked the algorithms classes, with a base OptimizationObj * class, derived (currently) to a MonteCarloObj class (which replaces the * old GlobalOptimiObj class, for simulated annealing and parallel * tempering). Also added a tentative GeneticAlgorithm class, still * in very early development and not usable yet for the common mortal. * \li restraints: added base Restraint class, not really used so far. * \li cleaned up a bit wxCryst classes in the hope to remove any GUI * bugs. Still some crashes under windows, unfortunately... * *\par 1.02(2001-nov 12th) * \li PowderPattern: Added the input format for Sietronics (.cpi) files. * Now importing data will allow null points without crashing. Also * when no phase (background, crystal) has been added to the pattern, * the calculated pattern returns a constant value (1.). * \li ZScatterer: corrected a bug in the fractionnal coordinates * calculation for mono/triclinic unit cells (thanks Mark Edgar). * *\par 0.9.1(2001-09-20-) * \li ZScatterer: corrected a nasty bug(thanks Yuri Andreev), * which made the Z-Matrix interpretation completely wrong. * \li wxRefPar: now all refinable parameters have a local menu * which can be used to remove or change limits. * \li wxZScatterer: now can globally change relative limits to * bond lengths and angles. * *\par 0.9(2001-09-18-first FOX Release) * \li wxCryst is now working, allowing the first compilation of Fox. * \li The data format to save files has been changed to an xml format * (see http://www.w3.org/XML/). * \li the definition of the refinable parameter types (RefParType) * are now made using pointers, in a tree-like fashion. This allows * an easier modification of status for groups of parameters. * \li Lots of other modifications... * *\par 0.5(july 2001) * \li Design largely improved for reusability (based on inheritance). * \li wxCryst (the GUI-Graphical User Interface) part is * in fast-moving development, mostly working, but not included here as code is still * ugly and its design is not stable. As of 10/july/2001, I can launch the program, * create a crystal, add a PowderPattern object, a GlobalOptimization object and do * the global optimization while looking at the 'live' evolution of the Crystal Structure * (3D display with OpenGL) and of the PowderPattern ! * \li Saving structures, data to files has been implemented. See RefinableObj::XMLOutput(). * Refinement flags are not saved (yet). * \li Changed all float to REAL precision. Performance hit=+15% on structure factor, * and +25% on full powder spectrums. * *\par 0.6(march 2001) * First public release. * *\par 0.5 (february, 2001): *\li ZPolyhedron * Added a ZPolyhedron class, based on the Zscatterer objects, to describe (almost) regular * polyhedra. *\li Interatomic distance calculations * Improved speed computation of the internel distance table, using non-symetrical atoms * and the Asymmetric unit cell. *\li AsymmetricUnit Cell * Finally implemented the AsymmetricUnit Cell class, to improve distance calculation. * Currently, upon Spacegroup construction, the (or one of the) smallest parallelepiped * (with sides parallel to the crystallographic axes) including an Asymmetric unit is computed, * using steps of 1/24. (So technically it is not an asymmetric unit cell, if no asymmetric * unit cell exists for the group with all vertices parallel to the unit cell faces) * *\par 0.4 (january 2001): *\li ZScatterer * Added a Zscatterer class, were cluster of atoms or molecules can be defined using * a Z-Matrix description (see http://chemistry.umeche.maine.edu/Modeling/GGZmat.html * or http://www.arl.hpc.mil/PET/cta/ccm/training/tech-notes/model/node4.html for a description * of what such a matrix is. The advantage of this description is that it will now be possible * to describe molecules using relevant parameters (separating bond lengths, bond angles * and dihedral angles), and that polyhedra (for inorganic crystals) can also be described by it. *\li Special positions-Dynamical Correction * Added a function to compute a 'smooth' correction of population * as several atoms overlap (this is a dynamical correction during model search) *\li Compilation & Makefiles * Cleaned up directories & makefile to minimize platform dependencies. All * platform-dependant commands should be in rules.mak, in the top directory. * *\par 0.3 (2000, november 24) : *\li RefinablePar * Now Scatterer, DiffractionData and Crystal inherit are children of RefinableParList, *which makes the 'refining' methods easier to write & use. *\li Compilation on Win32-Cygwin * Compilation works using the win32 port of gcc by cygnus : http://www.cygwin.com. * * *\par 0.2 (2000, november 07) : *\li SpaceGroup * Moved to SgLite package, thanks to R. Grosse-Kunstleve. *\li Powder Diffraction * Most of features needed for 'basic' powder profile spectrum generation/analysis * has been added (DiffractionDataPowder). *\li Least-Squares * Added an LSQObjNum class, to perform Least-Squares Refinement. * Num stands for 'numerical', since only numerical derivatives are used * for that object. Uses eigenvalue filtering to avoid correlations. *\li DiffractionData * is now an abstract base class, with children * DiffractionDataSingleCrystal, DiffractionDataPowder. * *\par 0.1 : *\li General * The basic classes (SpaceGroup, Crystal, Scatterer, Scatterer:Atom, * Scatterer:RegularPolyhedra, DiffractionData) are there. *\li Speed * Computing of structure factors works with a fair speed. * */ /*\section status Current Status * The Library is moving along beta stage. The interface has been changed to * a better design, especially for the scattering/diffraction class. The RefinableObj * is also being improved to be more 'generic' and easier to use with varied algorithms. *\par Spacegroup * Thanks to the sglite package, all SpaceGroup can be recognized from their symbol. * An AsymmetricUnit is also generated for each spacegroup (actually it is a parallelepipedic * approximation). Only 3D spacegroup are allowed. * We will eventually (that is, when I find time... at the autumn 2001, move * to the cctbx library *\par Crystal * For a Crystal, definition of spacegroup and adding of various types of scatterers * are working. Dynamical occupancy correction * for global optimizations has been implemeted (to correct overlap of identical * atoms due to sharing of corner atoms in polyhedra, or due to symmetry). An anti-bump * cost function (simple) is also implemented, and also enables atoms to merge continuously. * An output to povray file is provided, as well as an OpenGL display of the cystal structure * (only tested using Mesa under linux, with glut). Most important lacking features are * saving structure to CIF files. *\par Scatterer * Various type of Scatterer are provided : simple Atom but also ZScatterer, using a * Z-Matrix Description, and derived form it are ZPolyedron (tetrahedron...icosahedron..). * other types of scatterer can easily be added. So far the scattering power and thermic * factor must be isotropic. Scattering factors for X-Rays (Thomson using the interpolated * values and resonant (anomalous using either Sasaki or Henke tables) and neutrons are * provided. *\par ScatteringData * PowderPattern is the most developped class and its support is sufficient * for most Global Optimization work. DiffractionDataSingleCrystal is less being worked on, * but it can be used provided that the data has been corrected and merged beforehand. *\par Global optimization * GlobalOptimObj provides an algorithm for the so-called 'ab initio' structure determination * from diffraction data using either a simulated annealing or a parallel tempering * algorithm. Genetic algorithm may be added later. *\par Least Squares * LSQObjNum class provides a rough least squares support, but it is definitely not * the purpose (as of yet, at least) of this library. The most important lack is * that numerical derivatives are systematicllay used. I wrote this only for testing * purposes and have not sed it for some time, so try it at your own risk ! *\par Graphical user interface * Most objects have a graphical counterpart, which has been created using the * wxWindows (linux,unix,windows,mac,...) * library. The result is the * Fox program, but the GUI * interface can be used for any other purpose. It is of course possible * to use ObjCryst++ without the wxObjCryst part. */ objcryst-2022.1/ObjCryst/doc/doc-todo.h000066400000000000000000000057011430515525000176270ustar00rootroot00000000000000/*! \page page_wishlist Wishlist/Todo page for ObjCryst++ * * (stars indicate priority/complexity : (*****,**) is urgent,fairly easy) * *\section external Outside features *\par Examples * Make a few examples for each feature... *\par Compilation * Make the library and test programs compilable for other OS&configuration... * So far tests have been made on Linux (x86/ppc), MacOS and windows (cygwin) * Need to work on autoconf and automake (...) * *\section general Library Features *\par Check Results (****,*) (in constant progress) * Compare Structure Factors with the results of other programs (Jana,...) * for a number of different spacegroups. *\par Save & restore objects (******,***) DONE, using XML *\par Move from atominfo+sglite to cctbx (******,***) * Change to the newest R. Grosse-Kunstleve library. *\par CIF Import & Export (****,*****) * Ability to export (and import) Crystallographic Info Files. The importing will * be much harder, and is not a priority. *\par Export to other LSQ refinement programs(****,**) * Ability to export for other refinement programs (fullprof, gsas, shellx,...). *\par Anisotropic Thermic Factors (**,****) * Add support for anisotropic thermic factors. Spacegroup object should be able * to indicate the permutations needed for symetrical atoms. Also determine * the constraints between bij (eg beta12=beta13,etc...) * The Interface has been written, but no code. *\par Powder Diffraction Background(**,**) * Use splines to interpolate background. Automagically determine background by filtering * the spectrum. So far only linearly-interpolated background is available. *\par Intensity extraction from powder (*,***) * Extract F(hkl) from a powder spectrum. Not so interesting, there already are * numerous programs to do this. But the advantage to have it embeded is the possibility * to refine and refresh (recycle) these extracted intensities during an optimization. *\par Multi-phase (****,**) - DONE * Multiple phase for powder diffraction. *\par ZScatterer import(**,**) * Import Z-Matrix from file. Add the possibility to link two existing ZScatterer by * linking terminal atoms. *\par Genetic Algorithm (****,***) * And compare the 3 different algorithms on several structures. *\par Texture (***,***) * Include texture parameters in PowderPattern. Optionnaly, allow multiple * textured patterns (that would more difficult). * *\section internal Internal Design of the Library *\par Vector & arrays (Blitz++ usage,...) (**,***) * Test again the use of the blitz++ library for vector computing. * *\section wild Wild ideas (interesting possibilities, but no priority given) *\par Amorphous contribution * Add amorphous (disordered) contributions to powder spectrum. This could be easily * added from the PowderPatternComponent base class. *\par Magnetic scattering * Add calculations for magnetic scattering (->scattering factors) */ objcryst-2022.1/ObjCryst/doc/gnu.mak000066400000000000000000000017421430515525000172320ustar00rootroot00000000000000include ../rules.mak DIR_CRYST := .. #target to make documentation (requires doxygen) #also makes tags file, although it is not related to doxygen html/index.html: ../*/*.h doxygen doxygen.config cp ${DIR_CRYST}/license.txt html/ObjCryst-license.txt cp ${DIR_CRYST}/../newmat/nm10.htm html/newmat.htm cp ${DIR_CRYST}/../atominfo/readme.html html/atominfo.html cp ${DIR_CRYST}/../sglite/LICENSE html/sglite-license.txt doc: html/index.html pdf: doc cd latex ; pdflatex refman ; makeindex refman.idx ; pdflatex refman ctags: ctags ${DIR_LIBCRYST}/*.cpp ${DIR_VFNQUIRKS}/*.cpp ${DIR_SGLITE}/*.c ${DIR_ATOMINFO}/*.c ${DIR_REFOBJ}/*.cpp ${DIR_CRYSTVECTOR}/*.cpp ${DIR_WXWCRYST}/*.cpp ${DIR_LIBCRYST}/*.h ${DIR_VFNQUIRKS}/*.h ${DIR_SGLITE}/*.h ${DIR_ATOMINFO}/*.h ${DIR_CRYSTVECTOR}/*.h ${DIR_REFOBJ}/*.h ${DIR_CRYSTVECTOR}/*.h ${DIR_WXWCRYST}/*.h clean: @${RM} html/* latex/* sourceforge: scp -C -r html/* vincefn@shell.sourceforge.net:/home/groups/o/ob/objcryst/htdocs/ObjCryst/ objcryst-2022.1/ObjCryst/example/000077500000000000000000000000001430515525000166315ustar00rootroot00000000000000objcryst-2022.1/ObjCryst/example/.cvsignore000066400000000000000000000001771430515525000206360ustar00rootroot00000000000000*.o *.exe *.out *.old *.dep *.a .directory .systemG.Desktop tags html latex *.oxy *.xml profile.0.0.0 *.pov Makefile rules.mak objcryst-2022.1/ObjCryst/example/bc32.mak000066400000000000000000000021661430515525000200610ustar00rootroot00000000000000include ../rules.mak ${BIN_DIR}/%.o : %.cpp mkdir -p ${BIN_DIR} ${CXX} ${CPPFLAGS} ${CXXFLAGS} -c $< -o $@ #test-pbso4 on powder from RoundRobin pbso4-neutron: ${BIN_DIR}/pbso4-neutron.o libCrystVector libQuirks libRefinableObj libsglite libatominfo libCryst libwxCryst ${LINKER} ${LDFLAGS} -o $@.exe ${filter-out %.a %.so lib%, $^} ${LOADLIBES} #Same as above, but on X-Ray pbso4-xray: ${BIN_DIR}/pbso4-xray.o libCrystVector libQuirks libRefinableObj libsglite libatominfo libCryst libwxCryst ${LINKER} ${LDFLAGS} -o $@.exe ${filter-out %.a %.so lib%, $^} ${LOADLIBES} #Same as above, working on extracted from F's pbso4-xray2: ${BIN_DIR}/pbso4-xray2.o libCrystVector libQuirks libRefinableObj libsglite libatominfo libCryst libwxCryst ${LINKER} ${LDFLAGS} -o $@.exe ${filter-out %.a %.so lib%, $^} ${LOADLIBES} # target for making everything .PHONY : all all: pbso4-neutron pbso4-xray pbso4-xray2 dep: makedepend *.cpp -Y -I. -I../ -I../.. # target for removing all object files .PHONY : tidy tidy:: @${RM} core obj_debug/*.o obj_optimized/*.o # target for removing all object files and libraries .PHONY : clean clean:: tidy objcryst-2022.1/ObjCryst/example/fluorine/000077500000000000000000000000001430515525000204545ustar00rootroot00000000000000objcryst-2022.1/ObjCryst/example/fluorine/.cvsignore000066400000000000000000000001771430515525000224610ustar00rootroot00000000000000*.o *.exe *.out *.old *.dep *.a .directory .systemG.Desktop tags html latex *.oxy *.xml profile.0.0.0 *.pov Makefile rules.mak objcryst-2022.1/ObjCryst/example/fluorine/bc32.mak000066400000000000000000000004041430515525000216750ustar00rootroot00000000000000!include ../../rules.mak xray-single: xray-single.obj $(CPP) $(LINKFLAGS) xray-single.obj $(LINKLIBS) xray: xray.obj $(CPP) $(LINKFLAGS) xray.obj $(LINKLIBS) neutron: neutron.obj $(CPP) $(LINKFLAGS) neutron.obj $(LINKLIBS) all: xray-single xray neutron objcryst-2022.1/ObjCryst/example/fluorine/fluorine.cpp000066400000000000000000000061161430515525000230070ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Minimal example on CaF2. * */ #include #include #include "Quirks/VFNStreamFormat.h" #include "Quirks/Chronometer.h" #include "Quirks/VFNDebug.h" #include "RefinableObj/GlobalOptimObj.h" #include "ObjCryst/General.h" #include "ObjCryst/IO.h" #include "ObjCryst/ScatteringPower.h" #include "ObjCryst/Atom.h" #include "ObjCryst/Crystal.h" #include "ObjCryst/PowderPattern.h" using namespace ObjCryst; void fluorine() { //Create crystal structure Crystal caf2(5.46,5.46,5.46,"Fm3m"); caf2.SetName("CaF2"); // Create atom types ScatteringPowerAtom *ScattPowCa=new ScatteringPowerAtom("Ca","Pb",0.6); ScatteringPowerAtom *ScattPowF =new ScatteringPowerAtom("F" ,"F" ,0.8); //add atom types to the crystal caf2.AddScatteringPower(ScattPowCa); caf2.AddScatteringPower(ScattPowF); //create the atoms Atom *ca=new Atom(.0 ,.0 ,.0 ,"Ca",ScattPowCa ,1.); Atom *f=new Atom( .25,.25,.25,"F" ,ScattPowF ,1.); caf2.AddScatterer(ca); caf2.AddScatterer(f); //Create Diffraction data object, for Cu-Alpha1 PowderPattern data; data.SetWavelength("CuA1"); //add CaF2 as a Crystalline phase PowderPatternDiffraction * diffData=new PowderPatternDiffraction; diffData->SetCrystal(caf2); data.AddPowderPatternComponent(*diffData); //we don't have data, so just simulate (0->Pi/2).. //give a constant 'obs pattern of unit intensity data.SetPowderPatternPar(0,M_PI/10000.,5000); CrystVector_REAL obs(5000); obs=1; data.SetPowderPatternObs(obs); data.Prepare(); // Save the powder pattern in text format data.SavePowderPattern("caf2.dat"); // Save everything in xml so that we can reload it later XMLCrystFileSaveGlobal("caf2.xml"); } int main (int argc, char *argv[]) { TAU_PROFILE_SET_NODE(0); // sequential code TAU_PROFILE("main()","int()",TAU_DEFAULT); cout << " Beginning CaF2 example...." << endl ; int level =10; if(argc==2)//debug level hase been supplied { level=atoi(argv[1]); } VFN_DEBUG_GLOBAL_LEVEL(level); fluorine(); cout << " End of CaF2 example." << endl ; TAU_REPORT_STATISTICS(); return 0; } objcryst-2022.1/ObjCryst/example/fluorine/gnu.mak000066400000000000000000000011061430515525000217350ustar00rootroot00000000000000BUILD_DIR=$(CURDIR)/../../.. include $(BUILD_DIR)/ObjCryst/rules.mak OBJ= $@.o %.o : %.cpp @$(MAKEDEPEND) ${CXX} ${CPPFLAGS} ${CXXFLAGS} -c $< -o $@ -include $(OBJ:.o=.dep) fluorine: fluorine.o libCrystVector libQuirks libRefinableObj libsglite libatominfo libCryst libwxCryst ${LINKER} ${LDFLAGS} -o $@.exe ${filter-out %.a %.so lib%, $^} ${LOADLIBES} # target for making everything .PHONY : all all: fluorine default: all .PHONY : tidy tidy:: @${RM} core *.o *.obj *.dep .PHONY : clean clean:: tidy @${RM} core *.a *.exe cvsignore: cp -f ${DIR_CRYST}/.cvsignore ./ objcryst-2022.1/ObjCryst/example/gnu.mak000066400000000000000000000006421430515525000201160ustar00rootroot00000000000000SUBDIRS= pbso4 all: @for d in $(SUBDIRS); do (cd $$d && make -f gnu.mak all debug=$(debug) opengl=$(opengl) wxcryst=$(wxcryst)); done default:all # target for removing all object files .PHONY : tidy tidy:: @for d in $(SUBDIRS); do (cd $$d && make -f gnu.mak tidy); done # target for removing all object files and libraries .PHONY : clean clean:: @for d in $(SUBDIRS); do (cd $$d && make -f gnu.mak clean); done objcryst-2022.1/ObjCryst/example/pbso4/000077500000000000000000000000001430515525000176605ustar00rootroot00000000000000objcryst-2022.1/ObjCryst/example/pbso4/.cvsignore000066400000000000000000000001771430515525000216650ustar00rootroot00000000000000*.o *.exe *.out *.old *.dep *.a .directory .systemG.Desktop tags html latex *.oxy *.xml profile.0.0.0 *.pov Makefile rules.mak objcryst-2022.1/ObjCryst/example/pbso4/bc32.mak000066400000000000000000000013561430515525000211100ustar00rootroot00000000000000!include ../../rules.mak xray-single: xray-single.obj libsglite libatominfo libnewmat libCrystVector libQuirks libRefinableObj libcryst cd ${DIR_CRYST}\example\pbso4 ilink32 $(LINKFLAGS) -Tpe -ap c0x32 xray-single.obj,xray-single,, import32.lib cw32mt.lib $(LINKLIBS) xray: xray.obj libsglite libatominfo libnewmat libCrystVector libQuirks libRefinableObj libcryst cd ${DIR_CRYST}\example\pbso4 ilink32 $(LINKFLAGS) -Tpe -ap c0x32 xray.obj,xray,, import32.lib cw32mt.lib $(LINKLIBS) neutron: neutron.obj libsglite libatominfo libnewmat libCrystVector libQuirks libRefinableObj libcryst cd ${DIR_CRYST}\example\pbso4 ilink32 $(LINKFLAGS) -Tpe -ap c0x32 neutron.obj,neutron,, import32.lib cw32mt.lib $(LINKLIBS) all: xray-single xray neutron objcryst-2022.1/ObjCryst/example/pbso4/gnu.mak000066400000000000000000000016511430515525000211460ustar00rootroot00000000000000BUILD_DIR=$(CURDIR)/../../.. #We do not want to build wx libraries wxcryst= 0 include $(BUILD_DIR)/ObjCryst/rules.mak OBJ= $@.o %.o : %.cpp @$(MAKEDEPEND) ${CXX} ${CPPFLAGS} ${CXXFLAGS} -c $< -o $@ -include $(OBJ:.o=.dep) xray-single: xray-single.o libCrystVector libQuirks libRefinableObj libcctbx libCryst ${LINKER} ${LDFLAGS} -o $@.exe ${filter-out %.a %.so lib%, $^} ${LOADLIBES} xray: xray.o libCrystVector libQuirks libRefinableObj libcctbx libCryst ${LINKER} ${LDFLAGS} -o $@.exe ${filter-out %.a %.so lib%, $^} ${LOADLIBES} neutron: neutron.o libCrystVector libQuirks libRefinableObj libcctbx libCryst ${LINKER} ${LDFLAGS} -o $@.exe ${filter-out %.a %.so lib%, $^} ${LOADLIBES} # target for making everything .PHONY : all all: xray-single xray neutron default: all .PHONY : tidy tidy:: @${RM} core *.o *.obj *.dep .PHONY : clean clean:: tidy @${RM} core *.a *.exe cvsignore: cp -f ${DIR_CRYST}/.cvsignore ./ objcryst-2022.1/ObjCryst/example/pbso4/neutron-background.dat000066400000000000000000000000721430515525000241600ustar00rootroot0000000000000010 211 23 192 44 200 62 206 71 208 90 240 125 260 160 240 objcryst-2022.1/ObjCryst/example/pbso4/neutron-pattern.dat000066400000000000000000000427561430515525000235350ustar00rootroot0000000000000010.000 0.050 155.95 PbSO4 D1A(ILL)(Rietveld Refinement Round Robin,R.J. Hill,JApC 25,589) 220 214 219 224 198 229 224 216 202 229 202 215 215 196 235 207 205 238 202 213 226 198 222 186 216 218 225 200 196 224 199 204 189 211 190 184 204 204 219 207 227 211 193 206 208 191 194 185 200 203 197 203 200 200 205 208 205 201 221 218 218 216 202 206 197 210 199 219 192 211 199 196 195 203 202 200 199 191 204 191 200 199 197 202 210 202 198 191 194 198 194 193 212 214 197 195 205 209 203 197 191 192 215 194 189 188 202 201 198 208 197 187 187 190 197 200 193 180 194 206 195 193 205 194 196 194 199 207 188 203 188 180 198 200 201 210 206 189 194 187 195 201 197 206 208 199 192 193 204 201 200 177 193 199 201 194 184 192 199 190 183 189 196 196 198 210 212 219 198 195 198 191 193 197 194 187 209 187 198 206 197 191 200 207 205 198 196 209 211 203 200 192 208 213 221 216 226 228 228 215 224 226 213 239 250 247 240 231 236 223 231 226 214 208 214 196 204 199 186 192 199 200 184 184 189 182 184 185 195 190 194 185 183 193 194 193 188 191 189 188 201 195 205 200 200 192 197 204 207 192 201 190 195 194 182 189 196 196 200 190 183 199 187 196 191 191 195 194 192 182 188 203 187 192 206 201 184 192 205 196 193 194 195 194 201 193 176 187 188 196 192 185 195 198 205 200 208 195 187 193 197 202 193 196 202 201 197 204 208 206 212 207 207 212 216 218 221 218 207 203 204 202 206 202 202 181 193 205 198 196 197 195 201 205 195 196 196 205 198 200 199 180 187 193 197 197 196 194 197 204 201 187 191 205 200 198 200 204 196 195 194 200 198 201 208 205 211 211 220 220 212 208 214 226 235 233 237 242 242 245 239 226 232 238 226 218 218 214 205 200 193 195 196 195 207 215 207 218 218 220 220 229 236 254 264 280 289 289 303 302 297 281 278 280 265 258 243 240 232 231 233 246 248 249 256 272 289 311 340 363 393 440 474 482 492 508 494 475 439 413 368 331 299 286 262 241 238 252 267 276 278 300 325 336 359 405 458 501 564 640 719 783 837 851 866 828 763 697 634 541 465 391 351 301 284 260 248 257 242 246 263 271 281 302 309 335 342 345 356 351 341 334 321 286 268 256 238 229 218 223 216 203 203 194 205 196 193 206 201 201 201 200 194 196 203 195 196 211 216 207 215 221 237 248 261 279 319 337 364 423 489 557 630 729 822 943 1059 1196 1235 1220 1209 1128 1001 864 729 601 496 418 355 313 263 246 226 214 222 222 211 211 202 198 192 193 196 201 203 203 201 198 196 206 210 197 204 200 205 196 195 205 204 200 203 208 207 202 203 198 204 210 216 210 229 239 247 278 302 324 371 420 465 538 630 739 851 976 1076 1161 1222 1227 1187 1096 964 833 708 587 512 436 391 384 370 391 419 448 490 567 626 687 735 780 782 745 721 662 595 527 446 393 335 301 276 251 242 229 209 215 218 214 209 208 212 210 209 210 205 209 211 211 216 205 204 202 201 200 207 205 202 209 202 203 206 206 200 194 199 204 205 210 207 205 210 204 203 202 205 201 201 207 197 198 203 209 209 208 204 209 199 204 206 201 205 202 204 198 198 213 210 212 214 215 217 210 214 215 215 215 217 222 231 247 252 273 304 332 366 408 463 532 619 734 828 944 1003 1055 1070 1018 944 833 725 633 507 445 379 347 316 282 267 269 281 288 300 327 346 380 400 430 453 459 451 427 402 375 344 309 277 265 246 246 230 223 227 225 217 217 223 223 220 223 226 248 258 274 297 324 355 393 458 528 589 688 781 840 876 874 832 765 682 613 524 455 408 384 366 375 392 426 470 519 588 639 681 704 693 650 600 540 478 412 376 345 330 337 350 383 426 493 571 676 803 920 1071 1183 1247 1255 1251 1183 1068 945 861 811 813 872 969 1120 1309 1527 1706 1856 1888 1837 1713 1500 1289 1103 904 749 627 568 551 560 586 634 691 751 799 792 820 774 736 680 627 562 514 459 424 362 333 318 300 287 265 266 262 263 255 270 278 289 317 343 400 468 561 695 873 1100 1372 1660 1954 2224 2400 2459 2435 2245 1986 1671 1358 1086 868 682 578 521 512 537 600 704 855 1032 1232 1466 1693 1866 1966 2024 2016 1846 1667 1429 1179 950 763 599 484 404 351 304 284 273 259 251 251 252 245 259 250 253 256 264 285 301 346 390 458 528 624 733 829 916 988 994 929 843 742 638 527 434 377 320 282 273 256 243 240 240 230 220 230 227 224 219 227 227 224 222 223 217 213 216 219 219 218 220 220 220 223 233 237 249 258 261 283 304 324 347 353 359 363 352 341 330 308 291 271 254 245 245 239 228 217 217 218 223 207 218 222 215 210 216 213 212 215 212 214 211 214 217 205 207 213 208 211 205 214 213 212 212 213 207 203 211 211 214 214 207 203 212 212 214 213 202 210 211 211 214 221 217 212 214 219 223 225 227 235 240 243 252 249 249 255 262 282 308 351 398 470 525 596 646 681 665 615 563 484 421 364 317 289 261 245 233 228 219 219 217 216 221 215 215 210 212 212 204 209 206 216 207 214 207 209 218 215 222 226 230 239 249 263 275 292 317 323 341 350 330 320 307 284 275 265 269 275 292 311 338 387 413 463 510 534 559 539 533 500 471 455 410 373 342 307 288 286 281 292 291 312 326 336 346 341 327 305 277 267 249 229 221 220 217 211 204 203 220 217 217 214 205 205 211 206 208 201 208 214 212 206 216 219 215 217 211 214 215 224 217 215 218 218 228 227 228 225 219 216 219 218 214 212 221 214 208 204 209 209 208 212 213 218 212 205 207 204 206 211 216 214 210 219 222 224 231 227 237 235 238 245 242 248 246 243 253 259 278 281 297 310 324 322 311 295 281 259 250 239 233 227 226 223 211 209 217 214 213 217 220 210 209 215 218 215 217 221 217 219 220 228 229 230 234 251 261 288 313 362 424 524 646 781 920 1024 1120 1187 1187 1166 1114 1044 991 927 823 717 619 520 421 353 308 273 256 245 234 230 224 232 226 222 222 227 225 226 227 229 235 233 243 238 237 236 232 231 227 225 220 218 215 219 224 225 222 231 243 250 269 286 310 325 332 337 329 303 278 268 252 236 228 219 225 222 214 228 221 217 221 222 226 237 246 255 269 284 302 313 327 321 333 331 332 358 402 460 557 660 769 859 934 955 921 824 694 578 474 402 344 306 300 292 292 302 304 306 305 303 299 278 259 257 245 237 240 233 232 235 241 257 274 292 309 333 360 381 387 387 386 382 368 363 352 337 321 297 281 265 255 251 237 238 237 228 240 234 226 229 228 233 243 241 257 279 305 345 410 455 545 622 673 725 717 661 592 518 443 371 336 290 265 252 250 244 242 241 243 248 253 252 264 266 282 291 313 346 374 415 430 433 430 406 384 349 318 307 298 296 304 313 328 346 341 335 324 336 341 341 370 414 442 490 520 532 548 561 567 585 584 558 527 481 424 370 333 312 301 307 314 340 379 427 467 535 584 602 580 532 481 426 379 329 303 288 271 269 267 263 267 260 260 263 263 270 278 293 318 364 424 512 643 817 982 1163 1289 1373 1393 1348 1244 1157 1077 1020 965 907 858 771 647 555 468 405 348 316 291 277 278 270 262 268 270 279 287 300 319 347 378 420 469 536 645 773 925 1115 1254 1367 1400 1327 1188 1038 879 738 644 594 601 643 697 786 842 847 791 702 592 508 418 362 328 299 279 270 257 253 258 257 249 245 257 260 284 296 322 343 382 405 411 416 406 372 353 330 317 313 312 309 303 288 276 264 246 249 241 251 243 246 246 249 244 252 252 258 265 263 284 299 320 344 363 372 358 351 354 330 322 334 339 345 357 360 358 372 425 511 626 770 946 1118 1205 1227 1157 1041 873 715 562 446 377 332 297 282 276 264 261 266 261 253 258 262 260 283 307 344 402 453 529 604 661 672 629 588 510 440 377 330 301 280 269 258 252 251 252 256 253 253 253 262 265 284 291 323 374 431 511 602 678 743 756 717 657 581 490 418 364 335 306 290 286 283 283 274 262 266 261 261 264 269 278 288 306 319 330 343 341 325 318 298 299 288 309 344 382 422 470 512 514 515 488 440 396 366 332 311 305 300 293 286 306 313 317 327 343 330 320 307 298 282 274 266 274 271 274 290 302 321 350 367 386 394 370 356 332 310 288 279 281 274 284 280 270 278 269 273 268 267 265 257 258 267 267 277 287 302 332 360 411 457 524 608 699 861 1096 1377 1685 1901 2069 2016 1800 1500 1181 937 728 629 576 556 535 519 486 465 429 385 361 342 312 293 279 277 265 257 256 250 260 261 258 263 268 284 306 325 337 337 344 340 337 328 321 306 295 289 281 267 266 270 263 256 266 264 259 261 261 258 253 248 244 249 251 245 245 247 247 254 259 250 251 258 252 255 259 256 264 268 281 303 331 371 420 484 532 576 582 563 527 490 465 467 449 416 393 366 331 316 297 294 292 286 295 306 315 334 373 406 447 499 507 506 488 432 391 342 315 292 275 274 259 250 258 252 255 254 253 254 252 257 250 255 251 254 260 249 253 254 259 268 270 284 305 322 364 417 470 573 678 771 847 854 794 720 611 520 463 412 399 416 428 432 420 402 364 348 334 321 330 342 380 385 420 441 465 444 406 383 345 332 321 308 292 303 314 333 379 438 505 594 659 717 738 710 642 547 492 421 386 344 337 350 364 415 506 586 674 750 787 753 682 597 499 417 362 340 302 286 280 283 276 282 284 295 310 319 321 304 298 293 283 277 269 265 277 283 283 293 303 320 316 331 346 327 328 306 291 286 278 273 267 272 257 260 265 264 272 270 268 269 287 292 295 317 335 364 410 477 556 642 755 864 946 970 941 870 759 647 540 468 418 379 381 405 446 476 523 561 555 529 485 436 398 355 322 304 285 270 278 260 268 264 265 263 267 286 293 291 319 366 411 461 489 521 555 550 511 486 436 392 368 330 328 343 371 394 441 468 469 456 416 394 361 330 312 293 285 286 275 274 281 279 298 312 331 375 406 452 506 546 568 589 588 537 498 463 402 386 361 350 330 338 359 364 385 436 474 544 647 695 763 802 812 756 669 606 527 452 409 376 368 391 400 444 481 518 556 577 575 557 552 562 592 596 583 552 512 482 439 385 342 316 300 287 279 267 269 269 271 261 261 265 252 260 263 265 260 274 267 271 274 269 264 277 272 277 282 290 293 294 300 325 348 382 412 466 513 562 585 608 619 594 567 526 518 501 480 470 465 469 458 438 448 470 470 500 505 519 517 517 502 460 410 375 347 347 318 310 302 311 326 320 334 374 444 484 561 647 699 747 767 749 723 664 619 578 553 541 530 530 525 517 493 482 456 423 383 380 343 326 314 302 303 290 290 293 277 286 309 327 357 396 468 529 590 649 699 720 705 672 635 604 564 548 537 564 588 611 636 636 606 600 560 512 473 453 428 390 393 401 395 440 479 549 618 675 746 803 805 788 748 671 621 544 460 421 384 343 321 298 278 287 280 268 281 272 287 282 284 300 303 309 322 340 347 370 401 420 451 491 508 530 531 522 484 468 427 379 365 344 321 294 291 284 264 281 261 256 261 266 264 258 262 250 261 257 253 247 259 259 256 253 256 257 261 246 247 250 270 254 245 254 274 272 253 260 272 265 267 276 280 289 318 331 366 386 426 461 495 532 591 627 616 634 668 645 620 607 560 518 470 445 398 376 336 325 301 303 275 273 288 278 274 273 260 268 276 276 294 293 277 292 284 273 291 287 303 306 315 333 367 387 404 440 480 533 601 620 647 663 652 665 630 628 577 520 472 453 413 412 396 361 370 402 389 423 452 469 498 535 538 564 572 585 574 543 495 484 460 428 375 341 340 312 309 288 271 273 267 255 266 261 269 257 249 245 259 258 259 268 279 256 259 287 269 281 268 277 278 287 277 285 284 278 288 279 287 289 308 308 288 302 295 301 303 294 287 279 279 276 275 264 274 269 269 268 261 256 284 279 280 296 297 296 308 301 300 297 300 289 290 274 275 264 262 249 251 248 252 249 249 262 251 239 263 265 240 236 250 248 248 254 262 252 246 250 251 247 248 254 236 251 247 254 248 259 259 274 263 287 283 281 296 292 323 330 339 358 349 365 399 406 428 413 439 418 425 411 417 391 393 386 359 381 363 364 375 379 392 402 436 451 463 452 449 479 485 484 472 508 518 523 561 559 573 545 561 568 573 562 573 565 499 496 488 449 442 391 387 390 359 338 321 322 327 338 306 290 320 308 300 307 306 314 318 298 313 303 302 333 285 312 312 285 290 288 294 314 300 306 293 299 328 325 328 317 292 321 291 302 291 297 301 270 262 277 258 258 243 269 257 257 240 282 245 243 260 255 275 255 270 286 271 258 309 299 297 304 319 314 290 338 316 341 384 360 367 383 366 369 363 332 325 334 373 336 313 339 325 307 277 286 305 277 262 262 241 251 260 245 249 260 256 242 258 248 235 245 248 281 228 230 212 237 244 231 266 231 234 247 264 247 261 223 242 271 247 249 251 232 225 255 209 266 255 273 250 234 257 250 270 262 281 257 260 257 242 255 250 274 288 275 277 278 264 298 312 282 314 341 314 295 326 347 336 444 393 375 425 413 415 450 326 objcryst-2022.1/ObjCryst/example/pbso4/neutron.cpp000066400000000000000000000172571430515525000220720ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Global refinement example on PbSO4. * */ #include #include #include "ObjCryst/ZScatterer.h" #include "ObjCryst/Atom.h" #include "ObjCryst/PowderPattern.h" #include "Quirks/VFNStreamFormat.h" #include "Quirks/Chronometer.h" #include "Quirks/VFNDebug.h" #include "RefinableObj/GlobalOptimObj.h" //#include //#ifdef __MWERKS__ //#include //#else //#include "Profile/Profiler.h" //TAU profiling package //#endif using namespace ObjCryst; void testPbSO4() { //Create 'real' PBSO4 structure (for reference only-no cheating !) Crystal cryst_orig(8.482,5.398,6.959,"Pnma"); cryst_orig.SetName("PbSO4 (reference structure)"); cryst_orig.Print(); {//Create 'real' PBSO4 structure (for reference only) ScatteringPowerAtom *ScattPowPb=new ScatteringPowerAtom("Pb","Pb",1.48); ScatteringPowerAtom *ScattPowS =new ScatteringPowerAtom("S" ,"S",0.74); ScatteringPowerAtom *ScattPowO1=new ScatteringPowerAtom("O1","O",1.87); ScatteringPowerAtom *ScattPowO2=new ScatteringPowerAtom("O2","O",1.76); ScatteringPowerAtom *ScattPowO3=new ScatteringPowerAtom("O3","O",1.34); cryst_orig.AddScatteringPower(ScattPowPb); cryst_orig.AddScatteringPower(ScattPowS); cryst_orig.AddScatteringPower(ScattPowO1); cryst_orig.AddScatteringPower(ScattPowO2); cryst_orig.AddScatteringPower(ScattPowO3); Atom *Pb=new Atom(.188,.250,.167,"Pb",ScattPowPb ,1.); Atom *S=new Atom (.437,.750,.186,"S" ,ScattPowS ,1.); Atom *O1=new Atom(.595,.750,.100,"O1",ScattPowO1 ,1.); Atom *O2=new Atom(.319,.750,.043,"O2",ScattPowO2 ,1.); Atom *O3=new Atom(.415,.974,.306,"O3",ScattPowO3 ,1.); cryst_orig.AddScatterer(Pb); cryst_orig.AddScatterer(S); cryst_orig.AddScatterer(O1); cryst_orig.AddScatterer(O2); cryst_orig.AddScatterer(O3); } cryst_orig.PrintMinDistanceTable(.05); //cryst_orig.GLDisplayCrystal(); //Creating PbSo4 refined crystal, either with independent atoms or a SO4 tetrahedron cout << "Creating PBSO4 crystal..."<SetCrystal(cryst); data.AddPowderPatternComponent(*diffData); diffData->SetName("PbSo4-diffraction"); //approximate (hand-determined) background PowderPatternBackground *backgdData= new PowderPatternBackground; data.AddPowderPatternComponent(*backgdData); backgdData->ImportUserBackground("neutron-background.dat"); backgdData->SetName("PbSo4-background"); //Set sigma and weight to be used (useless here) data.SetSigmaToSqrtIobs(); data.SetWeightToInvSigmaSq(); // To go a bit faster -sufficient for structure solution data.SetMaxSinThetaOvLambda(0.25); //Profile=gaussian diffData->SetReflectionProfilePar(PROFILE_PSEUDO_VOIGT, .25*DEG2RAD*DEG2RAD, 0*DEG2RAD*DEG2RAD, 0*DEG2RAD*DEG2RAD, 0.15,0); //Use Dynamical population correction for special positions / shared atoms diffData->GetCrystal().SetUseDynPopCorr(true); //Create the global optimization object MonteCarloObj globalOptObj; globalOptObj.AddRefinableObj(data); //Refine only positionnal parameters globalOptObj.FixAllPar(); globalOptObj.SetParIsFixed(gpRefParTypeScattTransl,false); globalOptObj.SetParIsFixed(gpRefParTypeScattOrient,false); globalOptObj.SetParIsFixed(gpRefParTypeScattConformBondLength,false); globalOptObj.SetParIsFixed(gpRefParTypeScattConformBondAngle,false); globalOptObj.SetParIsFixed(gpRefParTypeScattConformDihedAngle,false); globalOptObj.SetLimitsRelative(gpRefParTypeScattConformBondLength,-.1,.1); globalOptObj.SetLimitsRelative(gpRefParTypeScattConformBondAngle,-10.*DEG2RAD,10.*DEG2RAD); globalOptObj.SetLimitsRelative(gpRefParTypeScattConformDihedAngle,-10.*DEG2RAD,10.*DEG2RAD); //Don't cheat ;-) globalOptObj.RandomizeStartingConfig(); //Print Crystal structure cout << "Random starting configuration"<PrintFhklCalc(); //Print Crystal structure cryst.Print(); //Print minimum distance between different atoms // (<.05 are considered identical, if same element) cryst.PrintMinDistanceTable(.05); //Also print real structure cryst_orig.Print(); //Save crystal POVRay file //ofstream out1("crystal.pov"); //cryst.POVRayDescription(out1); //out1.close(); //ofstream out2("pbso4/crystal-real.pov"); //cryst_orig.POVRayDescription(out2); //out2.close(); TAU_REPORT_STATISTICS(); } int main (int argc, char *argv[]) { TAU_PROFILE_SET_NODE(0); // sequential code TAU_PROFILE("main()","int()",TAU_DEFAULT); cout << " Beginning PbSO4 example...." << endl ; int level =10; if(argc==2)//debug level hase been supplied { level=atoi(argv[1]); } VFN_DEBUG_GLOBAL_LEVEL(level); testPbSO4(); cout << " End of PbSO4 example." << endl ; TAU_REPORT_STATISTICS(); return 0; } objcryst-2022.1/ObjCryst/example/pbso4/xray-background.dat000066400000000000000000000000511430515525000234460ustar00rootroot0000000000000010 160 14 95 18 89 35 94 120 170 155 249 objcryst-2022.1/ObjCryst/example/pbso4/xray-pattern.dat000066400000000000000000001370601430515525000230170ustar00rootroot0000000000000010.000 0.025 160.000 PbSO4 XrayDif (Rietveld Round Robin, R.J. Hill, JApC 2 179 147 165 172 150 165 150 158 134 146 167 159 139 145 165 150 149 156 143 166 154 131 144 131 140 147 155 148 140 138 127 146 147 114 129 129 128 136 148 132 141 135 141 145 131 142 148 151 127 133 131 125 129 128 134 142 115 138 125 120 130 118 118 116 119 101 117 142 112 114 111 122 131 107 121 123 120 126 125 120 103 121 109 115 122 123 107 126 133 120 100 130 130 109 116 121 99 107 110 136 113 102 117 111 105 92 110 116 124 111 91 106 122 121 119 114 129 95 117 102 102 117 99 124 107 108 99 113 104 92 98 107 88 96 104 81 111 78 104 119 106 105 96 81 95 96 103 91 112 107 87 112 92 79 92 103 97 102 86 97 103 93 111 95 96 93 85 104 98 108 76 92 95 89 105 95 92 105 89 99 101 97 93 99 100 83 93 96 69 101 97 85 95 85 111 85 86 100 88 98 92 93 94 93 81 98 78 79 93 81 88 73 85 106 88 94 96 91 101 89 87 95 87 97 81 87 93 90 73 98 86 80 82 97 80 81 80 81 73 106 92 101 98 104 106 98 114 97 129 112 141 167 157 200 215 321 397 434 445 313 197 155 110 118 86 110 95 93 98 80 85 106 86 103 92 88 94 79 92 106 82 104 94 88 97 93 90 120 93 106 89 92 100 91 99 81 89 79 91 84 92 107 99 92 87 88 67 81 86 85 103 85 77 105 93 96 93 85 75 105 85 89 86 76 86 71 101 100 89 74 101 103 95 100 87 94 84 102 92 80 82 105 84 83 93 92 105 94 88 97 88 110 110 84 89 98 92 86 110 98 93 94 104 96 105 99 117 111 100 125 99 107 107 98 84 112 99 93 108 100 91 98 124 98 121 114 93 87 95 95 121 102 127 119 118 107 100 95 116 136 92 127 127 115 124 130 123 137 136 165 150 173 190 211 212 255 264 305 353 415 507 623 833 1076 1417 1958 2624 3927 5466 7996 11062 12925 12506 10327 8178 6771 5910 4886 3432 2110 1182 802 623 527 435 393 356 333 295 316 280 248 264 216 202 211 187 168 208 160 171 149 166 138 168 129 147 134 125 137 112 128 134 121 138 103 124 115 119 109 119 116 127 133 121 109 114 113 120 118 102 110 118 123 116 112 107 121 104 124 105 128 115 128 99 130 109 125 138 141 135 125 140 152 177 177 191 195 225 258 301 337 468 618 837 1082 1507 2283 3235 4791 6588 8176 8122 6687 5078 3206 1822 1101 712 566 470 381 302 277 259 259 212 198 189 153 182 178 175 164 139 176 159 147 172 167 159 180 168 162 166 147 149 161 173 145 210 201 257 262 342 451 598 796 1089 1648 2386 3203 3155 2711 1970 1292 729 450 289 285 218 211 202 168 165 177 176 197 164 141 160 160 157 145 165 158 158 197 179 203 194 216 282 282 364 456 632 854 1213 1815 2863 4063 4649 4165 3168 2329 1423 738 438 367 295 246 246 191 179 178 170 182 158 182 179 184 181 169 171 191 175 216 195 224 209 251 257 298 297 378 406 499 590 746 983 1402 2108 3097 4641 7229 10690 13494 13106 10401 7908 5365 2857 1575 947 697 595 529 450 423 344 319 309 252 257 252 266 275 257 285 285 270 280 347 282 362 426 461 637 693 1051 1425 2158 3198 5190 8004 10350 9724 7797 6126 4329 2276 1177 756 591 486 352 340 314 270 256 253 245 206 212 183 205 185 164 197 167 175 159 152 162 168 151 153 128 167 147 140 139 153 153 154 145 147 134 160 137 134 131 157 137 145 151 164 171 172 165 168 162 193 169 199 186 208 196 182 246 245 284 340 364 382 519 665 837 1080 1566 2321 3438 5181 8141 12608 15702 14432 12071 9687 7137 4123 2094 1334 1013 780 668 467 438 379 355 263 287 299 247 253 236 223 193 198 184 204 185 174 201 168 185 175 171 153 162 135 159 139 147 127 143 140 115 142 123 156 133 135 128 130 127 120 121 106 134 114 107 123 111 92 134 87 130 97 101 113 119 122 114 117 84 105 111 104 119 119 101 117 122 105 128 116 126 115 121 116 144 141 128 148 165 172 182 174 193 230 247 312 325 423 589 755 1130 1670 2522 3976 5312 5540 4806 3984 3579 2684 1672 977 645 451 390 317 305 278 234 264 246 263 239 271 260 299 300 332 411 497 630 918 1214 1839 2852 4745 6636 7831 7010 5926 5069 4251 2900 1743 1167 841 646 517 412 354 301 282 234 204 235 226 207 200 180 180 179 172 180 157 154 173 198 147 168 157 199 209 242 257 328 467 631 994 1449 1522 1193 977 947 796 548 358 251 190 164 159 137 134 136 126 122 128 108 100 120 106 123 117 113 108 121 104 104 100 105 107 108 103 108 123 92 122 97 101 92 114 89 81 113 76 89 99 89 98 98 104 120 100 99 89 111 98 96 95 84 115 106 100 86 110 86 98 97 109 112 105 86 102 91 98 111 89 95 95 84 114 108 96 94 94 102 91 106 103 82 121 101 109 112 104 103 105 112 119 116 119 115 106 122 116 120 130 107 137 132 131 140 150 149 161 190 210 234 297 378 583 909 1431 2164 2620 2390 1970 1772 1685 1327 891 543 352 292 230 177 182 207 158 143 129 161 133 119 120 128 118 121 132 135 134 132 135 156 182 207 266 351 368 312 269 260 249 219 174 157 146 135 137 136 103 107 99 133 129 147 130 115 123 109 106 115 136 119 126 131 135 116 112 123 116 121 136 147 130 156 138 133 144 163 171 198 191 196 226 243 294 352 472 630 984 1383 2157 2946 2947 2469 1988 2056 1767 1317 793 524 362 282 264 227 186 194 168 177 199 174 169 183 194 204 189 213 296 350 476 746 894 816 615 549 596 524 395 306 223 164 206 198 162 173 163 144 169 160 156 143 187 146 146 157 177 173 171 197 214 254 333 505 760 1047 1074 910 689 698 717 570 382 273 291 231 278 239 272 257 316 315 377 419 593 709 1116 1749 2604 3739 4133 3642 2835 2622 2580 2147 1381 844 578 447 351 339 309 260 268 240 250 233 275 281 285 381 450 601 801 895 881 726 644 608 589 498 386 283 277 254 276 249 224 213 196 234 186 215 191 211 189 204 193 227 221 225 199 187 193 214 235 241 232 239 254 252 264 251 260 320 375 379 442 425 492 574 693 816 1046 1286 1773 2593 4047 6544 9907 12440 12196 9815 8006 7742 7431 5975 3773 2148 1465 1080 849 683 579 560 480 481 470 468 450 469 498 468 528 615 632 765 985 1263 1833 2821 4290 5647 5682 5372 5802 7664 7744 5866 4103 3552 3442 2855 1843 1102 771 578 517 456 381 379 335 326 303 286 287 274 272 282 267 236 255 238 218 224 209 228 244 234 221 237 224 217 187 261 216 246 244 282 276 314 333 385 413 609 855 1397 2190 3180 3151 2427 1819 1843 2058 1720 1115 716 480 364 297 300 267 227 215 189 213 174 175 193 183 178 166 171 171 172 161 151 143 141 139 172 153 169 141 125 135 142 134 142 138 152 159 140 143 136 147 144 148 153 112 148 138 119 121 160 136 164 137 166 142 158 176 175 183 249 309 389 541 720 682 600 452 443 453 437 329 289 226 201 182 160 178 146 181 142 201 182 174 168 174 233 275 331 464 712 969 1093 984 752 624 651 695 597 460 284 261 211 196 175 167 165 143 153 155 137 161 131 138 125 114 154 114 118 120 130 117 126 132 122 133 122 113 128 139 126 140 120 122 122 136 116 113 103 120 129 112 118 140 135 101 128 115 126 120 119 107 122 124 123 159 132 136 115 142 132 144 140 131 112 147 129 129 106 129 127 122 155 130 121 131 173 157 146 153 168 199 204 212 232 255 319 410 629 1090 1814 2668 2463 1752 1187 1257 1542 1549 1066 624 387 314 267 208 211 210 181 170 154 155 143 171 156 134 142 142 136 139 139 132 152 123 137 125 132 133 137 148 121 150 139 127 127 146 147 155 131 144 148 138 149 154 142 141 181 185 169 181 203 236 232 335 428 600 826 1143 1282 1262 1070 962 964 871 886 728 557 468 370 267 235 203 187 181 188 189 166 167 175 191 184 181 226 228 258 216 233 250 287 332 441 506 459 447 383 372 397 408 434 419 346 392 441 622 912 1096 1359 1605 1949 1937 1843 2020 1980 1741 1467 1209 1080 998 719 548 393 314 277 248 204 179 180 168 160 170 160 184 179 164 149 156 140 161 149 134 126 143 138 142 163 131 161 131 147 150 160 128 126 128 152 134 158 135 162 157 173 156 162 158 164 155 194 195 196 253 262 350 464 665 937 1141 1055 834 657 648 638 752 672 543 404 370 386 469 560 465 360 285 276 355 364 291 228 190 194 195 180 163 154 156 184 181 152 176 177 160 178 185 175 206 214 244 255 254 373 514 623 827 875 884 951 1181 1887 2582 2875 2303 1613 1270 1312 1510 1599 1288 890 794 643 683 884 1207 1571 1762 1506 1186 969 975 1015 1048 938 733 494 392 292 276 254 229 216 203 194 189 192 181 191 163 175 186 149 175 142 180 136 151 177 156 159 174 148 147 141 145 156 144 149 145 127 143 159 129 161 138 145 165 172 184 217 266 272 313 288 275 321 323 439 573 743 906 960 812 566 541 535 554 567 599 473 359 290 254 189 184 196 210 190 179 148 160 147 122 148 141 140 142 114 150 151 132 153 140 118 128 140 136 122 130 135 133 165 160 163 166 190 264 331 334 297 215 205 212 268 226 256 199 165 148 159 132 154 139 121 144 131 136 139 120 129 130 143 127 150 156 154 153 162 208 247 207 192 179 148 154 204 186 208 175 141 111 124 132 127 125 124 147 143 135 136 143 145 143 148 151 139 142 135 161 143 139 136 158 164 167 165 181 147 160 195 209 190 226 195 241 278 302 344 427 563 789 990 1317 1792 2342 2479 2083 1541 1233 1186 1301 1408 1348 1086 761 509 405 349 309 273 269 244 252 286 309 289 316 317 259 228 223 259 237 212 212 201 184 201 170 165 182 182 183 199 200 208 190 185 230 275 352 448 647 956 1241 1280 1063 730 559 576 678 833 919 838 736 578 449 352 332 306 308 321 300 245 216 201 182 162 147 163 193 149 171 166 202 155 141 162 155 166 190 174 189 211 169 195 197 235 250 286 344 394 561 722 930 1317 1481 1358 1037 813 746 717 877 916 896 663 502 396 302 255 280 238 238 233 267 258 267 346 468 667 897 976 870 617 478 483 485 541 636 625 465 354 276 231 232 190 216 192 191 172 178 212 172 174 183 142 176 174 159 196 194 202 246 258 272 227 206 220 234 235 252 241 246 280 326 391 456 640 670 639 521 515 493 632 854 1153 1468 1384 1196 879 770 660 705 773 815 766 626 469 409 338 280 267 303 290 315 308 375 471 637 830 1073 1024 833 639 528 502 569 667 732 600 516 444 417 430 431 409 399 319 289 333 368 368 375 332 257 253 244 250 251 239 260 202 234 236 222 268 246 261 301 352 434 507 687 891 929 869 744 766 883 1213 1390 1383 1276 1228 1172 1129 970 905 839 745 632 628 600 552 393 307 265 275 215 233 208 186 180 200 182 178 170 180 177 190 173 203 200 185 218 207 244 220 243 266 280 324 394 567 690 853 934 815 877 894 888 744 665 674 693 634 583 589 572 455 501 497 637 833 1120 968 776 526 397 372 472 548 682 632 479 341 304 211 213 199 185 190 194 183 193 204 201 264 298 373 364 306 270 271 259 298 371 433 565 625 581 460 365 291 270 311 317 411 435 426 481 415 358 268 245 239 204 246 236 272 241 203 182 189 163 165 161 145 149 163 166 138 141 158 145 131 135 147 133 140 144 155 157 196 193 175 172 174 148 164 177 183 250 310 439 401 356 276 178 216 209 222 263 281 270 217 181 183 174 171 151 142 130 147 146 148 124 129 128 135 143 135 145 134 131 154 135 139 155 143 151 154 160 141 160 155 171 166 159 187 205 212 230 313 346 402 511 535 696 717 624 520 421 399 344 380 468 482 453 373 267 229 209 176 193 210 179 173 207 225 265 315 289 229 197 204 221 249 258 290 401 434 421 368 358 396 462 547 580 497 442 397 313 316 296 341 355 373 333 274 262 290 329 333 356 280 237 214 238 243 204 239 255 249 226 191 222 193 236 264 308 340 330 282 229 235 204 203 252 249 232 222 217 226 222 238 265 341 339 338 302 275 242 218 232 297 360 399 423 365 273 254 262 216 316 339 402 509 598 700 742 619 470 398 379 352 351 379 443 466 438 357 289 258 233 216 241 235 277 309 358 356 323 273 243 224 243 250 220 267 291 282 252 255 328 357 411 375 323 267 240 208 209 236 248 261 256 244 203 173 170 174 168 167 181 159 195 168 180 186 175 191 213 274 266 323 421 552 799 1129 1277 1123 820 610 504 408 478 543 708 817 736 641 568 413 433 373 314 321 244 262 251 232 241 216 240 212 196 173 187 175 173 152 163 143 135 122 139 128 134 140 117 150 134 152 127 170 158 155 173 161 136 128 177 165 140 154 143 168 189 130 160 151 182 221 238 260 315 327 311 246 211 204 196 211 191 234 225 255 200 186 186 162 140 153 147 143 153 154 133 145 148 165 155 155 147 176 149 165 136 163 163 198 215 249 304 377 414 339 322 284 301 311 380 550 624 660 617 461 363 284 266 268 289 340 375 363 327 259 216 172 180 208 177 157 189 192 222 222 188 184 164 173 182 153 158 158 183 190 178 169 145 170 138 169 133 134 122 126 153 112 125 127 147 125 125 142 143 138 145 166 165 156 154 169 130 173 155 178 211 247 289 310 276 303 376 468 665 803 829 683 570 507 383 335 352 412 522 575 652 681 634 466 368 301 214 226 205 239 226 271 279 280 247 223 201 199 198 206 191 154 174 144 155 161 172 178 192 155 171 155 160 138 156 178 163 191 200 208 186 167 183 157 148 163 174 187 182 189 190 190 199 240 247 334 391 512 618 663 593 456 395 343 288 292 310 392 389 437 361 351 262 250 233 197 195 171 174 171 159 158 120 128 140 148 156 133 156 144 163 158 158 154 165 196 206 256 278 255 253 223 190 196 176 171 212 204 252 224 192 180 172 166 159 155 148 167 137 178 161 180 156 169 178 174 181 172 238 209 240 343 384 500 673 704 763 656 551 406 354 352 301 357 414 440 502 459 425 378 418 427 467 441 400 327 278 259 240 213 206 241 263 287 291 245 243 198 195 195 164 178 161 161 183 177 177 177 192 219 260 310 337 312 290 275 243 192 200 212 205 180 219 274 271 200 205 195 179 171 171 147 147 167 159 157 145 164 142 143 164 157 153 145 168 159 169 137 182 196 218 216 223 269 295 288 280 281 187 264 216 220 242 264 272 326 362 407 468 432 443 383 393 367 415 471 595 626 583 491 456 411 322 328 289 271 302 377 369 373 347 296 292 257 269 241 218 212 239 254 295 314 356 301 277 252 251 186 197 162 192 231 223 207 238 196 196 176 171 178 146 169 161 149 173 156 143 154 152 139 184 185 161 159 152 159 176 164 168 193 195 187 237 228 265 291 347 409 454 552 524 552 502 483 433 382 363 322 328 389 469 485 438 491 415 377 375 322 288 280 263 275 245 243 239 247 216 204 210 196 220 209 212 226 201 225 228 210 244 298 405 445 534 579 538 495 466 410 389 387 429 460 573 607 740 853 781 733 593 499 398 368 334 370 358 391 376 394 414 383 300 294 275 246 259 235 239 243 277 363 383 434 436 378 373 386 438 464 491 539 539 523 499 478 472 383 345 354 352 383 370 410 453 416 396 392 319 335 407 461 587 741 875 863 754 619 485 429 336 321 296 316 385 474 539 571 493 420 345 272 242 219 229 203 220 211 190 171 195 176 218 208 212 230 265 314 278 306 262 281 209 235 222 223 246 268 316 307 316 273 247 229 201 198 173 202 173 212 185 197 193 193 194 169 169 157 167 175 140 174 146 171 142 152 171 150 142 161 150 163 154 149 157 192 185 184 205 231 238 263 324 365 388 380 421 418 408 385 374 346 329 297 319 322 328 298 290 304 311 312 319 292 241 239 202 206 202 227 236 307 309 385 341 324 290 208 241 201 202 181 217 264 229 326 303 345 304 296 241 242 210 187 206 194 221 216 245 242 251 258 232 215 189 192 163 158 162 174 182 169 151 187 179 167 169 146 149 146 158 142 164 142 153 147 163 160 163 127 150 159 140 136 159 171 178 159 162 193 156 176 161 155 146 179 208 186 194 252 230 219 182 179 174 147 189 166 142 144 177 178 215 182 160 196 200 159 163 150 175 144 132 160 169 138 171 129 167 172 135 170 172 169 199 221 233 283 291 299 257 239 226 185 195 194 175 192 182 189 210 252 217 230 223 192 205 179 185 155 193 190 214 215 230 223 212 233 221 242 216 261 265 370 406 501 447 488 473 365 279 283 285 282 239 267 263 309 349 345 322 338 308 238 221 215 197 205 208 222 206 204 230 240 284 313 331 344 297 275 267 216 230 194 195 234 196 198 240 255 287 314 318 255 232 213 186 193 156 168 155 154 187 181 194 183 206 191 179 174 158 176 183 184 188 222 211 242 267 330 363 390 397 332 288 273 199 218 198 206 228 206 216 256 259 301 265 240 206 224 183 160 190 158 161 161 143 144 177 175 142 129 140 166 156 126 156 144 146 136 145 160 147 142 150 168 164 168 195 207 229 260 263 294 291 279 245 211 240 218 197 226 253 249 289 329 377 412 419 371 310 258 236 243 235 224 241 236 239 302 286 295 329 390 376 405 380 376 363 361 296 313 279 295 248 253 273 273 275 305 282 295 295 304 318 331 336 336 371 349 315 280 286 238 265 226 238 222 224 254 303 311 297 319 302 295 299 325 347 294 264 265 239 227 226 250 203 229 202 234 220 206 230 228 259 221 276 276 271 278 298 341 366 384 388 410 433 388 382 298 327 266 250 252 252 262 270 257 249 251 336 305 284 293 236 224 207 200 174 177 180 163 150 181 174 141 156 143 166 148 174 153 160 159 160 155 141 148 157 157 161 171 164 169 170 167 189 220 252 328 298 286 290 266 220 171 193 194 170 235 195 207 227 261 320 343 339 411 416 350 350 288 343 300 286 283 249 258 232 229 233 215 250 258 250 251 245 233 220 257 219 207 208 191 187 198 176 184 190 192 159 176 166 196 172 180 208 219 202 177 175 170 167 175 153 145 178 168 153 159 179 196 175 174 168 180 139 157 143 156 157 151 155 158 155 141 152 145 158 153 149 153 150 144 150 143 172 141 166 170 162 206 182 172 183 175 178 179 157 163 182 184 177 163 172 185 159 185 176 169 161 173 190 193 150 175 151 176 166 171 187 180 216 212 269 301 313 319 328 299 252 252 228 200 209 202 225 199 251 236 263 299 302 338 248 259 262 213 211 206 210 168 191 159 183 202 211 205 206 205 223 200 184 189 186 185 205 197 210 206 202 174 175 190 165 173 179 192 168 168 181 170 200 198 219 211 238 222 205 221 204 219 196 210 196 234 212 191 250 230 226 277 263 296 319 338 385 408 381 356 290 284 268 222 245 214 211 204 227 254 236 290 305 290 337 276 281 238 243 231 205 205 193 180 171 185 191 191 190 179 169 175 199 179 189 210 191 206 212 210 235 205 182 185 177 171 153 154 152 170 155 156 153 171 188 181 180 201 183 191 184 187 163 161 165 160 185 198 164 176 182 172 172 186 189 181 231 209 211 227 226 193 216 211 211 193 175 192 209 196 195 230 231 239 311 285 263 289 262 214 212 218 186 191 199 183 190 168 194 191 195 207 218 222 241 242 219 189 202 202 190 225 204 223 262 258 317 312 304 299 278 265 221 205 225 211 203 192 201 197 227 184 205 216 256 253 288 249 280 219 217 249 229 198 193 178 205 210 185 179 213 233 225 232 264 271 285 273 342 326 401 358 432 331 361 330 283 282 263 245 232 219 251 241 241 265 237 251 266 291 301 300 280 332 285 276 261 262 264 280 291 292 284 266 240 219 232 218 192 181 184 219 187 174 184 204 197 217 215 213 212 218 210 224 183 178 205 184 185 180 197 154 171 181 155 145 184 180 173 168 190 169 161 174 158 167 182 165 183 168 159 161 155 189 186 150 168 186 194 155 171 151 165 175 156 163 164 166 185 163 202 186 183 183 155 199 176 188 177 165 198 170 186 188 193 190 207 234 205 212 216 213 266 257 269 300 330 339 357 382 326 325 282 284 305 353 293 354 327 397 378 367 341 307 311 274 313 351 347 326 307 293 260 283 272 272 302 307 313 332 337 327 331 343 329 371 392 418 493 471 481 485 486 422 425 387 379 330 338 327 321 327 386 375 412 398 371 398 377 382 419 397 373 325 333 311 301 293 291 268 279 289 278 266 268 284 258 251 258 247 251 211 209 220 218 191 186 214 213 216 227 196 202 213 186 198 224 177 197 160 191 209 217 216 215 200 207 202 234 218 252 249 281 270 287 318 319 370 397 434 494 424 485 464 454 461 371 326 309 280 332 297 277 293 303 342 293 322 350 360 343 387 437 442 460 486 451 433 459 369 415 340 328 323 291 265 305 279 298 320 299 306 340 314 329 324 367 378 335 338 293 299 293 263 285 277 283 326 291 311 315 351 367 353 387 404 365 354 382 318 310 342 355 334 382 359 322 317 322 315 322 260 275 282 290 318 296 276 281 309 281 305 298 276 252 303 282 308 302 293 288 268 300 319 297 302 304 346 392 454 519 565 590 593 601 563 482 500 403 417 386 328 293 321 300 313 294 318 294 329 329 364 360 385 412 426 405 418 417 358 384 387 312 316 304 295 296 294 273 325 330 345 300 370 350 381 297 316 300 270 271 292 249 263 269 273 252 250 225 241 245 268 276 264 282 294 314 303 269 295 283 293 286 264 255 259 252 270 255 304 293 311 285 332 321 350 358 431 433 427 380 413 422 348 388 355 370 353 322 348 325 320 369 351 400 379 399 406 396 397 415 439 438 437 478 495 511 450 497 498 433 477 484 430 431 454 399 382 384 351 334 347 336 330 306 330 311 298 301 344 335 334 303 326 359 397 356 347 310 347 332 312 335 334 316 309 294 334 342 332 279 267 257 292 288 273 245 269 248 228 250 249 230 238 217 238 212 246 246 239 262 265 264 240 250 246 226 227 235 226 256 190 215 236 223 227 203 206 190 232 230 201 219 203 216 213 208 224 210 202 212 205 236 220 194 199 201 216 237 212 225 203 241 232 260 253 257 282 291 283 325 333 335 293 315 297 310 285 285 276 258 251 269 228 215 259 235 257 241 289 229 267 270 284 265 274 275 279 277 269 267 263 299 262 263 268 235 232 261 236 224 251 249 247 217 238 231 251 261 251 308 300 333 311 283 279 289 281 273 244 299 263 257 209 284 256 270 280 276 282 293 282 285 309 299 295 307 253 258 255 297 296 248 286 288 259 276 256 257 268 246 273 271 306 287 286 303 283 335 330 366 380 334 362 408 432 479 440 484 478 479 513 472 445 466 437 414 396 374 314 326 326 323 316 354 315 351 329 370 366 415 444 423 414 412 463 464 424 427 411 394 383 394 330 360 359 303 294 289 271 288 264 284 262 274 278 293 289 309 292 313 286 291 303 279 298 301 278 261 314 299 316 353 319 339 335 341 306 303 298 290 317 318 296 336 295 284 241 276 245 247 263 270 261 239 247 250 209 238 247 257 255 273 272 319 274 307 253 284 254 274 278 237 257 249 261 242 256 255 236 234 250 233 250 231 252 244 256 226 267 246 257 255 278 292 308 274 375 361 344 361 347 352 322 337 267 268 286 279 276 252 242 277 271 275 272 295 281 338 320 350 381 404 451 441 452 417 450 436 437 440 474 453 457 438 387 386 366 341 337 308 329 283 296 289 297 240 268 282 297 291 281 305 336 324 307 332 328 309 315 330 291 290 344 314 324 327 259 268 305 304 300 285 292 289 294 278 261 297 252 280 245 266 283 238 266 262 249 255 240 239 221 251 212 233 238 249 256 216 262 249 248 263 281 234 290 269 284 233 286 275 263 245 259 276 229 261 273 272 231 212 233 256 241 228 234 238 216 207 221 233 238 217 238 251 268 259 230 276 257 260 255 244 258 279 291 290 295 289 273 306 307 264 289 270 234 252 243 244 251 235 234 246 239 257 218 234 230 253 248 257 248 255 261 275 288 301 283 308 268 300 305 254 251 256 280 290 267 278 302 264 263 289 231 271 289 268 310 278 280 262 234 278 288 265 302 278 273 279 303 318 317 312 303 312 311 308 304 284 281 287 262 273 284 261 241 238 276 276 274 262 279 274 238 278 273 274 260 245 293 307 304 266 287 292 295 295 305 300 281 287 299 268 292 267 236 248 272 274 237 251 245 285 252 272 258 269 268 299 240 263 260 315 315 295 279 295 333 322 338 383 339 311 323 295 275 295 289 294 287 275 249 232 269 258 268 290 253 266 234 233 223 231 252 275 267 251 284 281 254 265 309 269 296 290 301 297 300 345 298 347 345 374 366 387 392 438 465 470 443 511 473 474 455 473 452 460 440 386 385 402 418 382 348 344 360 366 351 322 327 318 352 341 308 357 325 367 383 381 376 381 434 410 412 411 393 427 429 441 407 412 456 389 386 382 368 352 367 366 364 366 352 312 345 336 284 310 289 318 287 303 306 320 330 334 345 367 407 379 410 396 429 425 449 416 394 390 394 404 356 350 378 369 362 311 297 307 293 291 338 300 290 317 312 270 313 278 321 327 332 337 328 301 322 334 330 315 311 302 338 321 317 331 335 345 317 306 309 336 309 299 319 310 287 281 268 260 279 279 289 265 261 264 260 271 265 270 280 304 283 289 294 325 269 282 293 275 283 281 283 277 284 275 277 278 273 284 267 270 287 316 261 283 294 275 324 306 302 276 392 339 309 315 322 359 308 335 315 318 319 328 315 303 296 300 304 283 292 266 279 295 258 289 272 251 305 263 261 299 291 276 294 259 254 297 287 257 284 255 260 259 300 264 300 287 298 283 279 271 291 304 299 272 316 298 322 306 268 257 279 262 269 291 258 269 295 293 268 264 272 272 288 270 267 277 310 292 276 290 319 322 316 343 345 379 383 389 437 371 405 427 442 424 438 396 384 381 329 322 319 274 318 304 316 324 275 319 259 272 262 270 263 266 242 265 251 276 277 260 256 240 278 252 286 295 268 301 296 268 299 298 305 293 327 343 362 367 358 324 322 330 356 353 351 324 359 339 289 330 295 293 293 300 296 319 302 276 293 271 283 256 258 269 272 213 257 274 242 245 252 212 261 281 259 253 280 255 229 241 242 248 259 257 256 253 281 292 254 273 278 277 264 219 271 279 246 268 282 272 270 221 262 286 267 254 267 259 267 276 269 251 256 228 248 243 254 254 245 242 250 264 274 255 281 229 263 250 241 259 268 285 241 255 268 257 263 266 298 281 271 261 280 296 283 341 280 304 282 258 262 279 285 319 293 322 316 348 341 339 321 373 376 366 402 391 405 407 422 395 434 419 426 385 390 375 357 343 359 344 285 324 317 345 303 315 288 301 281 327 316 260 299 302 249 293 271 296 258 283 268 271 305 268 234 286 278 274 274 253 238 291 274 300 282 303 285 323 340 283 355 288 335 350 313 303 338 326 359 372 325 325 352 345 348 330 336 310 343 321 329 325 329 330 311 316 327 320 306 348 345 330 325 371 381 421 388 403 413 417 391 385 376 382 420 374 352 328 368 objcryst-2022.1/ObjCryst/example/pbso4/xray-single.cpp000066400000000000000000000145501430515525000226330ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Global refinement example on PbSO4. * */ #include #include #include "Quirks/VFNStreamFormat.h" #include "Quirks/Chronometer.h" #include "Quirks/VFNDebug.h" #include "RefinableObj/GlobalOptimObj.h" #include "ObjCryst/General.h" #include "ObjCryst/ScatteringPower.h" #include "ObjCryst/Atom.h" #include "ObjCryst/ZScatterer.h" #include "ObjCryst/Crystal.h" #include "ObjCryst/DiffractionDataSingleCrystal.h" using namespace ObjCryst; void testPbSO4() { //Create 'real' PBSO4 structure (for reference only-no cheating !) Crystal cryst_orig(8.482,5.398,6.959,"Pnma"); cryst_orig.SetName("PbSO4 (reference structure)"); cryst_orig.GetSpaceGroup().Print(); cryst_orig.Print(); {//Create 'real' PBSO4 structure (for reference only) ScatteringPowerAtom *ScattPowPb=new ScatteringPowerAtom("Pb","Pb",1.48); ScatteringPowerAtom *ScattPowS =new ScatteringPowerAtom("S" ,"S",0.74); ScatteringPowerAtom *ScattPowO1=new ScatteringPowerAtom("O1","O",1.87); ScatteringPowerAtom *ScattPowO2=new ScatteringPowerAtom("O2","O",1.76); ScatteringPowerAtom *ScattPowO3=new ScatteringPowerAtom("O3","O",1.34); cryst_orig.AddScatteringPower(ScattPowPb); cryst_orig.AddScatteringPower(ScattPowS); cryst_orig.AddScatteringPower(ScattPowO1); cryst_orig.AddScatteringPower(ScattPowO2); cryst_orig.AddScatteringPower(ScattPowO3); Atom *Pb=new Atom(.188,.250,.167,"Pb",ScattPowPb ,1.); Atom *S=new Atom (.437,.750,.186,"S" ,ScattPowS ,1.); Atom *O1=new Atom(.595,.750,.100,"O1",ScattPowO1 ,1.); Atom *O2=new Atom(.319,.750,.043,"O2",ScattPowO2 ,1.); Atom *O3=new Atom(.415,.974,.306,"O3",ScattPowO3 ,1.); cryst_orig.AddScatterer(Pb); cryst_orig.AddScatterer(S); cryst_orig.AddScatterer(O1); cryst_orig.AddScatterer(O2); cryst_orig.AddScatterer(O3); } cryst_orig.PrintMinDistanceTable(.05); //cryst_orig.GLDisplayCrystal(); //Creating PbSo4 refined crystal, either with independent atoms or a SO4 tetrahedron cout << "Creating PBSO4 crystal..."< #include #include "ObjCryst/ZScatterer.h" #include "ObjCryst/Atom.h" #include "ObjCryst/PowderPattern.h" #include "Quirks/VFNStreamFormat.h" #include "Quirks/Chronometer.h" #include "Quirks/VFNDebug.h" #include "RefinableObj/GlobalOptimObj.h" //#ifdef __MWERKS__ //#include //#else //#include "Profile/Profiler.h" //TAU profiling package //#endif using namespace ObjCryst; void testPbSO4() { //Create 'real' PBSO4 structure (for reference only-no cheating !) Crystal cryst_orig(8.482,5.398,6.959,"Pnma"); cryst_orig.SetName("PbSO4 (reference structure)"); cryst_orig.Print(); {//Create 'real' PBSO4 structure (for reference only) ScatteringPowerAtom *ScattPowPb=new ScatteringPowerAtom("Pb","Pb",1.48); ScatteringPowerAtom *ScattPowS =new ScatteringPowerAtom("S" ,"S",0.74); ScatteringPowerAtom *ScattPowO1=new ScatteringPowerAtom("O1","O",1.87); ScatteringPowerAtom *ScattPowO2=new ScatteringPowerAtom("O2","O",1.76); ScatteringPowerAtom *ScattPowO3=new ScatteringPowerAtom("O3","O",1.34); cryst_orig.AddScatteringPower(ScattPowPb); cryst_orig.AddScatteringPower(ScattPowS); cryst_orig.AddScatteringPower(ScattPowO1); cryst_orig.AddScatteringPower(ScattPowO2); cryst_orig.AddScatteringPower(ScattPowO3); Atom *Pb=new Atom(.188,.250,.167,"Pb",ScattPowPb ,1.); Atom *S=new Atom (.437,.750,.186,"S" ,ScattPowS ,1.); Atom *O1=new Atom(.595,.750,.100,"O1",ScattPowO1 ,1.); Atom *O2=new Atom(.319,.750,.043,"O2",ScattPowO2 ,1.); Atom *O3=new Atom(.415,.974,.306,"O3",ScattPowO3 ,1.); cryst_orig.AddScatterer(Pb); cryst_orig.AddScatterer(S); cryst_orig.AddScatterer(O1); cryst_orig.AddScatterer(O2); cryst_orig.AddScatterer(O3); } cryst_orig.PrintMinDistanceTable(.05); //cryst_orig.GLDisplayCrystal(); //Creating PbSo4 refined crystal, either with independent atoms or a SO4 tetrahedron cout << "Creating PBSO4 crystal..."<SetCrystal(cryst); data.AddPowderPatternComponent(*diffData); diffData->SetName("PbSo4-diffraction"); //approximate (hand-determined) background PowderPatternBackground *backgdData= new PowderPatternBackground; data.AddPowderPatternComponent(*backgdData); backgdData->ImportUserBackground("xray-background.dat"); backgdData->SetName("PbSo4-background"); //Profile (approximate parameters,again) diffData->SetReflectionProfilePar(PROFILE_PSEUDO_VOIGT, .03*DEG2RAD*DEG2RAD, 0*DEG2RAD*DEG2RAD, 0*DEG2RAD*DEG2RAD, 0.3,0); //Options for faster calculations //Use Dynamical population correction for special positions / shared atoms diffData->GetCrystal().SetUseDynPopCorr(true); // To go faster -sufficient for structure solution data.SetMaxSinThetaOvLambda(0.25); //Create the global optimization object MonteCarloObj globalOptObj; globalOptObj.AddRefinableObj(data); //Refine only positionnal parameters globalOptObj.FixAllPar(); globalOptObj.SetParIsFixed(gpRefParTypeScattTransl,false); globalOptObj.SetParIsFixed(gpRefParTypeScattOrient,false); globalOptObj.SetParIsFixed(gpRefParTypeScattConformBondLength,false); globalOptObj.SetParIsFixed(gpRefParTypeScattConformBondAngle,false); globalOptObj.SetParIsFixed(gpRefParTypeScattConformDihedAngle,false); globalOptObj.SetLimitsRelative(gpRefParTypeScattConformBondLength,-.1,.1); globalOptObj.SetLimitsRelative(gpRefParTypeScattConformBondAngle,-10.*DEG2RAD,10.*DEG2RAD); globalOptObj.SetLimitsRelative(gpRefParTypeScattConformDihedAngle,-10.*DEG2RAD,10.*DEG2RAD); //Don't cheat ;-) globalOptObj.RandomizeStartingConfig(); //Print Crystal structure cout << "Random starting configuration"<PrintFhklCalc(); //Print Crystal structure cryst.Print(); //Print minimum distance between different atoms // (<.05 are considered identical, if same element) cryst.PrintMinDistanceTable(.05); //Also print real structure cryst_orig.Print(); //Save crystal POVRay file //ofstream out1("crystal.pov"); //cryst.POVRayDescription(out1); //out1.close(); //ofstream out2("pbso4/crystal-real.pov"); //cryst_orig.POVRayDescription(out2); //out2.close(); } int main (int argc, char *argv[]) { TAU_PROFILE_SET_NODE(0); // sequential code TAU_PROFILE("main()","int()",TAU_DEFAULT); cout << " Beginning PbSO4 example...." << endl ; int level =10; if(argc==2)//debug level hase been supplied { level=atoi(argv[1]); } VFN_DEBUG_GLOBAL_LEVEL(level); testPbSO4(); cout << " End of PbSO4 example." << endl ; TAU_REPORT_STATISTICS(); return 0; } objcryst-2022.1/ObjCryst/gnu.mak000066400000000000000000000061301430515525000164610ustar00rootroot00000000000000BUILD_DIR=$(CURDIR)/.. include rules.mak ###################################################################### ##################### LIBRAIRIES ######################## ###################################################################### #All defined in rules.mak ###################################################################### ##################### PROGRAMS ######################## ###################################################################### #test-cristallo test: cd ${DIR_TEST} && make all ###################################################################### ##################### OTHER TARGETS ######################## ###################################################################### ctags: $(MAKE) -f gnu.mak -C ${DIR_DOC} ctags # target for making both libraries .PHONY : all all: libcryst test doc # target for removing all object files (does not affect blitz/newmat/sglite/atominfo) .PHONY : tidy tidy:: $(MAKE) -f gnu.mak -C ${DIR_LIBCRYST} tidy $(MAKE) -f gnu.mak -C ${DIR_CRYSTVECTOR} tidy $(MAKE) -f gnu.mak -C ${DIR_VFNQUIRKS} tidy $(MAKE) -f gnu.mak -C ${DIR_REFOBJ} tidy $(MAKE) -f gnu.mak -C ${DIR_WXWCRYST} tidy $(MAKE) -f gnu.mak -C ${DIR_EXAMPLE} tidy # target for removing all object files and libraries # (does not affect blitz/newmat/sglite/atominfo) .PHONY : clean clean:: $(MAKE) -f gnu.mak -C ${DIR_LIBCRYST} clean $(MAKE) -f gnu.mak -C ${DIR_CRYSTVECTOR} clean $(MAKE) -f gnu.mak -C ${DIR_VFNQUIRKS} clean $(MAKE) -f gnu.mak -C ${DIR_REFOBJ} clean $(MAKE) -f gnu.mak -C ${DIR_WXWCRYST} clean $(MAKE) -f gnu.mak -C ${DIR_EXAMPLE} clean # Build *shared* library - the "shared_libcryst=1" option is mandatory lib:libnewmat libcctbx libCrystVector libQuirks libRefinableObj libCryst gcc -shared -Wl,-soname,libObjCryst.so.1 -lnewmat -lcctbx -o libObjCryst.so.1.0.0 */*.o #target to make documentation (requires doxygen) #also makes tags file, although it is not related to doxygen doc: cd ${DIR_DOC}; $(MAKE) -f gnu.mak doc #target to make distribution archive of libcryst++ dist: tar -czf ../archives/ObjCryst.tar.gz -C .. --exclude='*.o' --exclude='.systemG.Desktop' --exclude='profile.0.0.0' --exclude='*.a' --exclude='*.pov' --exclude='latex' --exclude='*.exe' --exclude='*.out' --exclude='tags' --exclude='wxCryst/Fox' --exclude='Makefile' ObjCryst --dereference #these are libraries/programs used by ObjCryst but developped by other people. #These are needed to use ObjCryst, but not modified-so only get it once. # # ObjCryst/blitz dist-libs: tar -czf ../archives/ObjCryst-libs.tar.gz -C .. --exclude='*.o' --exclude='.systemG.Desktop' --exclude='*.a' --exclude='*.exe' cctbx newmat --exclude='Makefile' --dereference #target to make a complete archive of ObjCryst++ archive: tar -czf ../archives/ObjCryst-complete.tar.gz -C .. --exclude='*.o' --exclude='.systemG.Desktop' --exclude='*.a' --exclude='*.exe' --exclude='*.out' --exclude='CVS' --exclude='ObjCryst/doc/html' --exclude='ObjCryst/doc/latex' --exclude='*.oxy' --exclude='profile.0.0.0' --exclude='Makefile' cctbx newmat AsymProfLarryFinger ObjCryst --dereference objcryst-2022.1/ObjCryst/license.txt000066400000000000000000000354511430515525000173710ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS objcryst-2022.1/ObjCryst/rules-gnu.mak000066400000000000000000000236041430515525000176160ustar00rootroot00000000000000# Base building directory - This must be defined in the Makefile including this one #ROOT_DIR = ${CURDIR} # Base ObjCryst directory DIR_CRYST = $(BUILD_DIR)/ObjCryst #Libraries to be statically linked are installed in $(DIR_STATIC_LIBS)/lib, #with their headers in DIR_STATIC_LIBS)/include DIR_STATIC_LIBS = $(BUILD_DIR)/static-libs #Internal directories DIR_CRYSTVECTOR = ${DIR_CRYST}/CrystVector DIR_EXAMPLE = ${DIR_CRYST}/example DIR_LIBCRYST = ${DIR_CRYST}/ObjCryst DIR_REFOBJ = ${DIR_CRYST}/RefinableObj DIR_VFNQUIRKS = ${DIR_CRYST}/Quirks DIR_WXWCRYST = ${DIR_CRYST}/wxCryst DIR_DOC := ${DIR_CRYST}/doc # DO we want to use shared libraries for wxGTK, freeglut, fftw & newmat ? # User can also use shared libraries only for some libraries, by using # "make shared-wxgtk=1" instead of "make shared=1" ifeq ($(shared),1) shared-newmat=1 shared-wxgtk=1 shared-fftw=1 shared-glut=1 endif ### Rules for Linux & GCC # C compiler #CC := gcc CFLAGS = ${DEPENDFLAGS} # C++ compiler #CXX := g++ CXXFLAGS = ${DEPENDFLAGS} ${PROFILEFLAGS} # FORTRAN compiler FC := f77 FFLAGS = # linker LINKER := ${CXX} CRYST_LDFLAGS = ${LDFLAGS} -L/usr/lib -L/usr/local/lib -L$(DIR_CRYSTVECTOR) -L$(DIR_LIBCRYST) -L$(DIR_REFOBJ) -L$(DIR_STATIC_LIBS)/lib -L$(DIR_VFNQUIRKS) -L$(DIR_WXWCRYST) -L$(DIR_TAU)/x86_64/lib #to automatically generate dependencies MAKEDEPEND = gcc -MM ${CPPFLAGS} ${CXXFLAGS} ${C_BLITZFLAG} $< > $*.dep # header files SEARCHDIRS = -I$(DIR_TAU)/include -I${DIR_CRYST}/.. -I$(DIR_STATIC_LIBS)/include #wxWindows flags ifeq ($(wxcryst),1) WXCRYSTFLAGS = -D__WX__CRYST__ `$(WXCONFIG) --cxxflags` WX_LDFLAGS = -L/usr/X11R6/lib -lwxcryst `$(WXCONFIG) --libs adv,core,base,net` $(GL_WX_LIB) else WXCRYSTFLAGS := WX_LDFLAGS := endif #Profiling ifeq ($(profile),1) #activate profiling using TAU package DIR_TAU=$(BUILD_DIR)/../../utils/tau PROFILEFLAGS := -DPROFILING_ON -DTAU_GNU -DTAU_DOT_H_LESS_HEADERS -DTAU_LINUX_TIMERS -DTAU_LARGEFILE -D_LARGEFILE64_SOURCE -DHAVE_TR1_HASH_MAP -UTAU_MPI -I$(DIR_TAU)/include PROFILELIB := -ltau else ifeq ($(profile),2) # *generate* profiling using gcc PROFILEFLAGS := -fprofile-generate PROFILELIB := -fprofile-generate else ifeq ($(profile),3) # *use* profiling using gcc PROFILEFLAGS := -fprofile-use PROFILELIB := -fprofile-use else PROFILEFLAGS := PROFILELIB := endif endif endif #Use static linking to wx and freeglut libraries ? Unicode ifneq ($(shared-wxgtk),1) WXCONFIG= $(DIR_CRYST)/../static-libs/bin/wx-config --unicode=yes else WXCONFIG= wx-config --unicode=yes endif # Which command to use for download ? WGET=$(shell which wget 2>/dev/null) ifneq ($(WGET),) DOWNLOAD_COMMAND=wget else DOWNLOAD_COMMAND=curl -L -O endif # If using glut (freeglut) GLUT_FLAGS= -DHAVE_GLUT GLUT_LIB= -lglut #Specifiy REAL= float or double ifeq ($(real_double),1) REAL_FLAG= -DREAL=double else REAL_FLAG= -DREAL=float endif #Using OpenGL ? ifeq ($(opengl),1) GL_WX_LIB = `$(WXCONFIG) --gl-libs` -lGL -lGLU $(GLUT_LIB) GL_FLAGS = -DOBJCRYST_GL -I/usr/X11R6/include -IGL $(GLUT_FLAGS) else GL_WX_LIB := GL_FLAGS := endif #Using fftw ifneq ($(fftw),0) FFTW_LIB = -lfftw3f FFTW_FLAGS = -DHAVE_FFTW else FFTW_LIB := FFTW_FLAGS := endif ifneq ($(sse),0) SSE_FLAGS = -DHAVE_SSE_MATHFUN -DUSE_SSE2 -march=native else SSE_FLAGS = endif ifneq ($(shared-newmat),1) LDNEWMAT := $(DIR_STATIC_LIBS)/lib/libnewmat.a else LDNEWMAT := -lnewmat endif #Using COD, with MySQL ifneq ($(cod),0) COD_FLAGS = -D__FOX_COD__ else COD_FLAGS := endif ifeq ($(shared_libcryst),1) CPPFLAGS = -O3 -w -fPIC -g -ffast-math -fstrict-aliasing -pipe -funroll-loops ${SSE_FLAGS} DEPENDFLAGS = ${SEARCHDIRS} ${GL_FLAGS} ${WXCRYSTFLAGS} ${FFTW_FLAGS} ${REAL_FLAG} else ifeq ($(debug),1) #Set DEBUG options ifdef RPM_OPT_FLAGS # we are building a RPM ! CPPFLAGS = ${RPM_OPT_FLAGS} else CPPFLAGS = -g -Wall -D__DEBUG__ ${SSE_FLAGS} ${COD_FLAGS} endif DEPENDFLAGS = ${SEARCHDIRS} ${GL_FLAGS} ${WXCRYSTFLAGS} ${FFTW_FLAGS} ${REAL_FLAG} LOADLIBES = -lm -lcryst -lCrystVector -lQuirks -lRefinableObj -lcctbx ${LDNEWMAT} ${PROFILELIB} ${GL_LIB} ${WX_LDFLAGS} ${FFTW_LIB} else ifdef RPM_OPT_FLAGS # we are building a RPM ! CPPFLAGS = ${RPM_OPT_FLAGS} else #default flags - use "sse=1" to enable SSE optimizations CPPFLAGS = -O3 -w -ffast-math -fstrict-aliasing -pipe -fomit-frame-pointer -funroll-loops -ftree-vectorize ${SSE_FLAGS} ${COD_FLAGS} endif DEPENDFLAGS = ${SEARCHDIRS} ${GL_FLAGS} ${WXCRYSTFLAGS} ${FFTW_FLAGS} ${REAL_FLAG} LOADLIBES = -lm -lcryst -lCrystVector -lQuirks -lRefinableObj -lcctbx ${LDNEWMAT} ${PROFILELIB} ${GL_LIB} ${WX_LDFLAGS} ${FFTW_LIB} endif endif # Add to statically link: -nodefaultlibs -lgcc /usr/lib/libstdc++.a ###################################################################### ##################### LIBRAIRIES ######################## ###################################################################### #Newmat Matrix Algebra library (used for SVD) $(BUILD_DIR)/newmat.tar.bz2: cd $(BUILD_DIR) && $(DOWNLOAD_COMMAND) https://github.com/vincefn/objcryst/releases/download/v2021-3rdPartyLibs/newmat.tar.bz2 $(DIR_STATIC_LIBS)/lib/libnewmat.a: $(BUILD_DIR)/newmat.tar.bz2 cd $(BUILD_DIR) && tar -xjf newmat.tar.bz2 $(MAKE) -f nm_gnu.mak -C $(BUILD_DIR)/newmat libnewmat.a mkdir -p $(DIR_STATIC_LIBS)/lib/ cp $(BUILD_DIR)/newmat/libnewmat.a $(DIR_STATIC_LIBS)/lib/ mkdir -p $(DIR_STATIC_LIBS)/include/newmat cp $(BUILD_DIR)/newmat/*.h $(DIR_STATIC_LIBS)/include/newmat/ #rm -Rf $(BUILD_DIR)/newmat ifneq ($(shared-newmat),1) libnewmat= $(DIR_STATIC_LIBS)/lib/libnewmat.a else libnewmat= endif $(BUILD_DIR)/freeglut.tar.bz2: cd $(BUILD_DIR) && $(DOWNLOAD_COMMAND) https://github.com/vincefn/objcryst/releases/download/v2021-3rdPartyLibs/freeglut.tar.bz2 $(BUILD_DIR)/static-libs/lib/libglut.a: $(BUILD_DIR)/freeglut.tar.bz2 cd $(BUILD_DIR) && tar -xjf freeglut.tar.bz2 cd $(BUILD_DIR)/freeglut && ./configure --prefix=$(BUILD_DIR)/static-libs --disable-shared --disable-warnings --x-includes=/usr/X11R6/include/ && $(MAKE) install rm -Rf freeglut ifeq ($(opengl),1) ifneq ($(shared-glut),1) libfreeglut= $(DIR_STATIC_LIBS)/lib/libglut.a else libfreeglut= endif else libfreeglut= endif $(BUILD_DIR)/wxWidgets-3.1.6.tar.bz2: cd $(BUILD_DIR) && $(DOWNLOAD_COMMAND) https://github.com/wxWidgets/wxWidgets/releases/download/v3.1.6/wxWidgets-3.1.6.tar.bz2 $(BUILD_DIR)/static-libs/include/wx-3.1/wx/wx.h: $(BUILD_DIR)/wxWidgets-3.1.6.tar.bz2 cd $(BUILD_DIR) && rm -Rf wxWidgets-3.1.6 && tar -xjf wxWidgets-3.1.6.tar.bz2 cd $(BUILD_DIR)/wxWidgets-3.1.6 && ./configure --with-gtk --with-opengl --disable-glcanvasegl --prefix=$(BUILD_DIR)/static-libs --enable-unicode --enable-optimise --disable-shared --x-includes=/usr/X11R6/include/ && $(MAKE) install rm -Rf $(BUILD_DIR)/wxWidgets-3.1.6 ifneq ($(wxcryst),0) ifneq ($(shared-wxgtk),1) libwx = $(BUILD_DIR)/static-libs/include/wx-3.1/wx/wx.h else libwx= endif else libwx= endif #cctbx $(BUILD_DIR)/cctbx.tar.bz2: cd $(BUILD_DIR) && $(DOWNLOAD_COMMAND) https://github.com/vincefn/objcryst/releases/download/v2021-3rdPartyLibs/cctbx.tar.bz2 $(DIR_STATIC_LIBS)/lib/libcctbx.a: $(BUILD_DIR)/cctbx.tar.bz2 mkdir -p $(DIR_STATIC_LIBS)/lib/ $(DIR_STATIC_LIBS)/include/ cd $(BUILD_DIR) && tar -xjf cctbx.tar.bz2 $(MAKE) -f gnu.mak -C $(BUILD_DIR)/cctbx install #ln -sf $(BUILD_DIR)/boost $(DIR_STATIC_LIBS)/include/ #rm -Rf $(BUILD_DIR)/cctbx libcctbx: $(DIR_STATIC_LIBS)/lib/libcctbx.a $(BUILD_DIR)/fftw-3.3.9.tar.gz: cd $(BUILD_DIR) && $(DOWNLOAD_COMMAND) http://fftw.org/fftw-3.3.9.tar.gz $(DIR_STATIC_LIBS)/lib/libfftw3f.a: $(BUILD_DIR)/fftw-3.3.9.tar.gz cd $(BUILD_DIR) && tar -xzf fftw-3.3.9.tar.gz cd $(BUILD_DIR)/fftw-3.3.9 && ./configure --enable-single --prefix $(DIR_STATIC_LIBS) && $(MAKE) install rm -Rf $(BUILD_DIR)/fftw-3.3.9 ifneq ($(fftw),0) ifneq ($(shared-fftw),1) libfftw = $(DIR_STATIC_LIBS)/lib/libfftw3f.a else libfftw= endif else libfftw= endif # Boost library - used for cctbx and Fox. # TODO: clarify install to see if we use boost from cctbx or independently installed... $(BUILD_DIR)/boost_1_68_0.tar.bz2: cd $(BUILD_DIR) && $(DOWNLOAD_COMMAND) https://dl.bintray.com/boostorg/release/1.68.0/source/boost_1_68_0.tar.bz2 libboost:$(BUILD_DIR)/boost_1_68_0.tar.bz2 cd $(BUILD_DIR) && tar -xjf boost_1_68_0.tar.bz2 cd $(BUILD_DIR)/boost_1_68_0 && rsync -ar boost --exclude="accumulators/" --exclude="asio/" --exclude="asign/" --exclude="bimap/" --exclude="circular_buffer/" --exclude="concept_check/" --exclude="dynamic_bitset/" --exclude="filesystem/" --exclude="flyweight/" --exclude="function_types/" --exclude="gil/" --exclude="graph/" --exclude="interprocess/" --exclude="intrusive/" --exclude="iostreams/" --exclude="lambda/" --exclude="logic/" --exclude="mpi/" --exclude="parameter/" --exclude="pending/" --exclude="pool/" --exclude="program_options/" --exclude="proto/" --exclude="ptr_container/" --exclude="python/" --exclude="random/" --exclude="regex/" --exclude="signals/" --exclude="spirit/" --exclude="statechart/" --exclude="system/" --exclude="test/" --exclude="thread/" --exclude="units/" --exclude="unordered/" --exclude="wave/" --exclude="xpressive/" --filter="+ */" --filter="+ *.hpp" --filter="+ *.ipp" $(DIR_STATIC_LIBS)/include/ rm -Rf $(BUILD_DIR)/boost_1_68_0 #ObjCryst++ libCryst: $(libwx) libcctbx $(MAKE) -f gnu.mak -C ${DIR_LIBCRYST} lib libcryst: libCryst #wxCryst++ libwxCryst: $(libwx) $(libfreeglut) $(libfftw) libcctbx $(MAKE) -f gnu.mak -C ${DIR_WXWCRYST} lib #Vector computation library libCrystVector: $(libwx) $(MAKE) -f gnu.mak -C ${DIR_CRYSTVECTOR} lib #Quirks, including a (crude) library to display float, vectors, matrices, strings with some formatting.. libQuirks: $(libwx) $(MAKE) -f gnu.mak -C ${DIR_VFNQUIRKS} lib #Library to take care of refinable parameters, plus Global optimization and Least Squares refinements libRefinableObj:$(libnewmat) $(libwx) libcctbx $(MAKE) -f gnu.mak -C ${DIR_REFOBJ}/ lib objcryst-2022.1/ObjCryst/wxCryst/000077500000000000000000000000001430515525000166615ustar00rootroot00000000000000objcryst-2022.1/ObjCryst/wxCryst/.cvsignore000066400000000000000000000001771430515525000206660ustar00rootroot00000000000000*.o *.exe *.out *.old *.dep *.a .directory .systemG.Desktop tags html latex *.oxy *.xml profile.0.0.0 *.pov Makefile rules.mak objcryst-2022.1/ObjCryst/wxCryst/MC.cpp000066400000000000000000001415001430515525000176650ustar00rootroot00000000000000/* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ ///////////////////////////////////////////////////////////////////////////////////////////// // FileName: MarchingCubes.cpp // Author : Michael Y. Polyakov // email : myp@andrew.cmu.edu or mikepolyakov@hotmail.com // website : www.angelfire.com/linux/myp // date : July 2002 // // Description: 'Straight' and Recursive Marching Cubes Algorithms // Recursive method is faster than the 'straight' one, especially when intersection does not // have to be searched for every time. // Normal vectors are defined for each vertex as a gradients // For function definitions see MarchingCubes.h // For a tutorial on Marching Cubes please visit www.angelfire.com/myp/linux // // Please email me with any suggestion/bugs. ///////////////////////////////////////////////////////////////////////////////////////////// #include "MC.h" #include "MCTable.h" #include //Linear Interpolation between two points mpVector LinearInterp(mp4Vector p1, mp4Vector p2, float value) { mpVector p; if(fabs(p1.val - p2.val) > 0.00001) p = (mpVector)p1 + ((mpVector)p2 - (mpVector)p1)/(p2.val - p1.val)*(value - p1.val); else p = (mpVector)p1; return p; } //Macros used to compute gradient vector on each vertex of a cube //argument should be the name of array of vertices //can be verts or *verts if done by reference #define CALC_GRAD_VERT_0(verts) mp4Vector(points[ind-YtimeZ].val-(verts[1]).val,points[ind-pointsZ].val-(verts[4]).val,points[ind-1].val-(verts[3]).val, (verts[0]).val); #define CALC_GRAD_VERT_1(verts) mp4Vector((verts[0]).val-points[ind+2*YtimeZ].val,points[ind+YtimeZ-pointsZ].val-(verts[5]).val,points[ind+YtimeZ-1].val-(verts[2]).val, (verts[1]).val); #define CALC_GRAD_VERT_2(verts) mp4Vector((verts[3]).val-points[ind+2*YtimeZ+1].val,points[ind+YtimeZ-ncellsZ].val-(verts[6]).val,(verts[1]).val-points[ind+YtimeZ+2].val, (verts[2]).val); #define CALC_GRAD_VERT_3(verts) mp4Vector(points[ind-YtimeZ+1].val-(verts[2]).val,points[ind-ncellsZ].val-(verts[7]).val,(verts[0]).val-points[ind+2].val, (verts[3]).val); #define CALC_GRAD_VERT_4(verts) mp4Vector(points[ind-YtimeZ+ncellsZ+1].val-(verts[5]).val,(verts[0]).val-points[ind+2*pointsZ].val,points[ind+ncellsZ].val-(verts[7]).val, (verts[4]).val); #define CALC_GRAD_VERT_5(verts) mp4Vector((verts[4]).val-points[ind+2*YtimeZ+ncellsZ+1].val,(verts[1]).val-points[ind+YtimeZ+2*pointsZ].val,points[ind+YtimeZ+ncellsZ].val-(verts[6]).val, (verts[5]).val); #define CALC_GRAD_VERT_6(verts) mp4Vector((verts[7]).val-points[ind+2*YtimeZ+ncellsZ+2].val,(verts[2]).val-points[ind+YtimeZ+2*ncellsZ+3].val,(verts[5]).val-points[ind+YtimeZ+ncellsZ+3].val, (verts[6]).val); #define CALC_GRAD_VERT_7(verts) mp4Vector(points[ind-YtimeZ+ncellsZ+2].val-(verts[6]).val,(verts[3]).val-points[ind+2*ncellsZ+3].val,(verts[4]).val-points[ind+ncellsZ+3].val, (verts[7]).val); /////////////////////////////////////////////////////////////////////////////////////////////////////// // GLOBAL // //Global variables - so they dont have to be passed into functions int pointsZ; //number of points on Z zxis (equal to ncellsZ+1) int YtimeZ; //'plane' of cubes on YZ (equal to (ncellsY+1)*pointsZ ) /////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////// // 'STRAIGHT' MARCHING CUBES ALGORITHM /////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////// //for gradients at the edges values 1.0, 1.0, 1.0, 1.0 are given TRIANGLE* MC(int ncellsX, int ncellsY, int ncellsZ, float gradFactorX, float gradFactorY, float gradFactorZ, float minValue, mp4Vector * points, int &numTriangles) { //this should be enough space, if not change 3 to 4 TRIANGLE * triangles = new TRIANGLE[3*ncellsX*ncellsY*ncellsZ]; numTriangles = int(0); pointsZ = ncellsZ+1; //initialize global variable (for extra speed) YtimeZ = (ncellsY+1)*pointsZ; int lastX = ncellsX; //left from older version int lastY = ncellsY; int lastZ = ncellsZ; mp4Vector *verts[8]; //vertices of a cube (array of pointers for extra speed) mpVector intVerts[12]; //linearly interpolated vertices on each edge int cubeIndex; //shows which vertices are outside/inside int edgeIndex; //index returned by edgeTable[cubeIndex] mp4Vector gradVerts[8]; //gradients at each vertex of a cube mpVector grads[12]; //linearly interpolated gradients on each edge int indGrad; //shows which gradients already have been computed int ind, ni, nj; //ind: index of vertex 0 //factor by which corresponding coordinates of gradient vectors are scaled mpVector factor(1.0/(2.0*gradFactorX), 1.0/(2.0*gradFactorY), 1.0/(2.0*gradFactorZ)); //MAIN LOOP: goes through all the points for(int i=0; i < lastX; i++) { //x axis ni = i*YtimeZ; for(int j=0; j < lastY; j++) { //y axis nj = j*pointsZ; for(int k=0; k < lastZ; k++, ind++) //z axis { //initialize vertices ind = ni + nj + k; verts[0] = &points[ind]; verts[1] = &points[ind + YtimeZ]; verts[4] = &points[ind + pointsZ]; verts[5] = &points[ind + YtimeZ + pointsZ]; verts[2] = &points[ind + YtimeZ + 1]; verts[3] = &points[ind + 1]; verts[6] = &points[ind + YtimeZ + pointsZ + 1]; verts[7] = &points[ind + pointsZ + 1]; //get the index cubeIndex = int(0); for(int n=0; n < 8; n++) if(verts[n]->val <= minValue) cubeIndex |= (1 << n); //check if its completely inside or outside if(!edgeTable[cubeIndex]) continue; indGrad = int(0); edgeIndex = edgeTable[cubeIndex]; if(edgeIndex & 1) { intVerts[0] = LinearInterp(*verts[0], *verts[1], minValue); if(i != 0 && j != 0 && k != 0) gradVerts[0] = CALC_GRAD_VERT_0(*verts) else gradVerts[0] = mp4Vector(1.0, 1.0, 1.0, 1.0); //for now do not wrap around if(i != lastX-1 && j != 0 && k != 0) gradVerts[1] = CALC_GRAD_VERT_1(*verts) else gradVerts[1] = mp4Vector(1.0, 1.0, 1.0, 1.0); indGrad |= 3; grads[0] = LinearInterp(gradVerts[0], gradVerts[1], minValue); grads[0].x *= factor.x; grads[0].y *= factor.y; grads[0].z *= factor.z; } if(edgeIndex & 2) { intVerts[1] = LinearInterp(*verts[1], *verts[2], minValue); if(! (indGrad & 2)) { if(i != lastX-1 && j != 0 && k != 0) gradVerts[1] = CALC_GRAD_VERT_1(*verts) else gradVerts[1] = mp4Vector(1.0, 1.0, 1.0, 1.0); indGrad |= 2; } if(i != lastX-1 && j != 0 && k != 0) gradVerts[2] = CALC_GRAD_VERT_2(*verts) else gradVerts[2] = mp4Vector(1.0, 1.0, 1.0, 1.0); indGrad |= 4; grads[1] = LinearInterp(gradVerts[1], gradVerts[2], minValue); grads[1].x *= factor.x; grads[1].y *= factor.y; grads[1].z *= factor.z; } if(edgeIndex & 4) { intVerts[2] = LinearInterp(*verts[2], *verts[3], minValue); if(! (indGrad & 4)) { if(i != lastX-1 && j != 0 && k != 0) gradVerts[2] = CALC_GRAD_VERT_2(*verts) else gradVerts[2] = mp4Vector(1.0, 1.0, 1.0, 1.0); indGrad |= 4; } if(i != 0 && j != 0 && k != lastZ-1) gradVerts[3] = CALC_GRAD_VERT_3(*verts) else gradVerts[3] = mp4Vector(1.0, 1.0, 1.0, 1.0); indGrad |= 8; grads[2] = LinearInterp(gradVerts[2], gradVerts[3], minValue); grads[2].x *= factor.x; grads[2].y *= factor.y; grads[2].z *= factor.z; } if(edgeIndex & 8) { intVerts[3] = LinearInterp(*verts[3], *verts[0], minValue); if(! (indGrad & 8)) { if(i != 0 && j != 0 && k != lastZ-1) gradVerts[3] = CALC_GRAD_VERT_3(*verts) else gradVerts[3] = mp4Vector(1.0, 1.0, 1.0, 1.0); indGrad |= 8; } if(! (indGrad & 1)) { if(i != 0 && j != 0 && k != 0) gradVerts[0] = CALC_GRAD_VERT_0(*verts) else gradVerts[0] = mp4Vector(1.0, 1.0, 1.0, 1.0); indGrad |= 1; } grads[3] = LinearInterp(gradVerts[3], gradVerts[0], minValue); grads[3].x *= factor.x; grads[3].y *= factor.y; grads[3].z *= factor.z; } if(edgeIndex & 16) { intVerts[4] = LinearInterp(*verts[4], *verts[5], minValue); if(i != 0 && j != lastY-1 && k != 0) gradVerts[4] = CALC_GRAD_VERT_4(*verts) else gradVerts[4] = mp4Vector(1.0, 1.0, 1.0, 1.0); if(i != lastX-1 && j != lastY-1 && k != 0) gradVerts[5] = CALC_GRAD_VERT_5(*verts) else gradVerts[5] = mp4Vector(1.0, 1.0, 1.0, 1.0); indGrad |= 48; grads[4] = LinearInterp(gradVerts[4], gradVerts[5], minValue); grads[4].x *= factor.x; grads[4].y *= factor.y; grads[4].z *= factor.z; } if(edgeIndex & 32) { intVerts[5] = LinearInterp(*verts[5], *verts[6], minValue); if(! (indGrad & 32)) { if(i != lastX-1 && j != lastY-1 && k != 0) gradVerts[5] = CALC_GRAD_VERT_5(*verts) else gradVerts[5] = mp4Vector(1.0, 1.0, 1.0, 1.0); indGrad |= 32; } if(i != lastX-1 && j != lastY-1 && k != lastZ-1) gradVerts[6] = CALC_GRAD_VERT_6(*verts) else gradVerts[6] = mp4Vector(1.0, 1.0, 1.0, 1.0); indGrad |= 64; grads[5] = LinearInterp(gradVerts[5], gradVerts[6], minValue); grads[5].x *= factor.x; grads[5].y *= factor.y; grads[5].z *= factor.z; } if(edgeIndex & 64) { intVerts[6] = LinearInterp(*verts[6], *verts[7], minValue); if(! (indGrad & 64)) { if(i != lastX-1 && j != lastY-1 && k != lastZ-1) gradVerts[6] = CALC_GRAD_VERT_6(*verts) else gradVerts[6] = mp4Vector(1.0, 1.0, 1.0, 1.0); indGrad |= 64; } if(i != 0 && j != lastY-1 && k != lastZ-1) gradVerts[7] = CALC_GRAD_VERT_7(*verts) else gradVerts[7] = mp4Vector(1.0, 1.0, 1.0, 1.0); indGrad |= 128; grads[6] = LinearInterp(gradVerts[6], gradVerts[7], minValue); grads[6].x *= factor.x; grads[6].y *= factor.y; grads[6].z *= factor.z; } if(edgeIndex & 128) { intVerts[7] = LinearInterp(*verts[7], *verts[4], minValue); if(! (indGrad & 128)) { if(i != 0 && j != lastY-1 && k != lastZ-1) gradVerts[7] = CALC_GRAD_VERT_7(*verts) else gradVerts[7] = mp4Vector(1.0, 1.0, 1.0, 1.0); indGrad |= 128; } if(! (indGrad & 16)) { if(i != 0 && j != lastY-1 && k != 0) gradVerts[4] = CALC_GRAD_VERT_4(*verts) else gradVerts[4] = mp4Vector(1.0, 1.0, 1.0, 1.0); indGrad |= 16; } grads[7] = LinearInterp(gradVerts[7], gradVerts[4], minValue); grads[7].x *= factor.x; grads[7].y *= factor.y; grads[7].z *= factor.z; } if(edgeIndex & 256) { intVerts[8] = LinearInterp(*verts[0], *verts[4], minValue); if(! (indGrad & 1)) { if(i != 0 && j != 0 && k != 0) gradVerts[0] = CALC_GRAD_VERT_0(*verts) else gradVerts[0] = mp4Vector(1.0, 1.0, 1.0, 1.0); indGrad |= 1; } if(! (indGrad & 16)) { if(i != 0 && j != lastY-1 && k != 0) gradVerts[4] = CALC_GRAD_VERT_4(*verts) else gradVerts[4] = mp4Vector(1.0, 1.0, 1.0, 1.0); indGrad |= 16; } grads[8] = LinearInterp(gradVerts[0], gradVerts[4], minValue); grads[8].x *= factor.x; grads[8].y *= factor.y; grads[8].z *= factor.z; } if(edgeIndex & 512) { intVerts[9] = LinearInterp(*verts[1], *verts[5], minValue); if(! (indGrad & 2)) { if(i != lastX-1 && j != 0 && k != 0) gradVerts[1] = CALC_GRAD_VERT_1(*verts) else gradVerts[1] = mp4Vector(1.0, 1.0, 1.0, 1.0); indGrad |= 2; } if(! (indGrad & 32)) { if(i != lastX-1 && j != lastY-1 && k != 0) gradVerts[5] = CALC_GRAD_VERT_5(*verts) else gradVerts[5] = mp4Vector(1.0, 1.0, 1.0, 1.0); indGrad |= 32; } grads[9] = LinearInterp(gradVerts[1], gradVerts[5], minValue); grads[9].x *= factor.x; grads[9].y *= factor.y; grads[9].z *= factor.z; } if(edgeIndex & 1024) { intVerts[10] = LinearInterp(*verts[2], *verts[6], minValue); if(! (indGrad & 4)) { if(i != lastX-1 && j != 0 && k != 0) gradVerts[2] = CALC_GRAD_VERT_2(*verts) else gradVerts[5] = mp4Vector(1.0, 1.0, 1.0, 1.0); indGrad |= 4; } if(! (indGrad & 64)) { if(i != lastX-1 && j != lastY-1 && k != lastZ-1) gradVerts[6] = CALC_GRAD_VERT_6(*verts) else gradVerts[6] = mp4Vector(1.0, 1.0, 1.0, 1.0); indGrad |= 64; } grads[10] = LinearInterp(gradVerts[2], gradVerts[6], minValue); grads[10].x *= factor.x; grads[10].y *= factor.y; grads[10].z *= factor.z; } if(edgeIndex & 2048) { intVerts[11] = LinearInterp(*verts[3], *verts[7], minValue); if(! (indGrad & 8)) { if(i != 0 && j != 0 && k != lastZ-1) gradVerts[3] = CALC_GRAD_VERT_3(*verts) else gradVerts[3] = mp4Vector(1.0, 1.0, 1.0, 1.0); indGrad |= 8; } if(! (indGrad & 128)) { if(i != 0 && j != lastY-1 && k != lastZ-1) gradVerts[7] = CALC_GRAD_VERT_7(*verts) else gradVerts[7] = mp4Vector(1.0, 1.0, 1.0, 1.0); indGrad |= 128; } grads[11] = LinearInterp(gradVerts[3], gradVerts[7], minValue); grads[11].x *= factor.x; grads[11].y *= factor.y; grads[11].z *= factor.z; } //now build the triangles using triTable for (int n=0; triTable[cubeIndex][n] != -1; n+=3) { int index[3] = {triTable[cubeIndex][n+2], triTable[cubeIndex][n+1], triTable[cubeIndex][n]}; for(int h=0; h < 3; h++) { //copy vertices and normals into triangles array triangles[numTriangles].p[h] = intVerts[index[h]]; triangles[numTriangles].norm[h] = grads[index[h]]; } numTriangles++; //one more triangle has been added } } //END OF FOR LOOP ON Z AXIS } //END OF FOR LOOP ON Y AXIS } //END OF FOR LOOP ON X AXIS //free all wasted space TRIANGLE * retTriangles = new TRIANGLE[numTriangles]; for(int i=0; i < numTriangles; i++) retTriangles[i] = triangles[i]; delete [] triangles; return retTriangles; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // RECURSIVE MARCHING CUBES ALGORITHM //////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // MACROS /////////////////////////////////////////////////////////////////////////////////////////////////// //these macros initialize data and then run marching cubes on the cube with the surface having the specified // number as 'recieving' data (but number of that surface for the current cube is going to be 'opposite'). // Each runs the corresponding recursive function // For numbering, to see which indices of prevVerts,... correspong to indices of the current cube, see // my webpage at www.angelfire.com/linux/myp #define MC_FACE0 \ { \ if(! marchedCubes[ind - 1]) { \ passGradIndex = 0; \ if(gradIndex & 1) passGradIndex |= 8; \ if(gradIndex & 2) passGradIndex |= 4; \ if(gradIndex & 32) passGradIndex |= 64; \ if(gradIndex & 16) passGradIndex |= 128; \ passEdgeIndex = 0; \ if(edgeIndex & 1) passEdgeIndex |= 4; \ if(edgeIndex & 512) passGradIndex |= 1024; \ if(edgeIndex & 16) passEdgeIndex |= 64; \ if(edgeIndex & 256) passGradIndex |= 2048; \ prevVerts[0] = verts[0]; prevVerts[1] = verts[1]; prevVerts[2] = verts[5]; prevVerts[3] = verts[4]; \ prevIntVerts[0] = intVerts[0]; prevIntVerts[1] = intVerts[9]; \ prevIntVerts[2] = intVerts[4]; prevIntVerts[3] = intVerts[8]; \ prevGradVerts[0] = gradVerts[0]; prevGradVerts[1] = gradVerts[1]; \ prevGradVerts[2] = gradVerts[5]; prevGradVerts[3] = gradVerts[4]; \ prevGrads[0] = grads[0]; prevGrads[1] = grads[9]; prevGrads[2] = grads[4]; prevGrads[3] = grads[8]; \ triangles = MCFace0(ncellsX, ncellsY, ncellsZ, gradFactorX, gradFactorY, gradFactorZ, \ ind-1, i, j, k-1, minValue, points, triangles, numTriangles, \ prevVerts, prevIntVerts, passEdgeIndex, \ prevGradVerts, prevGrads, passGradIndex, marchedCubes); \ } \ } #define MC_FACE1 \ { \ if(! marchedCubes[ind + YtimeZ]) { \ passGradIndex = 0; \ if(gradIndex & 4) passGradIndex |= 8; \ if(gradIndex & 2) passGradIndex |= 1; \ if(gradIndex & 32) passGradIndex |= 16; \ if(gradIndex & 64) passGradIndex |= 128; \ passEdgeIndex = 0; \ if(edgeIndex & 2) passEdgeIndex |= 8; \ if(edgeIndex & 512) passEdgeIndex |= 256; \ if(edgeIndex & 32) passEdgeIndex |= 128; \ if(edgeIndex & 1024) passEdgeIndex |= 2048; \ prevVerts[0] = verts[2]; prevVerts[1] = verts[1]; prevVerts[2] = verts[5]; prevVerts[3] = verts[6]; \ prevIntVerts[0] = intVerts[1]; prevIntVerts[1] = intVerts[9]; \ prevIntVerts[2] = intVerts[5]; prevIntVerts[3] = intVerts[10]; \ prevGradVerts[0] = gradVerts[2]; prevGradVerts[1] = gradVerts[1]; \ prevGradVerts[2] = gradVerts[5]; prevGradVerts[3] = gradVerts[6]; \ prevGrads[0] = grads[1]; prevGrads[1] = grads[9]; prevGrads[2] = grads[5]; prevGrads[3] = grads[10]; \ triangles = MCFace1(ncellsX, ncellsY, ncellsZ, gradFactorX, gradFactorY, gradFactorZ, \ ind+YtimeZ, i+1, j, k, minValue, points, triangles, numTriangles, \ prevVerts, prevIntVerts, passEdgeIndex, \ prevGradVerts, prevGrads, passGradIndex, marchedCubes); \ } \ } #define MC_FACE2 \ { \ if(! marchedCubes[ind + 1]) { \ passGradIndex = 0; \ if(gradIndex & 8) passGradIndex |= 1; \ if(gradIndex & 4) passGradIndex |= 2; \ if(gradIndex & 64) passGradIndex |= 32; \ if(gradIndex & 128) passGradIndex |= 16; \ passEdgeIndex = 0; \ if(edgeIndex & 4) passEdgeIndex |= 1; \ if(edgeIndex & 1024) passEdgeIndex |= 512; \ if(edgeIndex & 64) passEdgeIndex |= 16; \ if(edgeIndex & 2048) passEdgeIndex |= 256; \ prevVerts[0] = verts[3]; prevVerts[1] = verts[2]; prevVerts[2] = verts[6]; prevVerts[3] = verts[7]; \ prevIntVerts[0] = intVerts[2]; prevIntVerts[1] = intVerts[10]; \ prevIntVerts[2] = intVerts[6]; prevIntVerts[3] = intVerts[11]; \ prevGradVerts[0] = gradVerts[3]; prevGradVerts[1] = gradVerts[2]; \ prevGradVerts[2] = gradVerts[6]; prevGradVerts[3] = gradVerts[7]; \ prevGrads[0] = grads[2]; prevGrads[1] = grads[10]; prevGrads[2] = grads[6]; prevGrads[3] = grads[11]; \ triangles = MCFace2(ncellsX, ncellsY, ncellsZ, gradFactorX, gradFactorY, gradFactorZ, \ ind+1, i, j, k+1, minValue, points, triangles, numTriangles, \ prevVerts, prevIntVerts, passEdgeIndex, \ prevGradVerts, prevGrads, passGradIndex, marchedCubes); \ } \ } #define MC_FACE3 \ { \ if(! marchedCubes[ind - YtimeZ]) { \ passGradIndex = 0; \ if(gradIndex & 8) passGradIndex |= 4; \ if(gradIndex & 1) passGradIndex |= 2; \ if(gradIndex & 128) passGradIndex |= 64; \ if(gradIndex & 16) passGradIndex |= 32; \ passEdgeIndex = 0; \ if(edgeIndex & 8) passEdgeIndex |= 2; \ if(edgeIndex & 256) passEdgeIndex |= 512; \ if(edgeIndex & 128) passEdgeIndex |= 32; \ if(edgeIndex & 2048) passEdgeIndex |= 1024; \ prevVerts[0] = verts[3]; prevVerts[1] = verts[0]; prevVerts[2] = verts[4]; prevVerts[3] = verts[7]; \ prevIntVerts[0] = intVerts[3]; prevIntVerts[1] = intVerts[8]; \ prevIntVerts[2] = intVerts[7]; prevIntVerts[3] = intVerts[11]; \ prevGradVerts[0] = gradVerts[3]; prevGradVerts[1] = gradVerts[0]; \ prevGradVerts[2] = gradVerts[4]; prevGradVerts[3] = gradVerts[7]; \ prevGrads[0] = grads[3]; prevGrads[1] = grads[8]; prevGrads[2] = grads[7]; prevGrads[3] = grads[11]; \ triangles = MCFace3(ncellsX, ncellsY, ncellsZ, gradFactorX, gradFactorY, gradFactorZ, \ ind-YtimeZ, i-1, j, k, minValue, points, triangles, numTriangles, \ prevVerts, prevIntVerts, passEdgeIndex, \ prevGradVerts, prevGrads, passGradIndex, marchedCubes); \ } \ } //done #define MC_FACE4 \ { \ if(! marchedCubes[ind + pointsZ]) { \ passGradIndex = 0; \ if(gradIndex & 128) passGradIndex |= 8; \ if(gradIndex & 64) passGradIndex |= 4; \ if(gradIndex & 32) passGradIndex |= 2; \ if(gradIndex & 16) passGradIndex |= 1; \ passEdgeIndex = 0; \ if(edgeIndex & 128) passEdgeIndex |= 8; \ if(edgeIndex & 64) passEdgeIndex |= 4; \ if(edgeIndex & 32) passEdgeIndex |= 2; \ if(edgeIndex & 16) passEdgeIndex |= 1; \ prevVerts[0] = verts[7]; prevVerts[1] = verts[6]; prevVerts[2] = verts[5]; prevVerts[3] = verts[4]; \ prevIntVerts[0] = intVerts[6]; prevIntVerts[1] = intVerts[5]; \ prevIntVerts[2] = intVerts[4]; prevIntVerts[3] = intVerts[7]; \ prevGradVerts[0] = gradVerts[7]; prevGradVerts[1] = gradVerts[6]; \ prevGradVerts[2] = gradVerts[5]; prevGradVerts[3] = gradVerts[4]; \ prevGrads[0] = grads[6]; prevGrads[1] = grads[5]; prevGrads[2] = grads[4]; prevGrads[3] = grads[7]; \ triangles = MCFace4(ncellsX, ncellsY, ncellsZ, gradFactorX, gradFactorY, gradFactorZ, \ ind+pointsZ, i, j+1, k, minValue, points, triangles, numTriangles, \ prevVerts, prevIntVerts, passEdgeIndex, \ prevGradVerts, prevGrads, passGradIndex, marchedCubes); \ } \ } #define MC_FACE5 \ { \ if(! marchedCubes[ind - ncellsZ - 1]) { \ passGradIndex = (gradIndex << 4) & 240; \ passEdgeIndex = (edgeIndex << 4) & 240; \ prevVerts[0] = verts[3]; prevVerts[1] = verts[2]; prevVerts[2] = verts[1]; prevVerts[3] = verts[0]; \ prevIntVerts[0] = intVerts[2]; prevIntVerts[1] = intVerts[1]; \ prevIntVerts[2] = intVerts[0]; prevIntVerts[3] = intVerts[3]; \ prevGradVerts[0] = gradVerts[3]; prevGradVerts[1] = gradVerts[2]; \ prevGradVerts[2] = gradVerts[1]; prevGradVerts[3] = gradVerts[0]; \ prevGrads[0] = grads[2]; prevGrads[1] = grads[1]; prevGrads[2] = grads[0]; prevGrads[3] = grads[3]; \ triangles = MCFace5(ncellsX, ncellsY, ncellsZ, gradFactorX, gradFactorY, gradFactorZ, \ ind-ncellsZ-1, i, j-1, k, minValue, points, triangles, numTriangles, \ prevVerts, prevIntVerts, passEdgeIndex, \ prevGradVerts, prevGrads, passGradIndex, marchedCubes); \ } \ } /// END FACE MACROS ///////////////////////////////////////////////////////////////////////////////////////// // RECURSIVE Marching Cubes Function - cubes at indexes ii, jj, kk intersect the surface // Number of intersecting cubes = numCubes TRIANGLE* MarchingCubesRec(int ncellsX, int ncellsY, int ncellsZ, float gradFactorX, float gradFactorY, float gradFactorZ, int numCubes, int *ii, int *jj, int *kk, float minValue, mp4Vector * points, int &numTriangles) { TRIANGLE * triangles = new TRIANGLE[3*ncellsX*ncellsY*ncellsZ]; numTriangles = int(0); //check if none of the starting points are on the outside perimeter for(int n=0; n < numCubes; n++) { if(ii[n] <= 0 || ii[n] >= ncellsX-1) return NULL; if(jj[n] <= 0 || jj[n] >= ncellsY-1) return NULL; if(kk[n] <= 0 || kk[n] >= ncellsZ-1) return NULL; } //array stores which cubes have been marched through - initialized to FALSE int all = ncellsX*ncellsY*ncellsZ; bool* marchedCubes = new bool[all]; for(int i=0; i < all; i++) marchedCubes[i] = FALSE; //initialize mp4Vector verts[8]; //vertices of a starting cube mpVector intVerts[12]; //linearly interpolated vertices on each edge int edgeIndex; //shows which edges are intersected mp4Vector gradVerts[8]; //gradients at each vertex of a cube mpVector grads[12]; //linearly interpolated gradients on each edge int gradIndex; //show on which vertices gradients have been computed //initialize global variables - for speed - these would be used by all the recursive functions pointsZ = ncellsZ+1; YtimeZ = (ncellsY+1)*pointsZ; //arrays used to pass already computed values from this initial cube to the next ones mp4Vector prevVerts[4]; //passes vertices mpVector prevIntVerts[4]; //passes interpolated vertices on edges mp4Vector prevGradVerts[4]; //passes gradients at vertices mpVector prevGrads[4]; //passes interpolated gradients on edges //two new indexes formed for each face int passEdgeIndex, passGradIndex; //used to tell which vertices and which edges have been initialized //indices int i, j, k; //initialize first cubes and 'launch' the recursion for each for(int n=0; n < numCubes; n++) { //init vertices i = ii[n]; j = jj[n]; k = kk[n]; int ind = i*YtimeZ + j*pointsZ + k; verts[0] = points[ind]; verts[1] = points[ind + YtimeZ]; verts[2] = points[ind + YtimeZ + 1]; verts[3] = points[ind + 1]; verts[4] = points[ind + pointsZ]; verts[5] = points[ind + YtimeZ + pointsZ]; verts[6] = points[ind + YtimeZ + pointsZ + 1]; verts[7] = points[ind + pointsZ + 1]; //first check if this cube wasnt marched in recursive calls of the previous cube if(! marchedCubes[ind]) { //run marching cubes on the initial cube gradIndex = edgeIndex = 0; triangles = MarchOneCube(ncellsX, ncellsY, ncellsZ, gradFactorX, gradFactorY, gradFactorZ, ind, i, j, k, minValue, points, triangles, numTriangles, verts, intVerts, edgeIndex, gradVerts, grads, gradIndex); //this cube has been done: marchedCubes[ind] = TRUE; //run M.C. on all 6 faces MC_FACE0 MC_FACE1 MC_FACE2 MC_FACE3 MC_FACE4 MC_FACE5 } } //free wasted space TRIANGLE * retTriangles = new TRIANGLE[numTriangles]; for(int i=0; i < numTriangles; i++) retTriangles[i] = triangles[i]; delete [] triangles; delete [] marchedCubes; return retTriangles; //done } //SURFACE 0 - Cube ran on surface 0 of previous cube. Recieving side: 2. TRIANGLE* MCFace0(int ncellsX, int ncellsY, int ncellsZ, float gradFactorX, float gradFactorY, float gradFactorZ, int ind, int i, int j, int k, float minValue, mp4Vector * points, TRIANGLE *triangles, int &numTriangles, mp4Vector prevVerts[4], mpVector prevIntVerts[4], int edgeIndex, mp4Vector prevGradVerts[4], mpVector prevGrads[4], int gradIndex, bool* marchedCubes) { //first check if not outside the region if(i <= 0 || i >= ncellsX-1 || j <= 0 || j >= ncellsY-1 || k <= 0 || k >= ncellsZ-1) return triangles; //make sure we save that this cube was marched through marchedCubes[ind] = TRUE; //initialize vertices mp4Vector verts[8]; verts[0] = points[ind]; verts[1] = points[ind + YtimeZ]; verts[2] = prevVerts[1]; verts[3] = prevVerts[0]; verts[4] = points[ind + ncellsZ + 1]; verts[5] = points[ind + YtimeZ + ncellsZ + 1]; verts[6] = prevVerts[2]; verts[7] = prevVerts[3]; //initialize edges from the last cube mpVector intVerts[12]; intVerts[2] = prevIntVerts[0]; intVerts[10] = prevIntVerts[1]; intVerts[6] = prevIntVerts[2]; intVerts[11] = prevIntVerts[3]; //initialize gradients on vertices mp4Vector gradVerts[8]; gradVerts[3] = prevGradVerts[0]; gradVerts[2] = prevGradVerts[1]; gradVerts[6] = prevGradVerts[2]; gradVerts[7] = prevGradVerts[3]; //initialize gradients on edges from the last cube mpVector grads[12]; grads[2] = prevGrads[0]; grads[10] = prevGrads[1]; grads[6] = prevGrads[2]; grads[11] = prevGrads[3]; //for test if this cube is intersected: int oldNumTriangles = numTriangles; //run marching cubes on this cube triangles = MarchOneCube(ncellsX, ncellsY, ncellsZ, gradFactorX, gradFactorY, gradFactorZ, ind, i, j, k, minValue, points, triangles, numTriangles, verts, intVerts, edgeIndex, gradVerts, grads, gradIndex); //check if this cube is intersected if(numTriangles == oldNumTriangles) return triangles; //two new indexes formed for each face to be passed into other recursive functions int passEdgeIndex, passGradIndex; //run recursive functions on each surface MC_FACE0 MC_FACE1 MC_FACE3 MC_FACE4 MC_FACE5 return triangles; } //SURFACE 1 - Cube ran on surface 1 of previous cube. Recieving side: 3. TRIANGLE* MCFace1(int ncellsX, int ncellsY, int ncellsZ, float gradFactorX, float gradFactorY, float gradFactorZ, int ind, int i, int j, int k, float minValue, mp4Vector * points, TRIANGLE *triangles, int &numTriangles, mp4Vector prevVerts[4], mpVector prevIntVerts[4], int edgeIndex, mp4Vector prevGradVerts[4], mpVector prevGrads[4], int gradIndex, bool* marchedCubes) { //first check if not outside the region if(i <= 0 || i >= ncellsX-1 || j <= 0 || j >= ncellsY-1 || k <= 0 || k >= ncellsZ-1) return triangles; //make sure we save that this cube was marched through marchedCubes[ind] = TRUE; //initialize vertices mp4Vector verts[8]; verts[0] = prevVerts[1]; verts[1] = points[ind + YtimeZ]; verts[2] = points[ind + YtimeZ + 1]; verts[3] = prevVerts[0]; verts[4] = prevVerts[2]; verts[5] = points[ind + YtimeZ + ncellsZ + 1]; verts[6] = points[ind + YtimeZ + ncellsZ + 2]; verts[7] = prevVerts[3]; //initialize edges from the last cube mpVector intVerts[12]; intVerts[3] = prevIntVerts[0]; intVerts[8] = prevIntVerts[1]; intVerts[7] = prevIntVerts[2]; intVerts[11] = prevIntVerts[3]; //initialize gradients on vertices mp4Vector gradVerts[8]; gradVerts[3] = prevGradVerts[0]; gradVerts[0] = prevGradVerts[1]; gradVerts[4] = prevGradVerts[2]; gradVerts[7] = prevGradVerts[3]; //initialize gradients on edges from the last cube mpVector grads[12]; grads[3] = prevGrads[0]; grads[8] = prevGrads[1]; grads[7] = prevGrads[2]; grads[11] = prevGrads[3]; //for test if this cube is intersected: int oldNumTriangles = numTriangles; //run marching cubes on this cube triangles = MarchOneCube(ncellsX, ncellsY, ncellsZ, gradFactorX, gradFactorY, gradFactorZ, ind, i, j, k, minValue, points, triangles, numTriangles, verts, intVerts, edgeIndex, gradVerts, grads, gradIndex); //check if this cube is intersected if(numTriangles == oldNumTriangles) return triangles; //two new indexes formed for each face to be passed into other recursive functions int passEdgeIndex, passGradIndex; //run recursive functions on each surface MC_FACE0 MC_FACE1 MC_FACE2 MC_FACE4 MC_FACE5 return triangles; } //SURFACE 2 - Cube ran on surface 2 of previous cube. Recieving side: 0. TRIANGLE* MCFace2(int ncellsX, int ncellsY, int ncellsZ, float gradFactorX, float gradFactorY, float gradFactorZ, int ind, int i, int j, int k, float minValue, mp4Vector * points, TRIANGLE *triangles, int &numTriangles, mp4Vector prevVerts[4], mpVector prevIntVerts[4], int edgeIndex, mp4Vector prevGradVerts[4], mpVector prevGrads[4], int gradIndex, bool* marchedCubes) { //first check if not outside the region if(i <= 0 || i >= ncellsX-1 || j <= 0 || j >= ncellsY-1 || k <= 0 || k >= ncellsZ-1) return triangles; //make sure we save that this cube was marched through marchedCubes[ind] = TRUE; //initialize vertices mp4Vector verts[8]; verts[0] = prevVerts[0]; verts[1] = prevVerts[1]; verts[2] = points[ind + YtimeZ + 1]; verts[3] = points[ind + 1]; verts[4] = prevVerts[3]; verts[5] = prevVerts[2]; verts[6] = points[ind + YtimeZ + ncellsZ + 2]; verts[7] = points[ind + ncellsZ + 2]; //initialize edges from the last cube mpVector intVerts[12]; intVerts[0] = prevIntVerts[0]; intVerts[9] = prevIntVerts[1]; intVerts[4] = prevIntVerts[2]; intVerts[8] = prevIntVerts[3]; //initialize gradients on vertices mp4Vector gradVerts[8]; gradVerts[0] = prevGradVerts[0]; gradVerts[1] = prevGradVerts[1]; gradVerts[5] = prevGradVerts[2]; gradVerts[4] = prevGradVerts[3]; //initialize gradients on edges from the last cube mpVector grads[12]; grads[0] = prevGrads[0]; grads[9] = prevGrads[1]; grads[4] = prevGrads[2]; grads[8] = prevGrads[3]; //for test if this cube is intersected int oldNumTriangles = numTriangles; //run marching cubes on this cube triangles = MarchOneCube(ncellsX, ncellsY, ncellsZ, gradFactorX, gradFactorY, gradFactorZ, ind, i, j, k, minValue, points, triangles, numTriangles, verts, intVerts, edgeIndex, gradVerts, grads, gradIndex); //check if this cube is intersected if(numTriangles == oldNumTriangles) return triangles; //two new indexes formed for each face int passEdgeIndex, passGradIndex; //run recursive functions on each surface MC_FACE1 MC_FACE2 MC_FACE3 MC_FACE4 MC_FACE5 return triangles; } //SURFACE 3 - Cube ran on surface 3 of previous cube. Recieving side: 1. TRIANGLE* MCFace3(int ncellsX, int ncellsY, int ncellsZ, float gradFactorX, float gradFactorY, float gradFactorZ, int ind, int i, int j, int k, float minValue, mp4Vector * points, TRIANGLE *triangles, int &numTriangles, mp4Vector prevVerts[4], mpVector prevIntVerts[4], int edgeIndex, mp4Vector prevGradVerts[4], mpVector prevGrads[4], int gradIndex, bool* marchedCubes) { //first check if not outside the region if(i <= 0 || i >= ncellsX-1 || j <= 0 || j >= ncellsY-1 || k <= 0 || k >= ncellsZ-1) return triangles; //make sure we save that this cube was marched through marchedCubes[ind] = TRUE; //initialize vertices mp4Vector verts[8]; verts[0] = points[ind]; verts[1] = prevVerts[1]; verts[2] = prevVerts[0]; verts[3] = points[ind + 1]; verts[4] = points[ind + ncellsZ + 1]; verts[5] = prevVerts[2]; verts[6] = prevVerts[3]; verts[7] = points[ind + ncellsZ + 2]; //initialize edges from the last cube mpVector intVerts[12]; intVerts[1] = prevIntVerts[0]; intVerts[9] = prevIntVerts[1]; intVerts[5] = prevIntVerts[2]; intVerts[10] = prevIntVerts[3]; //initialize gradients on vertices mp4Vector gradVerts[8]; gradVerts[2] = prevGradVerts[0]; gradVerts[1] = prevGradVerts[1]; gradVerts[5] = prevGradVerts[2]; gradVerts[6] = prevGradVerts[3]; //initialize gradients on edges from the last cube mpVector grads[12]; grads[1] = prevGrads[0]; grads[9] = prevGrads[1]; grads[5] = prevGrads[2]; grads[10] = prevGrads[3]; //for test if this cube is intersected int oldNumTriangles = numTriangles; //run marching cubes on this cube triangles = MarchOneCube(ncellsX, ncellsY, ncellsZ, gradFactorX, gradFactorY, gradFactorZ, ind, i, j, k, minValue, points, triangles, numTriangles, verts, intVerts, edgeIndex, gradVerts, grads, gradIndex); //check if this cube is intersected if(numTriangles == oldNumTriangles) return triangles; //two new indexes formed for each face int passEdgeIndex, passGradIndex; //run recursive functions on each surface MC_FACE0 MC_FACE2 MC_FACE3 MC_FACE4 MC_FACE5 return triangles; } //SURFACE 4 - Cube ran on surface 4 of previous cube. Recieving side: 5. TRIANGLE* MCFace4(int ncellsX, int ncellsY, int ncellsZ, float gradFactorX, float gradFactorY, float gradFactorZ, int ind, int i, int j, int k, float minValue, mp4Vector * points, TRIANGLE *triangles, int &numTriangles, mp4Vector prevVerts[4], mpVector prevIntVerts[4], int edgeIndex, mp4Vector prevGradVerts[4], mpVector prevGrads[4], int gradIndex, bool* marchedCubes) { //first check if not outside the region if(i <= 0 || i >= ncellsX-1 || j <= 0 || j >= ncellsY-1 || k <= 0 || k >= ncellsZ-1) return triangles; //make sure we save that this cube was marched through marchedCubes[ind] = TRUE; //initialize vertices mp4Vector verts[8]; verts[0] = prevVerts[3]; verts[1] = prevVerts[2]; verts[2] = prevVerts[1]; verts[3] = prevVerts[0]; verts[4] = points[ind + ncellsZ + 1]; verts[5] = points[ind + YtimeZ + ncellsZ + 1]; verts[6] = points[ind + YtimeZ + ncellsZ + 2]; verts[7] = points[ind + ncellsZ + 2]; //initialize edges from the last cube mpVector intVerts[12]; intVerts[2] = prevIntVerts[0]; intVerts[1] = prevIntVerts[1]; intVerts[0] = prevIntVerts[2]; intVerts[3] = prevIntVerts[3]; //initialize gradients on vertices mp4Vector gradVerts[8]; gradVerts[3] = prevGradVerts[0]; gradVerts[2] = prevGradVerts[1]; gradVerts[1] = prevGradVerts[2]; gradVerts[0] = prevGradVerts[3]; //initialize gradients on edges from the last cube mpVector grads[12]; grads[2] = prevGrads[0]; grads[1] = prevGrads[1]; grads[0] = prevGrads[2]; grads[3] = prevGrads[3]; //for test if this cube is intersected int oldNumTriangles = numTriangles; //run marching cubes on this cube triangles = MarchOneCube(ncellsX, ncellsY, ncellsZ, gradFactorX, gradFactorY, gradFactorZ, ind, i, j, k, minValue, points, triangles, numTriangles, verts, intVerts, edgeIndex, gradVerts, grads, gradIndex); //check if this cube is intersected if(numTriangles == oldNumTriangles) return triangles; //two new indexes formed for each face int passEdgeIndex, passGradIndex; //run recursive functions on each surface MC_FACE0 MC_FACE1 MC_FACE2 MC_FACE3 MC_FACE4 return triangles; } //SURFACE 5 - Cube ran on surface 5 of previous cube. Recieving side: 4. TRIANGLE* MCFace5(int ncellsX, int ncellsY, int ncellsZ, float gradFactorX, float gradFactorY, float gradFactorZ, int ind, int i, int j, int k, float minValue, mp4Vector * points, TRIANGLE *triangles, int &numTriangles, mp4Vector prevVerts[4], mpVector prevIntVerts[4], int edgeIndex, mp4Vector prevGradVerts[4], mpVector prevGrads[4], int gradIndex, bool* marchedCubes) { //first check if not outside the region if(i <= 0 || i >= ncellsX-1 || j <= 0 || j >= ncellsY-1 || k <= 0 || k >= ncellsZ-1) return triangles; //make sure we save that this cube was marched through marchedCubes[ind] = TRUE; //initialize vertices mp4Vector verts[8]; verts[0] = points[ind]; verts[1] = points[ind + YtimeZ]; verts[2] = points[ind + YtimeZ + 1]; verts[3] = points[ind + 1]; verts[4] = prevVerts[3]; verts[5] = prevVerts[2]; verts[6] = prevVerts[1]; verts[7] = prevVerts[0]; //initialize edges from the last cube mpVector intVerts[12]; intVerts[6] = prevIntVerts[0]; intVerts[5] = prevIntVerts[1]; intVerts[4] = prevIntVerts[2]; intVerts[7] = prevIntVerts[3]; //initialize gradients on vertices mp4Vector gradVerts[8]; gradVerts[7] = prevGradVerts[0]; gradVerts[6] = prevGradVerts[1]; gradVerts[5] = prevGradVerts[2]; gradVerts[4] = prevGradVerts[3]; //initialize gradients on edges from the last cube mpVector grads[12]; grads[6] = prevGrads[0]; grads[5] = prevGrads[1]; grads[4] = prevGrads[2]; grads[7] = prevGrads[3]; //for test if this cube is intersected int oldNumTriangles = numTriangles; //run marching cubes on this cube triangles = MarchOneCube(ncellsX, ncellsY, ncellsZ, gradFactorX, gradFactorY, gradFactorZ, ind, i, j, k, minValue, points, triangles, numTriangles, verts, intVerts, edgeIndex, gradVerts, grads, gradIndex); //check if this cube is intersected if(numTriangles == oldNumTriangles) return triangles; //two new indexes formed for each face int passEdgeIndex, passGradIndex; //run recursive functions on each surface MC_FACE0 MC_FACE1 MC_FACE2 MC_FACE3 MC_FACE5 return triangles; } //Marching Cubes on a single cube (i, j, k) // Verts should be initialized before hand // Global variables YtimeZ and pointsZ should be defined and initialized TRIANGLE* MarchOneCube(int ncellsX, int ncellsY, int ncellsZ, float gradFactorX, float gradFactorY, float gradFactorZ, int ind, int i, int j, int k, float minValue, mp4Vector * points, TRIANGLE *triangles, int &numTriangles, mp4Vector verts[8], mpVector intVerts[12], int &edgeIndex, mp4Vector gradVerts[8], mpVector grads[12], int &indGrad) { //factor by which gradients are scaled mpVector factor(1.0/(2.0*gradFactorX), 1.0/(2.0*gradFactorY), 1.0/(2.0*gradFactorZ)); //get the index int cubeIndex = int(0); for(int n=0; n < 8; n++) if(verts[n].val <= minValue) cubeIndex |= (1 << n); //check if its completely inside or outside if(!edgeTable[cubeIndex]) return triangles; int prevEdgeIndex = edgeIndex; edgeIndex = edgeTable[cubeIndex]; if((edgeIndex & 1) && !(prevEdgeIndex & 1)) { intVerts[0] = LinearInterp(verts[0], verts[1], minValue); if(! (indGrad & 1)) { gradVerts[0] = CALC_GRAD_VERT_0(verts) indGrad |= 1; } if(! (indGrad & 2)) { gradVerts[1] = CALC_GRAD_VERT_1(verts) indGrad |= 2; } grads[0] = LinearInterp(gradVerts[0], gradVerts[1], minValue); grads[0].x *= factor.x; grads[0].y *= factor.y; grads[0].z *= factor.z; } if((edgeIndex & 2) && !(prevEdgeIndex & 2)) { intVerts[1] = LinearInterp(verts[1], verts[2], minValue); if(! (indGrad & 2)) { gradVerts[1] = CALC_GRAD_VERT_1(verts) indGrad |= 2; } if(! (indGrad & 4)) { gradVerts[2] = CALC_GRAD_VERT_2(verts) indGrad |= 4; } grads[1] = LinearInterp(gradVerts[1], gradVerts[2], minValue); grads[1].x *= factor.x; grads[1].y *= factor.y; grads[1].z *= factor.z; } if(edgeIndex & 4) { intVerts[2] = LinearInterp(verts[2], verts[3], minValue); if(! (indGrad & 4)) { gradVerts[2] = CALC_GRAD_VERT_2(verts) indGrad |= 4; } if(! (indGrad & 8)) { gradVerts[3] = CALC_GRAD_VERT_3(verts) indGrad |= 8; } grads[2] = LinearInterp(gradVerts[2], gradVerts[3], minValue); grads[2].x *= factor.x; grads[2].y *= factor.y; grads[2].z *= factor.z; } if((edgeIndex & 8) && !(prevEdgeIndex & 8)) { intVerts[3] = LinearInterp(verts[3], verts[0], minValue); if(! (indGrad & 8)) { gradVerts[3] = CALC_GRAD_VERT_3(verts) indGrad |= 8; } if(! (indGrad & 1)) { gradVerts[0] = CALC_GRAD_VERT_0(verts) indGrad |= 1; } grads[3] = LinearInterp(gradVerts[3], gradVerts[0], minValue); grads[3].x *= factor.x; grads[3].y *= factor.y; grads[3].z *= factor.z; } if((edgeIndex & 16) && !(prevEdgeIndex & 16)) { intVerts[4] = LinearInterp(verts[4], verts[5], minValue); if(! (indGrad & 16)) { gradVerts[4] = CALC_GRAD_VERT_4(verts) indGrad |= 16; } if(! (indGrad & 32)) { gradVerts[5] = CALC_GRAD_VERT_5(verts) indGrad |= 32; } grads[4] = LinearInterp(gradVerts[4], gradVerts[5], minValue); grads[4].x *= factor.x; grads[4].y *= factor.y; grads[4].z *= factor.z; } if((edgeIndex & 32) && !(prevEdgeIndex & 32)) { intVerts[5] = LinearInterp(verts[5], verts[6], minValue); if(! (indGrad & 32)) { gradVerts[5] = CALC_GRAD_VERT_5(verts) indGrad |= 32; } if(! (indGrad & 64)) { gradVerts[6] = CALC_GRAD_VERT_6(verts) indGrad |= 64; } grads[5] = LinearInterp(gradVerts[5], gradVerts[6], minValue); grads[5].x *= factor.x; grads[5].y *= factor.y; grads[5].z *= factor.z; } if((edgeIndex & 64) && !(prevEdgeIndex & 64)) { intVerts[6] = LinearInterp(verts[6], verts[7], minValue); if(! (indGrad & 64)) { gradVerts[6] = CALC_GRAD_VERT_6(verts) indGrad |= 64; } if(! (indGrad & 128)) { gradVerts[7] = CALC_GRAD_VERT_7(verts) indGrad |= 128; } grads[6] = LinearInterp(gradVerts[6], gradVerts[7], minValue); grads[6].x *= factor.x; grads[6].y *= factor.y; grads[6].z *= factor.z; } if((edgeIndex & 128) && !(prevEdgeIndex & 128)) { intVerts[7] = LinearInterp(verts[7], verts[4], minValue); if(! (indGrad & 128)) { gradVerts[7] = CALC_GRAD_VERT_7(verts) indGrad |= 128; } if(! (indGrad & 16)) { gradVerts[4] = CALC_GRAD_VERT_4(verts) indGrad |= 16; } grads[7] = LinearInterp(gradVerts[7], gradVerts[4], minValue); grads[7].x *= factor.x; grads[7].y *= factor.y; grads[7].z *= factor.z; } if((edgeIndex & 256) && !(prevEdgeIndex & 256)) { intVerts[8] = LinearInterp(verts[0], verts[4], minValue); if(! (indGrad & 1)) { gradVerts[0] = CALC_GRAD_VERT_0(verts) indGrad |= 1; } if(! (indGrad & 16)) { gradVerts[4] = CALC_GRAD_VERT_4(verts) indGrad |= 16; } grads[8] = LinearInterp(gradVerts[0], gradVerts[4], minValue); grads[8].x *= factor.x; grads[8].y *= factor.y; grads[8].z *= factor.z; } if((edgeIndex & 512) && !(prevEdgeIndex & 512)) { intVerts[9] = LinearInterp(verts[1], verts[5], minValue); if(! (indGrad & 2)) { gradVerts[1] = CALC_GRAD_VERT_1(verts) indGrad |= 2; } if(! (indGrad & 32)) { gradVerts[5] = CALC_GRAD_VERT_5(verts) indGrad |= 32; } grads[9] = LinearInterp(gradVerts[1], gradVerts[5], minValue); grads[9].x *= factor.x; grads[9].y *= factor.y; grads[9].z *= factor.z; } if((edgeIndex & 1024) && !(prevEdgeIndex & 1024)) { intVerts[10] = LinearInterp(verts[2], verts[6], minValue); if(! (indGrad & 4)) { gradVerts[2] = CALC_GRAD_VERT_2(verts) indGrad |= 4; } if(! (indGrad & 64)) { gradVerts[6] = CALC_GRAD_VERT_6(verts) indGrad |= 64; } grads[10] = LinearInterp(gradVerts[2], gradVerts[6], minValue); grads[10].x *= factor.x; grads[10].y *= factor.y; grads[10].z *= factor.z; } if((edgeIndex & 2048) && !(prevEdgeIndex & 2048)) { intVerts[11] = LinearInterp(verts[3], verts[7], minValue); if(! (indGrad & 8)) { gradVerts[3] = CALC_GRAD_VERT_3(verts) indGrad |= 8; } if(! (indGrad & 128)) { gradVerts[7] = CALC_GRAD_VERT_7(verts) indGrad |= 128; } grads[11] = LinearInterp(gradVerts[3], gradVerts[7], minValue); grads[11].x *= factor.x; grads[11].y *= factor.y; grads[11].z *= factor.z; } //now build the triangles using triTable and add them to the triangle array for (int n=0; triTable[cubeIndex][n] != -1; n+=3) { int index[3] = {triTable[cubeIndex][n+2], triTable[cubeIndex][n+1], triTable[cubeIndex][n]}; for(int h=0; h < 3; h++) { triangles[numTriangles].p[h] = intVerts[index[h]]; triangles[numTriangles].norm[h] = grads[index[h]]; } numTriangles++; //one more triangle... } return triangles; } //Finds first intersecting cube and returns its indices (or -1 if nothing is found) float* MCFind(int ncellsX, int ncellsY, int ncellsZ, float minValue, mp4Vector * points) { pointsZ = ncellsZ+1; //initializes global variables YtimeZ = (ncellsY+1)*pointsZ; int lastX = ncellsX - 1, lastY = ncellsY - 1, lastZ = ncellsZ - 1; //for a little extra speed mp4Vector *verts[8]; //store address of each point rather than copying x,y,z, and val int cubeIndex, ind, ni; float *found = new float[3];//returned indices: initialized to -1 found[0] = -1; found[0] = -1; found[0] = -1; for(int i=1; i < lastX; i++) { ni = i*YtimeZ; for(int j=1; j < lastY; j++) { //get the first 4 vertices (0, 1, 4, 5) and place them into verts at indices 3, 2, 7, 6 ind = ni + j*pointsZ + 1; verts[3] = &points[ind]; verts[2] = &points[ind + YtimeZ]; verts[7] = &points[ind + pointsZ]; verts[6] = &points[ind + YtimeZ + pointsZ]; for(int k=1; k < lastZ; k++, ind++) { //initialize vertices verts[0] = verts[3]; //these are saved from the last iteration verts[1] = verts[2]; verts[4] = verts[7]; verts[5] = verts[6]; verts[4] = &points[ind + pointsZ]; verts[5] = &points[ind + YtimeZ + pointsZ]; verts[6] = &points[ind + YtimeZ + ncellsZ + 2]; verts[7] = &points[ind + ncellsZ + 2]; //build index - shows which vertices are outside/inside cubeIndex = int(0); for(int n=0; n < 8; n++) if(verts[n]->val <= minValue) cubeIndex |= (1 << n); if(edgeTable[cubeIndex]) { //if found then return them found[0] = i; found[1] = j; found[2] = k; return found; } } } } return found; } //First finds intersecting cube and runs recursive Marching Cubes. TRIANGLE* MCRecFind(int ncellsX, int ncellsY, int ncellsZ, float gradFactorX, float gradFactorY, float gradFactorZ, float minValue, mp4Vector * points, int &numTriangles) { float *found = MCFind(ncellsX, ncellsY, ncellsZ, minValue, points); if(found[0] == -1) { //if nothing is found return NULL numTriangles = 0; return NULL; } int i[1] = {(int)found[0]}, j[1] = {(int)found[1]}, k[1] = {(int)found[2]}; delete [] found; return MarchingCubesRec(ncellsX, ncellsY, ncellsZ, gradFactorX, gradFactorY, gradFactorZ, 1, i, j, k, minValue, points, numTriangles); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////// THE END /////////////////////////////////////////////////////////////// objcryst-2022.1/ObjCryst/wxCryst/MC.h000066400000000000000000000241331430515525000173340ustar00rootroot00000000000000///////////////////////////////////////////////////////////////////////////////////////////// // FileName: MarchingCubes.cpp // Author : Michael Y. Polyakov // email : myp@andrew.cmu.edu or mikepolyakov@hotmail.com // website : www.angelfire.com/linux/myp // date : July 2002 // // Description: 'Straight' and Recursive Marching Cubes Algorithms // Normal vectors are defined for each vertex as a gradients // For function definitions see MarchingCubes.h // For a tutorial on Marching Cubes please visit www.angelfire.com/myp/linux // // Please email me with any suggestion/bugs. ///////////////////////////////////////////////////////////////////////////////////////////// #ifndef MARCHINGCUBES_H_ #define MARCHINGCUBES_H_ #include "ObjCryst/wxCryst/mpVector.h" //struct for storing triangle information - 3 vertices and 3 normal vectors for each vertex typedef struct { mpVector p[3]; mpVector norm[3]; } TRIANGLE; //does Linear Interpolation between points p1 and p2 (they already contain their computed values) mpVector LinearInterp(mp4Vector p1, mp4Vector p2, float value); //////////////////////////////////////////////////////////////////////////////////////// //POINTERS TO FUNCTIONS //pointer to function which computes the value at point p typedef float (*FORMULA)(mpVector); //////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// ///// MARCHING CUBES ALGORITHM ///// ///////////////////////////////////////////////////////////////////////////////////////// // 'STRAIGHT' Marching Cubes Algorithm ////////////////////////////////////////////////// //takes number of cells (ncellsX, ncellsY, ncellsZ) to subdivide on each axis // minValue used to pass into LinearInterp // gradFactor for each axis (multiplies each component of gradient vector by 1/(2*gradFactor) ). // Should be set to the length of a side (or close to it) // array of length (ncellsX+1)(ncellsY+1)(ncellsZ+1) of mp4Vector points containing coordinates and values //returns pointer to triangle array and the number of triangles in numTriangles //note: array of points is first taken on z axis, then y and then x. So for example, if you iterate through it in a // for loop, have indexes i, j, k for x, y, z respectively, then to get the point you will have to make the // following index: i*(ncellsY+1)*(ncellsZ+1) + j*(ncellsZ+1) + k . // Also, the array starts at the minimum on all axes. TRIANGLE* MC(int ncellsX, int ncellsY, int ncellsZ, float gradFactorX, float gradFactorY, float gradFactorZ, float minValue, mp4Vector * points, int &numTriangles); ///////////////////////////////////////////////////////////////////////////////////////// // RECURSIVE Marching Cubes ///////////////////////////////////////////////////////////// //DrawBacks: must know how many objects are drawn //This function starts the Recursive Marching Cubes // numCubes: number of intersecting cubes passed as starting points // ii, jj, kk: arrays of size numCubes. Contain respective indexes of cubes that are intersected TRIANGLE* MarchingCubesRec(int ncellsX, int ncellsY, int ncellsZ, float gradFactorX, float gradFactorY, float gradFactorZ, int numCubes, int *ii, int *jj, int *kk, float minValue, mp4Vector * points, int &numTriangles); //Next 6 functions are called by the corresponding face of each cube (e.g. face 0 calls MCFace0 etc...) // Each function accepts the following information as arguments: // First 3 arguments: number of cells to subdivide on each axis // gradFactor: factor to scale the gradient vectors (multiplies by 1/(2*gradFactor) ) // ind: index of this cube in the points array (this is so it doesnt have to be computed again) // i,j,k: indexes of the this cube on x,y,z axis respectively // minValue: minimum used in LinearInterp // points: array of type mp4Vector and size (ncellsX+1)*(ncellsY+1)*(ncellsZ+1) that contains // coordinates and values at each point // triangle: array of triangles which is being built and returned at the end of recursion // numTriangles: number of triangles formed // prevVerts: adjacent 4 vertices of the previous cube, passed in the special order which the correspoding // MCFace function recognizes. For specificatino on which indexes passed from the last cube go to // which vertexes of the current cube visit my website at www.angelfire.com/linux/myp // prevIntVerts: array of 4 linearly interpolated vertices on 4 adjacent edges // edgeIndex: integer, bits of which correspond to the edges of the current cube which have been computed // from the previous cube // prevGradVerts: array of 4 gradient vectors at 4 adjacent vertices // prevGrads: linearly interpolated gradient vectors on 4 adjacent edges // gradIndex: integer bits of which correspond to already computed vertices of the current cube // marchedCubes: bool array of size ncellsX*ncellsY*ncellsZ which stores which cubes already have been marched // through. Initialized to FALSE. This is not the most effective way in terms of memory management, but // faster than using STLs vector which stores booleans as bits. //* NOTE *: Each of these 6 functions run marching cubes on the 'next'cube adjacent to the surface number // that is specified in their names (for numbering see my webpage). Each assigns the previous computed // values to the face 'opposite' of that specified. Then each one runs Marching Cubes for the current cube. // It returns doing nothing if the cube is not intersected, however, if it is then other recursive // functions are called using macros MC_FACE defined for each face. See MarchingCubes.cpp // For example MCFace0 will initialize surface 2 using the previous values that are passed to it. Then if // the current cube is intersected it will run MC_FACE0, MC_FACE1, MC_FACE3, MC_FACE4, and MC_FACE5. Each // returnes the pointer to the array of formed triangles. //FACE 0 Marching Cubes TRIANGLE* MCFace0(int ncellsX, int ncellsY, int ncellsZ, float gradFactorX, float gradFactorY, float gradFactorZ, int ind, int i, int j, int k, float minValue, mp4Vector * points, TRIANGLE *triangles, int &numTriangles, mp4Vector prevVerts[4], mpVector prevIntVerts[4], int edgeIndex, mp4Vector prevGradVerts[4], mpVector prevGrads[4], int gradIndex, bool* marchedCubes); //FACE 1 Marching Cubes TRIANGLE* MCFace1(int ncellsX, int ncellsY, int ncellsZ, float gradFactorX, float gradFactorY, float gradFactorZ, int ind, int i, int j, int k, float minValue, mp4Vector * points, TRIANGLE *triangles, int &numTriangles, mp4Vector prevVerts[4], mpVector prevIntVerts[4], int edgeIndex, mp4Vector prevGradVerts[4], mpVector prevGrads[4], int gradIndex, bool* marchedCubes); //FACE 2 Marching Cubes TRIANGLE* MCFace2(int ncellsX, int ncellsY, int ncellsZ, float gradFactorX, float gradFactorY, float gradFactorZ, int ind, int i, int j, int k, float minValue, mp4Vector * points, TRIANGLE *triangles, int &numTriangles, mp4Vector prevVerts[4], mpVector prevIntVerts[4], int edgeIndex, mp4Vector prevGradVerts[4], mpVector prevGrads[4], int gradIndex, bool* marchedCubes); //FACE 3 Marching Cubes TRIANGLE* MCFace3(int ncellsX, int ncellsY, int ncellsZ, float gradFactorX, float gradFactorY, float gradFactorZ, int ind, int i, int j, int k, float minValue, mp4Vector * points, TRIANGLE *triangles, int &numTriangles, mp4Vector prevVerts[4], mpVector prevIntVerts[4], int edgeIndex, mp4Vector prevGradVerts[4], mpVector prevGrads[4], int gradIndex, bool* marchedCubes); //FACE 4 Marching Cubes TRIANGLE* MCFace4(int ncellsX, int ncellsY, int ncellsZ, float gradFactorX, float gradFactorY, float gradFactorZ, int ind, int i, int j, int k, float minValue, mp4Vector * points, TRIANGLE *triangles, int &numTriangles, mp4Vector prevVerts[4], mpVector prevIntVerts[4], int edgeIndex, mp4Vector prevGradVerts[4], mpVector prevGrads[4], int gradIndex, bool* marchedCubes); //FACE 5 Marching Cubes TRIANGLE* MCFace5(int ncellsX, int ncellsY, int ncellsZ, float gradFactorX, float gradFactorY, float gradFactorZ, int ind, int i, int j, int k, float minValue, mp4Vector * points, TRIANGLE *triangles, int &numTriangles, mp4Vector prevVerts[4], mpVector prevIntVerts[4], int edgeIndex, mp4Vector prevGradVerts[4], mpVector prevGrads[4], int gradIndex, bool* marchedCubes); //Does Marching Cubes on cube (i, j, k) in points // Requirements: needs index ind which specifies which cube it is (its 0th point in points array) // If cube is intersected the triangles are added to triangles array passed to it, and numTriangles is // incremented appropriately. verts, array of vertices of this cube should be initialized. // intVerts, interpolated vertices on edges, gradVerts, gradients on vertices, and grads, interpolated // gradient vectors on edges dont have to be initialized, but if they are corresponding bits in edgeIndex // and indGrad index should show it. (for numbering see my web page) // Global variables YtimeZ should be initialized to (ncellsZ+1)*(ncellsY+1) and pointsZ should be ncellsZ+1 TRIANGLE* MarchOneCube(int ncellsX, int ncellsY, int ncellsZ, float gradFactorX, float gradFactorY, float gradFactorZ, int ind, int i, int j, int k, float minValue, mp4Vector * points, TRIANGLE *triangles, int &numTriangles, mp4Vector verts[8], mpVector intVerts[12], int &edgeIndex, mp4Vector gradVerts[8], mpVector grads[12], int &indGrad); //Find the first intersecting cube (if it exists). //Starts at (i,j,k)=(0,0,0) at the minimum x,y,z and then goes linearly searching for an intersecting cube. //Returns array of indices i,j,k of the first found cube or -1,-1,-1 if cube was not found float* MCFind(int ncellsX, int ncellsY, int ncellsZ, float minValue, mp4Vector * points); //Calls the MCFind and if found calls MarchingCubesRec with the returned indices //If not found NULL is returned and numTriangles is set to ZERO. TRIANGLE* MCRecFind(int ncellsX, int ncellsY, int ncellsZ, float gradFactorX, float gradFactorY, float gradFactorZ, float minValue, mp4Vector * points, int &numTriangles); #endif objcryst-2022.1/ObjCryst/wxCryst/MCTable.h000066400000000000000000000423241430515525000203060ustar00rootroot00000000000000/* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ //Tables used by Marching Cubes Algorithm //these tables came from Paul Baurke's web page at // http://astronomy.swin.edu.au/~pbourke/modelling/polygonise/ #ifndef MCTABLE_H_ #define MCTABLE_H_ static int edgeTable[256]={ 0x0 , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, 0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, 0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c, 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30, 0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac, 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, 0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60, 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc, 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c, 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc , 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, 0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, 0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0, 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, 0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, 0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, 0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460, 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0, 0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230, 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190, 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 }; static int triTable[256][16] = {{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1}, {3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1}, {3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1}, {3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1}, {9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1}, {1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1}, {9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1}, {2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1}, {8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1}, {9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1}, {4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1}, {3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1}, {1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1}, {4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1}, {4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1}, {9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1}, {1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1}, {5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1}, {2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1}, {9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1}, {0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1}, {2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1}, {10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1}, {4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1}, {5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1}, {5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1}, {9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1}, {0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1}, {10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1}, {8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1}, {2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1}, {7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1}, {9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1}, {2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1}, {11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1}, {9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1}, {5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1}, {11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1}, {11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1}, {1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1}, {9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1}, {5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1}, {2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1}, {0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1}, {5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1}, {6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1}, {3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1}, {6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1}, {5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1}, {1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1}, {10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1}, {6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1}, {1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1}, {8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1}, {7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1}, {3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1}, {5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1}, {0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1}, {9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1}, {8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1}, {5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1}, {0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1}, {6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1}, {10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1}, {10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1}, {8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1}, {1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1}, {3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1}, {0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1}, {10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1}, {3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1}, {6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1}, {9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1}, {8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1}, {3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1}, {6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1}, {0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1}, {10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1}, {10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1}, {1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1}, {2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1}, {7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1}, {7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1}, {2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1}, {1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1}, {11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1}, {8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1}, {0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1}, {7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1}, {10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1}, {2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1}, {6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1}, {7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1}, {2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1}, {1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1}, {10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1}, {10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1}, {0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1}, {7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1}, {6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1}, {8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1}, {9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1}, {6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1}, {1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1}, {4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1}, {10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1}, {8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1}, {0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1}, {1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1}, {8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1}, {10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1}, {4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1}, {10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1}, {5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1}, {11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1}, {9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1}, {6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1}, {7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1}, {3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1}, {7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1}, {9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1}, {3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1}, {6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1}, {9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1}, {1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1}, {4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1}, {7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1}, {6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1}, {3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1}, {0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1}, {6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1}, {1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1}, {0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1}, {11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1}, {6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1}, {5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1}, {9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1}, {1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1}, {10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1}, {0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1}, {5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1}, {10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1}, {11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1}, {9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1}, {7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1}, {2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1}, {8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1}, {9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1}, {9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1}, {1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1}, {9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1}, {9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1}, {5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1}, {0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1}, {10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1}, {2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1}, {0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1}, {0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1}, {9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1}, {5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1}, {3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1}, {5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1}, {8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1}, {0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1}, {9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1}, {1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1}, {3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1}, {4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1}, {9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1}, {11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1}, {11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1}, {2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1}, {9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1}, {3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1}, {1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1}, {4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1}, {4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1}, {0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1}, {3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1}, {3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1}, {0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1}, {9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1}, {1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}; #endif objcryst-2022.1/ObjCryst/wxCryst/bc32.mak000066400000000000000000000012601430515525000201030ustar00rootroot00000000000000!include ../rules.mak lib : wxTrackerGraph.obj wxMultiGraph.obj trackball.obj wxMolecule.obj wxScatteringPowerSphere.obj wxAtom.obj wxCryst.obj wxCrystal.obj wxGlobalOptimObj.obj wxPowderPattern.obj wxRefinableObj.obj wxScatterer.obj wxScatteringPower.obj wxZScatterer.obj wxDiffractionSingleCrystal.obj mpVector.obj MC.obj tlib "libwxCryst.lib" -+wxTrackerGraph.obj -+wxMultiGraph.obj -+trackball.obj -+wxMolecule.obj -+wxScatteringPowerSphere.obj -+wxAtom.obj -+wxCryst.obj -+wxCrystal.obj -+wxGlobalOptimObj.obj -+wxPowderPattern.obj -+wxRefinableObj.obj -+wxScatterer.obj -+wxScatteringPower.obj -+wxZScatterer.obj -+wxDiffractionSingleCrystal.obj -+mpVector.obj -+MC.obj all: lib objcryst-2022.1/ObjCryst/wxCryst/gnu.mak000066400000000000000000000022411430515525000201430ustar00rootroot00000000000000BUILD_DIR=$(CURDIR)/../.. include $(BUILD_DIR)/ObjCryst/rules.mak #wxGeneticAlgorithm.o OBJ= wxLSQ.o wxTrackerGraph.o wxMultiGraph.o wxScatteringPowerSphere.o trackball.o wxDiffractionSingleCrystal.o wxCryst.o wxRefinableObj.o wxScatteringPower.o wxScatterer.o wxAtom.o wxMolecule.o wxCrystal.o wxZScatterer.o wxPowderPattern.o wxGlobalOptimObj.o mpVector.o MC.o ifeq ($(profile),2) %.o : %.c @rm -f $(*F).gcda $(*F).gcno @$(MAKEDEPEND) ${CC} ${CPPFLAGS} ${CXXFLAGS} -c $< -o $@ else %.o : %.c @$(MAKEDEPEND) ${CC} ${CPPFLAGS} ${CXXFLAGS} -c $< -o $@ endif ifeq ($(profile),2) %.o : %.cpp @rm -f $(*F).gcda $(*F).gcno @$(MAKEDEPEND) ${CXX} ${CPPFLAGS} ${CXXFLAGS} -c $< -o $@ else %.o : %.cpp @$(MAKEDEPEND) ${CXX} ${CPPFLAGS} ${CXXFLAGS} -c $< -o $@ endif -include $(OBJ:.o=.dep) #wxCryst librarry libwxcryst.a : $(OBJ) @${RM} $@ ${AR} crs $@ ${filter-out %.a %.so, $^} lib: libwxcryst.a # target for making everything .PHONY : all all: lib # target for removing all object files .PHONY : tidy tidy:: @${RM} core *.o *.dep # target for removing all object files and libraries .PHONY : clean clean:: tidy @${RM} *.a cvsignore: cp -f ${DIR_CRYST}/.cvsignore ./ objcryst-2022.1/ObjCryst/wxCryst/mpVector.cpp000066400000000000000000000066421430515525000211740ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ ///////////////////////////////////////////////////////////////////////////////////////////////////// // // FileName: mpVector.cpp // Author : Michael Y. Polyakov // email : myp@andrew.cmu.edu or mikepolyakov@hotmail.com // Website : www.angelfire.com/linux/myp // Date : 7/16/2002 // // Provides basic vector handling. ////////////////////////////////////////////////////////////////////////////////////////////////////// #include "mpVector.h" mpVector::mpVector(float xx, float yy, float zz) : x(xx), y(yy), z(zz) { } mpVector::mpVector() : x(0), y(0), z(0) { } mpVector::mpVector(const mpVector& other) : x(other.x), y(other.y), z(other.z) { } mpVector& mpVector::Normalize() { float length = sqrt(x*x + y*y + z*z); if(!length) return *this; x /= length; y /= length; z /= length; return *this; } float mpVector::Magnitude() { return sqrt(x*x + y*y + z*z); } mpVector mpVector::Cross(const mpVector& other) { return mpVector(y*other.z-z*other.y, z*other.x-x*other.z, x*other.y-y*other.x); } mpVector mpVector::operator - (mpVector v) { return mpVector(x - v.x, y - v.y, z - v.z); } mpVector mpVector::operator + (mpVector v) { return mpVector(x + v.x, y + v.y, z + v.z); } float mpVector ::operator * (mpVector v) { return x*v.x + y*v.y + z*v.z; } mpVector mpVector::operator - (float c) { return mpVector(x-c, y-c, z-c); } mpVector mpVector::operator + (float c) { return mpVector(x+c, y+c, z+c); } mpVector mpVector::operator / (float c) { return mpVector(x/c, y/c, z/c); } mpVector mpVector::operator * (float c) { return mpVector(x*c, y*c, z*c); } void mpVector::operator = (const mpVector& other) { x = other.x; y = other.y; z = other.z; } mpVector::operator mp4Vector() const { return mp4Vector(*this); } mpVector::operator char*() const { return (char*)wxString::Format(_T("(%f %f %f)"), x, y, z).char_str(); } mp4Vector::mp4Vector() : x(0), y(0), z(0), val(0) { } mp4Vector::mp4Vector(float aa, float bb, float cc, float dd) : x(aa), y(bb), z(cc), val(dd) { } mp4Vector::mp4Vector(const mp4Vector& other) : x(other.x), y(other.y), z(other.z), val(other.val) { } mp4Vector::mp4Vector(const mpVector& v, const float value) : x(v.x), y(v.x), z(v.z), val(value) { } void mp4Vector::operator = (const mp4Vector& v) { x = v.x; y = v.y; z = v.z; val = v.val; } void mp4Vector::operator = (const mpVector& v) { x = v.x; y = v.y; z = v.z; } mp4Vector::operator mpVector() const { return mpVector(x, y, z); } bool mp4Vector::operator == (const mp4Vector& v) const { return x == v.x && y == v.y && z == v.z && val == v.val; } objcryst-2022.1/ObjCryst/wxCryst/mpVector.h000066400000000000000000000042311430515525000206310ustar00rootroot00000000000000/* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ ///////////////////////////////////////////////////////////////////////////////////////////////////// // // FileName: mpVector.h // Author : Michael Y. Polyakov // email : myp@andrew.cmu.edu or mikepolyakov@hotmail.com // Website : www.angelfire.com/linux/myp // Date : 7/16/2002 // // Provides basic vector handling. ////////////////////////////////////////////////////////////////////////////////////////////////////// #ifndef MPVECTOR_H #define MPVECTOR_H #include #include #include class mp4Vector; class mpVector { friend class mp4Vector; public: float x, y, z; mpVector(); mpVector(float xx, float yy, float zz); mpVector(const mpVector& other); mpVector& Normalize(); float Magnitude(); mpVector Cross(const mpVector& other); mpVector operator - (mpVector v); mpVector operator + (mpVector v); float operator * (mpVector v); mpVector operator - (float c); mpVector operator + (float c); mpVector operator / (float c); mpVector operator * (float c); void operator = (const mpVector& other); operator mp4Vector() const; operator char*() const; }; class mp4Vector { public: float x, y, z, val; mp4Vector(); mp4Vector(float aa, float bb, float cc, float dd); mp4Vector(const mp4Vector& other); mp4Vector(const mpVector& v, const float value); void operator = (const mp4Vector& v); void operator = (const mpVector& v); bool operator == (const mp4Vector& v) const; operator mpVector() const; }; #endif objcryst-2022.1/ObjCryst/wxCryst/trackball.c000066400000000000000000000203761430515525000207740ustar00rootroot00000000000000/* * (c) Copyright 1993, 1994, Silicon Graphics, Inc. * ALL RIGHTS RESERVED * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the above * copyright notice appear in all copies and that both the copyright notice * and this permission notice appear in supporting documentation, and that * the name of Silicon Graphics, Inc. not be used in advertising * or publicity pertaining to distribution of the software without specific, * written prior permission. * * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. * * US Government Users Restricted Rights * Use, duplication, or disclosure by the Government is subject to * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph * (c)(1)(ii) of the Rights in Technical Data and Computer Software * clause at DFARS 252.227-7013 and/or in similar or successor * clauses in the FAR or the DOD or NASA FAR Supplement. * Unpublished-- rights reserved under the copyright laws of the * United States. Contractor/manufacturer is Silicon Graphics, * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. * * OpenGL(TM) is a trademark of Silicon Graphics, Inc. */ /* * Trackball code: * * Implementation of a virtual trackball. * Implemented by Gavin Bell, lots of ideas from Thant Tessman and * the August '88 issue of Siggraph's "Computer Graphics," pp. 121-129. * * Vector manip code: * * Original code from: * David M. Ciemiewicz, Mark Grossman, Henry Moreton, and Paul Haeberli * * Much mucking with by: * Gavin Bell */ #include #include "trackball.h" /* * This size should really be based on the distance from the center of * rotation to the point on the object underneath the mouse. That * point would then track the mouse as closely as possible. This is a * simple example, though, so that is left as an Exercise for the * Programmer. */ #define TRACKBALLSIZE (0.8) /* * Local function prototypes (not defined in trackball.h) */ static float tb_project_to_sphere(float, float, float); static void normalize_quat(float [4]); void vzero(float *v) { v[0] = 0.0; v[1] = 0.0; v[2] = 0.0; } void vset(float *v, float x, float y, float z) { v[0] = x; v[1] = y; v[2] = z; } void vsub(const float *src1, const float *src2, float *dst) { dst[0] = src1[0] - src2[0]; dst[1] = src1[1] - src2[1]; dst[2] = src1[2] - src2[2]; } void vcopy(const float *v1, float *v2) { int i; for (i = 0 ; i < 3 ; i++) v2[i] = v1[i]; } void vcross(const float *v1, const float *v2, float *cross) { float temp[3]; temp[0] = (v1[1] * v2[2]) - (v1[2] * v2[1]); temp[1] = (v1[2] * v2[0]) - (v1[0] * v2[2]); temp[2] = (v1[0] * v2[1]) - (v1[1] * v2[0]); vcopy(temp, cross); } float vlength(const float *v) { return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); } void vscale(float *v, float div) { v[0] *= div; v[1] *= div; v[2] *= div; } void vnormal(float *v) { vscale(v,1.0/vlength(v)); } float vdot(const float *v1, const float *v2) { return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; } void vadd(const float *src1, const float *src2, float *dst) { dst[0] = src1[0] + src2[0]; dst[1] = src1[1] + src2[1]; dst[2] = src1[2] + src2[2]; } /* * Ok, simulate a track-ball. Project the points onto the virtual * trackball, then figure out the axis of rotation, which is the cross * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0) * Note: This is a deformed trackball-- is a trackball in the center, * but is deformed into a hyperbolic sheet of rotation away from the * center. This particular function was chosen after trying out * several variations. * * It is assumed that the arguments to this routine are in the range * (-1.0 ... 1.0) */ void trackball(float q[4], float p1x, float p1y, float p2x, float p2y) { float a[3]; /* Axis of rotation */ float phi; /* how much to rotate about axis */ float p1[3], p2[3], d[3]; float t; if (p1x == p2x && p1y == p2y) { /* Zero rotation */ vzero(q); q[3] = 1.0; return; } /* * First, figure out z-coordinates for projection of P1 and P2 to * deformed sphere */ vset(p1,p1x,p1y,tb_project_to_sphere(TRACKBALLSIZE,p1x,p1y)); vset(p2,p2x,p2y,tb_project_to_sphere(TRACKBALLSIZE,p2x,p2y)); /* * Now, we want the cross product of P1 and P2 */ vcross(p2,p1,a); /* * Figure out how much to rotate around that axis. */ vsub(p1,p2,d); t = vlength(d) / (2.0*TRACKBALLSIZE); /* * Avoid problems with out-of-control values... */ if (t > 1.0) t = 1.0; if (t < -1.0) t = -1.0; phi = 2.0 * asin(t); axis_to_quat(a,phi,q); } /* * Given an axis and angle, compute quaternion. */ void axis_to_quat(float a[3], float phi, float q[4]) { vnormal(a); vcopy(a,q); vscale(q,sin(phi/2.0)); q[3] = cos(phi/2.0); } /* * Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet * if we are away from the center of the sphere. */ static float tb_project_to_sphere(float r, float x, float y) { float d, t, z; d = sqrt(x*x + y*y); if (d < r * 0.70710678118654752440) { /* Inside sphere */ z = sqrt(r*r - d*d); } else { /* On hyperbola */ t = r / 1.41421356237309504880; z = t*t / d; } return z; } /* * Given two rotations, e1 and e2, expressed as quaternion rotations, * figure out the equivalent single rotation and stuff it into dest. * * This routine also normalizes the result every RENORMCOUNT times it is * called, to keep error from creeping in. * * NOTE: This routine is written so that q1 or q2 may be the same * as dest (or each other). */ #define RENORMCOUNT 97 void add_quats(float q1[4], float q2[4], float dest[4]) { static int count=0; float t1[4], t2[4], t3[4]; float tf[4]; vcopy(q1,t1); vscale(t1,q2[3]); vcopy(q2,t2); vscale(t2,q1[3]); vcross(q2,q1,t3); vadd(t1,t2,tf); vadd(t3,tf,tf); tf[3] = q1[3] * q2[3] - vdot(q1,q2); dest[0] = tf[0]; dest[1] = tf[1]; dest[2] = tf[2]; dest[3] = tf[3]; if (++count > RENORMCOUNT) { count = 0; normalize_quat(dest); } } /* * Quaternions always obey: a^2 + b^2 + c^2 + d^2 = 1.0 * If they don't add up to 1.0, dividing by their magnitued will * renormalize them. * * Note: See the following for more information on quaternions: * * - Shoemake, K., Animating rotation with quaternion curves, Computer * Graphics 19, No 3 (Proc. SIGGRAPH'85), 245-254, 1985. * - Pletinckx, D., Quaternion calculus as a basic tool in computer * graphics, The Visual Computer 5, 2-13, 1989. */ static void normalize_quat(float q[4]) { int i; float mag; mag = (q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]); for (i = 0; i < 4; i++) q[i] /= mag; } /* * Build a rotation matrix, given a quaternion rotation. * */ void build_rotmatrix(float m[4][4], float q[4]) { m[0][0] = 1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]); m[0][1] = 2.0 * (q[0] * q[1] - q[2] * q[3]); m[0][2] = 2.0 * (q[2] * q[0] + q[1] * q[3]); m[0][3] = 0.0; m[1][0] = 2.0 * (q[0] * q[1] + q[2] * q[3]); m[1][1]= 1.0 - 2.0 * (q[2] * q[2] + q[0] * q[0]); m[1][2] = 2.0 * (q[1] * q[2] - q[0] * q[3]); m[1][3] = 0.0; m[2][0] = 2.0 * (q[2] * q[0] - q[1] * q[3]); m[2][1] = 2.0 * (q[1] * q[2] + q[0] * q[3]); m[2][2] = 1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]); m[2][3] = 0.0; m[3][0] = 0.0; m[3][1] = 0.0; m[3][2] = 0.0; m[3][3] = 1.0; } objcryst-2022.1/ObjCryst/wxCryst/trackball.h000066400000000000000000000062531430515525000207770ustar00rootroot00000000000000/* * (c) Copyright 1993, 1994, Silicon Graphics, Inc. * ALL RIGHTS RESERVED * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the above * copyright notice appear in all copies and that both the copyright notice * and this permission notice appear in supporting documentation, and that * the name of Silicon Graphics, Inc. not be used in advertising * or publicity pertaining to distribution of the software without specific, * written prior permission. * * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. * * US Government Users Restricted Rights * Use, duplication, or disclosure by the Government is subject to * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph * (c)(1)(ii) of the Rights in Technical Data and Computer Software * clause at DFARS 252.227-7013 and/or in similar or successor * clauses in the FAR or the DOD or NASA FAR Supplement. * Unpublished-- rights reserved under the copyright laws of the * United States. Contractor/manufacturer is Silicon Graphics, * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. * * OpenGL(TM) is a trademark of Silicon Graphics, Inc. */ /* * trackball.h * A virtual trackball implementation * Written by Gavin Bell for Silicon Graphics, November 1988. */ /* * Pass the x and y coordinates of the last and current positions of * the mouse, scaled so they are from (-1.0 ... 1.0). * * The resulting rotation is returned as a quaternion rotation in the * first paramater. */ void trackball(float q[4], float p1x, float p1y, float p2x, float p2y); /* * Given two quaternions, add them together to get a third quaternion. * Adding quaternions to get a compound rotation is analagous to adding * translations to get a compound translation. When incrementally * adding rotations, the first argument here should be the new * rotation, the second and third the total rotation (which will be * over-written with the resulting new total rotation). */ void add_quats(float *q1, float *q2, float *dest); /* * A useful function, builds a rotation matrix in Matrix based on * given quaternion. */ void build_rotmatrix(float m[4][4], float q[4]); /* * This function computes a quaternion based on an axis (defined by * the given vector) and an angle about which to rotate. The angle is * expressed in radians. The result is put into the third argument. */ void axis_to_quat(float a[3], float phi, float q[4]); objcryst-2022.1/ObjCryst/wxCryst/vc.mak000066400000000000000000000012201430515525000177560ustar00rootroot00000000000000!include ../rules.mak lib : wxTrackerGraph.obj wxMultiGraph.obj trackball.obj wxMolecule.obj wxScatteringPowerSphere.obj wxAtom.obj wxCryst.obj wxCrystal.obj wxGlobalOptimObj.obj wxPowderPattern.obj wxRefinableObj.obj wxScatterer.obj wxScatteringPower.obj wxZScatterer.obj wxDiffractionSingleCrystal.obj mpVector.obj MC.obj lib -OUT:libwxCryst.lib wxTrackerGraph.obj wxMultiGraph.obj trackball.obj wxMolecule.obj wxScatteringPowerSphere.obj wxAtom.obj wxCryst.obj wxCrystal.obj wxGlobalOptimObj.obj wxPowderPattern.obj wxRefinableObj.obj wxScatterer.obj wxScatteringPower.obj wxZScatterer.obj wxDiffractionSingleCrystal.obj mpVector.obj MC.obj all: lib objcryst-2022.1/ObjCryst/wxCryst/wxAtom.cpp000066400000000000000000000055301430515525000206470ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ //#include //for stringstream #include // wx headers, with or without precompilation #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "ObjCryst/wxCryst/wxAtom.h" //Fixes for Cygwin; where do those stupid macros come from ? Somewhere in wxMSW headers #ifdef max #undef max #endif #ifdef min #undef min #endif #ifdef DrawText #undef DrawText #endif namespace ObjCryst { //////////////////////////////////////////////////////////////////////// // // WXAtom // //////////////////////////////////////////////////////////////////////// static const long ID_ATOM_SCATTPOW=WXCRYST_ID(); BEGIN_EVENT_TABLE(WXAtom,wxWindow) EVT_BUTTON(ID_ATOM_SCATTPOW, WXAtom::OnChangeScattPow) END_EVENT_TABLE() WXAtom::WXAtom(wxWindow* parent, Atom *obj): WXScatterer(parent,obj),mpAtom(obj) { VFN_DEBUG_MESSAGE("WXAtom::WXAtom()",6) //mpFieldScattPower=new WXFieldName(this,"Symbol:",this,-1); mpFieldScattPower=new WXFieldChoice(this,ID_ATOM_SCATTPOW,"Scattering Power:"); mpSizer->Add(mpFieldScattPower,0,wxALIGN_LEFT); mList.Add(mpFieldScattPower); this->BottomLayout(0); this->CrystUpdate(true,true); } WXAtom::~WXAtom() { mpAtom->WXNotifyDelete(); } void WXAtom::OnChangeScattPow(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_MESSAGE("WXAtom::OnChangeScattPow()",6) WXCrystValidateAllUserInput(); int choice; const ScatteringPower *scatt= WXDialogChooseFromRegistry (mpAtom->GetCrystal().GetScatteringPowerRegistry(),(wxWindow*)this, "Choose a new Scattering Power",choice); if(0==scatt) return; mpAtom->Init(mpAtom->GetX(),mpAtom->GetY(),mpAtom->GetZ(),mpAtom->GetName(), scatt,mpAtom->GetOccupancy()); this->CrystUpdate(true,true); } void WXAtom::UpdateUI(const bool lock) { mpFieldScattPower->SetValue(mpAtom->GetScatteringPower().GetName()); this->WXRefinableObj::UpdateUI(); } }// namespace objcryst-2022.1/ObjCryst/wxCryst/wxAtom.h000066400000000000000000000030561430515525000203150ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * header file for the RefinablePar and RefinableObj classes * * This is still in early development stages !! Not secure ! * */ #ifndef _VFN_WX_ATOM_H_ #define _VFN_WX_ATOM_H_ #include "ObjCryst/wxCryst/wxScatterer.h" #include "ObjCryst/ObjCryst/Atom.h" namespace ObjCryst { /// wxCryst class for Atoms class WXAtom: public WXScatterer { public: WXAtom(wxWindow *parent, Atom*); virtual ~WXAtom(); void OnChangeScattPow(wxCommandEvent & WXUNUSED(event)); virtual void UpdateUI(const bool mutexlock=false); private: Atom* mpAtom; WXFieldChoice* mpFieldScattPower; DECLARE_EVENT_TABLE() }; } //namespace #endif //_VFN_WX_ATOM_H_ objcryst-2022.1/ObjCryst/wxCryst/wxCryst.cpp000066400000000000000000000750121430515525000210550ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ //#include //for stringstream #include // wx headers, with or without precompilation #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "ObjCryst/wxCryst/wxCryst.h" #include "ObjCryst/ObjCryst/Undo.h" //#include "ObjCryst/Quirks/VFNStreamFormat.h" #include "ObjCryst/Quirks/VFNDebug.h" //#include "ObjCryst/RefinableObj/GlobalOptimObj.h" //Fixes for Cygwin; where do those stupid macros come from ? Somewhere in wxMSW headers #ifdef max #undef max #endif #ifdef min #undef min #endif #ifdef DrawText #undef DrawText #endif namespace ObjCryst { std::map > gvWindowPosition; wxMultiChoiceDialog_ListBox::wxMultiChoiceDialog_ListBox(wxWindow* parent, const wxString& message, const wxString& caption, int n, const wxString* choices): wxDialog(parent,-1,_T("Choose the molecule's atoms"),wxDefaultPosition,wxSize(300,400),wxCAPTION|wxSTAY_ON_TOP), mListBox(this,-1,wxDefaultPosition,wxSize(250,350),n,choices,wxLB_MULTIPLE) { wxBoxSizer *sizer=new wxBoxSizer(wxVERTICAL); sizer->Add(&mListBox); sizer->Add(this->CreateSeparatedButtonSizer(wxOK | wxCANCEL)); this->SetSizer(sizer); sizer->SetSizeHints(this); sizer->Fit(this); } wxArrayInt wxMultiChoiceDialog_ListBox::GetSelections() const { wxArrayInt choice; mListBox.GetSelections(choice); return choice; } //////////////////////////////////////////////////////////////////////// // // Unique ID for menus incrementer // //////////////////////////////////////////////////////////////////////// WXCRYST_ID::WXCRYST_ID(){mIndex=mCounter++;} WXCRYST_ID::operator long(){return mIndex;} long WXCRYST_ID::mCounter=wxID_HIGHEST+100; #ifdef VFN_CRYST_MUTEX //////////////////////////////////////////////////////////////////////// // // Mutex // //////////////////////////////////////////////////////////////////////// CrystMutex::CrystMutex():mNbLock(0){} CrystMutex::~CrystMutex() { cout <<"~CrystMutex("<wxMutex::TryLock(); if(res==wxMUTEX_NO_ERROR) cout <<"Thread:"<wxMutex::Lock(); cout <<"Thread:"<wxMutex::Unlock(); } #endif //////////////////////////////////////////////////////////////////////// // // WXCrystObjBasic // //////////////////////////////////////////////////////////////////////// WXCrystObjBasic::WXCrystObjBasic(wxWindow* parent): wxWindow(parent,-1),mWXCrystParent(0),mIsShown(true),mNeedUpdateUI(true) { VFN_DEBUG_MESSAGE("WXCrystObjBasic::WXCrystObjBasic() at "<(parent); #ifdef __WXGTK__ #ifndef __WXGTK20__ // Why is this necessary for GTK 1.2 ? wxWidgets 2.6.3 this->SetBackgroundColour(wxColour(240,240,240));// wxLIGHT_GREY #endif #endif VFN_DEBUG_MESSAGE("WXCrystObjBasic::WXCrystObjBasic():End",6) } WXCrystObjBasic::~WXCrystObjBasic() { // Every time we destroy a widget, validate all input to make sure the destroyed // widget does not have some unread info. WXCrystValidateAllUserInput(); set vpList=mvpList;//use a copy for(set::iterator pos=vpList.begin();pos!=vpList.end();++pos) (*pos)->Remove(this); } void WXCrystObjBasic::BottomLayout(WXCrystObjBasic *pChild) { VFN_DEBUG_ENTRY("WXCrystObjBasic::BottomLayout(...)"<GetSize().GetWidth()<<","<GetSize().GetHeight(),5); wxTheApp->GetTopWindow()->SendSizeEvent(); VFN_DEBUG_EXIT("WXCrystObjBasic::BottomLayout(...)"<GetSize().GetWidth()<<","<GetSize().GetHeight(),5); } void WXCrystObjBasic::AddChild(WXCrystObjBasic *pChild, bool doBottomLayout) { VFN_DEBUG_ENTRY("WXCrystObjBasic::AddChild(...)"<GetSize().GetWidth()<<","<GetSize().GetHeight(),5); wxSizer *pSizer=this->GetSizer(); if(pSizer!=0) { pSizer->Add(pChild); } if(doBottomLayout) wxTheApp->GetTopWindow()->SendSizeEvent(); VFN_DEBUG_EXIT("WXCrystObjBasic::AddChild(...)"<GetSize().GetWidth()<<","<GetSize().GetHeight(),5); } void WXCrystObjBasic::AddedToList(WXCrystObjBasicList* list){mvpList.insert(list);} void WXCrystObjBasic::RemovedFromList(WXCrystObjBasicList* list){mvpList.erase(list);} bool WXCrystObjBasic::Layout() { //static unsigned long ct=0; //cout<<"WXCrystObjBasic::Layout() #"<<++ct<wxWindow::SetToolTip(tip);} //////////////////////////////////////////////////////////////////////// // // WXCrystObjBasicList // //////////////////////////////////////////////////////////////////////// WXCrystObjBasicList::WXCrystObjBasicList() {} WXCrystObjBasicList::~WXCrystObjBasicList() { set vpWXCrystObj=mvpWXCrystObj; for(set::iterator pos=vpWXCrystObj.begin();pos!=vpWXCrystObj.end();pos++) (*pos)->RemovedFromList(this); mvpWXCrystObj.clear(); } unsigned int WXCrystObjBasicList::GetNb()const {return mvpWXCrystObj.size();} void WXCrystObjBasicList::Add(WXCrystObjBasic *win) { VFN_DEBUG_MESSAGE("WXCrystObjBasicList::Add()",6) win->AddedToList(this); mvpWXCrystObj.insert(win); } void WXCrystObjBasicList::Remove(WXCrystObjBasic *win) { VFN_DEBUG_MESSAGE("WXCrystObjBasicList::Remove():"<RemovedFromList(this); } bool WXCrystObjBasicList::Show(bool show) { VFN_DEBUG_MESSAGE("WXCrystObjBasicList::Show(bool)",3) for(set::iterator pos=mvpWXCrystObj.begin();pos!=mvpWXCrystObj.end();pos++) (*pos)->Show(show); //this->CrystUpdate(); VFN_DEBUG_MESSAGE("WXCrystObjBasicList::Show(bool):End",3) return true; } void WXCrystObjBasicList::CrystUpdate(const bool updateUI,const bool mutexlock) { VFN_DEBUG_ENTRY("WXCrystObjBasicList::CrystUpdate()",5) for(set::iterator pos=mvpWXCrystObj.begin();pos!=mvpWXCrystObj.end();pos++) { VFN_DEBUG_MESSAGE("WXCrystObjBasicList::CrystUpdate("<CrystUpdate(updateUI,mutexlock); } VFN_DEBUG_EXIT("WXCrystObjBasicList::CrystUpdate()",5) } void WXCrystObjBasicList::UpdateUI(const bool mutexlock) { VFN_DEBUG_ENTRY("WXCrystObjBasicList::UpdateUI("<::iterator pos=mvpWXCrystObj.begin();pos!=mvpWXCrystObj.end();pos++) (*pos)->UpdateUI(mutexlock); VFN_DEBUG_EXIT("WXCrystObjBasicList::UpdateUI()",5) } void WXCrystObjBasicList::Enable(bool enable) { for(set::iterator pos=mvpWXCrystObj.begin();pos!=mvpWXCrystObj.end();pos++) (*pos)->Enable(enable); } //////////////////////////////////////////////////////////////////////// // // For the automatic validation of user input // //////////////////////////////////////////////////////////////////////// /// This pointer records the last wxField in which something was enetered, /// so that it can be validated when inpu is finished (either when another /// input has begun in another field, or when an action requires to purge /// all input WXField *spLastWXFieldInputNotValidated=0; void WXCrystValidateAllUserInput() { #ifdef __FOX_UNDO__ // Hijack this function to record changes in the configuration gConfigHistory.Store(); #endif if(0==spLastWXFieldInputNotValidated) return; VFN_DEBUG_ENTRY("WXCrystValidateAllUserInput()...",6) static WXField *pField; pField=spLastWXFieldInputNotValidated; spLastWXFieldInputNotValidated=0;//avoid loops pField->ValidateUserInput(); VFN_DEBUG_EXIT("WXCrystValidateAllUserInput()...",6) } //////////////////////////////////////////////////////////////////////// // // WXField // //////////////////////////////////////////////////////////////////////// WXField::WXField(wxWindow *parent,const string& label,const int id): WXCrystObjBasic(parent),mId(id) { VFN_DEBUG_ENTRY("WXField::WXField()",6) mpSizer = new wxBoxSizer(wxHORIZONTAL); mpLabel=new wxStaticText(this,-1,wxString::FromAscii(label.c_str())); mpSizer->Add(mpLabel,0,wxALIGN_CENTER); this->SetSizer(mpSizer); //mpSizer->SetSizeHints(this); //this->Layout(); VFN_DEBUG_EXIT("WXField::WXField()",6) } void WXField::SetLabel(const string& s) { VFN_DEBUG_MESSAGE("WXField::SetLabel()",3) mpLabel->SetLabel(wxString::FromAscii(s.c_str())); mpLabel->Layout(); } bool WXField::SetForegroundColour(const wxColour& colour) { VFN_DEBUG_MESSAGE("WXField::SetLabel()",3) mpLabel->SetForegroundColour(colour); return this->wxWindow::SetForegroundColour(colour); } void WXField::SetSize(int width, int height) {} //////////////////////////////////////////////////////////////////////// // // WXFieldString // //////////////////////////////////////////////////////////////////////// BEGIN_EVENT_TABLE(WXFieldString,wxWindow) EVT_TEXT_ENTER(ID_WXFIELD, WXFieldString::OnEnter) EVT_TEXT( ID_WXFIELD, WXFieldString::OnText) END_EVENT_TABLE() WXFieldString::WXFieldString(wxWindow *parent,string& st, const int id,const int hsize, bool isEditable): WXField(parent,"",id),mpString(&st),mValue(st),mIsSelfUpdating(false) { VFN_DEBUG_MESSAGE("WXFieldString::WXFieldName():End",6) if(true==isEditable) mpField=new wxTextCtrl(this,ID_WXFIELD,wxString::FromAscii(mValue.c_str()), wxDefaultPosition,wxSize(hsize,-1),wxTE_PROCESS_ENTER, wxTextValidator(wxFILTER_ASCII)); else mpField=new wxTextCtrl(this,ID_WXFIELD,wxString::FromAscii(mValue.c_str()), wxDefaultPosition,wxSize(hsize,-1),wxTE_READONLY, wxTextValidator(wxFILTER_ASCII)); mpSizer->Add(mpField,0,wxALIGN_CENTER); mpSizer->SetSizeHints(this); this->Layout(); } void WXFieldString::OnEnter(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_MESSAGE("WXFieldString::OnEnter()",6) WXCrystValidateAllUserInput(); } void WXFieldString::OnText(wxCommandEvent & WXUNUSED(event)) { if(true==mIsSelfUpdating) return; VFN_DEBUG_MESSAGE("WXFieldString::OnText():",6) if(spLastWXFieldInputNotValidated!=this) { WXCrystValidateAllUserInput(); spLastWXFieldInputNotValidated=this; } } void WXFieldString::SetValue(const string&s) { VFN_DEBUG_ENTRY("WXFieldString::SetValue()",3) wxMutexLocker mlock(mMutex); if(mValue==s) { VFN_DEBUG_EXIT("WXFieldString::SetValue(): string unchanged",3) return; } mValue=s; mNeedUpdateUI=true; VFN_DEBUG_EXIT("WXFieldString::SetValue()",3) } const string WXFieldString::GetValue() const { VFN_DEBUG_MESSAGE("WXFieldString::GetValue()"<GetValue(),6) return mValue; } void WXFieldString::CrystUpdate(const bool uui,const bool lock) { VFN_DEBUG_ENTRY("WXFieldString::CrystUpdate()",3) if(lock) mMutex.Lock(); if(mValue==*mpString) { if(lock)mMutex.Unlock(); return; } mValueOld=mValue; mValue=*mpString; mNeedUpdateUI=true; if(lock) mMutex.Unlock(); if(uui) if(true==wxThread::IsMain()) this->UpdateUI(lock); VFN_DEBUG_EXIT("WXFieldString::CrystUpdate()",3) } void WXFieldString::UpdateUI(const bool lock) { if(lock) mMutex.Lock(); if(mNeedUpdateUI==false) { if(lock) mMutex.Unlock(); return; } VFN_DEBUG_ENTRY("WXFieldString::UpdateUI("<SetValue(wxString::FromAscii(mValue.c_str())); mIsSelfUpdating=false; mNeedUpdateUI=false; if(lock) mMutex.Unlock(); VFN_DEBUG_EXIT("WXFieldString::UpdateUI()",4) } void WXFieldString::Revert() { VFN_DEBUG_MESSAGE("WXFieldString::Revert()",3) wxMutexLocker mlock(mMutex); mValue=mValueOld; mNeedUpdateUI=true; } void WXFieldString::ValidateUserInput() { VFN_DEBUG_MESSAGE("WXFieldString::ValidateUserInput()",6) //:TODO: Check that the object is not busy (input should be frozen) wxMutexLocker mlock(mMutex); mValueOld=mValue; mValue=mpField->GetValue().ToAscii(); *mpString=mValue; } void WXFieldString::SetSize(int width, int height) { mpField->SetSize(width,height); //wxTheApp->GetTopWindow()->SendSizeEvent(); } void WXFieldString::SetToolTip(const wxString& tip){mpField->SetToolTip(tip);} //////////////////////////////////////////////////////////////////////// // // WXFieldName // //////////////////////////////////////////////////////////////////////// BEGIN_EVENT_TABLE(WXFieldName,wxWindow) EVT_TEXT_ENTER(ID_WXFIELD, WXFieldName::OnEnter) EVT_TEXT( ID_WXFIELD, WXFieldName::OnText) END_EVENT_TABLE() WXFieldName::WXFieldName(wxWindow *parent,const string& label, WXCrystObj* owner, const int id,const int hsize, bool isEditable): WXField(parent,label,id),mpWXObj(owner),mValue(""),mIsSelfUpdating(false) { VFN_DEBUG_ENTRY("WXFieldName::WXFieldName()",6) if(true==isEditable) mpField=new wxTextCtrl(this,ID_WXFIELD,wxString::FromAscii(mValue.c_str()), wxDefaultPosition,wxSize(hsize,-1),wxTE_PROCESS_ENTER, wxTextValidator(wxFILTER_ASCII)); else mpField=new wxTextCtrl(this,ID_WXFIELD,wxString::FromAscii(mValue.c_str()), wxDefaultPosition,wxSize(hsize,-1),wxTE_READONLY, wxTextValidator(wxFILTER_ASCII)); mpSizer->Add(mpField,0,wxALIGN_CENTER); //mpSizer->SetSizeHints(this); this->Layout(); VFN_DEBUG_EXIT("WXFieldName::WXFieldName()",6) } void WXFieldName::OnEnter(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_MESSAGE("WXFieldName::OnEnter()",6) WXCrystValidateAllUserInput(); } void WXFieldName::OnText(wxCommandEvent & WXUNUSED(event)) { if(true==mIsSelfUpdating) return; VFN_DEBUG_MESSAGE("WXFieldName::OnText():",6) if(spLastWXFieldInputNotValidated!=this) { WXCrystValidateAllUserInput(); spLastWXFieldInputNotValidated=this; } } void WXFieldName::SetValue(const string&s) { VFN_DEBUG_ENTRY("WXFieldName::SetValue()",3) wxMutexLocker mlock(mMutex); if(mValue==s) { VFN_DEBUG_EXIT("WXFieldName::SetValue():name unchanged",3) return; } mValue=s; mNeedUpdateUI=true; VFN_DEBUG_EXIT("WXFieldName::SetValue()",3) } const string WXFieldName::GetValue() const { VFN_DEBUG_MESSAGE("WXFieldName::GetValue()"<GetValue(),6) return mValue; } void WXFieldName::CrystUpdate(const bool updateUI,const bool lock) { VFN_DEBUG_MESSAGE("WXFieldName::CrystUpdate()",3) // The name must be updated by the owner } void WXFieldName::UpdateUI(const bool lock) { if(lock) mMutex.Lock(); if(mNeedUpdateUI==false) { if(lock) mMutex.Unlock(); return; } VFN_DEBUG_ENTRY("WXFieldName::UpdateUI("<SetValue(wxString::FromAscii(mValue.c_str())); //:TODO: Some way of resizing the field which is less of a kludge... int w=mpField->GetTextExtent(wxString::FromAscii(mValue.c_str())).GetWidth(); const int wmax=wxTheApp->GetTopWindow()->GetSize().GetWidth(); if(w>wmax)w=wmax; if(w>mpField->GetSize().GetWidth()) this->GetSizer()->SetItemMinSize(mpField,w+30,-1); this->GetSizer()->Fit(this); mIsSelfUpdating=false; mNeedUpdateUI=false; if(lock) mMutex.Unlock(); VFN_DEBUG_EXIT("WXFieldName::UpdateUI()",4) } void WXFieldName::Revert() { VFN_DEBUG_MESSAGE("WXFieldName::Revert()",3) wxMutexLocker mlock(mMutex); mValue=mValueOld; mNeedUpdateUI=true; } void WXFieldName::ValidateUserInput() { VFN_DEBUG_MESSAGE("WXFieldName::ValidateUserInput()",6) mMutex.Lock(); mValueOld=mValue; mValue=mpField->GetValue().ToAscii(); mMutex.Unlock(); mpWXObj->OnChangeName(mId); } void WXFieldName::SetSize(int width, int height) {//:TODO: deprecate this function ? mpField->SetSize(width,height); } void WXFieldName::SetToolTip(const wxString& tip){mpField->SetToolTip(tip);} //////////////////////////////////////////////////////////////////////// // // WXFieldParBase // //////////////////////////////////////////////////////////////////////// BEGIN_EVENT_TABLE(WXFieldParBase,wxWindow) EVT_TEXT_ENTER(ID_WXFIELD, WXFieldParBase::OnEnter) EVT_TEXT( ID_WXFIELD, WXFieldParBase::OnText) END_EVENT_TABLE() WXFieldParBase::WXFieldParBase(wxWindow *parent,const string& label, const int id, const int hsize): WXField(parent,label,id),mIsSelfUpdating(false),mFormat(_T("%8f")) { VFN_DEBUG_MESSAGE("WXFieldParBase::WXFieldName():End",6) mpField=new wxTextCtrl(this,ID_WXFIELD,_T(""), wxDefaultPosition,wxSize(hsize,-1),wxTE_PROCESS_ENTER, wxTextValidator(wxFILTER_NUMERIC)); mpSizer->Add(mpField,0,wxALIGN_CENTER); this->Layout(); } void WXFieldParBase::OnEnter(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_MESSAGE("WXFieldRefPar::OnEnter()",6) WXCrystValidateAllUserInput(); } void WXFieldParBase::OnText(wxCommandEvent & WXUNUSED(event)) { if(true==mIsSelfUpdating) return; VFN_DEBUG_MESSAGE("WXFieldRefPar::OnText()",6) if(spLastWXFieldInputNotValidated!=this) { WXCrystValidateAllUserInput(); spLastWXFieldInputNotValidated=this; } } void WXFieldParBase::ValidateUserInput() { VFN_DEBUG_MESSAGE("WXFieldRefPar::ValidateUserInput()",6) this->ReadNewValue(); } void WXFieldParBase::SetToolTip(const wxString& tip){mpField->SetToolTip(tip);} void WXFieldParBase::SetFormat(const wxString &format) { mFormat=format; } //////////////////////////////////////////////////////////////////////// // // WXFieldPar // //////////////////////////////////////////////////////////////////////// template WXFieldPar::WXFieldPar(wxWindow *parent,const string& label, const int id,T *par,const int hsize): WXFieldParBase(parent,label,id,hsize),mpValue(par),mValue(*par),mValueOld(*par),mHumanScale(1) { this->CrystUpdate(true,true); } template<> WXFieldPar::WXFieldPar(wxWindow *parent,const string& label, const int id,long *par,const int hsize): WXFieldParBase(parent,label,id,hsize),mpValue(par),mValue(*par),mValueOld(*par),mHumanScale(1) { mFormat=_T("%ld"); this->CrystUpdate(true,true); } template void WXFieldPar::CrystUpdate(const bool uui,const bool lock) { if(lock) mMutex.Lock(); if(mValue==*mpValue) { if(lock) mMutex.Unlock(); return; } VFN_DEBUG_ENTRY("WXFieldPar::CrystUpdate()",6) mValueOld=mValue; mValue=*mpValue; mNeedUpdateUI=true; if(lock) mMutex.Unlock(); if(uui) if(true==wxThread::IsMain()) this->UpdateUI(lock); VFN_DEBUG_EXIT("WXFieldPar::CrystUpdate()",6) } template<> void WXFieldPar::UpdateUI(const bool lock) { if(lock)mMutex.Lock(); if(mNeedUpdateUI==false) { if(lock)mMutex.Unlock(); return; } VFN_DEBUG_ENTRY("WXFieldPar::UpdateUI("<0.01)) tmp.Printf(_T("%6.4f"),mValue*mHumanScale); else tmp.Printf(mFormat,mValue*mHumanScale); mIsSelfUpdating=true; mpField->SetValue(tmp); mIsSelfUpdating=false; mNeedUpdateUI=false; if(lock)mMutex.Unlock(); VFN_DEBUG_EXIT("WXFieldPar::UpdateUI()",4) } template<> void WXFieldPar::UpdateUI(const bool lock) { if(lock)mMutex.Lock(); if(mNeedUpdateUI==false) { if(lock)mMutex.Unlock(); return; } VFN_DEBUG_ENTRY("WXFieldPar::UpdateUI("<SetValue(tmp); mIsSelfUpdating=false; mNeedUpdateUI=false; if(lock)mMutex.Unlock(); VFN_DEBUG_EXIT("WXFieldPar::UpdateUI()",4) } /* template void WXFieldPar::UpdateUI(const bool lock) { if(lock)mMutex.Lock(); if(mNeedUpdateUI==false) { if(lock)mMutex.Unlock(); return; } stringstream s; s <<*mpValue; mIsSelfUpdating=true; mpField->SetValue(s.str().c_str());; mpField->SetValue(wxString::Printf("%f",mValue)); mIsSelfUpdating=false; mNeedUpdateUI=false; if(lock)mMutex.Unlock(); } */ template void WXFieldPar::Revert() { VFN_DEBUG_MESSAGE("WXFieldPar::Revert()",6) mMutex.Lock(); *mpValue=mValueOld; mValue=mValueOld; mNeedUpdateUI=true; mMutex.Unlock(); if(true==wxThread::IsMain()) this->UpdateUI(true); } template void WXFieldPar::SetHumanValueScale(const T s) { mHumanScale=s; } template<> void WXFieldPar::ReadNewValue() { VFN_DEBUG_MESSAGE("WXFieldPar::ReadNewValue()",6) wxMutexLocker mlock(mMutex); mValueOld=*mpValue; wxString s=mpField->GetValue(); double tmp; s.ToDouble(&tmp); *mpValue=tmp; *mpValue /= mHumanScale; } template<> void WXFieldPar::ReadNewValue() { VFN_DEBUG_MESSAGE("WXFieldPar::ReadNewValue()",6) wxMutexLocker mlock(mMutex); mValueOld=*mpValue; wxString s=mpField->GetValue(); s.ToLong(mpValue); *mpValue /= mHumanScale; } template class WXFieldPar; template class WXFieldPar; //////////////////////////////////////////////////////////////////////// // // WXFieldChoice // //////////////////////////////////////////////////////////////////////// WXFieldChoice::WXFieldChoice (wxWindow *parent,const int field_id,const string &name,const int hsize): WXField(parent,name,field_id) { mpButton=new wxButton(this,field_id,wxString::FromAscii(name.c_str()),wxDefaultPosition,wxSize(hsize,-1)); mpSizer->Add(mpButton,0,wxALIGN_CENTER); //mpSizer->SetItemMinSize(mpButton, // mpButton->GetSize().GetWidth(), // mpButton->GetSize().GetHeight()); //mpSizer->SetSizeHints(this); this->Layout(); } void WXFieldChoice::CrystUpdate(const bool uui,const bool lock) { //Nothing to do. This should be done by the owner } void WXFieldChoice::UpdateUI(const bool lock) { //Nothing to do. This should be done by the owner } void WXFieldChoice::Revert() { //Nothing to do. This should be done by the owner } void WXFieldChoice::SetValue(const string&name) { mpButton->SetLabel(wxString::FromAscii(name.c_str())); } void WXFieldChoice::ValidateUserInput(){} //////////////////////////////////////////////////////////////////////// // // WXCrystObj // //////////////////////////////////////////////////////////////////////// const long ID_WXOBJ_ENABLE=WXCRYST_ID(); //These are used in ObjCryst/RefinableObj.cpp const long ID_WXOBJ_DISABLE=WXCRYST_ID(); BEGIN_EVENT_TABLE(WXCrystObj,wxWindow) EVT_BUTTON(ID_WXOBJ_COLLAPSE,WXCrystObj::OnToggleCollapse) EVT_UPDATE_UI(ID_WXOBJ_ENABLE,WXCrystObj::OnEnable) EVT_UPDATE_UI(ID_WXOBJ_DISABLE,WXCrystObj::OnEnable) END_EVENT_TABLE() WXCrystObj::WXCrystObj(wxWindow* parent,int orient,bool showName): WXCrystObjBasic(parent),mIsExpanded(true) { VFN_DEBUG_ENTRY("WXCrystObj::WXCrystObj()",6) mpTopSizer= new wxBoxSizer(orient); this->SetSizer(mpTopSizer); mpCollapseButton=new wxButton(this,ID_WXOBJ_COLLAPSE,_T("-"), wxDefaultPosition,wxSize(14,14)); mpTopSizer->Add(mpCollapseButton,0, wxALIGN_TOP);//wxRIGHT | wxTOP | wxALIGN_TOP,4 //mpCollapseButton->PushEventHandler(this); mpSizer=new wxBoxSizer(wxVERTICAL); mpTopSizer->Add(mpSizer,0, wxALIGN_TOP); if(showName) { mpWXTitle = new WXFieldName(this,"name:",this,ID_WXOBJ_NAME,100); mpSizer->Add(mpWXTitle,0,wxALIGN_LEFT); }else mpWXTitle=0; //this->Layout(); VFN_DEBUG_EXIT("WXCrystObj::WXCrystObj():End",6) } WXCrystObj::~WXCrystObj() { //if(0!=mpWXTitle) //{ // delete mpWXTitle; //} //delete mpCollapseButton; //sizers are automatically deleted } void WXCrystObj::OnToggleCollapse(wxCommandEvent & WXUNUSED(event)) { #if 0 VFN_DEBUG_MESSAGE("WXCrystObj::OnToggleCollapse()",6) mIsExpanded = !mIsExpanded; mList.Show(mIsExpanded); if(true==mIsExpanded) mpCollapseButton->SetLabel("-"); else mpCollapseButton->SetLabel("+"); this->Layout(); VFN_DEBUG_MESSAGE("WXCrystObj::OnToggleCollapse():End",6) #endif } void WXCrystObj::CrystUpdate(const bool uui,const bool lock) { VFN_DEBUG_ENTRY("WXCrystObj::CrystUpdate("<Enable(true); else this->Enable(false); event.Skip(); } bool WXCrystObj::Enable(bool enable) { mList.Enable(enable); return this->wxWindow::Enable(enable); } void WXCrystObj::AddChild(WXCrystObjBasic *pChild, bool doBottomLayout) { VFN_DEBUG_ENTRY("WXCrystObj::AddChild(..)"<GetSize().GetWidth()<<","<GetSize().GetHeight(),5); if(mpSizer!=0) { mpSizer->Add(pChild); } if(doBottomLayout) wxTheApp->GetTopWindow()->SendSizeEvent(); VFN_DEBUG_EXIT("WXCrystObj::AddChild(..)"<GetSize().GetWidth()<<","<GetSize().GetHeight(),5); } //////////////////////////////////////////////////////////////////////// // // WXCrystMenuBar // //////////////////////////////////////////////////////////////////////// WXCRYST_ID ID_CRYST_MENU1; WXCRYST_ID ID_CRYST_MENU2; WXCRYST_ID ID_CRYST_MENU3; WXCRYST_ID ID_CRYST_MENU4; WXCRYST_ID ID_CRYST_MENU5; WXCRYST_ID ID_CRYST_MENU6; WXCRYST_ID ID_CRYST_MENU7; WXCRYST_ID ID_CRYST_MENU8; WXCRYST_ID ID_CRYST_MENU9; WXCRYST_ID ID_CRYST_MENU10; WXCRYST_ID ID_CRYST_MENU11; WXCRYST_ID ID_CRYST_MENU12; WXCRYST_ID ID_CRYST_MENU13; WXCRYST_ID ID_CRYST_MENU14; WXCRYST_ID ID_CRYST_MENU15; WXCRYST_ID ID_CRYST_MENU16; BEGIN_EVENT_TABLE(WXCrystMenuBar,wxWindow) EVT_BUTTON(ID_CRYST_MENU1 ,WXCrystMenuBar::OnPopupMenu) EVT_BUTTON(ID_CRYST_MENU2 ,WXCrystMenuBar::OnPopupMenu) EVT_BUTTON(ID_CRYST_MENU3 ,WXCrystMenuBar::OnPopupMenu) EVT_BUTTON(ID_CRYST_MENU4 ,WXCrystMenuBar::OnPopupMenu) EVT_BUTTON(ID_CRYST_MENU5 ,WXCrystMenuBar::OnPopupMenu) EVT_BUTTON(ID_CRYST_MENU6 ,WXCrystMenuBar::OnPopupMenu) EVT_BUTTON(ID_CRYST_MENU7 ,WXCrystMenuBar::OnPopupMenu) EVT_BUTTON(ID_CRYST_MENU8 ,WXCrystMenuBar::OnPopupMenu) EVT_BUTTON(ID_CRYST_MENU9 ,WXCrystMenuBar::OnPopupMenu) END_EVENT_TABLE() WXCrystMenuBar::WXCrystMenuBar(wxWindow *parent, WXCrystObj* owner): WXCrystObjBasic(parent) { VFN_DEBUG_MESSAGE("WXCrystMenuBar::WXCrystMenuBar():",6) mpSizer=new wxBoxSizer(wxHORIZONTAL); this->SetSizer(mpSizer); } void WXCrystMenuBar::AddMenu(const string &name,const int menuId, const string& help) { VFN_DEBUG_MESSAGE("WXCrystMenuBar::AddMenu()",6) const long id=ID_CRYST_MENU1+mvpMenu.size(); mvpMenu[menuId]=make_pair(new wxMenu(wxString::FromAscii(name.c_str())), new wxButton(this,id,wxString::FromAscii(name.c_str()))); VFN_DEBUG_MESSAGE("WXCrystMenuBar::AddMenu():2",6) mvpMenu[menuId].second->Layout(); mpSizer->Add(mvpMenu[menuId].second,0,wxALIGN_CENTER); //wxTheApp->GetTopWindow()->SendSizeEvent(); VFN_DEBUG_MESSAGE("WXCrystMenuBar::AddMenu():End",6) } wxMenu& WXCrystMenuBar::GetMenu(const int menuId) { //:TODO: Check we found the correct menu return *(mvpMenu[menuId].first); } void WXCrystMenuBar::AddMenuItem(const int menuId, int id, const string& item, const string& help,const bool checkable) { VFN_DEBUG_MESSAGE("WXCrystMenuBar::AddMenuItem():",6) //:TODO: Check we found the correct menu this->GetMenu(menuId).Append(id,wxString::FromAscii(item.c_str()),wxString::FromAscii(help.c_str()),checkable); } void WXCrystMenuBar::AddMenuItem(const int menuId,int id, const wxString& item, wxMenu *subMenu, const wxString& helpString) { VFN_DEBUG_MESSAGE("WXCrystMenuBar::AddMenuItem():",6) //:TODO: Check we found the correct menu this->GetMenu(menuId).Append(id,item,subMenu,helpString); } void WXCrystMenuBar::CrystUpdate(const bool updateUI,const bool mutexlock) { } void WXCrystMenuBar::UpdateUI(const bool mutexlock) { } void WXCrystMenuBar::OnPopupMenu(wxCommandEvent & event) { VFN_DEBUG_MESSAGE("WXCrystMenuBar::OnPopupMenu():",6) // The ID of the button is not the same as the ID of the menu, // so look it up. (to have the same ID we'd need to delegate event handling, // which would be a pain. std::map >::iterator pos; const int i=event.GetId(); for(pos=mvpMenu.begin();pos!=mvpMenu.end();++pos) if(i==pos->second.second->GetId()) break; if(pos!=mvpMenu.end()) this->PopupMenu(pos->second.first,pos->second.second->GetPosition()); } void WXCrystMenuBar::SetToolTip(const wxString& tip,long menuId){mvpMenu[menuId].second->SetToolTip(tip);} }//namespace objcryst-2022.1/ObjCryst/wxCryst/wxCryst.h000066400000000000000000000510561430515525000205240ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * header file for the general wxCryst functions. * * */ #ifndef _VFN_WX_CRYST_H_ #define _VFN_WX_CRYST_H_ #include #include #include #include // wx headers, with or without precompilation #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "ObjCryst/CrystVector/CrystVector.h" namespace ObjCryst { /** Used to remember window positions * * */ extern std::map > gvWindowPosition; #if 1 /** Provides the same functionnality as wxMultiChoiceDialog, but always using * a wxListBox, which is much easier when selecting a large number of successive * choices (using shift-click). */ class wxMultiChoiceDialog_ListBox:public wxDialog { public: wxMultiChoiceDialog_ListBox(wxWindow* parent, const wxString& message, const wxString& caption, int n, const wxString* choices); wxArrayInt GetSelections() const; private: wxListBox mListBox; }; #endif //////////////////////////////////////////////////////////////////////// // // Unique ID for menus incrementer // //////////////////////////////////////////////////////////////////////// /** Class to automatically assign a unique wxID to each window * */ class WXCRYST_ID { public: WXCRYST_ID(); operator long(); private: long mIndex; static long mCounter; }; extern const long ID_WXOBJ_ENABLE; //These are used in ObjCryst/RefinableObj.cpp extern const long ID_WXOBJ_DISABLE;// and defined in wxCryst/wxCryst.cpp #undef VFN_CRYST_MUTEX #ifdef VFN_CRYST_MUTEX /** Derived Mutex class, to keep track of Mutexes * */ class CrystMutex:public wxMutex { public: CrystMutex(); ~CrystMutex(); wxMutexError Lock(); wxMutexError Unlock(); private: unsigned long mNbLock; }; #else #define CrystMutex wxMutex #endif #ifndef DOXYGEN_SKIP_THIS // constants that are shared between several classes must // be defined here. Constants declared as "extern..." are // not correctly used in EVT_MENU() macros etc.. enum { ID_REFOBJ_MENU_OBJ=wxID_HIGHEST+1, ID_REFOBJ_MENU_OBJ_SAVE, ID_REFOBJ_MENU_OBJ_LOAD, ID_REFOBJ_MENU_PAR, ID_REFOBJ_MENU_PAR_FIXALL, ID_REFOBJ_MENU_PAR_UNFIXALL, ID_REFOBJ_MENU_PAR_RANDOMIZE, ID_CRYST_UPDATEUI, ID_WXOBJ_COLLAPSE, ID_WXOBJ_NAME, ID_WXFIELD }; #endif // Forward declaration class WXCrystObjBasicList; /// Abstract base class for all objects in wxCryst class WXCrystObjBasic: public wxWindow { public: /// Constructor WXCrystObjBasic(wxWindow* parent); /// Destructor virtual ~WXCrystObjBasic(); /** Get new values to be displayed from the underlying object, * and raise flag if an UI update is necessary. * The actual GUI update is not made here. UpdateUI() should be * called separately, from the main thread. * * \param updateUI: if true, this will call UpdateUI, either directly *(if in the main thread), or by sending a message. * \param mutexlock: if true, a Mutex will be used to lock the data shared * between main and background thread. The idea is to only use a few Mutexes * to lock data from the top objects (wxRefinableObj,...), when * calling CrystUpdate() and UpdateUI(). As sub-objects (WXField,...) * are only updated from within a top object, the mutex lock in the top object * will also lock the data in the sub-objects. */ virtual void CrystUpdate(const bool updateUI=false,const bool mutexlock=false)=0; /** Update the User Interface, if necessary * * \param mutexlock: if true, a Mutex will be used to lock the data shared * between main and background thread. * * The idea is to only use a few Mutexes * to lock data from the top objects (wxRefinableObj,...), when * calling CrystUpdate() and UpdateUI(). As sub-objects (WXField,...) * are only updated from within a top object, the mutex lock in the top object * will also lock the data in the sub-objects. */ virtual void UpdateUI(const bool mutexlock=false)=0; /** Redo the Layout for the object and ask parent to take it into account * * \deprecated: use instead wxWindow::Layout() + wxTheApp->GetTopWindow()->SendSizeEvent(); */ wxDEPRECATED(virtual void BottomLayout(WXCrystObjBasic *pChild)); /// Notify that a new children has been added, also adding it to the /// correct sizer (which can be the top sizer or not). /// /// \param doBottomLayout ask for a new Layout of the window and of its parents. virtual void AddChild(WXCrystObjBasic *pChild, bool doBottomLayout=true); /// \internal Tell the object it has been added to a list void AddedToList(WXCrystObjBasicList* list); /// \internal Tell the object it has been removed from a list void RemovedFromList(WXCrystObjBasicList* list); virtual bool Layout(); /// Set tooltip for this window. The WXCrystObjBasicList::SetToolTip() will just /// call wxWindow::SetToolTip(), but is virtual and will correctly call specialized /// derived function. This is needed to avoid settin a tooltip on widgets /// not receiving motion events (e.g. static text under windows). virtual void SetToolTip(const wxString& tip); protected: /// Parent, if a WXCrystObjBasic itself WXCrystObjBasic *mWXCrystParent; /// Is the the window currently shown ? bool mIsShown; /// Do we need to update the display ? bool mNeedUpdateUI; /// Mutex used to lock data when preparing to update the UI in non-main thread CrystMutex mMutex; /// WXCrystObjBasicList which are aware of this object, /// and which should be told on destruction. std::set mvpList; }; /// A List of WXCrystObjBasic. class WXCrystObjBasicList { public: /// Constructor WXCrystObjBasicList(); /// Destructor ~WXCrystObjBasicList(); /// Number of objects. unsigned int GetNb()const; /// Add an object to the list. The object is just referenced, /// not copied. void Add(WXCrystObjBasic *); /// remove an object from the list void Remove(WXCrystObjBasic *); /// Show or hide all of the windows bool Show(bool); /** Forces all objects in the list to update. See WXCrystObjBasic::CrystUpdate() * * see WXCrystObjBasic::CrystUpdate() on the use of updateUI and mutexlock * * Normally WXCrystObjBasicList::CrystUpdate() should never be used with mutexlock=true, * as the mutex locking should be done from the calling object. */ void CrystUpdate(const bool updateUI=false,const bool mutexlock=false); /** Forces all objects in the list to update. See WXCrystObjBasic::CrystUpdate() * * see WXCrystObjBasic::UpdateUI() on the use of updateUI and mutexlock. * * Normally WXCrystObjBasicList::UpdateUI() should never be used with mutexlock=true, * as the mutex locking should be done from the calling object. */ void UpdateUI(const bool mutexlock=false); void Enable(bool enable); private: /// List of pointers to the objects. std::set mvpWXCrystObj; }; class WXFieldName; /** Base class for all displayed ObjCryst objects (with a title, * and a sizer to stack objects). * * A button (which should be used to collapse the object) is used * to create an indentation for the sub-objects. * * \todo Allow the objects to be collabsable. The difficulty is that * even if the object is not shown, it is not removed by the Sizer as long * as it is not deleted... Needs some testing ! Otherwise it would also * be possible to delete and re-create sub-objects when collapsing, but * that would be more difficult. */ class WXCrystObj: public WXCrystObjBasic { public: /// Constructor, with a WXCrystObj(wxWindow* parent,int orient=wxHORIZONTAL,bool showName=true); virtual ~WXCrystObj(); /// Only display the title, and collapse everything else. /// \bug : the windows do collapse, but the size of the window is not /// changed, so it is pretty useless so far... void OnToggleCollapse(wxCommandEvent & WXUNUSED(event)); /// When a WXFieldName has been changed by the user, it is handled /// here. This returns true if the value has been handled (for inheritance /// purposes). virtual bool OnChangeName(const int id)=0; virtual void CrystUpdate(const bool updateUI=false,const bool mutexlock=false); virtual void UpdateUI(const bool mutexlock=false); virtual void OnEnable(wxUpdateUIEvent &event); virtual bool Enable(bool enable); virtual void AddChild(WXCrystObjBasic *pChild, bool doBottomLayout=true); protected: /// Top sizer including the title and WXCrystObj::mpSizer wxBoxSizer *mpTopSizer; /// Sizer including all sub-objects wxBoxSizer *mpSizer; /// The title WXFieldName *mpWXTitle; /// To be used for collapsing the sub-objects. bool mIsExpanded; ///All windows but the title and collapse button are in this list WXCrystObjBasicList mList; /// The collapse button wxButton * mpCollapseButton; DECLARE_EVENT_TABLE() }; /** This is the abstract base class for all fields, wether they contain * a floating-point parameter, or a string,... All WXField have a title * and an entry field. * * Note that WXField::CrystUpdate() and WXField::UpdateUI() should be done * from the parent object. Notably using WXField::CrystUpdate(updateui=true) * will not trigger an update of the UI. */ class WXField: public WXCrystObjBasic { public: /** Constructor, specifying the label of the field. * */ WXField(wxWindow *parent,const string& label,const int field_id); /// Change the field's label. void SetLabel(const string&); /// After a user entry, this allows to go back to the last value, if for some reason /// the entry was rejected (because the object is currently busy, ...) virtual void Revert()=0; /// Change the colour of the field's title. Can be used (with parcimony) /// to clarify the interface. virtual bool SetForegroundColour(const wxColour& colour); /// This function shall be called when a new value has been entered. virtual void ValidateUserInput()=0; /// Change the size of the field (excluding the title) virtual void SetSize(int width, int height); protected: /// The horizontal sizer in which the title, button, fields, are put. wxBoxSizer *mpSizer; /// The label wxStaticText *mpLabel; /// The Id of this field const int mId; }; /// This function validates all user input (in a WXField) /// not yet taken into account, if needs be. This should be called by \b ALL /// functions using data stored in fields (basically all functions !) void WXCrystValidateAllUserInput(); /** A field which directly links to a string. * * */ class WXFieldString:public WXField { public: WXFieldString(wxWindow *parent,string& st,const int field_id, const int hsize=50, bool isEditable=true); /// When a new value is entered (must type it and then hit the 'enter' key). /// The Field reads the new value, then /// forwards the event to its owner, who will take care of anything /// that must be done. void OnEnter(wxCommandEvent & event); /// Records when text is entered (either from self-updating or user input) void OnText(wxCommandEvent & WXUNUSED(event)); /// This actually posts an UpdateUI event, so that it is safe to call it /// from a non-graphic thread. void SetValue(const string&); /// Get the current name. const string GetValue() const; virtual void CrystUpdate(const bool updateUI=false,const bool mutexlock=false); virtual void UpdateUI(const bool mutexlock=false); void Revert(); virtual void ValidateUserInput(); virtual void SetSize(int width, int height); /// Set tooltip for this window. It will be activated when going over the entry field. virtual void SetToolTip(const wxString& tip); protected: /// The WXCrystObj whose name is shown here string* mpString; /// Last name displayed. string mValue; /// The text window wxTextCtrl *mpField; /// Last name displayed, before the value was changed by the user. Not used yet, /// could be useful for undo. string mValueOld; /// Set to true if the Field is being updated, so that no /// 'EVT_TEXT' is understood as user input. bool mIsSelfUpdating; DECLARE_EVENT_TABLE() }; /** A field with the name of a WXCrystObj. Updating must be done by the WXCrystObj owner. * For a simple string field linked directly to a string, use ObjCryst::WXFieldString * */ class WXFieldName:public WXField { public: WXFieldName(wxWindow *parent,const string& label, WXCrystObj* owner,const int field_id, const int hsize=50, bool isEditable=true); /// When a new value is entered (must type it and then hit the 'enter' key). /// The Field reads the new value, then /// forwards the event to its owner, who will take care of anything /// that must be done. void OnEnter(wxCommandEvent & event); /// Records when text is entered (either from self-updating or user input) void OnText(wxCommandEvent & WXUNUSED(event)); /// This actually posts an UpdateUI event, so that it is safe to call it /// from a non-graphic thread. void SetValue(const string&); /// Get the current name. const string GetValue() const; /// This does nothing. Updates should be done by the owner in the particular /// case of names. virtual void CrystUpdate(const bool updateUI=false,const bool mutexlock=false); virtual void UpdateUI(const bool mutexlock=false); void Revert(); virtual void ValidateUserInput(); virtual void SetSize(int width, int height); /// Set tooltip for this window. It will be activated when going over the entry field. virtual void SetToolTip(const wxString& tip); protected: /// The WXCrystObj whose name is shown here WXCrystObj* mpWXObj; /// Last name displayed. string mValue; /// The text window wxTextCtrl *mpField; /// Last name displayed, before the value was changed by the user. Not used yet, /// could be useful for undo. string mValueOld; /// Set to true if the Field is being updated, so that no /// 'EVT_TEXT' is understood as user input. bool mIsSelfUpdating; DECLARE_EVENT_TABLE() }; /// A field for a parameter. This is a an abstract bas class, which can /// handle events (the real classes to use is the templated WXFieldPar class). /// If the parameter is a RefinablePar, use WXFieldRefPar. class WXFieldParBase:public WXField { public: /// Constructor WXFieldParBase(wxWindow *parent,const string& label, const int field_id, const int hsize=65); /// When a new value is entered (must type it and then hit the 'enter' key). /// The Field reads the new value, /// and directly changes the RefinablePar value (contrary to what happens /// for WXFieldName)by using RefinablePar::SetHumanValue(). void OnEnter(wxCommandEvent & WXUNUSED(event)); /// Records when text is entered (either from self-updating or user input) void OnText(wxCommandEvent & WXUNUSED(event)); /// This gets a new value from the parameter. virtual void CrystUpdate(const bool updateUI=false,const bool mutexlock=false)=0; virtual void Revert()=0; virtual void ValidateUserInput(); /// Set tooltip for this window. It will be activated when going over the entry field. virtual void SetToolTip(const wxString& tip); /// Set Format void SetFormat(const wxString &format); protected: /// Reads the new value when the Enter key is hit virtual void ReadNewValue()=0; /// The field in which the value is written. wxTextCtrl *mpField; /// Set to true if the Field is being updated, so that no /// 'EVT_TEXT' is understood as user input. bool mIsSelfUpdating; /// Format to be used, default = _T("%8f") wxString mFormat; DECLARE_EVENT_TABLE() }; /// A field for a parameter. Template version. /// If the parameter is a RefinablePar, use WXFieldRefPar instead. templateclass WXFieldPar:public WXFieldParBase { public: /// Constructor WXFieldPar(wxWindow *parent,const string& label, const int field_id, T *par,const int hsize=65); /// This gets a new value from the parameter. virtual void CrystUpdate(const bool updateUI=false,const bool mutexlock=false); virtual void UpdateUI(const bool mutexlock=false); virtual void Revert(); /// Set Coefficient between the value used by ObjCryst++ and the one /// to be displayed to the user. Typically, 180/pi void SetHumanValueScale(const T s); protected: /// Reads the new value when the Enter key is hit virtual void ReadNewValue(); /// A pointer to the value displayed T* mpValue; /// The value displayed T mValue; /// Last value T mValueOld; /// Coefficient between the value used by ObjCryst++ and the one /// to be displayed to the user. Typically, 180/pi T mHumanScale; }; /// Class to pick one choice... Choice change/update is handled by the WXCrystObj owner, who /// should grab the incoming event. /// Useful, for example, to change the scattering power associated to an atom. class WXFieldChoice:public WXField { public: /// Constructor WXFieldChoice(wxWindow *parent,const int field_id, const string &name,const int hsize=80); /// Does nothing virtual void CrystUpdate(const bool updateUI=false,const bool mutexlock=false); /// Does nothing virtual void UpdateUI(const bool mutexlock=false); void Revert(); /// Used by the owner to change the name of the choice void SetValue(const string&); /// Unnecessary here. Any change is immediately taken into account. virtual void ValidateUserInput(); protected: /// The button to be clicked to change the value. wxButton *mpButton; }; /// Our own local menu bar, using buttons and Popup menus class WXCrystMenuBar: public WXCrystObjBasic { public: /// Ctor WXCrystMenuBar(wxWindow *parent, WXCrystObj* owner); /// Add a menu void AddMenu(const string &name,const int menuId, const string& help=""); /// Get access to a menu wxMenu& GetMenu(const int menuId); /// Add an entry to a menu void AddMenuItem(const int menuId, int id, const string& item, const string& help="", const bool checkable= false); /// Add a sub-menu to a menu void AddMenuItem(const int menuId,int id, const wxString& item, wxMenu *subMenu, const wxString& helpString = _T("")); virtual void CrystUpdate(const bool updateUI=false,const bool mutexlock=false); virtual void UpdateUI(const bool mutexlock=false); /// Event handler to popu the menu when the button is clicked. void OnPopupMenu(wxCommandEvent & event); /// Set tooltip for each menu. virtual void SetToolTip(const wxString& tip,long menu=0); protected: /// The sizer of the menu wxBoxSizer* mpSizer; /// List of menus, first is the menu Id and second is a pair of /// std::map > mvpMenu; DECLARE_EVENT_TABLE() }; } //namespace #endif //_VFN_WX_CRYST_H_ objcryst-2022.1/ObjCryst/wxCryst/wxCrystal.cpp000066400000000000000000006161721430515525000214020ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2009 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include //for stringstream #include #include // wx headers, with or without precompilation #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "wx/notebook.h" #include "wx/minifram.h" #include "ObjCryst/wxCryst/wxCrystal.h" #include "wx/colordlg.h" #include "wx/progdlg.h" #include "wx/busyinfo.h" #include "wx/config.h" #include "ObjCryst/Quirks/Chronometer.h" #include "ObjCryst/ObjCryst/Atom.h" #include "ObjCryst/ObjCryst/ZScatterer.h" #include "ObjCryst/ObjCryst/Molecule.h" #include "ObjCryst/ObjCryst/PowderPattern.h" #include "ObjCryst/ObjCryst/ScatteringPowerSphere.h" #include "ObjCryst/ObjCryst/Polyhedron.h" #ifdef OBJCRYST_GL #ifdef __WXGTK__ #include "GL/glu.h" #endif #ifdef __WXMAC__ // For the wxMac version of wxWindows, i.e. with the "Aqua" look #include #include "AGL/agl.h" #endif #ifdef __LINUX__ #include "GL/glx.h" #endif #ifdef __WIN32__ #include "gl/glu.h" #endif #ifdef HAVE_GLUT #ifdef __WXMAC__ // For the wxMac version of wxWindows, i.e. with the "Aqua" look #include #else #include "GL/glut.h" #endif #endif #ifdef HAVE_FFTW #include "fftw3.h" #endif #endif extern "C" { #include "ObjCryst/wxCryst/trackball.h" } //Fixes for Cygwin; where do those stupid macros come from ? Somewhere in wxMSW headers #ifdef max #undef max #endif #ifdef min #undef min #endif #ifdef DrawText #undef DrawText #endif //#include "ObjCryst/ObjCryst/Map.cpp" namespace ObjCryst { #ifndef HAVE_GLUT // This must be changed for each GL world to the correct first display list, // i.e. in SetCurrent(). static int sFontDisplayListBase=0; #endif GLvoid crystGLPrint(const string &s) { glDisable (GL_BLEND); #ifdef HAVE_GLUT for(unsigned int l=0;lNotifyDeleteListWin(this); } //////////////////////////////////////////////////////////////////////// // // WXCrystal Grid objects // //////////////////////////////////////////////////////////////////////// WXCrystal::RowScattPow::RowScattPow(): mName("H"), mBiso(1.0),mFormalCharge(0.0),mR(1.0),mG(1.0),mB(1.0),mMaximumLikelihoodError(0.0),mNbGhostAtoms(0.0), mNeedUpdateUI(true),mIdx(-1) {} //////////////////////////////////////////////////////////////////////// // // Convert a list of atoms to one molecule // //////////////////////////////////////////////////////////////////////// Molecule* Atoms2Molecule(list &vAtom) { VFN_DEBUG_ENTRY("Atoms2Molecule()",6) Molecule *mol=new Molecule((*vAtom.begin())->GetCrystal(),"Molecule"); const unsigned long nb=vAtom.size(); REAL x0=0,y0=0,z0=0; unsigned int i=0; for(list::iterator pos=vAtom.begin();pos!=vAtom.end();++pos) { REAL x=(*pos)->GetX(); REAL y=(*pos)->GetY(); REAL z=(*pos)->GetZ(); (*pos)->GetCrystal().FractionalToOrthonormalCoords(x,y,z); x0+=x; y0+=y; z0+=z; mol->AddAtom(x,y,z,&((*pos)->GetScatteringPower()),(*pos)->GetName()); mol->GetAtom(i++).SetOccupancy((*pos)->GetOccupancy()); } CrystVector_REAL x(nb),y(nb),z(nb),radius(nb); vector > scattpow(nb); for(unsigned int i=0;iGetAtom(i).GetX(); y(i)=mol->GetAtom(i).GetY(); z(i)=mol->GetAtom(i).GetZ(); if(mol->GetAtom(i).IsDummy()) { radius(i)=-1; scattpow[i].first=0; } else { radius(i)=mol->GetAtom(i).GetScatteringPower().GetRadius(); scattpow[i].first=dynamic_cast (&(mol->GetAtom(i).GetScatteringPower())); scattpow[i].second=scattpow[i].first->GetAtomicNumber(); } } for(unsigned int i=0;i d="<AddBond(mol->GetAtom(i),mol->GetAtom(j),dist,.01,.02,false); } } } x += x1; y += y1; z += z1; } mol->BuildConnectivityTable(); for(map >::const_iterator pos=mol->GetConnectivityTable().begin(); pos!=mol->GetConnectivityTable().end();++pos) { for(set::const_iterator pos1=pos->second.begin(); pos1!=pos->second.end();++pos1) { for(set::const_iterator pos2=pos1; pos2!=pos->second.end();++pos2) { if(pos2==pos1) continue; if(mol->FindBondAngle(**pos1,*(pos->first),**pos2)== mol->GetBondAngleList().end()) mol->AddBondAngle(**pos1,*(pos->first),**pos2, GetBondAngle(**pos1,*(pos->first),**pos2),0.01,0.02,false); } } } x0 /= nb; y0 /= nb; z0 /= nb; mol->GetCrystal().OrthonormalToFractionalCoords(x0,y0,z0); mol->SetX(x0); mol->SetY(y0); mol->SetZ(z0); mol->UpdateDisplay(); VFN_DEBUG_EXIT("ZScatterer2Molecule()",6) return mol; } //////////////////////////////////////////////////////////////////////// // // WXCrystal // //////////////////////////////////////////////////////////////////////// static const long ID_CRYSTAL_MENU_SAVECIF =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_SAVETEXT =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_DISPLAY =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_DISPLAY_3DVIEW =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_SCATT =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_PAR_SETRELATIVEXYZLIMITS =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_PAR_TEST_RANDOM_MOVES =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_SCATT_REMOVESCATTPOW =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_SCATT_ADDSCATTPOWATOM =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_SCATT_ADDSCATTPOWSPHERE =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_SCATT_ADDATOM =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_SCATT_IMPORTATOMLIST =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_SCATT_ADDZSCATTERER =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_SCATT_ADDMOLECULE =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_SCATT_ATOMS2MOLECULE =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_SCATT_IMPORTFENSKEHALLZMATRIX =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_SCATT_IMPORTNAMEDZMATRIX =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_SCATT_ADDTETRAHEDRON =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_SCATT_ADDOCTAHEDRON =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_SCATT_ADDTRIANGLE =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_SCATT_ADDSQUAREPLANE =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_SCATT_ADDCUBE =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_SCATT_ADDANTIPRISMTETRAGONAL =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_SCATT_ADDPRISMTRIGONAL =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_SCATT_ADDICOSAHEDRON =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_SCATT_REMOVESCATTERER =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_SCATT_DUPLICSCATTERER =WXCRYST_ID(); static const long ID_CRYSTAL_SPACEGROUP =WXCRYST_ID(); static const long ID_GLCRYSTAL_MENU_UPDATE =WXCRYST_ID(); static const long ID_GLCRYSTAL_WINDOW =WXCRYST_ID(); static const long ID_CRYSTAL_WIN_SCATTPOW =WXCRYST_ID(); static const long ID_CRYSTAL_WIN_ANTIBUMP =WXCRYST_ID(); static const long ID_CRYSTAL_WIN_BONDVALENCE =WXCRYST_ID(); static const long ID_CRYSTAL_MENU_SHOW_SCATTPOW_WIN =WXCRYST_ID(); //static const long ID_CRYSTAL_MENU_SHOW_PDF =WXCRYST_ID(); static const long ID_GLCRYSTAL_FOURIER_ADD= WXCRYST_ID(); static const long ID_GLCRYSTAL_FOURIER_REMOVE= WXCRYST_ID(); static const long ID_GLCRYSTAL_FOURIER_UPDATE= WXCRYST_ID(); static const long ID_GLCRYSTAL_FOURIER_WIREFRAME= WXCRYST_ID(); static const long ID_GLCRYSTAL_FOURIER_SHOW= WXCRYST_ID(); static const long ID_GLCRYSTAL_FOURIER_SHARPEN= WXCRYST_ID(); static const long ID_GLCRYSTAL_FOURIER_LISTMAP= WXCRYST_ID(); static const long ID_GLCRYSTAL_FOURIER_LISTGLMAP= WXCRYST_ID(); static const long ID_GLCRYSTAL_FOURIER_CONTOUR= WXCRYST_ID(); static const long ID_GLCRYSTAL_FOURIER_NEWCONTOUR= WXCRYST_ID(); static const long ID_GLCRYSTAL_FOURIER_COLOURPICKER= WXCRYST_ID(); BEGIN_EVENT_TABLE(WXCrystal,wxWindow) EVT_BUTTON(ID_WXOBJ_COLLAPSE, WXCrystObj::OnToggleCollapse) EVT_MENU(ID_REFOBJ_MENU_OBJ_SAVE, WXRefinableObj::OnMenuSave) EVT_MENU(ID_REFOBJ_MENU_OBJ_LOAD, WXRefinableObj::OnMenuLoad) EVT_MENU(ID_CRYSTAL_MENU_SAVECIF, WXCrystal::OnMenuSaveCIF) EVT_MENU(ID_CRYSTAL_MENU_SAVETEXT, WXCrystal::OnMenuSaveText) EVT_MENU(ID_REFOBJ_MENU_PAR_FIXALL, WXRefinableObj::OnMenuFixAllPar) EVT_MENU(ID_REFOBJ_MENU_PAR_UNFIXALL, WXRefinableObj::OnMenuUnFixAllPar) EVT_MENU(ID_REFOBJ_MENU_PAR_RANDOMIZE, WXRefinableObj::OnMenuParRandomize) EVT_MENU(ID_CRYSTAL_MENU_PAR_SETRELATIVEXYZLIMITS, WXCrystal::OnMenuSetRelativeXYZLimits) EVT_MENU(ID_CRYSTAL_MENU_PAR_TEST_RANDOM_MOVES, WXCrystal::OnMenuTestRandomMoves) #ifdef OBJCRYST_GL EVT_MENU(ID_CRYSTAL_MENU_DISPLAY_3DVIEW, WXCrystal::OnMenuCrystalGL) #endif EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDSCATTPOWATOM, WXCrystal::OnMenuAddScattPowAtom) EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDSCATTPOWSPHERE, WXCrystal::OnMenuAddScattPowSphere) EVT_MENU(ID_CRYSTAL_MENU_SCATT_REMOVESCATTPOW, WXCrystal::OnMenuRemoveScattPow) EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDATOM, WXCrystal::OnMenuAddScatterer) EVT_MENU(ID_CRYSTAL_MENU_SCATT_IMPORTATOMLIST, WXCrystal::OnMenuAddScatterer) EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDZSCATTERER, WXCrystal::OnMenuAddScatterer) EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDMOLECULE, WXCrystal::OnMenuAddScatterer) EVT_MENU(ID_CRYSTAL_MENU_SCATT_ATOMS2MOLECULE, WXCrystal::OnMenuAtoms2Molecule) EVT_MENU(ID_CRYSTAL_MENU_SCATT_IMPORTFENSKEHALLZMATRIX,WXCrystal::OnMenuImportMoleculeFromFenskeHallZMatrix) EVT_MENU(ID_CRYSTAL_MENU_SCATT_IMPORTNAMEDZMATRIX, WXCrystal::OnMenuImportMoleculeFromFenskeHallZMatrix) EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDTETRAHEDRON, WXCrystal::OnMenuAddScatterer) EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDOCTAHEDRON, WXCrystal::OnMenuAddScatterer) EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDTRIANGLE, WXCrystal::OnMenuAddScatterer) EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDSQUAREPLANE, WXCrystal::OnMenuAddScatterer) EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDCUBE, WXCrystal::OnMenuAddScatterer) EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDANTIPRISMTETRAGONAL,WXCrystal::OnMenuAddScatterer) EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDPRISMTRIGONAL, WXCrystal::OnMenuAddScatterer) EVT_MENU(ID_CRYSTAL_MENU_SCATT_ADDICOSAHEDRON, WXCrystal::OnMenuAddScatterer) EVT_MENU(ID_CRYSTAL_MENU_SCATT_REMOVESCATTERER, WXCrystal::OnMenuRemoveScatterer) EVT_MENU(ID_CRYSTAL_MENU_SCATT_DUPLICSCATTERER, WXCrystal::OnMenuDuplicateScatterer) EVT_MENU(ID_CRYSTAL_MENU_SHOW_SCATTPOW_WIN, WXCrystal::OnMenuShowScattPowWindow) EVT_UPDATE_UI(ID_CRYST_UPDATEUI, WXRefinableObj::OnUpdateUI) EVT_GRID_CMD_CELL_CHANGED(ID_CRYSTAL_WIN_SCATTPOW, WXCrystal::OnEditGridScattPow) EVT_GRID_CMD_CELL_CHANGED(ID_CRYSTAL_WIN_ANTIBUMP, WXCrystal::OnEditGridScattPowAntiBump) EVT_GRID_CMD_CELL_CHANGED(ID_CRYSTAL_WIN_BONDVALENCE,WXCrystal::OnEditGridScattPowBondValence) // EVT_MENU(ID_CRYSTAL_MENU_SHOW_PDF, WXCrystal::OnMenuPDF) END_EVENT_TABLE() WXCrystal::WXCrystal(wxWindow* parent, Crystal *obj): WXRefinableObj(parent,(RefinableObj*)obj),mpCrystal(obj), mpScattPowWin(0),mpAntiBumpWin(0),mpBondValenceWin(0), mIsSelfUpdating(false) #ifdef OBJCRYST_GL ,mCrystalGLDisplayList(0),mCrystalGLNameDisplayList(0), mpCrystalGL(0) #endif ,mpConditionGLUpdate(0) //,mpPDF(0) { VFN_DEBUG_ENTRY("WXCrystal::WXCrystal()",6) //this->SetBackgroundColour("Red"); //mpWXTitle->SetBackgroundColour(wxColour(255,200,200)); mpWXTitle->SetForegroundColour(wxColour(255,0,0)); // Menu mpMenuBar->AddMenu("File",ID_REFOBJ_MENU_OBJ); //mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_REFOBJ_MENU_OBJ_LOAD,"Load"); //mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_REFOBJ_MENU_OBJ_SAVE,"Save"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_CRYSTAL_MENU_SAVETEXT,"Save as text"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_CRYSTAL_MENU_SAVECIF,"Save as CIF"); mpMenuBar->AddMenu("Parameters",ID_REFOBJ_MENU_PAR); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_FIXALL,"Fix all"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_UNFIXALL,"Unfix all"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_RANDOMIZE, "Randomize Configuration"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_CRYSTAL_MENU_PAR_SETRELATIVEXYZLIMITS, "Set Relative Limits On All XYZ Parameters"); mpMenuBar->GetMenu(ID_REFOBJ_MENU_PAR).AppendSeparator(); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_CRYSTAL_MENU_PAR_TEST_RANDOM_MOVES, "Test Random Moves for 30s"); mpMenuBar->AddMenu("Scatterers",ID_CRYSTAL_MENU_SCATT); mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SHOW_SCATTPOW_WIN, "Show Scattering Powers Parameters Window"); mpMenuBar->GetMenu(ID_CRYSTAL_MENU_SCATT).AppendSeparator(); mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDSCATTPOWATOM, "Add Atomic Scattering Power"); mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDSCATTPOWSPHERE, "Add Sphere Scattering Power"); mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_REMOVESCATTPOW, "Remove Scattering Power"); mpMenuBar->GetMenu(ID_CRYSTAL_MENU_SCATT).AppendSeparator(); mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDATOM, "Add Atom"); mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_IMPORTATOMLIST, "Import a List of Atoms"); mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDMOLECULE, "Add Molecule"); mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ATOMS2MOLECULE, "Convert Atoms to a Molecule"); mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_IMPORTFENSKEHALLZMATRIX, "Import Molecule from Fenske-Hall Z-Matrix"); mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_IMPORTNAMEDZMATRIX, "Import Molecule from a named Z-Matrix"); mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_REMOVESCATTERER, "Remove Scatterer"); mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_DUPLICSCATTERER, "Duplicate Scatterer"); mpMenuBar->GetMenu(ID_CRYSTAL_MENU_SCATT).AppendSeparator(); mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDTETRAHEDRON, "Add Tetrahedron"); mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDOCTAHEDRON, "Add Octahedron"); mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDTRIANGLE, "Add Triangle Plane"); mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDSQUAREPLANE, "Add Square Plane"); mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDCUBE, "Add Cube"); mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT, ID_CRYSTAL_MENU_SCATT_ADDANTIPRISMTETRAGONAL, "Add Antiprism Tetragonal"); mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDPRISMTRIGONAL, "Add Prism Trigonal"); mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_SCATT,ID_CRYSTAL_MENU_SCATT_ADDICOSAHEDRON, "Add Icosahedron"); mpMenuBar->AddMenu("Display",ID_CRYSTAL_MENU_DISPLAY); mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_DISPLAY,ID_CRYSTAL_MENU_DISPLAY_3DVIEW, "3D Display"); //mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_DISPLAY,ID_CRYSTAL_MENU_SHOW_PDF, // "PDF"); //mpSizer->SetItemMinSize(mpMenuBar, // mpMenuBar->GetSize().GetWidth(), // mpMenuBar->GetSize().GetHeight()); // KLUDGE : this only works as long as the option order does not change ! dynamic_cast(mpCrystal->GetOption(0).WXGet())->SetToolTip( _T("Use this option ONLY if you want to use\n") _T("a higher symmetry than the one allowed by\n") _T("the spacegroup. This can be useful to search\n") _T("structures derived from higher symmetries.\n\n") _T("This option should almost never be used.")); dynamic_cast(mpCrystal->GetOption(1).WXGet())->SetToolTip( _T("This option allows Fox to automatically adjust\n") _T("the occupancy of atoms that are on a special position,\n") _T("or overlapping with another (e.g. two oxygens from\n") _T("two polyhedra).\n\n") _T("Practically you should choose:\n") _T("- Yes for inorganic structures\n") _T("- No for organic structures\n\n") _T("This option increases computing time\n") _T("by up to 50%, so only use when necessary\n\n") _T("In doubt, choose Yes")); dynamic_cast(mpCrystal->GetOption(2).WXGet())->SetToolTip( _T("This option only affects the 3D display,\n") _T("and is used to display the enantiomer\n") _T("of the crystal structure.\n\n") _T("This can be used to compare several\n") _T("crystal structures.")); // AntiBump-ProMerge cost wxBoxSizer* pAntiBumpSizer=new wxBoxSizer(wxHORIZONTAL); WXFieldPar *pWXFieldBumpMerge= new WXFieldPar(this,"AntiBump",-1,&(mpCrystal->mBumpMergeCost),100); WXFieldPar *pAntiBumpScale= new WXFieldPar(this,"Scale",-1,&(mpCrystal->mBumpMergeScale)); pAntiBumpSizer->Add(pWXFieldBumpMerge); pAntiBumpSizer->Add(pAntiBumpScale); mpSizer->Add(pAntiBumpSizer,0,wxALIGN_LEFT); mList.Add(pWXFieldBumpMerge); mList.Add(pAntiBumpScale); pWXFieldBumpMerge->SetFormat(_T("%8.2f")); pAntiBumpScale->SetFormat(_T("%8.2f")); pWXFieldBumpMerge->SetToolTip(_T("Current anti-bump cost")); pAntiBumpScale->SetToolTip( _T("Scale (multiplier) for the anti-bump cost.\n") _T("If 0, the anti-bump will be ignored and not calculated\n") _T("during optimization (saving time)\n\n") _T("Use a value larger than 1 to increase the importance\n") _T("of the anti-bump relatively to the diffraction data Chi^2\n\n") _T("Note that anti-bump should only be used if the diffraction data\n\n") _T("is not of good enough quality to ensure finding the correct\n\n") _T("structure.")); // Bond Valence cost wxBoxSizer* pBondValenceSizer=new wxBoxSizer(wxHORIZONTAL); WXFieldPar *pWXFieldBondValence= new WXFieldPar(this,"Bond Valence Cost",-1,&(mpCrystal->mBondValenceCost),100); WXFieldPar *pBondValenceScale= new WXFieldPar(this,"Scale",-1,&(mpCrystal->mBondValenceCostScale)); pBondValenceSizer->Add(pWXFieldBondValence); pBondValenceSizer->Add(pBondValenceScale); mpSizer->Add(pBondValenceSizer,0,wxALIGN_LEFT); mList.Add(pWXFieldBondValence); mList.Add(pBondValenceScale); pWXFieldBondValence->SetFormat(_T("%8.2f")); pBondValenceScale->SetFormat(_T("%8.2f")); pWXFieldBondValence->SetToolTip(_T("Current bond valence cost")); pBondValenceScale->SetToolTip( _T("Scale (multiplier) for the bond valence cost.\n") _T("If 0, the bond valence will be ignored and not calculated\n") _T("during optimization (saving time)\n\n") _T("Use a value larger than 1 to increase the importance\n") _T("of the bond valence relatively to the diffraction data Chi^2\n\n") _T("Note that bond valence should only be used if the diffraction data\n\n") _T("is not of good enough quality to ensure finding the correct\n\n") _T("structure.")); // Lattice wxBoxSizer* lattice=new wxBoxSizer(wxHORIZONTAL); WXCrystObjBasic* pFieldLatticeA =mpCrystal->GetPar("a").WXCreate(this); WXCrystObjBasic* pFieldLatticeB =mpCrystal->GetPar("b").WXCreate(this); WXCrystObjBasic* pFieldLatticeC =mpCrystal->GetPar("c").WXCreate(this); WXCrystObjBasic* pFieldLatticeAlpha =mpCrystal->GetPar("alpha").WXCreate(this); WXCrystObjBasic* pFieldLatticeBeta =mpCrystal->GetPar("beta").WXCreate(this); WXCrystObjBasic* pFieldLatticeGamma =mpCrystal->GetPar("gamma").WXCreate(this); lattice->Add(pFieldLatticeA ,0,wxALIGN_CENTER|wxRESERVE_SPACE_EVEN_IF_HIDDEN); lattice->Add(pFieldLatticeB ,0,wxALIGN_CENTER|wxRESERVE_SPACE_EVEN_IF_HIDDEN); lattice->Add(pFieldLatticeC ,0,wxALIGN_CENTER|wxRESERVE_SPACE_EVEN_IF_HIDDEN); lattice->Add(pFieldLatticeAlpha,0,wxALIGN_CENTER|wxRESERVE_SPACE_EVEN_IF_HIDDEN); lattice->Add(pFieldLatticeBeta ,0,wxALIGN_CENTER|wxRESERVE_SPACE_EVEN_IF_HIDDEN); lattice->Add(pFieldLatticeGamma,0,wxALIGN_CENTER|wxRESERVE_SPACE_EVEN_IF_HIDDEN); lattice->Layout(); mpSizer->Add(lattice,0,wxALIGN_LEFT); mList.Add(pFieldLatticeA); mList.Add(pFieldLatticeB); mList.Add(pFieldLatticeC); mList.Add(pFieldLatticeAlpha); mList.Add(pFieldLatticeBeta); mList.Add(pFieldLatticeGamma); dynamic_cast(pFieldLatticeA)->SetFormat(_T("%8.4f")); dynamic_cast(pFieldLatticeB)->SetFormat(_T("%8.4f")); dynamic_cast(pFieldLatticeC)->SetFormat(_T("%8.4f")); dynamic_cast(pFieldLatticeAlpha)->SetFormat(_T("%8.3f")); dynamic_cast(pFieldLatticeBeta)->SetFormat(_T("%8.3f")); dynamic_cast(pFieldLatticeGamma)->SetFormat(_T("%8.3f")); pFieldLatticeA->SetToolTip(_T("Lattice length parameter (in Angstroems)")); pFieldLatticeB->SetToolTip(_T("Lattice length parameter (in Angstroems)")); pFieldLatticeC->SetToolTip(_T("Lattice length parameter (in Angstroems)")); pFieldLatticeAlpha->SetToolTip(_T("Lattice angle parameter (in degrees)")); pFieldLatticeBeta->SetToolTip(_T("Lattice angle parameter (in degrees)")); pFieldLatticeGamma->SetToolTip(_T("Lattice angle parameter (in degrees)")); // SpaceGroup mpFieldSpacegroup=new WXFieldName(this,"SpaceGroup:",this,ID_CRYSTAL_SPACEGROUP,100); mpSizer->Add(mpFieldSpacegroup,0,wxALIGN_LEFT); mList.Add(mpFieldSpacegroup); mpFieldSpacegroup->SetToolTip(_T("Spacegroup Symbol. You can use:\n\n") _T("- spacegroup number: \"1\" \"62\" ... \"227\",\"230\"\n") _T("- Hermann-Mauguin symbol: \"P1\" \"Pnma\" ... \"Fd3m\",\"Ia3d\"\n") _T("- Hall symbol: \"P1\" \"-P 2ac 2n\" ... \"-F 4vw 2vw 3\",\"-I 4bd 2c 3\"\n\n") _T("ORIGIN CHOICE: for some spacegroups there are several\n") _T("possible origins - the default is the one on \n") _T("the center of symmetry (origin 2). You can specify\n") _T(" the origin by writing \"Fd3m:1\" or \"Fd3m:2\"\n\n") _T("CELL CHOICE: to specify a rhomboedral or hexagonal unit cell,\n") _T("append R or H to the symbol:\"R-3:R\"or \"R-3:H\"\n")); // Scattering Powers mpWXScatteringPowerRegistry=mpCrystal ->GetScatteringPowerRegistry().WXCreate(this); mpSizer->Add(mpWXScatteringPowerRegistry,0,wxALIGN_LEFT); mList.Add(mpWXScatteringPowerRegistry); // Scatterers mpWXScattererRegistry=mpCrystal ->GetScattererRegistry().WXCreate(this); mpSizer->Add(mpWXScattererRegistry,0,wxALIGN_LEFT); mList.Add(mpWXScattererRegistry); this->CrystUpdate(true); { bool val; if(!wxConfigBase::Get()->HasEntry(_T("Crystal/BOOL/Automatically open crystal 3D view"))) wxConfigBase::Get()->Write(_T("Crystal/BOOL/Automatically open crystal 3D view"), false); else { wxConfigBase::Get()->Read(_T("Crystal/BOOL/Automatically open crystal 3D view"), &val); if(val) { (*fpObjCrystInformUser)("Automatically opening 3D Crystal view"); wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,ID_CRYSTAL_MENU_DISPLAY_3DVIEW); wxPostEvent(this,event); (*fpObjCrystInformUser)("Finished opening 3D Crystal view"); } } } wxTheApp->GetTopWindow()->PostSizeEvent(); VFN_DEBUG_EXIT("WXCrystal::WXCrystal()",6) } WXCrystal::~WXCrystal() { VFN_DEBUG_ENTRY("WXCrystal::~WXCrystal()",10) if(0!=mpScattPowWin) mpScattPowWin->GetParent()->Destroy(); VFN_DEBUG_EXIT("WXCrystal::~WXCrystal()",10) } void WXCrystal::CrystUpdate(const bool uui,const bool lock) { VFN_DEBUG_ENTRY("WXCrystal::CrystUpdate()",5) wxWakeUpIdle(); mpCrystal->GetBumpMergeCost(); mpCrystal->GetBondValenceCost(); #ifdef OBJCRYST_GL if(mpCrystalGL!=0) { if(lock) mMutex.Lock(); BBox box=mpCrystalGL->GetCellBBox(); const REAL fadeDistance=mpCrystalGL->GetFadeDistance(); if(lock) mMutex.Unlock(); bool showFullMolecule; wxConfigBase::Get()->Read(_T("Crystal/BOOL/Show full molecules in 3D view"), &showFullMolecule); this->UpdateGL(false,box.xMin,box.xMax,box.yMin,box.yMax,box.zMin,box.zMax,fadeDistance, showFullMolecule); } #endif if(lock) mMutex.Lock(); // Necessary to change the "used" status of unit cell parameters. if((false==this->GetCrystal().IsBeingRefined()) && wxThread::IsMain() ) this->GetCrystal().InitRefParList(); if((false==this->GetCrystal().IsBeingRefined()) && wxThread::IsMain() &&(mpScattPowWin!=0)&&(mpAntiBumpWin!=0)&&(mpBondValenceWin!=0)) { //set vpRemovedScattPow; //set vpAddedScattPow; bool needLayout=false; // Delete rows & cols as required for(map::iterator pos=mvpRowScattPow.begin();pos!=mvpRowScattPow.end();) if(this->GetCrystal().GetScatteringPowerRegistry().Find(pos->second.mName,"ScatteringPowerAtom",true)<0) { VFN_DEBUG_MESSAGE("WXCrystal::CrystUpdate(): Removing scattering power: "<second.mName,5) mpScattPowWin->DeleteRows(mvpRowScattPow.size()-1,1,false); mpAntiBumpWin->DeleteRows(mvpRowScattPow.size()-1,1,false); mpBondValenceWin->DeleteRows(mvpRowScattPow.size()-1,1,false); mpAntiBumpWin->DeleteCols(mvpRowScattPow.size()-1,1,false); mpBondValenceWin->DeleteCols(mvpRowScattPow.size()-1,1,false); mvpRowScattPow.erase(pos++); needLayout=true; } else ++pos; // See Josuttis, p.205 // Add rows & cols as required for(int i=0;iGetCrystal().GetScatteringPowerRegistry().GetNb();++i) { ScatteringPower *s=&(this->GetCrystal().GetScatteringPowerRegistry().GetObj(i)); if(s->GetClassName()=="ScatteringPowerAtom") { ScatteringPowerAtom *p=dynamic_cast(s); if(mvpRowScattPow.find(p)==mvpRowScattPow.end()) { VFN_DEBUG_MESSAGE("WXCrystal::CrystUpdate(): Adding scattering power: "<GetName(),5) mpScattPowWin->AppendRows(); mpAntiBumpWin->AppendRows(); mpAntiBumpWin->AppendCols(); mpBondValenceWin->AppendRows(); mpBondValenceWin->AppendCols(); mvpRowScattPow.insert(make_pair(p,RowScattPow())); needLayout=true; } } } // Put the scattering powers in the same order as they have been declared, // for user convenience { int j=0; // :KLUDGE: number of scattering powers that are not ScatteringPowerAtom for(int i=0;iGetCrystal().GetScatteringPowerRegistry().GetNb();++i) { ScatteringPower *s=&(this->GetCrystal().GetScatteringPowerRegistry().GetObj(i)); if(s->GetClassName()=="ScatteringPowerAtom") { ScatteringPowerAtom *p=dynamic_cast(s); if(mvpRowScattPow[p].mIdx!=i-j) { mvpRowScattPow[p].mIdx=i-j; mvpRowScattPow[p].mNeedUpdateUI=true; } } else j++; } } if(needLayout) { mpScattPowWin->FitInside(); mpAntiBumpWin->FitInside(); mpBondValenceWin->FitInside(); } // Update windows //if(mpScattPowWin!=0) { map::iterator pos; for(pos=mvpRowScattPow.begin();pos!=mvpRowScattPow.end();++pos) { const string name=pos->first->GetName(); const REAL biso=pos->first->GetBiso(); const REAL formalCharge=pos->first->GetFormalCharge(); const float *pRGB=pos->first->GetColourRGB(); const REAL mlerror=pos->first->GetMaximumLikelihoodPositionError(); const REAL nbghost=pos->first->GetMaximumLikelihoodNbGhostAtom(); if( (name !=pos->second.mName) ||(biso !=pos->second.mBiso) ||(formalCharge!=pos->second.mFormalCharge) ||(pRGB[0]!=pos->second.mR) ||(pRGB[1]!=pos->second.mG) ||(pRGB[2]!=pos->second.mB) ||(mlerror!=pos->second.mMaximumLikelihoodError) ||(nbghost!=pos->second.mNbGhostAtoms) || pos->second.mNeedUpdateUI) { pos->second.mName=name; pos->second.mBiso=biso; pos->second.mFormalCharge=formalCharge; pos->second.mR=pRGB[0]; pos->second.mG=pRGB[1]; pos->second.mB=pRGB[2]; pos->second.mMaximumLikelihoodError=mlerror; pos->second.mNbGhostAtoms=nbghost; pos->second.mNeedUpdateUI=true; } } } //if(mpAntiBumpWin!=0) { map::iterator pos,pos1; for(pos=mvpRowScattPow.begin();pos!=mvpRowScattPow.end();++pos) { const string name=pos->first->GetName(); const Crystal::VBumpMergePar *pMap=&(mpCrystal->GetBumpMergeParList()); vector dist(mvpRowScattPow.size()); for(pos1=mvpRowScattPow.begin();pos1!=mvpRowScattPow.end();++pos1) { Crystal::VBumpMergePar::const_iterator pos2; if(pos->firstfirst) pos2=pMap->find(make_pair(pos->first,pos1->first)); else pos2=pMap->find(make_pair(pos1->first,pos->first)); if(pos2==pMap->end()) dist[pos1->second.mIdx]=-999; else dist[pos1->second.mIdx]=sqrt(pos2->second.mDist2); } if( (name!=pos->second.mName) ||(dist!=pos->second.mvAntiBumpDistance) || pos->second.mNeedUpdateUI) { pos->second.mName=name; pos->second.mvAntiBumpDistance=dist; pos->second.mNeedUpdateUI=true; } } } //if(mpBondValenceWin!=0) { map::iterator pos,pos1; for(pos=mvpRowScattPow.begin();pos!=mvpRowScattPow.end();++pos) { const string name=pos->first->GetName(); const std::map, REAL> *pMap=&(mpCrystal->GetBondValenceRoList()); vector ro(mvpRowScattPow.size()); for(pos1=mvpRowScattPow.begin();pos1!=mvpRowScattPow.end();++pos1) { map, REAL>::const_iterator pos2; if(pos->firstfirst) pos2=pMap->find(make_pair(pos->first,pos1->first)); else pos2=pMap->find(make_pair(pos1->first,pos->first)); if(pos2==pMap->end()) ro[pos1->second.mIdx]=-999; else ro[pos1->second.mIdx]=pos2->second; } if( (name!=pos->second.mName) ||(ro!=pos->second.mvBondValenceRo) || pos->second.mNeedUpdateUI) { pos->second.mName=name; pos->second.mvBondValenceRo=ro; pos->second.mNeedUpdateUI=true; } } } } if(lock) mMutex.Unlock(); this->WXRefinableObj::CrystUpdate(uui,lock); VFN_DEBUG_EXIT("WXCrystal::CrystUpdate():End",5) } #ifdef OBJCRYST_GL void WXCrystal::UpdateGL(const bool onlyIndependentAtoms, const REAL xMin,const REAL xMax, const REAL yMin,const REAL yMax, const REAL zMin,const REAL zMax, const REAL fadeDistance, const bool fullMoleculeInLimits) { // :KLUDGE: !!! UGLY !!! This should be done in WXGLCrystalCanvas ! VFN_DEBUG_ENTRY("WXCrystal::UpdateGL()",8) WXCrystValidateAllUserInput(); if(mpCrystalGL!=0) { VFN_DEBUG_MESSAGE("WXCrystal::UpdateGL():mpCrystalGL",7) if(false==wxThread::IsMain()) { mpConditionGLUpdate=new wxCondition(mMutexGLUpdate); bool ok=mpConditionGLUpdate->IsOk(); mMutexGLUpdate.Lock(); wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,ID_GLCRYSTAL_MENU_UPDATE); wxPostEvent(mpCrystalGL,event); wxWakeUpIdle(); wxThread::This()->Yield(); int ct=0; while(mpConditionGLUpdate->WaitTimeout(200)!=wxCOND_NO_ERROR) { cout<<"WXCrystal::UpdateGL():timeout waiting for mpConditionGLUpdate release: #"<<++ct<<":"<10) break;//and hope for the best... } mMutexGLUpdate.Unlock(); delete mpConditionGLUpdate; mpConditionGLUpdate=0; VFN_DEBUG_EXIT("WXCrystal::UpdateGL()-Not in main thread :End",8) return; } mpCrystalGL->SetCurrent(); if(mCrystalGLDisplayList==0) { mCrystalGLDisplayList=glGenLists(1); mCrystalGLNameDisplayList=glGenLists(1); VFN_DEBUG_MESSAGE("WXCrystal::UpdateGL():created mCrystalGLDisplayList=" << mCrystalGLDisplayList << ",mCrystalGLNameDisplayList=" << mCrystalGLNameDisplayList, 10) } glNewList(mCrystalGLDisplayList,GL_COMPILE); glPushMatrix(); mpCrystal->GLInitDisplayList(onlyIndependentAtoms,xMin,xMax,yMin,yMax,zMin,zMax,false,!(mpCrystalGL->GetShowHydrogens()),fadeDistance,fullMoleculeInLimits); //ScatteringPowerMap map1(mpCrystal->GetScatteringPowerRegistry().GetObj(0), // *mpCrystal,.02,.05,.05,RAD_XRAY); //map1.GLInitDisplayList(xMin,xMax,yMin,yMax,zMin,zMax); //UnitCellScattererDensityMap map2(*mpCrystal,21,21,21); //cout << map2.GetMap3D()<GLInitDisplayList(onlyIndependentAtoms,xMin,xMax,yMin,yMax,zMin,zMax,true,!(mpCrystalGL->GetShowHydrogens()),fadeDistance,fullMoleculeInLimits); glPopMatrix(); glEndList(); mpCrystalGL->CrystUpdate(); if(mpConditionGLUpdate!=0) { wxMutexLocker lock(mMutexGLUpdate); mpConditionGLUpdate->Signal(); } } else { VFN_DEBUG_MESSAGE("WXCrystal::UpdateGL():No mpCrystalGL",7) } VFN_DEBUG_EXIT("WXCrystal::UpdateGL():End",8) } int WXCrystal::GetCrystalGLDisplayList(const bool atomName)const { VFN_DEBUG_MESSAGE("WXCrystal::GetCrystalGLDisplayList()",7) if(atomName) return mCrystalGLNameDisplayList; return mCrystalGLDisplayList; } class WXGLCrystalCanvasFrame :public wxFrame { public: WXGLCrystalCanvasFrame(wxWindow *parent, wxWindowID id, const wxString& title, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_FRAME_STYLE, const wxString& name = wxFrameNameStr) : wxFrame(parent, id, title, pos, size, style, name) {} ~WXGLCrystalCanvasFrame() { gvWindowPosition[ID_GLCRYSTAL_WINDOW] = make_pair(this->GetScreenPosition(), this->GetSize()); //VFN_DEBUG_MESSAGE("~ @(" << gvWindowPosition[ID_GLCRYSTAL_WINDOW].first.x << "," << gvWindowPosition[ID_GLCRYSTAL_WINDOW].first.y << ")",10) } }; void WXCrystal::OnMenuCrystalGL(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_MESSAGE("WXCrystal::OnMenuCrystalGL()",6) if(mpCrystalGL!=0) return; wxFrame* frame; if (gvWindowPosition.count(ID_GLCRYSTAL_WINDOW)) { //cout << "WXCrystal::OnMenuCrystalGL():@(" << gvWindowPosition[ID_GLCRYSTAL_WINDOW].first.x << "," << gvWindowPosition[ID_GLCRYSTAL_WINDOW].first.y << ")" << endl; frame = new WXGLCrystalCanvasFrame(this, ID_GLCRYSTAL_WINDOW, wxString::Format("%s [%s]",mpCrystal->GetName().c_str(), mpCrystal->GetSpaceGroup().GetName().c_str()), gvWindowPosition[ID_GLCRYSTAL_WINDOW].first, gvWindowPosition[ID_GLCRYSTAL_WINDOW].second, wxCLOSE_BOX | wxRESIZE_BORDER | wxCAPTION | wxMINIMIZE_BOX | wxMAXIMIZE_BOX);//wxFRAME_FLOAT_ON_PARENT } else frame = new WXGLCrystalCanvasFrame(this, ID_GLCRYSTAL_WINDOW, wxString::Format("%s [%s]",mpCrystal->GetName().c_str(), mpCrystal->GetSpaceGroup().GetName().c_str()), wxDefaultPosition, wxSize(400, 400), wxCLOSE_BOX | wxRESIZE_BORDER | wxCAPTION | wxMINIMIZE_BOX | wxMAXIMIZE_BOX);//wxFRAME_FLOAT_ON_PARENT mpCrystalGL=new WXGLCrystalCanvas(this,frame,-1); #if wxUSE_STATUSBAR frame->CreateStatusBar(1); frame->SetStatusText(wxString::Format("%s [%s]",mpCrystal->GetName().c_str(), mpCrystal->GetSpaceGroup().GetName().c_str())); #endif frame->Show(true); frame->Raise(); //The contents to be displayed will be generated on the first OnPaint event, in InitGL } void WXCrystal::NotifyCrystalGLDelete() { VFN_DEBUG_MESSAGE("WXCrystal::NotifyCrystalGLDelete()",7) mpCrystalGL=0; } WXGLCrystalCanvas * WXCrystal::GetCrystalGL() { VFN_DEBUG_MESSAGE("WXCrystal::GetCrystalGL()",7) return mpCrystalGL; } #endif void WXCrystal::OnMenuSaveCIF(wxCommandEvent & WXUNUSED(event)) { WXCrystValidateAllUserInput(); wxFileDialog save(this,_T("Choose a file"),_T(""),_T(""),_T("*.cif"),wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if(save.ShowModal() != wxID_OK) return; ofstream out(save.GetPath().ToAscii()); if(!out) return;//:TODO: mpCrystal->CIFOutput(out); out.close(); } void WXCrystal::OnMenuSaveText(wxCommandEvent & WXUNUSED(event)) { WXCrystValidateAllUserInput(); wxFileDialog save(this,_T("Choose a file"),_T(""),_T(""),_T("*.txt"),wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if(save.ShowModal() != wxID_OK) return; ofstream out(save.GetPath().ToAscii()); if(!out) return;//:TODO: mpCrystal->Print(out); mpCrystal->PrintMinDistanceTable(.05,out); out.close(); } void WXCrystal::OnMenuAddScattPowAtom(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_MESSAGE("WXCrystal::OnMenuAddScattPowAtom()",6) WXCrystValidateAllUserInput(); ScatteringPowerAtom *scatt=new ScatteringPowerAtom("Change me","H"); mpCrystal->AddScatteringPower(scatt); VFN_DEBUG_MESSAGE("WXCrystal::OnMenuAddScattPowAtom():End",6) this->Layout(); this->CrystUpdate(true,false); wxTheApp->GetTopWindow()->Layout(); wxTheApp->GetTopWindow()->SendSizeEvent(); } void WXCrystal::OnMenuAddScattPowSphere(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXCrystal::OnMenuAddScattSphere()",6) WXCrystValidateAllUserInput(); ScatteringPower *scatt= new ScatteringPowerSphere; mpCrystal->AddScatteringPower(scatt); this->Layout(); this->CrystUpdate(true,false); VFN_DEBUG_EXIT("WXCrystal::OnMenuAddScattPowSphere()",6) wxTheApp->GetTopWindow()->Layout(); wxTheApp->GetTopWindow()->SendSizeEvent(); } void WXCrystal::OnMenuRemoveScattPow(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXCrystal::OnButtonRemoveScattPow()",6) WXCrystValidateAllUserInput(); int choice; ScatteringPower *scatt= WXDialogChooseFromRegistry(mpCrystal->GetScatteringPowerRegistry(),this, "Choose Scattering Power to remove:",choice); if(0==scatt) { VFN_DEBUG_EXIT("WXCrystal::OnButtonRemoveScattPow():Cancelled",6) return; } const ScatteringComponentList *pList=&(mpCrystal->GetScatteringComponentList()); for(long i=0;iGetNbComponent();++i) if((*pList)(i).mpScattPow==scatt) { wxMessageDialog dumbUser(this,_T("This Scattering Power is still used !"), _T("Whooops"),wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); VFN_DEBUG_EXIT("WXCrystal::OnButtonRemoveScattPow()",6) return; } mpCrystal->RemoveScatteringPower(scatt); VFN_DEBUG_EXIT("WXCrystal::OnButtonRemoveScattPow()",6) this->Layout(); this->CrystUpdate(true,false); wxTheApp->GetTopWindow()->Layout(); wxTheApp->GetTopWindow()->SendSizeEvent(); } void WXCrystal::OnMenuAddScatterer(wxCommandEvent &event) { VFN_DEBUG_ENTRY("WXCrystal::OnMenuAddScatterer()",6) WXCrystValidateAllUserInput(); Scatterer *scatt=0; if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDATOM) { int choice; ScatteringPower *scattPow= WXDialogChooseFromRegistry(mpCrystal->GetScatteringPowerRegistry(),this, "Choose an atom type (ScatteringPower):",choice); if(0==scattPow) { VFN_DEBUG_EXIT("WXCrystal::OnMenuAddScatterer():Canceled",6) return; } scatt=new Atom(0,0,0,"Change Me!",scattPow); } if(event.GetId()== ID_CRYSTAL_MENU_SCATT_IMPORTATOMLIST) { wxFileDialog open(this,_T("Choose a file with a list of atoms: Element x y z occup"),_T(""),_T(""),_T("*"), wxFD_OPEN | wxFD_FILE_MUST_EXIST); if(open.ShowModal() != wxID_OK) return; ifstream fin (open.GetPath().ToAscii()); if(!fin) { throw ObjCrystException("WXCrystal::OnMenuAddScatterer() : Error opening file for input:"+string(open.GetPath().ToAscii())); } string symbol; REAL x,y,z,occup; int n=1; char buf [10]; int scattPow; while(true) { fin>>symbol; if(fin.eof()) break; fin>>x>>y>>z>>occup; cout<GetScatteringPowerRegistry().Find(symbol,"ScatteringPowerAtom",true); if(scattPow<0) { cout<<"Scattering power "<AddScatteringPower(new ScatteringPowerAtom(symbol,symbol)); } sprintf(buf,"%d",n++); mpCrystal->AddScatterer(new Atom(x,y,z,symbol+(string)buf,&(mpCrystal->GetScatteringPower(symbol)),occup)); if(fin.eof()) break; } fin.close(); scatt=0; } if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDZSCATTERER) { scatt=new ZScatterer("Change Me!",*mpCrystal); } if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDMOLECULE) { scatt=new Molecule(*mpCrystal,"Molecule"); } if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDTETRAHEDRON) { int choice; //Scattering power 1 const ScatteringPower *scattPow1=WXDialogChooseFromRegistry( mpCrystal->GetScatteringPowerRegistry(), this,"Central atom type (ScatteringPower):",choice); if(0==scattPow1) { VFN_DEBUG_EXIT("WXCrystal::OnMenuAddScatterer():Canceled",6) return; } //Scattering power 2 const ScatteringPower *scattPow2=WXDialogChooseFromRegistry( mpCrystal->GetScatteringPowerRegistry(), this,"Corner atom type (ScatteringPower):",choice); if(0==scattPow2) { VFN_DEBUG_EXIT("WXCrystal::OnMenuAddScatterer():Canceled",6) return; } //Bond length wxTextEntryDialog bondLengthDialog(this,_T("Bond length"), _T("Enter bond length (Angstroems)"),_T("1"),wxOK | wxCANCEL); bondLengthDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=bondLengthDialog.ShowModal()) { VFN_DEBUG_EXIT("WXZScatterer))OnMenuAddZAtom())Cancelled",6) return; } double bondLength; bondLengthDialog.GetValue().ToDouble(&bondLength); Molecule *mol=MakeTetrahedron(*mpCrystal,scattPow1->GetName()+scattPow2->GetName()+"4", scattPow1,scattPow2,bondLength); mol->RestraintStatus(cout); scatt=mol; } if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDOCTAHEDRON) { int choice; //Scattering power 1 const ScatteringPower *scattPow1=WXDialogChooseFromRegistry( mpCrystal->GetScatteringPowerRegistry(), this,"Central atom type (ScatteringPower):",choice); if(0==scattPow1) { VFN_DEBUG_EXIT("WXCrystal::OnMenuAddScatterer():Canceled",6) return; } //Scattering power 2 const ScatteringPower *scattPow2=WXDialogChooseFromRegistry( mpCrystal->GetScatteringPowerRegistry(), this,"Corner atom type (ScatteringPower))",choice); if(0==scattPow2) { VFN_DEBUG_EXIT("WXCrystal::OnMenuAddScatterer():Canceled",6) return; } //Bond length wxTextEntryDialog bondLengthDialog(this,_T("Bond length"), _T("Enter bond length (Angstroems)"),_T("1"),wxOK | wxCANCEL); bondLengthDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=bondLengthDialog.ShowModal()) { VFN_DEBUG_EXIT("WXZScatterer))OnMenuAddZAtom())Cancelled",6) return; } double bondLength; bondLengthDialog.GetValue().ToDouble(&bondLength); Molecule *mol=MakeOctahedron(*mpCrystal,scattPow1->GetName()+scattPow2->GetName()+"6", scattPow1,scattPow2,bondLength); mol->RestraintStatus(cout); scatt=mol; } if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDTRIANGLE) { VFN_DEBUG_MESSAGE("WXCrystal::OnMenuAddScatterer())Add triangle plane",6) int choice; //Scattering power 1 const ScatteringPower *scattPow1=WXDialogChooseFromRegistry( mpCrystal->GetScatteringPowerRegistry(), this,"Central atom type (ScatteringPower))",choice); if(0==scattPow1) { VFN_DEBUG_EXIT("WXCrystal::OnMenuAddScatterer():Canceled",6) return; } //Scattering power 2 const ScatteringPower *scattPow2=WXDialogChooseFromRegistry( mpCrystal->GetScatteringPowerRegistry(), this,"Corner atom type (ScatteringPower))",choice); if(0==scattPow2) { VFN_DEBUG_EXIT("WXCrystal::OnMenuAddScatterer():Canceled",6) return; } //Bond length wxTextEntryDialog bondLengthDialog(this,_T("Bond length"), _T("Enter bond length (Angstroems)"),_T("1"),wxOK | wxCANCEL); bondLengthDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=bondLengthDialog.ShowModal()) { VFN_DEBUG_EXIT("WXZScatterer::OnMenuAddZAtom():Cancelled",6) return; } double bondLength; bondLengthDialog.GetValue().ToDouble(&bondLength); Molecule *mol=MakeTriangle(*mpCrystal,scattPow1->GetName()+scattPow2->GetName()+"3", scattPow1,scattPow2,bondLength); mol->RestraintStatus(cout); scatt=mol; } if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDSQUAREPLANE) { VFN_DEBUG_MESSAGE("WXCrystal::OnMenuAddScatterer():Add square plane",6) int choice; //Scattering power 1 const ScatteringPower *scattPow1=WXDialogChooseFromRegistry( mpCrystal->GetScatteringPowerRegistry(), this,"Central atom type (ScatteringPower))",choice); if(0==scattPow1) { VFN_DEBUG_EXIT("WXCrystal::OnMenuAddScatterer():Canceled",6) return; } //Scattering power 2 const ScatteringPower *scattPow2=WXDialogChooseFromRegistry( mpCrystal->GetScatteringPowerRegistry(), this,"Corner atom type (ScatteringPower))",choice); if(0==scattPow2) { VFN_DEBUG_EXIT("WXCrystal::OnMenuAddScatterer():Canceled",6) return; } //Bond length wxTextEntryDialog bondLengthDialog(this,_T("Bond length"), _T("Enter bond length (Angstroems)"),_T("1"),wxOK | wxCANCEL); bondLengthDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=bondLengthDialog.ShowModal()) { VFN_DEBUG_EXIT("WXZScatterer::OnMenuAddZAtom():Cancelled",6) return; } double bondLength; bondLengthDialog.GetValue().ToDouble(&bondLength); Molecule *mol=MakeSquarePlane(*mpCrystal,scattPow1->GetName()+scattPow2->GetName()+"4", scattPow1,scattPow2,bondLength); mol->RestraintStatus(cout); scatt=mol; } if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDCUBE) { int choice; //Scattering power 1 const ScatteringPower *scattPow1=WXDialogChooseFromRegistry( mpCrystal->GetScatteringPowerRegistry(), this,"Central atom type (ScatteringPower):",choice); if(0==scattPow1) { VFN_DEBUG_EXIT("WXCrystal::OnMenuAddScatterer():Canceled",6) return; } //Scattering power 2 const ScatteringPower *scattPow2=WXDialogChooseFromRegistry( mpCrystal->GetScatteringPowerRegistry(), this,"Corner atom type (ScatteringPower))",choice); if(0==scattPow2) { VFN_DEBUG_EXIT("WXCrystal::OnMenuAddScatterer():Canceled",6) return; } //Bond length wxTextEntryDialog bondLengthDialog(this,_T("Bond length"), _T("Enter bond length (Angstroems)"),_T("1"),wxOK | wxCANCEL); bondLengthDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=bondLengthDialog.ShowModal()) { VFN_DEBUG_EXIT("WXZScatterer::OnMenuAddZAtom():Cancelled",6) return; } double bondLength; bondLengthDialog.GetValue().ToDouble(&bondLength); Molecule *mol=MakeCube(*mpCrystal,scattPow1->GetName()+scattPow2->GetName()+"8", scattPow1,scattPow2,bondLength); mol->RestraintStatus(cout); scatt=mol; } if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDANTIPRISMTETRAGONAL) { int choice; //Scattering power 1 const ScatteringPower *scattPow1=WXDialogChooseFromRegistry( mpCrystal->GetScatteringPowerRegistry(), this,"Central atom type (ScatteringPower):",choice); if(0==scattPow1) { VFN_DEBUG_EXIT("WXCrystal::OnMenuAddScatterer():Canceled",6) return; } //Scattering power 2 const ScatteringPower *scattPow2=WXDialogChooseFromRegistry( mpCrystal->GetScatteringPowerRegistry(), this,"Corner atom type (ScatteringPower))",choice); if(0==scattPow2) { VFN_DEBUG_EXIT("WXCrystal::OnMenuAddScatterer():Canceled",6) return; } //Bond length wxTextEntryDialog bondLengthDialog(this,_T("Bond length"), _T("Enter bond length (Angstroems)"),_T("1"),wxOK | wxCANCEL); bondLengthDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=bondLengthDialog.ShowModal()) { VFN_DEBUG_EXIT("WXZScatterer::OnMenuAddZAtom():Cancelled",6) return; } double bondLength; bondLengthDialog.GetValue().ToDouble(&bondLength); Molecule *mol=MakeAntiPrismTetragonal(*mpCrystal,scattPow1->GetName()+scattPow2->GetName()+"8", scattPow1,scattPow2,bondLength); mol->RestraintStatus(cout); scatt=mol; } if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDPRISMTRIGONAL) { int choice; //Scattering power 1 const ScatteringPower *scattPow1=WXDialogChooseFromRegistry( mpCrystal->GetScatteringPowerRegistry(), this,"Central atom type (ScatteringPower))",choice); if(0==scattPow1) { VFN_DEBUG_EXIT("WXCrystal::OnMenuAddScatterer():Canceled",6) return; } //Scattering power 2 const ScatteringPower *scattPow2=WXDialogChooseFromRegistry( mpCrystal->GetScatteringPowerRegistry(), this,"Corner atom type (ScatteringPower))",choice); if(0==scattPow2) { VFN_DEBUG_EXIT("WXCrystal::OnMenuAddScatterer():Canceled",6) return; } //Bond length wxTextEntryDialog bondLengthDialog(this,_T("Bond length"), _T("Enter bond length (Angstroems)"),_T("1"),wxOK | wxCANCEL); bondLengthDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=bondLengthDialog.ShowModal()) { VFN_DEBUG_EXIT("WXZScatterer::OnMenuAddZAtom())Cancelled",6) return; } double bondLength; bondLengthDialog.GetValue().ToDouble(&bondLength); Molecule *mol=MakePrismTrigonal(*mpCrystal,scattPow1->GetName()+scattPow2->GetName()+"6", scattPow1,scattPow2,bondLength); mol->RestraintStatus(cout); scatt=mol; } if(event.GetId()== ID_CRYSTAL_MENU_SCATT_ADDICOSAHEDRON) { int choice; //Scattering power 1 const ScatteringPower *scattPow1=WXDialogChooseFromRegistry( mpCrystal->GetScatteringPowerRegistry(), this,"Central atom type (ScatteringPower):",choice); if(0==scattPow1) { VFN_DEBUG_EXIT("WXCrystal::OnMenuAddScatterer():Canceled",6) return; } //Scattering power 2 const ScatteringPower *scattPow2=WXDialogChooseFromRegistry( mpCrystal->GetScatteringPowerRegistry(), this,"Corner atom type (ScatteringPower):",choice); if(0==scattPow2) { VFN_DEBUG_EXIT("WXCrystal::OnMenuAddScatterer():Canceled",6) return; } //Bond length wxTextEntryDialog bondLengthDialog(this,_T("Bond length"), _T("Enter bond length (Angstroems)"),_T("1"),wxOK | wxCANCEL); bondLengthDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=bondLengthDialog.ShowModal()) { VFN_DEBUG_EXIT("WXZScatterer::OnMenuAddZAtom():Cancelled",6) return; } double bondLength; bondLengthDialog.GetValue().ToDouble(&bondLength); Molecule *mol=MakeIcosahedron(*mpCrystal,scattPow1->GetName()+scattPow2->GetName()+"12", scattPow1,scattPow2,bondLength); mol->RestraintStatus(cout); scatt=mol; } if(scatt!=0) { mpCrystal->AddScatterer(scatt); mpCrystal->UpdateDisplay(); } VFN_DEBUG_MESSAGE("WXCrystal::OnMenuAddScatterer():calling Layout()",6) //this->CrystUpdate(); this->Layout(); wxTheApp->GetTopWindow()->Layout(); wxTheApp->GetTopWindow()->SendSizeEvent(); VFN_DEBUG_EXIT("WXCrystal::OnMenuAddScatterer()",6) } void WXCrystal::OnMenuRemoveScatterer(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_MESSAGE("WXCrystal::OnButtonRemoveScatterer()",6) WXCrystValidateAllUserInput(); int choice; Scatterer *scatt=WXDialogChooseFromRegistry(mpCrystal->GetScattererRegistry(),this, "Select the Scatterer to remove:",choice); if(0==scatt) return; mpCrystal->RemoveScatterer(scatt); VFN_DEBUG_MESSAGE("WXCrystal::OnButtonRemoveScatterer():End",6) this->Layout(); wxTheApp->GetTopWindow()->Layout(); wxTheApp->GetTopWindow()->SendSizeEvent(); this->CrystUpdate(true); } void WXCrystal::OnMenuDuplicateScatterer(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXCrystal::OnMenuDuplicateScatterer()",6) WXCrystValidateAllUserInput(); int choice; Scatterer *scatt=WXDialogChooseFromRegistry(mpCrystal->GetScattererRegistry(),this, "Select the Scatterer to duplicate:",choice); if(0==scatt) return; Scatterer *copy=scatt->CreateCopy(); scatt->SetName(scatt->GetName()+(string)"(copy)"); mpCrystal->AddScatterer(copy); this->Layout(); wxTheApp->GetTopWindow()->Layout(); wxTheApp->GetTopWindow()->SendSizeEvent(); VFN_DEBUG_EXIT("WXCrystal::OnMenuDuplicateScatterer():End",6) } Molecule *ZScatterer2Molecule(ZScatterer *scatt);//defined in wxZScatterer.cpp void WXCrystal::OnMenuAtoms2Molecule(wxCommandEvent &event) { vector v; for(unsigned int i=0; iGetScattererRegistry().GetNb();++i) { Atom *pAtom=dynamic_cast(&(mpCrystal->GetScattererRegistry().GetObj(i))); if(pAtom!=0) v.push_back(pAtom); } const unsigned int nb=v.size(); wxString *choices = new wxString[nb]; for(unsigned int i=0;iGetName()).c_str()); #if 0 wxMultiChoiceDialog dialog (this,_T("Choose the molecule's atoms"),_T("Select Atoms"),nb,choices,wxOK | wxCANCEL); dialog.SetSize(300,300); #else wxMultiChoiceDialog_ListBox dialog(this,_T("Choose the molecule's atoms"),_T("Select Atoms"),nb,choices); #endif if(wxID_OK!=dialog.ShowModal()) return; wxArrayInt choice=dialog.GetSelections(); if(choice.GetCount()>0) { list vChoice; for(unsigned int i=0;iAddScatterer(Atoms2Molecule(vChoice)); for(unsigned int i=0;iRemoveScatterer(v[choice.Item(i)]); mpCrystal->UpdateDisplay(); } wxTheApp->GetTopWindow()->Layout(); wxTheApp->GetTopWindow()->SendSizeEvent(); } void WXCrystal::OnMenuImportMoleculeFromFenskeHallZMatrix(wxCommandEvent &event) { VFN_DEBUG_ENTRY("WXCrystal::OnMenuImportFenskeHallZMatrix()",6) WXCrystValidateAllUserInput(); string tmp("Fenske-Hall z-matrix|*.fhz;*.fh"); if(event.GetId()==ID_CRYSTAL_MENU_SCATT_IMPORTNAMEDZMATRIX) tmp="Fox z-matrix|*.zmat"; wxFileDialog open(this,_T("Choose a file with a Fenske-Hall Z-matrix"),_T(""),_T(""), wxString::FromAscii(tmp.c_str()), wxFD_OPEN | wxFD_FILE_MUST_EXIST); if(open.ShowModal() != wxID_OK) return; ifstream fin ( open.GetPath().ToAscii()); if(!fin) { throw ObjCrystException("WXCrystal::OnMenuImportFenskeHallZMatrix() : \ Error opening file for input:"+string(open.GetPath().ToAscii())); } string filename(open.GetPath().ToAscii()); string shortName; {// Use short name std::string::size_type idx =filename.rfind("/"); std::string::size_type idx2=filename.rfind("\\"); std::string::size_type idx3=filename.rfind(":"); if(((long)idx2!=(long)string::npos)&&((long)idx2>(long)idx))idx=idx2; if(((long)idx3!=(long)string::npos)&&((long)idx3>(long)idx))idx=idx3; if(idx==string::npos) shortName=filename; else shortName=filename.substr(idx+1); } ZScatterer scatt(shortName,*mpCrystal); bool named=false; if(event.GetId()==ID_CRYSTAL_MENU_SCATT_IMPORTNAMEDZMATRIX) named=true; scatt.ImportFenskeHallZMatrix(fin,named); fin.close(); mpCrystal->AddScatterer(ZScatterer2Molecule(&scatt)); wxTheApp->GetTopWindow()->Layout(); wxTheApp->GetTopWindow()->SendSizeEvent(); this->CrystUpdate(true); VFN_DEBUG_EXIT("WXCrystal::OnMenuImportFenskeHallZMatrix()",6) } void WXCrystal::OnMenuSetRelativeXYZLimits(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXCrystal::OnMenuSetRelativeXYZLimits():Cancelled",6) WXCrystValidateAllUserInput(); wxTextEntryDialog limitDialog(this,_T("Relative limits"), _T("Enter relative limits for x,y,z (Angstroems)"), _T("0.5"),wxOK | wxCANCEL); limitDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=limitDialog.ShowModal()) { VFN_DEBUG_EXIT("WXCrystal::OnMenuSetRelativeXYZLimits():Cancelled",6) return; } double limit; limitDialog.GetValue().ToDouble(&limit); limit=fabs(limit); mpCrystal->SetLimitsRelative(gpRefParTypeScattTranslX, -limit/mpCrystal->GetLatticePar(0), limit/mpCrystal->GetLatticePar(0)); mpCrystal->SetLimitsRelative(gpRefParTypeScattTranslY, -limit/mpCrystal->GetLatticePar(1), limit/mpCrystal->GetLatticePar(1)); mpCrystal->SetLimitsRelative(gpRefParTypeScattTranslZ, -limit/mpCrystal->GetLatticePar(2), limit/mpCrystal->GetLatticePar(2)); VFN_DEBUG_EXIT("WXCrystal::OnMenuSetRelativeXYZLimits()",6) } /// Local class for a thread doing random moves to the structure class TestCrystalThread: public wxThread { public: TestCrystalThread(Crystal &cryst,float seconds): wxThread(wxTHREAD_DETACHED),mpCryst(&cryst),mSeconds(seconds){}; virtual void *Entry() { cout<BeginOptimization(); Chronometer chrono; float dt0=chrono.seconds(); while(chrono.seconds()<30) { mpCryst->BeginGlobalOptRandomMove(); mpCryst->GlobalOptRandomMove(0.05,gpRefParTypeObjCryst); wxMilliSleep(1);// Slow down display for simple structures if((chrono.seconds()-dt0)>0.05) {mpCryst->UpdateDisplay();dt0=chrono.seconds();} } mpCryst->EndOptimization(); return NULL; }; virtual void OnExit() { cout <Create() != wxTHREAD_NO_ERROR) wxLogError(_T("Can't create test optimization thread")); else pTest->Run(); } bool WXCrystal::OnChangeName(const int id) { VFN_DEBUG_MESSAGE("WXCrystal::OnChangeName()",6) if(this->WXRefinableObj::OnChangeName(id)==true) return true; if(id==ID_CRYSTAL_SPACEGROUP) { VFN_DEBUG_MESSAGE("WXCrystal::OnChangeName():Changing SpaceGroup",6) mpCrystal->Init(mpCrystal->GetLatticePar(0), mpCrystal->GetLatticePar(1), mpCrystal->GetLatticePar(2), mpCrystal->GetLatticePar(3), mpCrystal->GetLatticePar(4), mpCrystal->GetLatticePar(5), mpFieldSpacegroup->GetValue(), mpCrystal->GetName()); this->CrystUpdate(true); this->Layout(); return true; } return false; } void WXCrystal::UpdateUI(const bool lock) { VFN_DEBUG_ENTRY("WXCrystal::UpdateUI()",6) if(!mpCrystal->IsBeingRefined()) { if(lock) mMutex.Lock(); mpFieldSpacegroup->SetValue(mpCrystal->GetSpaceGroup().GetName()); #ifdef OBJCRYST_GL if(0!=mpCrystalGL) mpCrystalGL->GetParent()->SetLabel(wxString::Format("%s [%s]",mpCrystal->GetName().c_str(), mpCrystal->GetSpaceGroup().GetName().c_str())); #endif if(lock) mMutex.Unlock(); } if(lock) mMutex.Lock(); if(0!=mpScattPowWin) { map::iterator pos; for(pos=mvpRowScattPow.begin();pos!=mvpRowScattPow.end();++pos) { if(pos->second.mNeedUpdateUI==true) { mIsSelfUpdating=true; mpScattPowWin->SetRowLabelValue(pos->second.mIdx, wxString::FromAscii(pos->second.mName.c_str())); wxString tmp; tmp.Printf(_T("%f"),pos->second.mBiso); mpScattPowWin->SetCellValue(pos->second.mIdx, 0, tmp); tmp.Printf(_T("%f"),pos->second.mFormalCharge); mpScattPowWin->SetCellValue(pos->second.mIdx, 1, tmp); tmp.Printf(_T("%f"),pos->second.mR); mpScattPowWin->SetCellValue(pos->second.mIdx, 2, tmp); tmp.Printf(_T("%f"),pos->second.mG); mpScattPowWin->SetCellValue(pos->second.mIdx, 3, tmp); tmp.Printf(_T("%f"),pos->second.mB); mpScattPowWin->SetCellValue(pos->second.mIdx, 4, tmp); tmp.Printf(_T("%f"),pos->second.mMaximumLikelihoodError); mpScattPowWin->SetCellValue(pos->second.mIdx, 5, tmp); tmp.Printf(_T("%f"),pos->second.mNbGhostAtoms); mpScattPowWin->SetCellValue(pos->second.mIdx, 6, tmp); mIsSelfUpdating=false; } } } if(0!=mpAntiBumpWin) { map::iterator pos; for(pos=mvpRowScattPow.begin();pos!=mvpRowScattPow.end();++pos) { if(pos->second.mNeedUpdateUI==true) { mIsSelfUpdating=true; mpAntiBumpWin->SetRowLabelValue(pos->second.mIdx, wxString::FromAscii(pos->second.mName.c_str())); mpAntiBumpWin->SetColLabelValue(pos->second.mIdx, wxString::FromAscii(pos->second.mName.c_str())); wxString tmp; for(unsigned long j=0;jsecond.mvAntiBumpDistance.size();++j) { VFN_DEBUG_MESSAGE("WXCrystal::UpdateUI():Antibump("<first->GetName() <<",?"//<GetName() <<")="<second.mvAntiBumpDistance[j],3); if(pos->second.mvAntiBumpDistance[j]>-998) { tmp.Printf(_T("%f"),pos->second.mvAntiBumpDistance[j]); mpAntiBumpWin->SetCellValue(pos->second.mIdx,j,tmp); } else mpAntiBumpWin->SetCellValue(pos->second.mIdx,j,_T("")); } mIsSelfUpdating=false; } } } if(0!=mpBondValenceWin) { map::iterator pos; for(pos=mvpRowScattPow.begin();pos!=mvpRowScattPow.end();++pos) { if(pos->second.mNeedUpdateUI==true) { mIsSelfUpdating=true; mpBondValenceWin->SetRowLabelValue(pos->second.mIdx, wxString::FromAscii(pos->second.mName.c_str())); mpBondValenceWin->SetColLabelValue(pos->second.mIdx, wxString::FromAscii(pos->second.mName.c_str())); wxString tmp; for(unsigned long j=0;jsecond.mvBondValenceRo.size();++j) { VFN_DEBUG_MESSAGE("WXCrystal::UpdateUI():BondValence("<first->GetName() <<",?"//<GetName() <<")="<second.mvBondValenceRo[j],3); if(pos->second.mvBondValenceRo[j]>-998) { tmp.Printf(_T("%f"),pos->second.mvBondValenceRo[j]); mpBondValenceWin->SetCellValue(pos->second.mIdx,j,tmp); } else mpBondValenceWin->SetCellValue(pos->second.mIdx,j,_T("")); } mIsSelfUpdating=false; } } } if(lock) mMutex.Unlock(); this->WXRefinableObj::UpdateUI(lock); VFN_DEBUG_EXIT("WXCrystal::UpdateUI()",6) } Crystal& WXCrystal::GetCrystal(){return *mpCrystal;} const Crystal& WXCrystal::GetCrystal()const{return *mpCrystal;} void WXCrystal::OnMenuShowScattPowWindow(wxCommandEvent &event) { VFN_DEBUG_MESSAGE("WXCrystal::OnMenuShowScattPowWindow()",10) if(0!=mpScattPowWin) return; WXCrystValidateAllUserInput(); // Frame with notebook wxFrame *frame= new wxFrame(this,-1,_T("Scattering Powers parameters for: ") + wxString::FromAscii(this->GetCrystal().GetName().c_str()), wxDefaultPosition,wxSize(800,300)); wxNotebook *notebook = new wxNotebook(frame, -1); {// Individual parameters mpScattPowWin = new WXCrystalScrolledGridWindow(notebook,this,ID_CRYSTAL_WIN_SCATTPOW); notebook->AddPage(mpScattPowWin, _T("Scattering Powers"), true); mpScattPowWin->SetDefaultRenderer(new wxGridCellFloatRenderer(5,3)); mpScattPowWin->SetDefaultEditor(new wxGridCellFloatEditor(5,3)); mpScattPowWin->SetColMinimalAcceptableWidth(150); mpScattPowWin->CreateGrid(0,7); mpScattPowWin->SetColLabelValue(0,_T("Biso")); mpScattPowWin->SetColLabelValue(1,_T("Charge")); mpScattPowWin->SetColLabelValue(2,_T("Red")); mpScattPowWin->SetColLabelValue(3,_T("Green")); mpScattPowWin->SetColLabelValue(4,_T("Blue")); mpScattPowWin->SetColLabelValue(5,_T("ML Error")); mpScattPowWin->SetColLabelValue(6,_T("#ghost")); mpScattPowWin->AutoSizeRows(); mpScattPowWin->AutoSizeColumns(); } {// Anti-Bump mpAntiBumpWin = new WXCrystalScrolledGridWindow(notebook,this,ID_CRYSTAL_WIN_ANTIBUMP); notebook->AddPage(mpAntiBumpWin, _T("AntiBump"), true); mpAntiBumpWin->SetDefaultRenderer(new wxGridCellFloatRenderer(5,3)); mpAntiBumpWin->SetDefaultEditor(new wxGridCellFloatEditor(5,3)); mpAntiBumpWin->SetColMinimalAcceptableWidth(150); mpAntiBumpWin->CreateGrid(0,0); mpAntiBumpWin->AutoSizeRows(); mpAntiBumpWin->AutoSizeColumns(); } {// Bond Valence mpBondValenceWin = new WXCrystalScrolledGridWindow(notebook,this,ID_CRYSTAL_WIN_BONDVALENCE); notebook->AddPage(mpBondValenceWin, _T("BondValence"), true); mpBondValenceWin->SetDefaultRenderer(new wxGridCellFloatRenderer(5,3)); mpBondValenceWin->SetDefaultEditor(new wxGridCellFloatEditor(5,3)); mpBondValenceWin->SetColMinimalAcceptableWidth(150); mpBondValenceWin->CreateGrid(0,0); mpBondValenceWin->AutoSizeRows(); mpBondValenceWin->AutoSizeColumns(); } notebook->SetSelection(0); this->CrystUpdate(true); frame->Show(true); frame->Layout(); } void WXCrystal::OnEditGridScattPow(wxGridEvent &e) { if(mIsSelfUpdating) return; const int r=e.GetRow(); const int c=e.GetCol(); map::iterator pos=mvpRowScattPow.begin(); while(pos->second.mIdx!=r)++pos; ScatteringPowerAtom *const p=pos->first; wxString s=mpScattPowWin->GetCellValue(r,c); switch(c) { case 0: { if(s!=_T("")) { double d; s.ToDouble(&d); p->SetBiso(d); } break; } case 1: { if(s!=_T("")) { double d; s.ToDouble(&d); p->SetFormalCharge(d); } break; } case 2: { if(s!=_T("")) { double d; s.ToDouble(&d); const REAL gg=p->GetColourRGB()[1]; const REAL bb=p->GetColourRGB()[2]; p->SetColour(d,gg,bb); } break; } case 3: { if(s!=_T("")) { double d; s.ToDouble(&d); const REAL rr=p->GetColourRGB()[0]; const REAL bb=p->GetColourRGB()[2]; p->SetColour(rr,d,bb); } break; } case 4: { if(s!=_T("")) { double d; s.ToDouble(&d); const REAL rr=p->GetColourRGB()[0]; const REAL gg=p->GetColourRGB()[1]; p->SetColour(rr,gg,d); } break; } case 5: { if(s!=_T("")) { double d; s.ToDouble(&d); p->SetMaximumLikelihoodPositionError(d); } break; } case 6: { if(s!=_T("")) { double d; s.ToDouble(&d); p->SetMaximumLikelihoodNbGhostAtom(d); } break; } } this->CrystUpdate(); } void WXCrystal::OnEditGridScattPowAntiBump(wxGridEvent &e) { if(mIsSelfUpdating) return; const int r=e.GetRow(); const int c=e.GetCol(); map::iterator pos=mvpRowScattPow.begin(); while(pos->second.mIdx!=r)++pos; const ScatteringPowerAtom *const p1=pos->first; pos=mvpRowScattPow.begin(); while(pos->second.mIdx!=c)++pos; const ScatteringPowerAtom *const p2=pos->first; wxString s=mpAntiBumpWin->GetCellValue(r,c); double d; s.ToDouble(&d); if(d>0.01) mpCrystal->SetBumpMergeDistance(*p1,*p2,d); else mpCrystal->RemoveBumpMergeDistance(*p1,*p2); this->CrystUpdate(true,false); } void WXCrystal::OnEditGridScattPowBondValence(wxGridEvent &e) { if(mIsSelfUpdating) return; const int r=e.GetRow(); const int c=e.GetCol(); map::iterator pos=mvpRowScattPow.begin(); while(pos->second.mIdx!=r)++pos; const ScatteringPowerAtom *const p1=pos->first; pos=mvpRowScattPow.begin(); while(pos->second.mIdx!=c)++pos; const ScatteringPowerAtom *const p2=pos->first; wxString s=mpBondValenceWin->GetCellValue(r,c); double d; s.ToDouble(&d); if(d>0.01) mpCrystal->AddBondValenceRo(*p1,*p2,d); else mpCrystal->RemoveBondValenceRo(*p1,*p2); this->CrystUpdate(true,false); } void WXCrystal::NotifyDeleteListWin(WXCrystalScrolledGridWindow *win) { if(win==mpScattPowWin) mpScattPowWin=0; if(win==mpAntiBumpWin) mpAntiBumpWin=0; if(win==mpBondValenceWin) mpBondValenceWin=0; // NOTE : all three subwindows should actually be deleted at the *same* time. if((mpScattPowWin==0)&&(mpAntiBumpWin==0)&&(mpBondValenceWin==0)) mvpRowScattPow.clear(); } /* void WXCrystal::OnMenuPDF(wxCommandEvent &event) { const unsigned int nb=1000; // Simulate data if(mpPDF!=0) delete mpPDF; mpPDF=new PDF(); CrystVector_REAL r,obs; r.resize(nb);obs.resize(nb); for(unsigned int i=0;iSetPDFObs(r,obs); PDFCrystal *pPDFCrystal=new PDFCrystal(*mpPDF,*mpCrystal); mpPDF->AddPDFPhase(*pPDFCrystal); // WX window wxFrame *frame= new wxFrame(this,-1,"PDF", wxDefaultPosition,wxSize(300,200)); WXMultiGraph* pGraph =new WXMultiGraph(frame); wxSizer *ps=new wxBoxSizer(wxHORIZONTAL); ps->Add(pGraph,1,wxEXPAND); frame->CreateStatusBar(2); frame->SetSizer(ps); frame->SetAutoLayout(true); frame->Show(true); unsigned long id=pGraph->AddGraph("PDF"); valarray vr(nb),vcalc(nb); CrystVector_REAL v2r,v2calc; v2r=mpPDF->GetPDFR(); v2calc=mpPDF->GetPDFCalc(); for(unsigned int i=0;iSetGraphData(id,vr,vcalc); pGraph->UpdateDisplay(); } */ bool WXCrystal::Enable(bool e) { if(0!=mpScattPowWin) mpScattPowWin ->Enable(e); if(0!=mpAntiBumpWin) mpAntiBumpWin ->Enable(e); if(0!=mpBondValenceWin) mpBondValenceWin->Enable(e); return this->::wxWindow::Enable(e); } #ifdef OBJCRYST_GL //////////////////////////////////////////////////////////////////////// // // UnitCellMap // //////////////////////////////////////////////////////////////////////// UnitCellMap::UnitCellMap(const Crystal&crystal): mpCrystal(&crystal) {} UnitCellMap::~UnitCellMap(){} void UnitCellMap::GLInitDisplayList(const float minValue, WXGLCrystalCanvas * parentCrystal) const { VFN_DEBUG_ENTRY("UnitCellMap::GLInitDisplayList()",10) //cout<<"Generating OpenGL Triangles for Fourier map:"<GetMapBBox(); // use cell bbox if mapbbox has zero volume (default) if (mapbbox.xMin == mapbbox.xMax) mapbbox = parentCrystal->GetCellBBox(); nxMin = (int)(mapbbox.xMin * nx); nxMax = (int)(mapbbox.xMax * nx); nyMin = (int)(mapbbox.yMin * ny); nyMax = (int)(mapbbox.yMax * ny); nzMin = (int)(mapbbox.zMin * nz); nzMax = (int)(mapbbox.zMax * nz); const int snx = nxMax-nxMin+1, sny = nyMax-nyMin+1, snz = nzMax-nzMin+1; const unsigned int sny_snz = sny*snz; int i, j, k; unsigned int ni, nj, si, sj, sk, sni, snj, sind; REAL x, y, z; //create new set of points mp4Vector * subPoints = new mp4Vector[snx*sny*snz]; for(i=nxMin, si=0; i <= nxMax; i++, si++) { ni = ((nx + i % nx) % nx); //this will 'wrap' around any value (negative or positive) sni = si*sny_snz; for(j=nyMin, sj=0; j <= nyMax; j++, sj++) { nj = ((ny + j % ny) % ny); snj = sj*snz; for(k=nzMin, sk=0; k <= nzMax; k++, sk++) { sind = sni + snj + sk; x = i*step[0]; y = j*step[1]; z = k*step[2]; mpCrystal->FractionalToOrthonormalCoords(x, y, z); subPoints[sind].x = x; subPoints[sind].y = y; subPoints[sind].z = z; //cout << ni <<" "<0) for(int j=0; j < 3; j++) { //VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnPaint():MC1:"<FractionalToOrthonormalCoords(normx, normy, normz); //mpCrystal->OrthonormalToFractionalCoords(normx, normy, normz); glNormal3f(normx, normy, normz); glVertex3f(pTriangles[i].p[j].x ,pTriangles[i].p[j].y ,pTriangles[i].p[j].z); } else for(int j=2; j >=0; j--) { //VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnPaint():MC1:"<FractionalToOrthonormalCoords(normx, normy, normz); //mpCrystal->OrthonormalToFractionalCoords(normx, normy, normz); glNormal3f(normx, normy, normz); glVertex3f(pTriangles[i].p[j].x ,pTriangles[i].p[j].y ,pTriangles[i].p[j].z); } } glEnd(); delete [] subPoints; delete [] pTriangles; VFN_DEBUG_EXIT("UnitCellMap::GLInitDisplayList():nb triangles="<FractionalToOrthonormalCoords(x, y, z); subPoints[sind].x = x; subPoints[sind].y = y; subPoints[sind].z = z; //cout << ni <<" "<FractionalToOrthonormalCoords(normx, normy, normz); //mpCrystal->OrthonormalToFractionalCoords(normx, normy, normz); os<<" ObjCrystMeshTriangle(" <>a >>b >>c >>alpha >>beta >>gamma; if(!ffile.good()) { (*fpObjCrystInformUser)("Error reading file: "+filename); return 0; } //compare dimensions with the original crystal and notify the user if not equal /* float afac = 180/M_PI, limit = 0.0001; if((a - mpWXCrystal->GetCrystal().GetLatticePar()(0)) > limit || (b - mpWXCrystal->GetCrystal().GetLatticePar()(1))> limit || (c - mpWXCrystal->GetCrystal().GetLatticePar()(2)) > limit || (alpha - mpWXCrystal->GetCrystal().GetLatticePar()(3)*afac) > limit || (beta - mpWXCrystal->GetCrystal().GetLatticePar()(4)*afac) > limit || (gamma - mpWXCrystal->GetCrystal().GetLatticePar()(5)*afac) > limit ) if(wxMessageBox(wxString::Format("Cell dimensions in the file do not match those of the crystal loaded:\n\n" + wxString("These are the value:\n") + " Crystal: File:\n a = %f a = %f\n" " b = %f b = %f\n c = %f c = %f\n alpha = %f alpha = %f\n" + " beta = %f beta = %f\n gamma = %f gamma = %f\n\nPercent errors are:\n" + " a: %f\n b: %f\n c: %f\n alpha: %f\n beta: %f\n gamma: %f\n\n\n"+ "Continue loading " + filename.c_str() + " ?", mpWXCrystal->GetCrystal().GetLatticePar()(0), a, mpWXCrystal->GetCrystal().GetLatticePar()(1), b, mpWXCrystal->GetCrystal().GetLatticePar()(2), c, mpWXCrystal->GetCrystal().GetLatticePar()(3)*afac, alpha, mpWXCrystal->GetCrystal().GetLatticePar()(4)*afac, beta,mpWXCrystal->GetCrystal().GetLatticePar()(5)*afac, gamma, fabs(a-mpWXCrystal->GetCrystal().GetLatticePar()(0)) / mpWXCrystal->GetCrystal().GetLatticePar()(0)*100, fabs(b-mpWXCrystal->GetCrystal().GetLatticePar()(1)) / mpWXCrystal->GetCrystal().GetLatticePar()(1)*100, fabs(c-mpWXCrystal->GetCrystal().GetLatticePar()(2)) / mpWXCrystal->GetCrystal().GetLatticePar()(2)*100, fabs(alpha-mpWXCrystal->GetCrystal().GetLatticePar()(3)*afac) / mpWXCrystal->GetCrystal().GetLatticePar()(3)*afac*100, fabs(beta-mpWXCrystal->GetCrystal().GetLatticePar()(4)*afac ) / mpWXCrystal->GetCrystal().GetLatticePar()(4)*afac*100, fabs(gamma-mpWXCrystal->GetCrystal().GetLatticePar()(5)*afac) / mpWXCrystal->GetCrystal().GetLatticePar()(5)*afac*100 ), "Cell Dimensions Notice", wxYES_NO | wxCENTRE, (wxWindow*)this) == wxNO) { ffile.close(); return; } */ int nx,ny,nz; ffile >>nx >>ny >>nz; if(!ffile.good()) { (*fpObjCrystInformUser)("Error reading file: "+filename); return 0; } mPoints.resize(nz,ny,nx); for(int i=0; i < nx; i++) { for(int j=0; j < ny; j++) { for(int k=0; k < nz; k++) { ffile >>mPoints(k,j,i); //reading rhos } } } ffile.close(); mMean=mPoints.sum()/(REAL)(mPoints.numElements()); mMin=mPoints.min(); mMax=mPoints.max(); { mStandardDeviation=0.0; const REAL *tmp=mPoints.data(); for(long i=0;i(long)idx))idx=idx2; if(((long)idx3!=(long)string::npos)&&((long)idx3>(long)idx))idx=idx3; if(idx==string::npos) mName=filename; else { cout<<"name="<(long)idx))idx=idx2; if(((long)idx3!=(long)string::npos)&&((long)idx3>(long)idx))idx=idx3; if(idx==string::npos) mName=filename; else { //cout<<"name="<v) { if((n-v)(v+bestdiff)) break; } v5*=5;i5+=1; if(v5>(v+bestdiff)) break; } return best; } int UnitCellMap::CalcFourierMap(const ScatteringData& data, unsigned int type0, const bool normalized_sf) { mpData=&data; const float resolution=0.3;//Approximate resolution in Ansgtroem // We need something like 2^n2 * 3^n3 * 5^n5 - just use a power of 2 now const unsigned long sizex=closest235((unsigned int)floor(mpCrystal->GetLatticePar(0)/resolution+.5)) ;//int(pow((double)2, (double)ceil(log(mpCrystal->GetLatticePar(0)/resolution)/log(2)))+.00001); const unsigned long sizey=closest235((unsigned int)floor(mpCrystal->GetLatticePar(1)/resolution+.5)) ;//int(pow((double)2, (double)ceil(log(mpCrystal->GetLatticePar(1)/resolution)/log(2)))+.00001); const unsigned long sizez=closest235((unsigned int)floor(mpCrystal->GetLatticePar(2)/resolution+.5)) ;//int(pow((double)2, (double)ceil(log(mpCrystal->GetLatticePar(2)/resolution)/log(2)))+.00001); //cout<<"UnitCellMap::CalcFourierMap():"< *pSF=&(data.GetScatteringFactor()); const ScatteringComponentList *pComp =&(mpCrystal->GetScatteringComponentList()); REAL norm0=0;// norm_sf normalized to 1 at low angle for(unsigned int i=0;iGetNbComponent();i++) { tmp=pSF->find((*pComp)(i).mpScattPow)->second;// safe enough ? tmp*=tmp; tmp*= (*pComp)(i).mOccupancy * (*pComp)(i).mDynPopCorr; const REAL sf0=(*pComp)(i).mpScattPow->GetForwardScatteringFactor(data.GetRadiationType ()); norm0+=(*pComp)(i).mOccupancy * (*pComp)(i).mDynPopCorr *sf0*sf0; norm_sf+=tmp; } REAL *p=norm_sf.data(); norm0=1/norm0; for(unsigned int i=norm_sf.numElements();i>0;i--) {*p=sqrt(*p * norm0);p++;} } // Auto-scale Fcalc and Fobs ? REAL scale_fobs=1.0; if(mType!=1) { REAL tmp=0; scale_fobs=0; for(long i=0;iGetVolume();//(REAL)(size*size*size);// mpCrystal->GetVolume(); (REAL)(size*size*size); for(long i=0;iGetSpaceGroup().GetAllEquivRefl (data.GetH()(i),data.GetK()(i),data.GetL()(i), false, data.IsIgnoringImagScattFact(), data.GetFhklCalcReal()(i),data.GetFhklCalcImag()(i)); REAL norm=1.0; if(normalized_sf) norm=1/norm_sf(i); for(int j=0;jsizex)||(abs(k*2)>sizey)||(abs(l*2)>sizez)) continue; h=(h+sizex)%sizex;// e.g. h=-1 is at nx-1 k=(k+sizey)%sizey; l=(l+sizez)%sizez; /* cout <GetSpaceGroup().IsReflCentric(data.GetH()(i),data.GetK()(i),data.GetL()(i))<<"):" <GetSpaceGroup().GetNbSymmetrics(false,false); const ScatteringComponentList *pScattCompList=&(mpCrystal->GetScatteringComponentList()); const long nbComp=pScattCompList->GetNbComponent(); for(long i=0;iGetForwardScatteringFactor(data.GetRadiationType()) *(*pScattCompList)(i).mOccupancy *(*pScattCompList)(i).mDynPopCorr *nbSymmetrics*v; } //cout<<"F(000)="<(&data); if(diff!=0) mName+=diff->GetParentPowderPattern().GetName(); } if(data.GetClassName()=="DiffractionDataSingleCrystal") { mName="S:"; if(data.GetRadiationType()==RAD_XRAY) mName+="Xray:"; if(data.GetRadiationType()==RAD_NEUTRON) mName+="Neut:"; if(data.GetRadiationType()==RAD_ELECTRON) mName+="Elec:"; char buf[100]; if(data.GetRadiation().GetWavelengthType()==WAVELENGTH_TOF) mName+="TOF:"; else { sprintf(buf,"%6.3fA:",data.GetWavelength()(0)); mName+=buf; } mName+=data.GetName(); } if(mType==0) mName="(Fo)"+mName; if(mType==1) mName="(Fc)"+mName; if(mType==2) mName="(Fo-Fc)"+mName; return 1; } #endif const string & UnitCellMap::GetName()const { return mName; } REAL UnitCellMap::GetValue(const REAL x,const REAL y,const REAL z)const { const int nx=mPoints.cols(); const int ny=mPoints.rows(); const int nz=mPoints.depth(); long ix=((long)floor(x*nx+.5))%nx; long iy=((long)floor(y*ny+.5))%ny; long iz=((long)floor(z*nz+.5))%nz; if(ix<0) ix+=nx; if(iy<0) iy+=ny; if(iz<0) iz+=nz; return mPoints(iz,iy,ix); } REAL UnitCellMap::Max()const{return mMax;} REAL UnitCellMap::Min()const{return mMin;} REAL UnitCellMap::Mean()const{return mMean;} REAL UnitCellMap::StandardDeviation()const{return mStandardDeviation;} int UnitCellMap::GetType()const{return mType;} const Crystal &UnitCellMap::GetCrystal()const{return *mpCrystal;} const ScatteringData *UnitCellMap::GetData()const{return mpData;} //////////////////////////////////////////////////////////////////////// // // UnitCellMapGLList // //////////////////////////////////////////////////////////////////////// UnitCellMapGLList::UnitCellMapGLList(const UnitCellMap &ucmap,WXGLCrystalCanvas * parent, const bool showWire,float contour, const float r,const float g,const float b,const float t): mGLDisplayList(0),mShowWire(showWire),mShow(true),mContour(contour),mpUCMap(&ucmap),mpParent(parent) { VFN_DEBUG_MESSAGE("UnitCellMapGLList::UnitCellMapGLList()",10) this->SetColour(r,g,b,t); } UnitCellMapGLList::~UnitCellMapGLList() { VFN_DEBUG_MESSAGE("UnitCellMapGLList::~UnitCellMapGLList()",10) if(0!=mGLDisplayList) glDeleteLists(mGLDisplayList,1); } void UnitCellMapGLList::GenList() { VFN_DEBUG_ENTRY("UnitCellMapGLList::GenList()",7) if(0==mGLDisplayList) mGLDisplayList=glGenLists(1); glNewList(mGLDisplayList,GL_COMPILE); glPushMatrix(); mpUCMap->GLInitDisplayList(mContour, mpParent); glPopMatrix(); glEndList(); VFN_DEBUG_EXIT("UnitCellMapGLList::GenList()",7) } void UnitCellMapGLList::SetColour(const float r,const float g,const float b, const float t) { mColour[0]=r; mColour[1]=g; mColour[2]=b; mColour[3]=t; } const float* UnitCellMapGLList::GetColour()const { return mColour; } void UnitCellMapGLList::ToggleShowWire() { mShowWire =! mShowWire; } bool UnitCellMapGLList::ShowWire()const { return mShowWire; } void UnitCellMapGLList::Draw()const { if(0==mGLDisplayList) { VFN_DEBUG_MESSAGE("UnitCellMapGLList::Draw():No Display list generated !",7) return; } glPushMatrix(); if(mShowWire) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); else glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glMaterialfv(GL_FRONT, GL_AMBIENT, mColour); glMaterialfv(GL_FRONT, GL_DIFFUSE, mColour); glMaterialfv(GL_FRONT, GL_SPECULAR, mColour); const GLfloat colour0[] = {0.0f, 0.0f, 0.0f, 0.0f}; glMaterialfv(GL_FRONT, GL_EMISSION, colour0); // :TODO: // Disabled Shininess as there is a problem with normals // and non-orthogonal unit cells glMaterialf( GL_FRONT, GL_SHININESS, 0.0); const GLfloat colorBack [] = {mColour[0]/3.0f, mColour[1]/3.0f, mColour[2]/3.0f, mColour[3]}; glMaterialfv(GL_BACK, GL_AMBIENT, colorBack); glMaterialfv(GL_BACK, GL_DIFFUSE, colorBack); glMaterialfv(GL_BACK, GL_SPECULAR, colorBack); glMaterialf( GL_BACK, GL_SHININESS, 0.0); // :TODO: Check display list is not being modified (lock it), useless for now // as the map is not dynamically updated. glCallList(mGLDisplayList); glPopMatrix(); VFN_DEBUG_EXIT("UnitCellMapGLList::Draw()",7) } void UnitCellMapGLList::SetName(const string &name) { mName=name; } const string &UnitCellMapGLList::GetName()const { return mName; } void UnitCellMapGLList::SetShow(bool show) {mShow=show;} bool UnitCellMapGLList::Show()const {return mShow;} void UnitCellMapGLList::SetContour(float contour) {mContour=contour;} float UnitCellMapGLList::GetContour()const {return mContour;} const UnitCellMap & UnitCellMapGLList::GetMap()const {return *mpUCMap;} //////////////////////////////////////////////////////////////////////// // // WXGLCrystalCanvas::WXFourierMapList // //////////////////////////////////////////////////////////////////////// WXGLCrystalCanvas::WXFourierMapList::WXFourierMapList(WXGLCrystalCanvas *pGLCrystalCanvas,wxWindow *parent): wxWindow(parent,-1),mpGLCrystalCanvas(pGLCrystalCanvas),mIsUpdating(false) { this->SetFont(wxFont(8,wxTELETYPE,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL)); wxBoxSizer* pSizer=new wxBoxSizer(wxVERTICAL); // Top buttons wxBoxSizer* pSizerButtons=new wxBoxSizer(wxHORIZONTAL); wxButton *pButtonUpdate=new wxButton(this,ID_GLCRYSTAL_FOURIER_UPDATE,_T("Update 3D View")); mpWireFrame=new wxCheckBox(this,ID_GLCRYSTAL_FOURIER_WIREFRAME,_T("Wireframe")); mpShowFourier=new wxCheckBox(this,ID_GLCRYSTAL_FOURIER_SHOW,_T("Show Fourier")); mpSharpenMap=new wxCheckBox(this,ID_GLCRYSTAL_FOURIER_SHARPEN,_T("Sharpen maps")); pSizerButtons->Add(pButtonUpdate,0,wxALIGN_CENTER); pSizerButtons->Add(mpWireFrame,0,wxALIGN_CENTER); pSizerButtons->Add(mpShowFourier,0,wxALIGN_CENTER); pSizerButtons->Add(mpSharpenMap,0,wxALIGN_CENTER); pSizer->Add(pSizerButtons,0,wxALIGN_CENTER); // Map lists wxBoxSizer* pSizerMaps=new wxBoxSizer(wxHORIZONTAL); // Left column - available maps wxBoxSizer* pSizerLeft=new wxBoxSizer(wxVERTICAL); pSizerMaps->Add(pSizerLeft,0,wxALIGN_TOP); wxStaticText *mpLabel0=new wxStaticText(this,-1,_T("Available Maps")); pSizerLeft->Add(mpLabel0,0,wxALIGN_CENTER); mpAvailableMapList=new wxListBox(this,ID_GLCRYSTAL_FOURIER_LISTMAP,wxDefaultPosition,wxSize(400,150)); pSizerLeft->Add(mpAvailableMapList,0,wxALIGN_CENTER); mpMapInfo=new wxStaticText(this,-1,_T("min=+00.00 max=+00.00 sigma=00.00")); pSizerLeft->Add(mpMapInfo,0,wxALIGN_CENTER); wxBoxSizer* pSizerLeft2=new wxBoxSizer(wxHORIZONTAL); pSizerLeft->Add(pSizerLeft2,0,wxALIGN_CENTER); wxStaticText *mpLabel2=new wxStaticText(this,-1,_T("New Contour:")); mpNewContourValue=new wxTextCtrl(this,ID_GLCRYSTAL_FOURIER_NEWCONTOUR,_T(""),wxDefaultPosition,wxDefaultSize, wxTE_PROCESS_ENTER,wxTextValidator(wxFILTER_NUMERIC)); pSizerLeft2->Add(mpLabel2,0,wxALIGN_CENTER); pSizerLeft2->Add(mpNewContourValue,0,wxALIGN_CENTER); wxButton *pButtonAdd=new wxButton(this,ID_GLCRYSTAL_FOURIER_ADD,_T("Add")); pSizerLeft->Add(pButtonAdd,0,wxALIGN_CENTER); pSizerMaps->AddSpacer(5); // Right column - displayed maps & contours wxBoxSizer* pSizerRight=new wxBoxSizer(wxVERTICAL); pSizerMaps->Add(pSizerRight,0,wxALIGN_TOP); wxStaticText *mpLabel0r=new wxStaticText(this,-1,_T("Displayed Maps")); pSizerRight->Add(mpLabel0r,0,wxALIGN_CENTER); mpDisplayedMapList=new wxListBox(this,ID_GLCRYSTAL_FOURIER_LISTGLMAP,wxDefaultPosition,wxSize(400,150)); pSizerRight->Add(mpDisplayedMapList,0,wxALIGN_CENTER); wxBoxSizer* pSizerRight1=new wxBoxSizer(wxHORIZONTAL); pSizerRight->Add(pSizerRight1,0,wxALIGN_CENTER); wxStaticText *mpLabel3=new wxStaticText(this,-1,_T("Contour:")); mpContourValue=new wxTextCtrl(this,ID_GLCRYSTAL_FOURIER_CONTOUR,_T(""),wxDefaultPosition,wxDefaultSize, wxTE_PROCESS_ENTER,wxTextValidator(wxFILTER_NUMERIC)); pSizerRight1->Add(mpLabel3,0,wxALIGN_CENTER); pSizerRight1->Add(mpContourValue,0,wxALIGN_CENTER); mpColourPicker=new wxColourPickerCtrl(this, ID_GLCRYSTAL_FOURIER_COLOURPICKER, *wxRED, wxDefaultPosition, wxDefaultSize,wxCLRP_USE_TEXTCTRL); wxButton *pButtonRemove=new wxButton(this,ID_GLCRYSTAL_FOURIER_REMOVE,_T("Remove")); pSizerRight->Add(mpColourPicker,0,wxALIGN_CENTER); pSizerRight->Add(pButtonRemove,0,wxALIGN_CENTER); pSizer->Add(pSizerMaps,0,wxALIGN_CENTER); this->SetSizer(pSizer); this->SetAutoLayout(true); pSizer->SetSizeHints(this); pSizer->SetSizeHints(parent); this->Layout(); } WXGLCrystalCanvas::WXFourierMapList::~WXFourierMapList() { mpGLCrystalCanvas->NotifyDeleteFourierWin(); } struct GLCrystalConfig { GLCrystalConfig(const bool saved=false); float mDist; REAL mX0, mY0,mZ0; float mViewAngle; float mQuat [4]; bool mSaved; bool mShowAtomName; bool mShowCursor; BBox mcellbbox; BBox mmapbbox; Triple mViewCntr; }; GLCrystalConfig::GLCrystalConfig(const bool saved) { mSaved=saved; } static GLCrystalConfig sGLCrystalConfig; //////////////////////////////////////////////////////////////////////// // // WXGLCrystalCanvas // //////////////////////////////////////////////////////////////////////// static const long ID_GLCRYSTAL_MENU_SHOWATOMLABEL= WXCRYST_ID(); static const long ID_GLCRYSTAL_MENU_SHOWHYDROGENS= WXCRYST_ID(); static const long ID_GLCRYSTAL_MENU_SHOWCURSOR= WXCRYST_ID(); static const long ID_GLCRYSTAL_MENU_SETCURSOR= WXCRYST_ID(); static const long ID_GLCRYSTAL_UPDATEUI= WXCRYST_ID(); static const long ID_GLCRYSTAL_MENU_CHANGELIMITS= WXCRYST_ID(); static const long ID_GLCRYSTAL_MENU_LIMITS_FULLCELL= WXCRYST_ID(); static const long ID_GLCRYSTAL_MENU_LIMITS_ASYMCELL= WXCRYST_ID(); static const long ID_GLCRYSTAL_MENU_SHOWCRYSTAL= WXCRYST_ID(); static const long ID_GLCRYSTAL_MENU_FOURIER= WXCRYST_ID(); static const long ID_GLCRYSTAL_MENU_LOADFOURIERGRD= WXCRYST_ID(); static const long ID_GLCRYSTAL_MENU_LOADFOURIERDSN6= WXCRYST_ID(); //static const long ID_GLCRYSTAL_MENU_UNLOADFOURIER= WXCRYST_ID(); static const long ID_GLCRYSTAL_MENU_POVRAY= WXCRYST_ID(); static const long ID_GLCRYSTAL_MENU_SHOWHELP= WXCRYST_ID(); BEGIN_EVENT_TABLE(WXGLCrystalCanvas, wxGLCanvas) EVT_PAINT (WXGLCrystalCanvas::OnPaint) EVT_ERASE_BACKGROUND (WXGLCrystalCanvas::OnEraseBackground) EVT_MOUSE_EVENTS (WXGLCrystalCanvas::OnMouse) EVT_MENU (ID_GLCRYSTAL_MENU_UPDATE, WXGLCrystalCanvas::OnUpdate) EVT_MENU (ID_GLCRYSTAL_MENU_CHANGELIMITS, WXGLCrystalCanvas::OnChangeLimits) EVT_MENU (ID_GLCRYSTAL_MENU_LIMITS_FULLCELL, WXGLCrystalCanvas::OnChangeLimits) EVT_MENU (ID_GLCRYSTAL_MENU_LIMITS_ASYMCELL, WXGLCrystalCanvas::OnChangeLimits) EVT_MENU (ID_GLCRYSTAL_MENU_SHOWCRYSTAL, WXGLCrystalCanvas::OnShowCrystal) EVT_MENU (ID_GLCRYSTAL_MENU_SHOWATOMLABEL, WXGLCrystalCanvas::OnShowAtomLabel) EVT_MENU (ID_GLCRYSTAL_MENU_SHOWHYDROGENS, WXGLCrystalCanvas::OnShowHydrogens) EVT_MENU (ID_GLCRYSTAL_MENU_SHOWCURSOR, WXGLCrystalCanvas::OnShowCursor) EVT_MENU (ID_GLCRYSTAL_MENU_SETCURSOR, WXGLCrystalCanvas::OnSetCursor) EVT_MENU (ID_GLCRYSTAL_MENU_SHOWHELP, WXGLCrystalCanvas::OnShowHelp) EVT_MENU (ID_GLCRYSTAL_MENU_LOADFOURIERGRD, WXGLCrystalCanvas::OnLoadFourierGRD) EVT_MENU (ID_GLCRYSTAL_MENU_LOADFOURIERDSN6, WXGLCrystalCanvas::OnLoadFourierDSN6) // EVT_MENU (ID_GLCRYSTAL_MENU_UNLOADFOURIER, WXGLCrystalCanvas::OnUnloadFourier) EVT_MENU (ID_GLCRYSTAL_MENU_POVRAY, WXGLCrystalCanvas::OnPOVRay) EVT_MENU (ID_GLCRYSTAL_MENU_FOURIER, WXGLCrystalCanvas::OnFourier) EVT_LISTBOX (ID_GLCRYSTAL_FOURIER_LISTGLMAP, WXGLCrystalCanvas::OnFourier) EVT_LISTBOX (ID_GLCRYSTAL_FOURIER_LISTMAP, WXGLCrystalCanvas::OnFourier) EVT_BUTTON (ID_GLCRYSTAL_FOURIER_ADD, WXGLCrystalCanvas::OnFourier) EVT_BUTTON (ID_GLCRYSTAL_FOURIER_REMOVE, WXGLCrystalCanvas::OnFourier) EVT_BUTTON (ID_GLCRYSTAL_FOURIER_UPDATE, WXGLCrystalCanvas::OnFourier) EVT_CHECKBOX (ID_GLCRYSTAL_FOURIER_WIREFRAME, WXGLCrystalCanvas::OnFourier) EVT_CHECKBOX (ID_GLCRYSTAL_FOURIER_SHOW, WXGLCrystalCanvas::OnFourier) EVT_CHECKBOX (ID_GLCRYSTAL_FOURIER_SHARPEN, WXGLCrystalCanvas::OnFourier) EVT_TEXT_ENTER (ID_GLCRYSTAL_FOURIER_NEWCONTOUR, WXGLCrystalCanvas::OnFourier) EVT_TEXT_ENTER (ID_GLCRYSTAL_FOURIER_CONTOUR, WXGLCrystalCanvas::OnFourier) EVT_COLOURPICKER_CHANGED(ID_GLCRYSTAL_FOURIER_COLOURPICKER, WXGLCrystalCanvas::OnFourierChangeColour) EVT_CHAR (WXGLCrystalCanvas::OnKeyDown) EVT_KEY_DOWN (WXGLCrystalCanvas::OnKeyDown) EVT_KEY_UP (WXGLCrystalCanvas::OnKeyUp) EVT_UPDATE_UI(ID_GLCRYSTAL_UPDATEUI,WXGLCrystalCanvas::OnUpdateUI) END_EVENT_TABLE() int AttribList [] = {WX_GL_RGBA , WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 16,0}; WXGLCrystalCanvas::WXGLCrystalCanvas(WXCrystal *wxcryst, wxFrame *parent, wxWindowID id, const wxPoint &pos, const wxSize &size): wxGLCanvas(parent, id,AttribList,pos,size,wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE,_T("GLCanvas"),wxNullPalette), //wxGLCanvas(parent,id,pos,size,wxDEFAULT_FRAME_STYLE,_T("GLCanvas"),AttribList), mpParentFrame(parent), mpWXCrystal(wxcryst),mIsGLInit(false),mDist(60),mX0(0),mY0(0),mZ0(0),mViewAngle(15), mShowFourier(true),mShowCrystal(true),mShowAtomName(true),mShowHydrogens(true), mShowCursor(false),mSharpenMap(true),mShowHelp(false),mShowFullMolecule(false), mWhiteBackground(false), mIsGLFontBuilt(false),mGLFontDisplayListBase(0),mpFourierMapListWin(0),mFadeDistance(0) { mpwxGLContext=new wxGLContext(this); VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::WXGLCrystalCanvas()",3) if(sGLCrystalConfig.mSaved) { mDist=sGLCrystalConfig.mDist; mX0=sGLCrystalConfig.mX0; mY0=sGLCrystalConfig.mY0; mZ0=sGLCrystalConfig.mZ0; mViewAngle=sGLCrystalConfig.mViewAngle; for(int i=0;i<4;++i) mQuat[i]=sGLCrystalConfig.mQuat[i]; mShowAtomName=sGLCrystalConfig.mShowAtomName; mShowCursor=sGLCrystalConfig.mShowCursor; mcellbbox.xMin=sGLCrystalConfig.mcellbbox.xMin; mcellbbox.xMax=sGLCrystalConfig.mcellbbox.xMax; mcellbbox.yMin=sGLCrystalConfig.mcellbbox.yMin; mcellbbox.yMax=sGLCrystalConfig.mcellbbox.yMax; mcellbbox.zMin=sGLCrystalConfig.mcellbbox.zMin; mcellbbox.zMax=sGLCrystalConfig.mcellbbox.zMax; mmapbbox.xMin=sGLCrystalConfig.mmapbbox.xMin; mmapbbox.xMax=sGLCrystalConfig.mmapbbox.xMax; mmapbbox.yMin=sGLCrystalConfig.mmapbbox.yMin; mmapbbox.yMax=sGLCrystalConfig.mmapbbox.yMax; mmapbbox.zMin=sGLCrystalConfig.mmapbbox.zMin; mmapbbox.zMax=sGLCrystalConfig.mmapbbox.zMax; mViewCntr.x=sGLCrystalConfig.mViewCntr.x; mViewCntr.y=sGLCrystalConfig.mViewCntr.y; mViewCntr.z=sGLCrystalConfig.mViewCntr.z; } else { mcellbbox.xMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Xmin(); mcellbbox.yMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Ymin(); mcellbbox.zMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Zmin(); mcellbbox.xMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Xmax(); mcellbbox.yMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Ymax(); mcellbbox.zMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Zmax(); } // N.B. xMin=xMax so that the previous cell bbox is used for Maps // until mmapbbox is changed mmapbbox.xMin = mmapbbox.xMax = mmapbbox.yMin = mmapbbox.zMin = 0.; mmapbbox.yMax = mmapbbox.zMax = 1.; mpPopUpMenu=new wxMenu(_T("Crystal")); mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_UPDATE, _T("&Update")); mpPopUpMenu->AppendSeparator(); mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_CHANGELIMITS, _T("Change display &Limits")); mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_LIMITS_FULLCELL, _T("Show Full Unit Cell")); mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_LIMITS_ASYMCELL, _T("Show Asymmetric Unit Cell")); mpPopUpMenu->AppendSeparator(); mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_SHOWCRYSTAL, _T("Hide Crystal")); mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_SHOWATOMLABEL, _T("Hide Atom Labels")); mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_SHOWHYDROGENS, _T("Hide Hydrogens")); mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_SHOWCURSOR, _T("Show Cursor")); mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_SETCURSOR, _T("Set view cntr and cursor pos.")); mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_POVRAY, _T("Create POVRay file")); mpPopUpMenu->AppendSeparator(); mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_FOURIER, _T("Fourier Maps")); mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_LOADFOURIERGRD, _T("Load GRD Fourier Map")); mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_LOADFOURIERDSN6,_T("Load DSN6 Fourier Map")); mpPopUpMenu->AppendSeparator(); mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_SHOWHELP, _T("Show &Help")); /* mpPopUpMenu->Append(ID_GLCRYSTAL_MENU_UNLOADFOURIER, "Unload Fourier Map(s)"); mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_UNLOADFOURIER, FALSE); */ if(sGLCrystalConfig.mSaved==false) { if(!wxConfigBase::Get()->HasEntry(_T("Crystal/BOOL/Default-display only asymmetric unit cell in 3D view"))) wxConfigBase::Get()->Write(_T("Crystal/BOOL/Default-display only asymmetric unit cell in 3D view"), true); else { bool val; wxConfigBase::Get()->Read(_T("Crystal/BOOL/Default-display only asymmetric unit cell in 3D view"), &val); if(val) { mcellbbox.xMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Xmin(); mcellbbox.yMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Ymin(); mcellbbox.zMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Zmin(); mcellbbox.xMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Xmax(); mcellbbox.yMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Ymax(); mcellbbox.zMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Zmax(); } else { mcellbbox.xMin = 0; mcellbbox.yMin = 0; mcellbbox.zMin = 0; mcellbbox.xMax = 1; mcellbbox.yMax = 1; mcellbbox.zMax = 1; } } if(!wxConfigBase::Get()->HasEntry(_T("Crystal/BOOL/Default-display atom names in 3D view"))) wxConfigBase::Get()->Write(_T("Crystal/BOOL/Default-display atom names in 3D view"), mShowAtomName); else { wxConfigBase::Get()->Read(_T("Crystal/BOOL/Default-display atom names in 3D view"), &mShowAtomName); } } // Fade distance for showing transparent atoms beyond display limit if(!wxConfigBase::Get()->HasEntry(_T("Crystal/REAL/3D fade distance"))) wxConfigBase::Get()->Write(_T("Crystal/REAL/3D fade distance"), 4); wxConfigBase::Get()->Read(_T("Crystal/REAL/3D fade distance"), &mFadeDistance); // Show full molecules for those centered inside the display limits ? if(!wxConfigBase::Get()->HasEntry(_T("Crystal/BOOL/Show full molecules in 3D view"))) wxConfigBase::Get()->Write(_T("Crystal/BOOL/Show full molecules in 3D view"), mShowFullMolecule); wxConfigBase::Get()->Read(_T("Crystal/BOOL/Show full molecules in 3D view"), &mShowFullMolecule); if(mShowAtomName) mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWATOMLABEL, _T("Hide Atom Labels")); else mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWATOMLABEL, _T("Show Atom Labels")); } WXGLCrystalCanvas::~WXGLCrystalCanvas() { mpWXCrystal->NotifyCrystalGLDelete(); #ifndef HAVE_GLUT this->DeleteGLFont(); #endif // The frame position is saved in ~WXGLCrystalCanvasFrame() to store position before the frame decoration are destroyed sGLCrystalConfig.mDist = mDist; sGLCrystalConfig.mX0=mX0; sGLCrystalConfig.mY0=mY0; sGLCrystalConfig.mZ0=mZ0; sGLCrystalConfig.mViewAngle=mViewAngle; for(int i=0;i<4;++i) sGLCrystalConfig.mQuat[i]=mQuat[i]; sGLCrystalConfig.mShowAtomName=mShowAtomName; sGLCrystalConfig.mShowCursor=mShowCursor; sGLCrystalConfig.mcellbbox.xMin=mcellbbox.xMin; sGLCrystalConfig.mcellbbox.xMax=mcellbbox.xMax; sGLCrystalConfig.mcellbbox.yMin=mcellbbox.yMin; sGLCrystalConfig.mcellbbox.yMax=mcellbbox.yMax; sGLCrystalConfig.mcellbbox.zMin=mcellbbox.zMin; sGLCrystalConfig.mcellbbox.zMax=mcellbbox.zMax; sGLCrystalConfig.mmapbbox.xMin=mmapbbox.xMin; sGLCrystalConfig.mmapbbox.xMax=mmapbbox.xMax; sGLCrystalConfig.mmapbbox.yMin=mmapbbox.yMin; sGLCrystalConfig.mmapbbox.yMax=mmapbbox.yMax; sGLCrystalConfig.mmapbbox.zMin=mmapbbox.zMin; sGLCrystalConfig.mmapbbox.zMax=mmapbbox.zMax; sGLCrystalConfig.mViewCntr.x=mViewCntr.x; sGLCrystalConfig.mViewCntr.y=mViewCntr.y; sGLCrystalConfig.mViewCntr.z=mViewCntr.z; sGLCrystalConfig.mSaved=true; delete mpwxGLContext; } void WXGLCrystalCanvas::OnExit(wxCommandEvent &event) { } void WXGLCrystalCanvas::OnPaint(wxPaintEvent &event) { VFN_DEBUG_ENTRY("WXGLCrystalCanvas::OnPaint()",7) wxPaintDC dc(this); this->SetCurrent(); if(false==mIsGLInit) { mIsGLInit=true; this->InitGL(); } { int width, height; GetClientSize(& width, & height); this->SetCurrent(); glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if( (width>0)&&(height>0)) //in case the window is docked... gluPerspective(mViewAngle,(float)width/(float)height,1.f,2.*mDist); } glMatrixMode( GL_MODELVIEW ); //clear if(mWhiteBackground) glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // White background else glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Black background glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); //Orientation using the trackball GLfloat m[4][4]; glLoadIdentity(); glTranslatef( 0, 0, -mDist ); build_rotmatrix( m,mQuat); glMultMatrixf( &m[0][0] ); glTranslatef( mX0, mY0, mZ0 ); //Draw first non-transparent object then transparent ones for(unsigned int passnum = 0; passnum<2; passnum++) { if (passnum == 0) { glDepthMask(GL_TRUE); glAlphaFunc(GL_GREATER,0.99); } else { glDepthMask(GL_FALSE); glAlphaFunc(GL_LEQUAL,0.99); } if(mShowCrystal) { glLoadIdentity(); if(mWhiteBackground) glColor3f(0.0,0.0,0.0); else glColor3f(1.0,1.0,1.0); glTranslatef(0, 0, -mDist); glMultMatrixf(&m[0][0]); glTranslatef(mX0, mY0, mZ0); glCallList(mpWXCrystal->GetCrystalGLDisplayList()); //Draw Crystal if(mShowAtomName) { glLoadIdentity(); if(mWhiteBackground) glColor3f(0.0,0.0,0.0); else glColor3f(1.0,1.0,1.0); glTranslatef( -0.3, 0, -mDist+1. );// Put labels in front of the atom position glMultMatrixf( &m[0][0] ); glTranslatef( mX0, mY0, mZ0 ); glCallList(mpWXCrystal->GetCrystalGLDisplayList(true)); //Draw Atom Names } } {//Show display limits and help text int w, h; GetClientSize(& w, & h); GLfloat colour2 [] = {1.00, 1.00, 1.00, 0.3}; if(mWhiteBackground) for(unsigned int i=0;i<3;i++) colour2[i] = 0.0; else for(unsigned int i=0;i<3;i++) colour2[i] = 1.0; glMaterialfv(GL_FRONT, GL_EMISSION, colour2); glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluOrtho2D(0,w,0,h); if(mWhiteBackground) glColor3f(0.0,0.0,0.0); else glColor3f(1.0,1.0,1.0); unsigned int i=1; glRasterPos2i(2,h-12*i); char c[256]; sprintf(c,"%5.3fGetCrystal().OrthonormalToFractionalCoords(x,y,z); x=(mcellbbox.xMax+mcellbbox.xMin)/2.-x; y=(mcellbbox.yMax+mcellbbox.yMin)/2.-y; z=(mcellbbox.zMax+mcellbbox.zMin)/2.-z; statusText.Printf(_T("Center@(%5.3f,%5.3f,%5.3f)"),x,y,z); for(unsigned int i=0;iGetName().c_str()) +wxString::Format(_T(")=%5.2fe"),mvpUnitCellMap[i]->GetValue(x,y,z)); } mpParentFrame->SetStatusText(statusText); } if (mShowFourier && (passnum==0)) { glAlphaFunc(GL_ALWAYS,1); glLoadIdentity(); glTranslatef( 0, 0, -mDist ); build_rotmatrix( m,mQuat); glMultMatrixf( &m[0][0] ); glTranslatef( mX0, mY0, mZ0 ); glPushMatrix(); // The display origin is the center of the Crystal BoundingBox, so translate BBox cellbbox = this->GetCellBBox(); REAL xc=(cellbbox.xMin+cellbbox.xMax)/2.; REAL yc=(cellbbox.yMin+cellbbox.yMax)/2.; REAL zc=(cellbbox.zMin+cellbbox.zMax)/2.; mpWXCrystal->GetCrystal().FractionalToOrthonormalCoords(xc, yc, zc); glTranslatef(-xc, -yc, -zc); // Draw all Fourier maps vector >::const_iterator pos; for(pos=mvpUnitCellMapGLList.begin();pos != mvpUnitCellMapGLList.end();++pos) if((*pos)->Show()) (*pos)->Draw(); glPopMatrix(); } } glDepthMask(GL_TRUE); glAlphaFunc(GL_ALWAYS,1); glFlush(); SwapBuffers(); VFN_DEBUG_EXIT("WXGLCrystalCanvas::OnPaint():End",7) } void WXGLCrystalCanvas::OnEraseBackground(wxEraseEvent& event) { } void WXGLCrystalCanvas::OnKeyDown(wxKeyEvent& event) { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnKeyDown():"<0)&&(height>0)) //in case size is null... gluPerspective(mViewAngle,(float)width/(float)height, (mDist>100)?(mDist-100):1.,mDist+100); Refresh(FALSE); break; } case(43):// - { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnKeyDown():Smaller",2) int width, height; GetClientSize(& width, & height); mDist *= .95; SetCurrent(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if( (width>0)&&(height>0)) //in case size is null... gluPerspective(mViewAngle,(float)width/(float)height, (mDist>100)?(mDist-100):1.,mDist+100); Refresh(FALSE); break; } case(WXK_INSERT): mY0 += 0.1; Refresh(FALSE); break; case(WXK_DELETE): mY0 -= 0.1; Refresh(FALSE); break; case(WXK_HOME): mX0 -= 0.1; Refresh(FALSE); break; case(WXK_END): mX0 += 0.1; Refresh(FALSE); break; case(WXK_PAGEUP): mZ0 -= 0.1; Refresh(FALSE); break; case(WXK_PAGEDOWN): mZ0 += 0.1; Refresh(FALSE); break; case(52):// 4 { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnKeyDown():rotate left",2) float spin_quat[4]; trackball(spin_quat,0,0,-.05,0); add_quats( spin_quat, mQuat, mQuat ); Refresh(FALSE); break; } case(54):// 6 { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnKeyDown():rotate right",2) float spin_quat[4]; trackball(spin_quat,0,0,.05,0); add_quats( spin_quat, mQuat, mQuat ); Refresh(FALSE); break; } case(50):// 2 { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnKeyDown():rotate down",2) float spin_quat[4]; trackball(spin_quat,0,0,0,-.05); add_quats( spin_quat, mQuat, mQuat ); Refresh(FALSE); break; } case(56):// 8 { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnKeyDown():rotate up",2) float spin_quat[4]; trackball(spin_quat,0,0,0,.05); add_quats( spin_quat, mQuat, mQuat ); Refresh(FALSE); break; } case(68):// D { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnKeyDown():rotate left",2) float spin_quat[4]; trackball(spin_quat,0,0,-.05,0); add_quats( spin_quat, mQuat, mQuat ); Refresh(FALSE); break; } case(70):// F { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnKeyDown():rotate right",2) float spin_quat[4]; trackball(spin_quat,0,0,.05,0); add_quats( spin_quat, mQuat, mQuat ); Refresh(FALSE); break; } case(67):// C { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnKeyDown():rotate down",2) float spin_quat[4]; trackball(spin_quat,0,0,0,-.05); add_quats( spin_quat, mQuat, mQuat ); Refresh(FALSE); break; } case(66):// B { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnKeyDown():toggle black/white background",2) mWhiteBackground = !mWhiteBackground; Refresh(FALSE); break; } case(82):// R { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnKeyDown():rotate up",2) float spin_quat[4]; trackball(spin_quat,0,0,0,.05); add_quats( spin_quat, mQuat, mQuat ); Refresh(FALSE); break; } case(72):// H { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnKeyDown():toggle help",2) mShowHelp = !mShowHelp; Refresh(FALSE); break; } case(76):// L { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnKeyDown():toggle atom labels",2) mShowAtomName = !mShowAtomName; Refresh(FALSE); break; } case(77):// M { mShowFullMolecule = !mShowFullMolecule; wxConfigBase::Get()->Write(_T("Crystal/BOOL/Show full molecules in 3D view"), mShowFullMolecule); VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnKeyDown():toggle showing full molecules: "<GetCrystal().IsBeingRefined())) mpWXCrystal->UpdateGL(false, mcellbbox.xMin,mcellbbox.xMax, mcellbbox.yMin,mcellbbox.yMax, mcellbbox.zMin,mcellbbox.zMax, mFadeDistance, mShowFullMolecule); break; } case(89):// y { mShowHydrogens = !mShowHydrogens; // Should be done with an event ? if(!(mpWXCrystal->GetCrystal().IsBeingRefined())) mpWXCrystal->UpdateGL(false, mcellbbox.xMin,mcellbbox.xMax, mcellbbox.yMin,mcellbbox.yMax, mcellbbox.zMin,mcellbbox.zMax, mFadeDistance, mShowFullMolecule); break; } case(WXK_F1): { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnKeyDown():F1",2) if(event.ShiftDown()) { mcellbbox.xMin -= 0.05; mcellbbox.xMax -= 0.05; } else { if((mcellbbox.xMax-mcellbbox.xMin)>0.1) { mcellbbox.xMin += 0.05; mcellbbox.xMax -= 0.05; } } break; } case(WXK_F2): { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnKeyDown():F2",2) if(event.ShiftDown()) { mcellbbox.xMin += 0.05; mcellbbox.xMax += 0.05; } else { mcellbbox.xMin -= 0.05; mcellbbox.xMax += 0.05; } break; } case(WXK_F3): { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnKeyDown():F3",2) if(event.ShiftDown()) { mcellbbox.yMin -= 0.05; mcellbbox.yMax -= 0.05; } else { if((mcellbbox.yMax-mcellbbox.yMin)>0.1) { mcellbbox.yMin += 0.05; mcellbbox.yMax -= 0.05; } } break; } case(WXK_F4): { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnKeyDown():F4",2) if(event.ShiftDown()) { mcellbbox.yMin += 0.05; mcellbbox.yMax += 0.05; } else { mcellbbox.yMin -= 0.05; mcellbbox.yMax += 0.05; } break; } case(WXK_F5): { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnKeyDown():F5",2) if(event.ShiftDown()) { mcellbbox.zMin -= 0.05; mcellbbox.zMax -= 0.05; } else { if((mcellbbox.zMax-mcellbbox.zMin)>0.1) { mcellbbox.zMin += 0.05; mcellbbox.zMax -= 0.05; } } break; } case(WXK_F6): { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnKeyDown():F6",2) if(event.ShiftDown()) { mcellbbox.zMin += 0.05; mcellbbox.zMax += 0.05; } else { mcellbbox.zMin -= 0.05; mcellbbox.zMax += 0.05; } break; } case(WXK_F7): { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnKeyDown():F5",2) mFadeDistance -=0.5; if(mFadeDistance<0) { mFadeDistance=0; } break; } case(WXK_F8): { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnKeyDown():F6",2) mFadeDistance+=0.5; break; } case(WXK_F9): { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnKeyDown():F9",2) mcellbbox.xMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Xmin(); mcellbbox.yMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Ymin(); mcellbbox.zMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Zmin(); mcellbbox.xMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Xmax(); mcellbbox.yMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Ymax(); mcellbbox.zMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Zmax(); break; } case(WXK_F10): { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnKeyDown():F10",2) mcellbbox.xMin = 0; mcellbbox.yMin = 0; mcellbbox.zMin = 0; mcellbbox.xMax = 1; mcellbbox.yMax = 1; mcellbbox.zMax = 1; break; } default: { cout<<"WXGLCrystalCanvas::OnKeyDown(): Unknown KeyCode: "<GetCrystal().IsBeingRefined())) mpWXCrystal->UpdateGL(false, mcellbbox.xMin,mcellbbox.xMax, mcellbbox.yMin,mcellbbox.yMax, mcellbbox.zMin,mcellbbox.zMax, mFadeDistance, mShowFullMolecule); } } void WXGLCrystalCanvas::OnKeyUp(wxKeyEvent& event) { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnKeyUp():"<UnProject(vx1,vy1,vz1); this->UnProject(vx2,vy2,vz2); mX0 += vx2-vx1; mY0 += vy2-vy1; mZ0 += vz2-vz1; VFN_DEBUG_MESSAGE("Origin (ortho) = "<0)&&(height>0)) //in case size is null... gluPerspective(mViewAngle,(float)width/(float)height, (mDist>101)?(mDist-100):1.,mDist+100); Refresh(FALSE); VFN_DEBUG_MESSAGE(mViewAngle <<" "<GetCrystal().IsBeingRefined()) { mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_UPDATE, false); mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_POVRAY, false); mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_LOADFOURIERGRD, false); mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_LOADFOURIERDSN6, false); } else { mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_UPDATE, true); mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_POVRAY, true); mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_LOADFOURIERGRD, true); mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_LOADFOURIERDSN6, true); } this->PopupMenu(mpPopUpMenu, event.GetX(), event.GetY() ); } else if (event.GetWheelDelta()>0) {// Double-touch event on OSX + trackpad if(event.ControlDown()) { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnMouse(): Mouse Wheel / double touch + control (OSX: command)",2) //Change zoom / angle int width, height; GetClientSize(& width, & height); const int delta=event.GetWheelDelta(); const int rotation=event.GetWheelRotation(); if(event.GetWheelAxis()==0) mDist *= (1.+float(rotation)/100.); else { mDist /= (1.+float(rotation)/100.); mViewAngle *=(1.+float(rotation)/100.); } SetCurrent(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if( (width>0)&&(height>0)) //in case size is null... gluPerspective(mViewAngle,(float)width/(float)height, (mDist>101)?(mDist-100):1.,mDist+100); Refresh(FALSE); VFN_DEBUG_MESSAGE(mViewAngle <<" "<UpdateGL(false, mcellbbox.xMin,mcellbbox.xMax, mcellbbox.yMin,mcellbbox.yMax, mcellbbox.zMin,mcellbbox.zMax, mFadeDistance, mShowFullMolecule); VFN_DEBUG_EXIT("WXGLCrystalCanvas::OnUpdate()",4) } void WXGLCrystalCanvas::CrystUpdate() { // This can only be called from the main (graphical) thread VFN_DEBUG_ENTRY("WXGLCrystalCanvas::CrystUpdate():"<mMutex.Lock(); // Remove maps that cannot be computed any more for(vector >::iterator pos=mvpUnitCellMap.begin();pos!=mvpUnitCellMap.end();) { bool keep=false; if((*pos)->GetType()==3) keep=true; if(((*pos)->GetType()==0)||((*pos)->GetType()==2)) { /* cout<<"WXGLCrystalCanvas::CrystUpdate()"<GetName()<<(*pos)->GetType()<<" " <GetCrystal().GetScatteringComponentList().GetNbComponent()<<"," <<(*pos)->GetData()->GetFhklObsSq().numElements()<GetCrystal().GetClientRegistry().Find((RefinableObj*)(*pos)->GetData())>=0) if(mpWXCrystal->GetCrystal().GetScatteringComponentList().GetNbComponent()>0) if((*pos)->GetData()->GetFhklObsSq().numElements()>0) keep=true; } if((*pos)->GetType()==1) { if(mpWXCrystal->GetCrystal().GetClientRegistry().Find((RefinableObj*)(*pos)->GetData())>=0) if(mpWXCrystal->GetCrystal().GetScatteringComponentList().GetNbComponent()>0) keep=true; } VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::CrystUpdate()"<<(*pos)->GetName()<<(*pos)->GetType()<<": keep="< >::iterator posgl=mvpUnitCellMapGLList.begin();posgl!=mvpUnitCellMapGLList.end();) { if(&(**pos)==&((*posgl)->GetMap())) { VFN_DEBUG_MESSAGE("Erasing GL map:"<<(*posgl)->GetName(),8) posgl=mvpUnitCellMapGLList.erase(posgl); } else ++posgl; } pos=mvpUnitCellMap.erase(pos); } else { if((*pos)->GetType()!=3) { #ifdef HAVE_FFTW // During optimization, only update Fourier maps if one is displayed or the Fourier win is opened if( (mvpUnitCellMapGLList.size()>0) ||(!(mpWXCrystal->GetCrystal().IsBeingRefined())) ||(mpFourierMapListWin!=0)) (*pos)->CalcFourierMap(*((*pos)->GetData()),(*pos)->GetType(),mSharpenMap); #endif } ++pos; } } #ifdef HAVE_FFTW // Add newly computable maps if(mpWXCrystal->GetCrystal().GetScatteringComponentList().GetNbComponent()>0) for(int i=0;iGetCrystal().GetClientRegistry().GetNb();++i) { ScatteringData* data=dynamic_cast(&(mpWXCrystal->GetCrystal().GetClientRegistry().GetObj(i))); if(data!=0) { // Add if not already listed bool addCalcMap=true,addObsDiffMaps=true; for(vector >::iterator pos=mvpUnitCellMap.begin();pos!=mvpUnitCellMap.end();++pos) if((*pos)->GetData()==data) { if((*pos)->GetType()==1) addCalcMap=false; if((*pos)->GetType()==0) addObsDiffMaps=false;//type==2 will also be there } //cout<<__FILE__<<":"<<__LINE__<<":WXGLCrystalCanvas::CrystUpdate()" // <GetNbRefl()>0)) { mvpUnitCellMap.push_back(boost::shared_ptr(new UnitCellMap(mpWXCrystal->GetCrystal()))); mvpUnitCellMap.back()->CalcFourierMap(*data,1); VFN_DEBUG_MESSAGE("Added GL map:"<GetName(),8) } if(addObsDiffMaps && (data->GetFhklObsSq().numElements()>0) ) { mvpUnitCellMap.push_back(boost::shared_ptr(new UnitCellMap(mpWXCrystal->GetCrystal()))); mvpUnitCellMap.back()->CalcFourierMap(*data,0); VFN_DEBUG_MESSAGE("Added GL map:"<GetName()<<":"<GetFhklObsSq().numElements(),8) mvpUnitCellMap.push_back(boost::shared_ptr(new UnitCellMap(mpWXCrystal->GetCrystal()))); mvpUnitCellMap.back()->CalcFourierMap(*data,2); VFN_DEBUG_MESSAGE("Added GL map:"<GetName()<<":"<GetFhklObsSq().numElements(),8) } } } #endif //update GL maps for(vector >::iterator pos=mvpUnitCellMapGLList.begin();pos!=mvpUnitCellMapGLList.end();++pos) { //cout<<"Updating GL map:"<<(*pos)->GetName()<GenList(); } if(mpFourierMapListWin!=0) mpFourierMapListWin->mMutex.Unlock(); VFN_DEBUG_EXIT("WXGLCrystalCanvas::CrystUpdate()",10) wxUpdateUIEvent event(ID_GLCRYSTAL_UPDATEUI); wxPostEvent(this,event); /* // To make a movie if(mpWXCrystal->GetCrystal().IsBeingRefined()) { // Export POV-Ray file to make a movie char povFile[40]; time_t date=time(0); strftime(povFile,sizeof(povFile),"pov/%Y%m%d-%Hh%Mm%Ss%Z.pov",gmtime(&date));//%Y-%m-%dT%H:%M:%S%Z this->POVRayOutput(povFile); } */ } void WXGLCrystalCanvas::OnUpdateUI(wxUpdateUIEvent&event) { VFN_DEBUG_ENTRY("WXGLCrystalCanvas::OnUpdateUI()",5) if(mpFourierMapListWin!=0) { mpFourierMapListWin->mIsUpdating=true; mpFourierMapListWin->mMutex.Lock(); wxArrayString maps; for(vector >::iterator pos=mvpUnitCellMap.begin();pos!=mvpUnitCellMap.end();++pos) maps.Add( wxString::FromAscii((*pos)->GetName().c_str())); if(mpFourierMapListWin->mpAvailableMapList->GetStrings()!=maps) mpFourierMapListWin->mpAvailableMapList->Set(maps); wxArrayString glmaps; for(vector >::iterator pos=mvpUnitCellMapGLList.begin();pos!=mvpUnitCellMapGLList.end();++pos) glmaps.Add( wxString::FromAscii((*pos)->GetName().c_str())); if(mpFourierMapListWin->mpDisplayedMapList->GetStrings()!=glmaps) mpFourierMapListWin->mpDisplayedMapList->Set(glmaps); if(mpFourierMapListWin->mpAvailableMapList->GetSelection()>=0) { boost::shared_ptr pMap=mvpUnitCellMap[mpFourierMapListWin->mpAvailableMapList->GetSelection()]; mpFourierMapListWin->mpMapInfo->SetLabel(wxString::Format(_T("min=%5.2f max=%5.2f sigma=%5.2f"), pMap->Min(),pMap->Max(),pMap->StandardDeviation())); } mpFourierMapListWin->mMutex.Unlock(); mpFourierMapListWin->mIsUpdating=false; } this->Refresh(false); event.Skip(); VFN_DEBUG_EXIT("WXGLCrystalCanvas::OnUpdateUI()",5) } void WXGLCrystalCanvas::SetCurrent() { VFN_DEBUG_ENTRY("WXGLCrystalCanvas::SetCurrent()",4) this->wxGLCanvas::SetCurrent(*mpwxGLContext); #ifndef HAVE_GLUT this->BuildGLFont(); sFontDisplayListBase=mGLFontDisplayListBase; #endif VFN_DEBUG_EXIT("WXGLCrystalCanvas::SetCurrent()",4) } void WXGLCrystalCanvas::NotifyDeleteFourierWin() { mpFourierMapListWin=0; } void WXGLCrystalCanvas::InitGL() { // This is called once, when the window is actually displayed wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,ID_GLCRYSTAL_MENU_UPDATE); wxPostEvent(this,event); VFN_DEBUG_ENTRY("WXGLCrystalCanvas::InitGL()",8) this->SetCurrent(); #ifdef HAVE_GLUT static bool needglutinit=true; if(needglutinit) { needglutinit=false; //glutInit(&(wxApp::GetInstance()->argc),wxApp::GetInstance()->argv); char **argv=new char*; int argc=0; glutInit(&argc,argv);// We cannot pass arguments directly in Unicode mode, so... } #endif int width, height; GetClientSize(& width, & height); glViewport(0, 0, width, height); glEnable(GL_DEPTH_TEST); glEnable(GL_ALPHA_TEST); glEnable(GL_LIGHTING); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); const GLfloat colour_Ambient [] = {0.4, 0.4, 0.4, 1.00}; const GLfloat colour_Diffuse [] = {0.6, 0.6, 0.6, 1.00}; const GLfloat colour_Specular[] = {0.2, 0.2, 0.2, 1.00}; glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 1.0); const GLfloat LightPosition[]= { -10.0f, 10.0f, 10.0f, 0.0f }; glLightfv(GL_LIGHT1, GL_AMBIENT, colour_Ambient); glLightfv(GL_LIGHT1, GL_DIFFUSE, colour_Diffuse); glLightfv(GL_LIGHT1, GL_SPECULAR, colour_Specular); glLightfv(GL_LIGHT1, GL_SHININESS,colour_Specular); glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); glEnable(GL_LIGHT1); glEnable(GL_NORMALIZE); glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);//GL_FASTEST glHint(GL_POLYGON_SMOOTH_HINT,GL_NICEST);//GL_FASTEST if(sGLCrystalConfig.mSaved==false) { //Initialize Trackball trackball(mQuat,0.,0.,0.,0.); } wxSizeEvent ev; wxPostEvent(this,ev); //First display this->CrystUpdate(); VFN_DEBUG_EXIT("WXGLCrystalCanvas::InitGL()",8) } void WXGLCrystalCanvas::OnChangeLimits(wxCommandEvent &event) { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnChangeLimits()",10) if(event.GetId()==ID_GLCRYSTAL_MENU_LIMITS_FULLCELL) { mcellbbox.xMin = 0; mcellbbox.yMin = 0; mcellbbox.zMin = 0; mcellbbox.xMax = 1; mcellbbox.yMax = 1; mcellbbox.zMax = 1; vector >::iterator pos; for(pos=mvpUnitCellMapGLList.begin();pos != mvpUnitCellMapGLList.end();pos++) { wxBusyInfo wait(_T("Processing Fourier Map...")); (*pos)->GenList(); } } if(event.GetId()==ID_GLCRYSTAL_MENU_LIMITS_ASYMCELL) { mcellbbox.xMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Xmin(); mcellbbox.yMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Ymin(); mcellbbox.zMin = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Zmin(); mcellbbox.xMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Xmax(); mcellbbox.yMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Ymax(); mcellbbox.zMax = mpWXCrystal->GetCrystal().GetSpaceGroup().GetAsymUnit().Zmax(); vector >::iterator pos; for(pos=mvpUnitCellMapGLList.begin();pos != mvpUnitCellMapGLList.end();pos++) { wxBusyInfo wait(_T("Processing Fourier Map...")); (*pos)->GenList(); } } if(event.GetId()==ID_GLCRYSTAL_MENU_CHANGELIMITS) { UserSelectBoundingBox *BoxDlg = new UserSelectBoundingBox(this, "Set bounding box for display of\natoms (fractional coordinates)", mcellbbox); if (BoxDlg->ShowModal() == wxID_OK ) { mcellbbox = BoxDlg->GetBBox(); mpWXCrystal->UpdateGL(false, mcellbbox.xMin,mcellbbox.xMax, mcellbbox.yMin,mcellbbox.yMax, mcellbbox.zMin,mcellbbox.zMax, mFadeDistance, mShowFullMolecule); vector >::iterator pos; for(pos=mvpUnitCellMapGLList.begin();pos != mvpUnitCellMapGLList.end();pos++) { wxBusyInfo wait(_T("Processing Fourier Map...")); (*pos)->GenList(); } VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnChangeLimits (X: " << mcellbbox.xMin << ", " << mcellbbox.xMax << " Y: " << mcellbbox.yMin << ", " << mcellbbox.yMax << " Z: " << mcellbbox.zMin << ", " << mcellbbox.zMax << ")", 10) } BoxDlg->Destroy(); } if(!(mpWXCrystal->GetCrystal().IsBeingRefined())) mpWXCrystal->UpdateGL(false, mcellbbox.xMin,mcellbbox.xMax, mcellbbox.yMin,mcellbbox.yMax, mcellbbox.zMin,mcellbbox.zMax, mFadeDistance, mShowFullMolecule); VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnChangeLimits():UserSelectBoundingBox done",10) } void WXGLCrystalCanvas::OnShowCrystal( wxCommandEvent & WXUNUSED(event)) { if(mShowCrystal) mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWCRYSTAL, _T("Show Crystal")); else mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWCRYSTAL, _T("Hide Crystal")); mShowCrystal = !mShowCrystal; if(!(mpWXCrystal->GetCrystal().IsBeingRefined())) this->CrystUpdate(); } void WXGLCrystalCanvas::OnShowAtomLabel( wxCommandEvent & WXUNUSED(event)) { if(mShowAtomName) mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWATOMLABEL, _T("Show Atom Labels")); else mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWATOMLABEL, _T("Hide Atom Labels")); mShowAtomName= !mShowAtomName; if(!(mpWXCrystal->GetCrystal().IsBeingRefined())) this->CrystUpdate(); } void WXGLCrystalCanvas::OnShowHydrogens( wxCommandEvent & WXUNUSED(event)) { if(mShowHydrogens) mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWHYDROGENS, _T("Show Hydrogens")); else mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWHYDROGENS, _T("Hide Hydrogens")); mShowHydrogens= !mShowHydrogens; if(!(mpWXCrystal->GetCrystal().IsBeingRefined())) { wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,ID_GLCRYSTAL_MENU_UPDATE); wxPostEvent(this,event); } } bool WXGLCrystalCanvas::GetShowHydrogens() const {return mShowHydrogens;} void WXGLCrystalCanvas::OnShowCursor( wxCommandEvent & WXUNUSED(event)) { if(mShowCursor) mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWCURSOR, _T("Show Cursor")); else mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWCURSOR, _T("Hide Cursor")); mShowCursor= !mShowCursor; if(!(mpWXCrystal->GetCrystal().IsBeingRefined())) this->CrystUpdate(); } void WXGLCrystalCanvas::OnSetCursor( wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnSetCursor",1) REAL x=mX0; REAL y=mY0; REAL z=mZ0; mpWXCrystal->GetCrystal().OrthonormalToFractionalCoords(x,y,z); mViewCntr.x = (mcellbbox.xMax+mcellbbox.xMin)/2. - x; mViewCntr.y = (mcellbbox.yMax+mcellbbox.yMin)/2. - y; mViewCntr.z = (mcellbbox.zMax+mcellbbox.zMin)/2. - z; UserXYZBox *BoxDlg = new UserXYZBox(this, wxString("Set fractional coordinates for view\ncenter and cursor position"), mViewCntr); if (BoxDlg->ShowModal() == wxID_OK ) { mViewCntr = BoxDlg->GetXYZ(); VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::OnSetCursor (frac) = " << mViewCntr.x << "," << mViewCntr.y << "," << mViewCntr.z,1) mX0 = (mcellbbox.xMax+mcellbbox.xMin)/2. - mViewCntr.x; mY0 = (mcellbbox.yMax+mcellbbox.yMin)/2. - mViewCntr.y; mZ0 = (mcellbbox.zMax+mcellbbox.zMin)/2. - mViewCntr.z; mpWXCrystal->GetCrystal().FractionalToOrthonormalCoords(mX0, mY0, mZ0); VFN_DEBUG_MESSAGE("...ortho" << mX0 << "," << mY0 << "," << mZ0,1) Refresh(FALSE); } } void WXGLCrystalCanvas::OnShowHelp(wxCommandEvent &event) { if(mShowHelp) mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWHELP, _T("Show Help")); else mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWCURSOR, _T("Hide Help")); mShowHelp= !mShowHelp; if(!(mpWXCrystal->GetCrystal().IsBeingRefined())) this->CrystUpdate(); } void WXGLCrystalCanvas::OnFourier(wxCommandEvent &event) { if(event.GetId()==ID_GLCRYSTAL_MENU_FOURIER) { if(mpFourierMapListWin!=0) return; if(mpWXCrystal->GetCrystal().IsBeingRefined()) { wxMessageBox(_T("The Fourier maps dialog \ncannot be opened during an optimization"), _T("Error"), wxOK, this); return; } wxFrame *frame= new wxMiniFrame(this,-1, wxString::FromAscii(("Available Fourier maps for "+mpWXCrystal->GetCrystal().GetName()).c_str()), wxDefaultPosition,wxSize(500,500),wxCLOSE_BOX|wxCAPTION|wxSYSTEM_MENU); mpFourierMapListWin=new WXFourierMapList(this,frame); mpFourierMapListWin->mpWireFrame->SetValue(true); mpFourierMapListWin->mpShowFourier->SetValue(mShowFourier); mpFourierMapListWin->mpSharpenMap->SetValue(mSharpenMap); frame->Show(true); mpWXCrystal->GetCrystal().UpdateDisplay(); return; } if(mpFourierMapListWin==0) return; if(mpFourierMapListWin->mIsUpdating) return; if( (event.GetId()==ID_GLCRYSTAL_FOURIER_UPDATE) ||(event.GetId()==ID_GLCRYSTAL_FOURIER_CONTOUR)) { mpFourierMapListWin->mMutex.Lock(); //Changed colour or contour ? unsigned int choice=mpFourierMapListWin->mpDisplayedMapList->GetSelection(); if(wxNOT_FOUND!=choice) { double contour; mpFourierMapListWin->mpContourValue->GetValue().ToDouble(&contour); wxColour col(mpFourierMapListWin->mpColourPicker->GetColour()); if(abs((float)contour-mvpUnitCellMapGLList[choice]->GetContour())>.0001) { mvpUnitCellMapGLList[choice]->SetContour((float)contour); if(false==mpWXCrystal->GetCrystal().IsBeingRefined()) { wxBusyInfo wait(_T("Processing Fourier Map...")); mvpUnitCellMapGLList[choice]->GenList(); } } mvpUnitCellMapGLList[choice]->SetColour(col.Red()/255.0,col.Green()/255.0,col.Blue()/255.0,0.5); } mpFourierMapListWin->mMutex.Unlock(); } if(event.GetId()==ID_GLCRYSTAL_FOURIER_LISTMAP) {// Selected one map mpFourierMapListWin->mMutex.Lock(); if(mpFourierMapListWin->mpAvailableMapList->GetSelection()>=0) { boost::shared_ptr pMap=mvpUnitCellMap[mpFourierMapListWin->mpAvailableMapList->GetSelection()]; mpFourierMapListWin->mpMapInfo->SetLabel(wxString::Format(_T("min=%5.2f max=%5.2f sigma=%5.2f"), pMap->Min(),pMap->Max(),pMap->StandardDeviation())); } mpFourierMapListWin->mMutex.Unlock(); } if(event.GetId()==ID_GLCRYSTAL_FOURIER_LISTGLMAP) { mpFourierMapListWin->mMutex.Lock(); if(mpFourierMapListWin->mpDisplayedMapList->GetSelection()>=0) { boost::shared_ptr pMap=mvpUnitCellMapGLList[mpFourierMapListWin->mpDisplayedMapList->GetSelection()]; mpFourierMapListWin->mpContourValue->SetValue(wxString::Format(_T("%5.2f"),pMap->GetContour())); mpFourierMapListWin->mpColourPicker->SetColour(wxColour(pMap->GetColour()[0]*255,pMap->GetColour()[1]*255, pMap->GetColour()[2]*255,pMap->GetColour()[3]*255)); } mpFourierMapListWin->mMutex.Unlock(); } if((event.GetId()==ID_GLCRYSTAL_FOURIER_ADD)||(event.GetId()==ID_GLCRYSTAL_FOURIER_NEWCONTOUR)) { mpFourierMapListWin->mMutex.Lock(); if(mpFourierMapListWin->mpAvailableMapList->GetSelection()!=wxNOT_FOUND) { boost::shared_ptr pMap=mvpUnitCellMap[mpFourierMapListWin->mpAvailableMapList->GetSelection()]; double contour=0; wxString scontour=mpFourierMapListWin->mpNewContourValue->GetValue(); if(scontour==_T("")) contour=pMap->Min()+pMap->StandardDeviation()*3; else scontour.ToDouble(&contour); wxColor ncolor(255,0,0); ncolor = wxGetColourFromUser((wxWindow*)this, ncolor); wxBusyInfo wait(_T("Processing Fourier Map...")); mvpUnitCellMapGLList.push_back(boost::shared_ptr(new UnitCellMapGLList(*pMap,this,true,(float)contour))); mvpUnitCellMapGLList.back()->SetName(pMap->GetName()); mvpUnitCellMapGLList.back()->SetColour(ncolor.Red()/255.0,ncolor.Green()/255.0,ncolor.Blue()/255.0,0.5); mpFourierMapListWin->mMutex.Unlock(); if(false==mpWXCrystal->GetCrystal().IsBeingRefined()) { this->SetCurrent(); mvpUnitCellMapGLList.back()->GenList(); } } } if(event.GetId()==ID_GLCRYSTAL_FOURIER_REMOVE) { mpFourierMapListWin->mMutex.Lock(); unsigned int choice=mpFourierMapListWin->mpDisplayedMapList->GetSelection(); if(wxNOT_FOUND!=choice) mvpUnitCellMapGLList.erase(mvpUnitCellMapGLList.begin()+choice); mpFourierMapListWin->mMutex.Unlock(); } if(event.GetId()==ID_GLCRYSTAL_FOURIER_SHOW) { mpFourierMapListWin->mMutex.Lock(); mShowFourier=mpFourierMapListWin->mpShowFourier->GetValue(); mpFourierMapListWin->mMutex.Unlock(); } if(event.GetId()==ID_GLCRYSTAL_FOURIER_WIREFRAME) { mpFourierMapListWin->mMutex.Lock(); vector >::iterator pos; for(pos=mvpUnitCellMapGLList.begin();pos != mvpUnitCellMapGLList.end();pos++) (*pos)->ToggleShowWire(); mpFourierMapListWin->mMutex.Unlock(); } if(event.GetId()==ID_GLCRYSTAL_FOURIER_SHARPEN) { mpFourierMapListWin->mMutex.Lock(); mSharpenMap=mpFourierMapListWin->mpSharpenMap->GetValue(); mpFourierMapListWin->mMutex.Unlock(); } // Update - if the crystal is being refined, it will be done at the next display update if(false==mpWXCrystal->GetCrystal().IsBeingRefined()) this->CrystUpdate(); } void WXGLCrystalCanvas::OnLoadFourierGRD( wxCommandEvent & WXUNUSED(event)) { wxFileDialog fd((wxWindow*)this, _T("Choose a file containing a Fourier Map"), _T(""), _T(""), _T("Fourier Map files (*.grd)|*.grd"), wxFD_OPEN | wxFD_FILE_MUST_EXIST); //if okay then read Fourier map, run MC on it and display the triangles if(fd.ShowModal() == wxID_OK) { const string filename(fd.GetPath().ToAscii()); UnitCellMap *pMap=new UnitCellMap(mpWXCrystal->GetCrystal()); if (pMap->ImportGRD(filename) == 0) { string tmp="Error reading Fourier file:"+filename; wxMessageBox( wxString::FromAscii(tmp.c_str()), _T("File error"), wxOK, this); return; } this->AddFourier(pMap); } } void WXGLCrystalCanvas::OnLoadFourierDSN6( wxCommandEvent & WXUNUSED(event)) { wxFileDialog fd((wxWindow*)this, _T("Choose a file containing a Fourier Map"), _T(""), _T(""), _T("Fourier Map files (*.DN6)|*.DN6"), wxFD_OPEN | wxFD_FILE_MUST_EXIST); //if okay then read Fourier map, run MC on it and display the triangles if(fd.ShowModal() == wxID_OK) { const string filename(fd.GetPath().ToAscii()); UnitCellMap *pMap=new UnitCellMap(mpWXCrystal->GetCrystal()); if (pMap->ImportDSN6(filename) == 0) { string tmp="Error reading Fourier file:"+filename; wxMessageBox( wxString::FromAscii(tmp.c_str()), _T("File error"), wxOK, this); return; } this->AddFourier(pMap); } } void WXGLCrystalCanvas::AddFourier(UnitCellMap *map) { mvpUnitCellMap.push_back(boost::shared_ptr(map)); wxBusyInfo wait(_T("Processing Fourier Map...")); { float contour=map->Mean()+2*map->StandardDeviation(); if(contour>map->Max()) contour=map->Mean()+0.75*(map->Max()-map->Mean()); mvpUnitCellMapGLList.push_back(boost::shared_ptr(new UnitCellMapGLList(*map,this))); switch(mvpUnitCellMapGLList.size()) { case 1: mvpUnitCellMapGLList.back()->SetColour(1.,0.,0.,.5);break; case 2: mvpUnitCellMapGLList.back()->SetColour(0.,0.,1.,.5);break; default:mvpUnitCellMapGLList.back()->SetColour(0.,1.,0.,.5);break; } this->SetCurrent(); mvpUnitCellMapGLList.back()->GenList(); mvpUnitCellMapGLList.back()->SetName(map->GetName()); } if(!(mpWXCrystal->GetCrystal().IsBeingRefined())) this->CrystUpdate(); } void WXGLCrystalCanvas::OnFourierChangeColour(wxColourPickerEvent &event) { mpFourierMapListWin->mMutex.Lock(); //Changed colour or contour ? unsigned int choice=mpFourierMapListWin->mpDisplayedMapList->GetSelection(); if(wxNOT_FOUND!=choice) { double contour; mpFourierMapListWin->mpContourValue->GetValue().ToDouble(&contour); wxColour col(mpFourierMapListWin->mpColourPicker->GetColour()); if(abs((float)contour-mvpUnitCellMapGLList[choice]->GetContour())>.0001) { wxBusyInfo wait(_T("Processing Fourier Map...")); mvpUnitCellMapGLList[choice]->SetContour((float)contour); mvpUnitCellMapGLList[choice]->GenList(); } mvpUnitCellMapGLList[choice]->SetColour(col.Red()/255.0,col.Green()/255.0,col.Blue()/255.0,0.5); } mpFourierMapListWin->mMutex.Unlock(); mpWXCrystal->GetCrystal().UpdateDisplay(); } /* void WXGLCrystalCanvas::OnUnloadFourier( wxCommandEvent & WXUNUSED(event)) { wxMessageDialog * msure = new wxMessageDialog((wxWindow*)this, "Are you sure you want to unload all Fourier Map Data?", "Unload Fourier Map", wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION ); if(msure->ShowModal() == wxID_YES) { mvpUnitCellMap.clear(); mvpUnitCellMapGLList.clear(); mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWCRYSTAL, "Hide Crystal"); mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_CHANGECONTOUR, FALSE); //disable all of these mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_ADDCONTOUR, FALSE); //disable all of these mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_SHOWFOURIER, FALSE); mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWFOURIER, "Hide Fourier Map"); mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_UNLOADFOURIER, FALSE); mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_FOURIERCHANGECOLOR, FALSE); mpPopUpMenu->SetLabel(ID_GLCRYSTAL_MENU_SHOWWIRE, "Show Filled"); mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_SHOWWIRE, FALSE); mpPopUpMenu->Enable(ID_GLCRYSTAL_MENU_FOURIERCHANGEBBOX, FALSE); this->CrystUpdate(); } delete msure; } */ void WXGLCrystalCanvas::OnPOVRay( wxCommandEvent & WXUNUSED(event)) { WXCrystValidateAllUserInput(); wxFileDialog save(this,_T("Choose filename"),_T(""),_T(""),_T("*.pov"),wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if(save.ShowModal() != wxID_OK) return; this->POVRayOutput(string(save.GetPath().char_str())); } void WXGLCrystalCanvas::POVRayOutput(const std::string &filename) { ofstream os(filename.c_str()); os << "#version 3.6 ;"<' statement in the camera definition"<,atomr*1.0'"<GetCrystal().GetName() <}"<GetCrystal().FractionalToOrthonormalCoords(x,y,z); x-=mX0; y-=mY0; z-=mZ0; { const REAL q1=mQuat[0];const REAL q2=mQuat[1]; const REAL q3=mQuat[2];const REAL q4=mQuat[3]; REAL yaw =(q4*q4 + q1*q1 - q2*q2 - q3*q3); if(abs(yaw)>1e-6) yaw =atan( 2*(q1*q2+q4*q3) /yaw )*RAD2DEG; else { if((q1*q2+q4*q3)>0) yaw =90.; else yaw =-90;} const REAL pitch=asin(-2*(q1*q3-q4*q2))*RAD2DEG; REAL roll=(q4*q4 - q1*q1 - q2*q2 + q3*q3); if(abs(roll)>1e-6) roll =atan( 2*(q4*q1+q2*q3) /roll)*RAD2DEG; else { if((q4*q1+q2*q3)>0) roll=90.; else roll=-90;} if((q4*q4 + q1*q1 - q2*q2 - q3*q3)<0) yaw +=180; if((q4*q4 - q1*q1 - q2*q2 + q3*q3)<0) roll +=180; os<"<"< //change handedness as in OpenGL, aspect ratio=4/3"<"<" <" <" <"<"<" <"<" <" <" <"< }"<GetCrystal().POVRayDescription(os,options); } if(mShowFourier) { wxBusyInfo wait(_T("Processing Fourier Map...")); // use cell bbox if mapbbox has zero volume (default) if (mmapbbox.xMin != mmapbbox.xMax) { options.mXmin=mmapbbox.xMin; options.mXmax=mmapbbox.xMax; options.mYmin=mmapbbox.yMin; options.mYmax=mmapbbox.yMax; options.mZmin=mmapbbox.zMin; options.mZmax=mmapbbox.zMax; } os<<"/////////////////// FOURIER MAPS///////////////////////////"< >::const_iterator pos; for(pos=mvpUnitCellMapGLList.begin();pos != mvpUnitCellMapGLList.end();++pos) { const float *prgbf=(*pos)->GetColour(); if((*pos)->ShowWire()) { os << "#macro ObjCrystMeshTriangle(x1,y1,z1,x2,y2,z2,x3,y3,z3," << "nx1,ny1,nz1,nx2,ny2,nz2,nx3,ny3,nz3)"<,"<,"<}"<,"<,"<}"<,"<,"<}"<GetMap().POVRayDescription(os,(*pos)->GetContour(),options); } else { os << "#macro ObjCrystMeshTriangle(x1,y1,z1,x2,y2,z2,x3,y3,z3," << "nx1,ny1,nz1,nx2,ny2,nz2,nx3,ny3,nz3)"<,"<,"<,}"<GetMap().POVRayDescription(os,(*pos)->GetContour(),options); os << " texture"<}"<SetCurrent(); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glTranslatef( 0, 0, -mDist ); glGetDoublev(GL_MODELVIEW_MATRIX,modelMatrix); glGetDoublev(GL_PROJECTION_MATRIX,projMatrix); glGetIntegerv(GL_VIEWPORT,viewport); // First, get the z depth of where we want to translate gluProject(0, 0, 0 ,modelMatrix,projMatrix,viewport,&junk,&junk,&z0); // Get the orthonormal coordinates gluUnProject(x,y,z0,modelMatrix,projMatrix,viewport,&vx,&vy,&vz); vy = -vy; // Use Quaternion to get the correct position GLfloat m[4][4]; build_rotmatrix( m,mQuat); x= m[0][0]* vx + m[0][1]*vy + m[0][2]*vz -mX0; y= m[1][0]* vx + m[1][1]*vy + m[1][2]*vz -mY0; z= m[2][0]* vx + m[2][1]*vy + m[2][2]*vz -mZ0; VFN_DEBUG_MESSAGE("WXGLCrystalCanvas::UnProject():X Y Z = "<fid, 32, 96, mGLFontDisplayListBase); XFreeFont(dpy, fontInfo); XCloseDisplay(dpy); #endif #ifdef __WIN32__ HFONT font; HFONT oldfont; wxPaintDC dc(this); HDC hDC = (HDC)dc.GetHDC(); // Use 3mm font size wxSize s = dc.GetPPI(); int height = int(round(3 * (s.GetHeight() + s.GetWidth()) / 2 / 25.4)); mGLFontDisplayListBase = 100; font = CreateFont(-height, // Height of font 0, // Width of font 0, // Angle of escapement 0, // Orientation angle FW_NORMAL, // Font weight FALSE, // Italic FALSE, // Underline FALSE, // Strikeout ANSI_CHARSET, // Character set identifier OUT_TT_PRECIS, // Output precision CLIP_DEFAULT_PRECIS, // Clipping precision ANTIALIASED_QUALITY, // Output quality FF_DONTCARE|DEFAULT_PITCH, // Family and pitch _T("Helvetica")); // Font name oldfont = (HFONT)SelectObject(hDC, font); wglUseFontBitmaps(hDC, 0, 128, mGLFontDisplayListBase); SelectObject(hDC, oldfont); DeleteObject(font); #endif mIsGLFontBuilt=true; sFontDisplayListBase=mGLFontDisplayListBase; VFN_DEBUG_EXIT("WXGLCrystalCanvas::BuildGLFont()",6) } void WXGLCrystalCanvas::DeleteGLFont() const { if(!mIsGLFontBuilt) return; glDeleteLists(mGLFontDisplayListBase, 96); mIsGLFontBuilt=false; mGLFontDisplayListBase=0; } #endif //////////////////////////////////////////////////////////////////////// // // UserSelectBoundingBox // //////////////////////////////////////////////////////////////////////// BEGIN_EVENT_TABLE(UserSelectBoundingBox, wxDialog) EVT_BUTTON(wxID_OK, UserSelectBoundingBox::OnOk) END_EVENT_TABLE() UserSelectBoundingBox::UserSelectBoundingBox (wxWindow *parent, const char * title, const BBox bbox) : wxDialog((wxWindow *)parent, -1, _T("Set bounding box"), wxDefaultPosition, wxSize(250, 250), wxDEFAULT_DIALOG_STYLE) { wxBoxSizer *dialogSizer = new wxBoxSizer(wxVERTICAL); wxFlexGridSizer *inputSizer = new wxFlexGridSizer(4, 3, 10, 10); // headers inputSizer->Add(new wxStaticText(this, -1, _T("")), 0, wxALIGN_CENTRE_VERTICAL); inputSizer->Add(new wxStaticText(this, -1, _T("minimum")), 0, wxALIGN_CENTER); inputSizer->Add(new wxStaticText(this, -1, _T("maximum")), 0, wxALIGN_CENTER); // 1st row inputSizer->Add(new wxStaticText(this, -1, _T("a")), 0, wxALIGN_CENTRE_VERTICAL); inputSizer->Add(mpXminCtrl = new wxTextCtrl(this, -1, wxString::Format(_T("%f"),bbox.xMin), wxDefaultPosition, wxDefaultSize, 0, wxTextValidator(wxFILTER_NUMERIC)), 0, wxALIGN_CENTRE_VERTICAL); inputSizer->Add(mpXmaxCtrl = new wxTextCtrl(this, -1, wxString::Format(_T("%f"),bbox.xMax), wxDefaultPosition, wxDefaultSize, 0, wxTextValidator(wxFILTER_NUMERIC)), 0, wxALIGN_CENTRE_VERTICAL); // 2nd row inputSizer->Add(new wxStaticText(this, -1, _T("b")), 0, wxALIGN_CENTRE_VERTICAL); inputSizer->Add(mpYminCtrl = new wxTextCtrl(this, -1, wxString::Format(_T("%f"),bbox.yMin), wxDefaultPosition, wxDefaultSize, 0, wxTextValidator(wxFILTER_NUMERIC)), 0, wxALIGN_CENTRE_VERTICAL); inputSizer->Add(mpYmaxCtrl = new wxTextCtrl(this, -1, wxString::Format(_T("%f"),bbox.yMax), wxDefaultPosition, wxDefaultSize, 0, wxTextValidator(wxFILTER_NUMERIC)), 0, wxALIGN_CENTRE_VERTICAL); // 3rd row inputSizer->Add(new wxStaticText(this, -1, _T("c")), 0, wxALIGN_CENTRE_VERTICAL); inputSizer->Add(mpZminCtrl = new wxTextCtrl(this, -1, wxString::Format(_T("%f"),bbox.zMin), wxDefaultPosition, wxDefaultSize, 0, wxTextValidator(wxFILTER_NUMERIC)), 0, wxALIGN_CENTRE_VERTICAL); inputSizer->Add(mpZmaxCtrl = new wxTextCtrl(this, -1, wxString::Format(_T("%f"),bbox.zMax), wxDefaultPosition, wxDefaultSize, 0, wxTextValidator(wxFILTER_NUMERIC)), 0, wxALIGN_CENTRE_VERTICAL); // button section wxFlexGridSizer *buttonSizer = new wxFlexGridSizer(1, 2, 10, 10); buttonSizer->Add(new wxButton(this, wxID_OK, _T("OK")), 0, wxALIGN_CENTRE_VERTICAL); buttonSizer->Add(new wxButton(this, wxID_CANCEL, _T("Cancel")), 0, wxALIGN_CENTRE_VERTICAL); dialogSizer->Add(10, 10); dialogSizer->Add(new wxStaticText(this, -1, wxString::FromAscii(title)), 0, wxALIGN_CENTER); dialogSizer->Add(10, 10); dialogSizer->Add(inputSizer, 0, wxALIGN_CENTER); dialogSizer->Add(20, 20); dialogSizer->Add(buttonSizer, 0, wxALIGN_CENTER); SetSizer(dialogSizer); SetAutoLayout(TRUE); Layout(); } UserSelectBoundingBox::~UserSelectBoundingBox () { // if the sizers must be deleted, put them in the class and delete them here //delete dialogSizer; //delete inputSizer; //delete buttonSizer; }; void UserSelectBoundingBox::OnOk (wxCommandEvent & WXUNUSED(event)) { double val; mpXminCtrl->GetValue().ToDouble(&val); mbbox.xMin = val; mpXmaxCtrl->GetValue().ToDouble(&val); mbbox.xMax = val; if (mbbox.xMin == mbbox.xMax) {wxMessageBox(_T("Sorry, Xmin must be less than Xmax!"), _T("Zero bounding volume"), wxOK, this); return;} if (mbbox.xMin > mbbox.xMax) { float tmp = mbbox.xMax; mbbox.xMax = mbbox.xMin; mbbox.xMin = tmp; } VFN_DEBUG_MESSAGE("Xmin " << mbbox.xMin << " Xmax " << mbbox.xMax,1) mpYminCtrl->GetValue().ToDouble(&val); mbbox.yMin = val; mpYmaxCtrl->GetValue().ToDouble(&val); mbbox.yMax = val; if (mbbox.yMin == mbbox.yMax) {wxMessageBox(_T("Sorry, Ymin must be less than Ymax!"), _T("Zero bounding volume"), wxOK, this); return;} if (mbbox.yMin > mbbox.yMax) { float tmp = mbbox.yMax; mbbox.yMax = mbbox.yMin; mbbox.yMin = tmp; } VFN_DEBUG_MESSAGE("Ymin " << mbbox.yMin << " Ymax " << mbbox.yMax,1) mpZminCtrl->GetValue().ToDouble(&val); mbbox.zMin = val; mpZmaxCtrl->GetValue().ToDouble(&val); mbbox.zMax = val; if (mbbox.zMin == mbbox.zMax) {wxMessageBox(_T("Sorry, Zmin must be less than Zmax!"), _T("Zero bounding volume"), wxOK, this); return;} if (mbbox.zMin > mbbox.zMax) { float tmp = mbbox.zMax; mbbox.zMax = mbbox.zMin; mbbox.zMin = tmp; } VFN_DEBUG_MESSAGE("Zmin " << mbbox.zMin << " Zmax " << mbbox.zMax,1) // close the dialog EndModal(wxID_OK); } BBox UserSelectBoundingBox::GetBBox () { return mbbox; } //////////////////////////////////////////////////////////////////////// // // UserXYZBox // //////////////////////////////////////////////////////////////////////// BEGIN_EVENT_TABLE(UserXYZBox, wxDialog) EVT_BUTTON(wxID_OK, UserXYZBox::OnOk) END_EVENT_TABLE() UserXYZBox::UserXYZBox (wxWindow *parent, const wxString &title, const Triple xyz) : wxDialog((wxWindow *)parent, -1, _T("Set position"), wxDefaultPosition, wxSize(250, 250), wxDEFAULT_DIALOG_STYLE) { wxBoxSizer *dialogSizer = new wxBoxSizer(wxVERTICAL); wxFlexGridSizer *inputSizer = new wxFlexGridSizer(3, 2, 10, 10); // 1st row inputSizer->Add(new wxStaticText(this, -1, _T("x")), 0, wxALIGN_CENTRE_VERTICAL); inputSizer->Add(mpXCtrl = new wxTextCtrl(this, -1, wxString::Format(_T("%.3f"),xyz.x), wxDefaultPosition, wxDefaultSize, wxTE_CENTRE, wxTextValidator(wxFILTER_NUMERIC)), 0, wxALIGN_CENTRE_VERTICAL); // 2nd row inputSizer->Add(new wxStaticText(this, -1, _T("y")), 0, wxALIGN_CENTRE_VERTICAL); inputSizer->Add(mpYCtrl = new wxTextCtrl(this, -1, wxString::Format(_T("%.3f"),xyz.y), wxDefaultPosition, wxDefaultSize, wxTE_CENTRE, wxTextValidator(wxFILTER_NUMERIC)), 0, wxALIGN_CENTRE_VERTICAL); // 3rd row inputSizer->Add(new wxStaticText(this, -1, _T("z")), 0, wxALIGN_CENTRE_VERTICAL); inputSizer->Add(mpZCtrl = new wxTextCtrl(this, -1, wxString::Format(_T("%.3f"),xyz.z), wxDefaultPosition, wxDefaultSize, wxTE_CENTRE, wxTextValidator(wxFILTER_NUMERIC)), 0, wxALIGN_CENTRE_VERTICAL); // button section wxFlexGridSizer *buttonSizer = new wxFlexGridSizer(1, 2, 10, 10); buttonSizer->Add(new wxButton(this, wxID_OK, _T("OK")), 0, wxALIGN_CENTRE_VERTICAL); buttonSizer->Add(new wxButton(this, wxID_CANCEL, _T("Cancel")), 0, wxALIGN_CENTRE_VERTICAL); dialogSizer->Add(10, 10); dialogSizer->Add(new wxStaticText(this, -1, title), 0, wxALIGN_CENTER); dialogSizer->Add(10, 10); dialogSizer->Add(inputSizer, 0, wxALIGN_CENTER); dialogSizer->Add(20, 20); dialogSizer->Add(buttonSizer, 0, wxALIGN_CENTER); SetSizer(dialogSizer); SetAutoLayout(TRUE); Layout(); } UserXYZBox::~UserXYZBox () { }; void UserXYZBox::OnOk (wxCommandEvent & WXUNUSED(event)) { double tmp; mpXCtrl->GetValue().ToDouble(&tmp); mXYZ.x = tmp; mpYCtrl->GetValue().ToDouble(&tmp); mXYZ.y = tmp; mpZCtrl->GetValue().ToDouble(&tmp); mXYZ.z = tmp; // close the dialog EndModal(wxID_OK); } Triple UserXYZBox::GetXYZ () { return mXYZ; } #endif // #ifdef OBJCRYST_GL }// namespace objcryst-2022.1/ObjCryst/wxCryst/wxCrystal.h000066400000000000000000000432401430515525000210350ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2009 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * header file for the RefinablePar and RefinableObj classes * * This is still in early development stages !! Not secure ! * */ #ifndef _VFN_WX_CRYSTAL_H_ #define _VFN_WX_CRYSTAL_H_ #include #include #include "ObjCryst/wxCryst/wxRefinableObj.h" #include "wx/glcanvas.h" #include "wx/grid.h" #include "wx/clrpicker.h" #include "ObjCryst/ObjCryst/Crystal.h" //#include "ObjCryst/ObjCryst/PDF.h" #include "ObjCryst/wxCryst/MC.h" namespace ObjCryst { typedef struct { float xMin; float xMax; float yMin; float yMax; float zMin; float zMax; } BBox; typedef struct { float x; float y; float z; } Triple; class WXGLCrystalCanvas; class WXCrystal; class WXCrystalScrolledGridWindow:public wxGrid { public: WXCrystalScrolledGridWindow(wxWindow* parent, WXCrystal* pWXMol,long id=-1); virtual ~WXCrystalScrolledGridWindow(); private: /// The WXCrystal window which created this window, and who should be told /// if it is destroyed. WXCrystal* mpWXCrystal; }; /// wxCryst class for Crystals class WXCrystal: public WXRefinableObj { public: WXCrystal(wxWindow *parent, Crystal*); ~WXCrystal(); virtual void CrystUpdate(const bool updateUI=false,const bool mutexlock=false); #ifdef OBJCRYST_GL /// Update the OpenGL Display List void UpdateGL(const bool onlyIndependentAtoms=false, const REAL xMin=-.1,const REAL xMax=1.1, const REAL yMin=-.1,const REAL yMax=1.1, const REAL zMin=-.1,const REAL zMax=1.1, const REAL fadeDistance=0, const bool fullMoleculeInLimits=false); /// Gets the integer index of the OpenGL display list. Wait, if necessary, for the list /// not to be used any more. When finished, ReleaseCrystalGLDisplayList() must be called. /// if AtomName=true, then the display list returned is the one with the atom names. int GetCrystalGLDisplayList(const bool atomName=false)const; /// Create OpenGL Display of the Crystal Structure void OnMenuCrystalGL(wxCommandEvent & WXUNUSED(event)); /// Tell this object that its 3D OpenGL display has been destroyed void NotifyCrystalGLDelete(); /// get a pointer to the 3D OpenGL display object WXGLCrystalCanvas * GetCrystalGL(); #endif void OnMenuSaveCIF(wxCommandEvent & WXUNUSED(event)); void OnMenuSaveText(wxCommandEvent & WXUNUSED(event)); void OnMenuAddScattPowAtom(wxCommandEvent & WXUNUSED(event)); void OnMenuAddScattPowSphere(wxCommandEvent & WXUNUSED(event)); void OnMenuRemoveScattPow(wxCommandEvent & WXUNUSED(event)); void OnMenuAddScatterer(wxCommandEvent & event); void OnMenuRemoveScatterer(wxCommandEvent & WXUNUSED(event)); void OnMenuDuplicateScatterer(wxCommandEvent & WXUNUSED(event)); void OnMenuImportMoleculeFromFenskeHallZMatrix(wxCommandEvent &event); void OnMenuAtoms2Molecule(wxCommandEvent &event); void OnMenuSetRelativeXYZLimits(wxCommandEvent & WXUNUSED(event)); void OnMenuTestRandomMoves(wxCommandEvent &event); bool OnChangeName(const int id); void UpdateUI(const bool mutexlock=false); Crystal& GetCrystal(); const Crystal& GetCrystal()const; void OnMenuShowScattPowWindow(wxCommandEvent &event); void OnEditGridScattPow(wxGridEvent &e); void OnEditGridScattPowAntiBump(wxGridEvent &e); void OnEditGridScattPowBondValence(wxGridEvent &e); void NotifyDeleteListWin(WXCrystalScrolledGridWindow *win); //void OnMenuPDF(wxCommandEvent &event); virtual bool Enable(bool enable=true); private: Crystal* mpCrystal; /// SpaceGroup WXFieldName* mpFieldSpacegroup; /// Scatterers WXRegistry* mpWXScattererRegistry; /// Scattering Powers WXRegistry* mpWXScatteringPowerRegistry; /// Structure to store the scattering power parameters struct RowScattPow { RowScattPow(); std::string mName; /// Last displayed values REAL mBiso,mFormalCharge,mR,mG,mB,mMaximumLikelihoodError,mNbGhostAtoms; /// Last displayed values for antibump std::vector mvAntiBumpDistance; /// Last displayed values for bond valence std::vector mvBondValenceRo; /// True if we need to update the displayed values bool mNeedUpdateUI; /// Current position in the list of rows or columns int mIdx; }; WXCrystalScrolledGridWindow* mpScattPowWin; WXCrystalScrolledGridWindow* mpAntiBumpWin; WXCrystalScrolledGridWindow* mpBondValenceWin; std::map mvpRowScattPow; /// Flag to indicate that we are updating values in the wxGrid data, /// and that it is not the user inputing data. bool mIsSelfUpdating; #ifdef OBJCRYST_GL //OpenGl /// OpenGL Display of the Crystal-Display List. Updated each time CrystUpdate() is called. unsigned int mCrystalGLDisplayList; /// OpenGL Display of the Crystal-Display List. Updated each time CrystUpdate() is called. /// This is the list with all the scatterer (atoms) names unsigned int mCrystalGLNameDisplayList; /// the frame in which the crystal is displayed. There can only be one... WXGLCrystalCanvas* mpCrystalGL; #endif /// Mutex used when updating the OpenGL display List, between background and main thread wxMutex mMutexGLUpdate; /// wxCondition used when updating the OpenGL display List, between background and main thread wxCondition *mpConditionGLUpdate; /// PDF, for tests //PDF *mpPDF; DECLARE_EVENT_TABLE() }; #ifdef OBJCRYST_GL /// Class to store a Fourier map, imported from another package. /// This can also generate a 3d view (OpenGL display list) of the map. class UnitCellMap { public: /** Creator * * \param crystal: the crystal correponding to this map */ UnitCellMap(const Crystal&crystal); ~UnitCellMap(); /// Perform the OpenGL drawing, to be stored in an OpenGL Display List. /// Assumes the color and type of drawing (GL_LINE or GL_FILL) /// is chosen before calling this display list. void GLInitDisplayList(const float contourValue, WXGLCrystalCanvas * parentCrystal) const; /// Generate POVRay script to draw void POVRayDescription(ostream &os,const float contourValue, const CrystalPOVRayOptions &options)const; /** Import map from a '.grd' GSAS/EXPGUI map. * Returns 0 on error, 1 on success * \param filename: the file with the fourier map */ int ImportGRD(const string&filename); /** Import map with DSN6 format. * Returns 0 on error, 1 on success * \param filename: the file with the fourier map */ int ImportDSN6(const string&filename); #ifdef HAVE_FFTW /** Calculate Fourier map (type0=obs,1=calc,2=diff) for a given scattering data object * * \param type: 0=obs,1=calc,2=diff (Fobs-Fcalc) * \param normalized_sf: if true, normalize structure factors * by the sum of the squared scattering factor to sharpen the map. */ int CalcFourierMap(const ScatteringData& data, unsigned int type=0, const bool normalized_sf=false); #endif /// Name associated to this map (the filename) const string & GetName()const; /// Get the value of the map at a given set of fractionnal coordinates REAL GetValue(const REAL x,const REAL y,const REAL z)const; /// Max value of the map REAL Max()const; /// Min value of the map REAL Min()const; /// Mean value of the map REAL Mean()const; /// Standard Deviation of the map REAL StandardDeviation()const; /// Type of map (-1=imported, 0=obs, 1=calc,2=diff) int GetType()const; /// Corresponding Crystal const Crystal &GetCrystal()const; /// For computed maps, the scattering data it corresponds to - otherwise NULL. const ScatteringData *GetData()const; private: /// The crystal corresponding to this map const Crystal *mpCrystal; /// For computed maps, the scattering data it corresponds to - otherwise NULL. const ScatteringData *mpData; /// The map data points CrystArray3D_REAL mPoints; /// Name associated to this map (the filename for imported maps) string mName; /// Min and max value of the map REAL mMin,mMax; /// Mean value of the map REAL mMean; /// Standard Deviation of the map REAL mStandardDeviation; /// Type of map (-1=imported, 0=obs, 1=calc, 2=diff, 3=static from file (e.g. GRD or DSN6 from gsas)) int mType; }; /// Class to store and execute OpenGL Display Lists of fourier maps. /// Only display information is kept here. struct UnitCellMapGLList { public: UnitCellMapGLList(const UnitCellMap &ucmap,WXGLCrystalCanvas * parent, const bool showWire=true,float contour=1.0, const float r=1.0,const float g=0.0,const float b=0.0,const float t=0.5); ~UnitCellMapGLList(); /// Generates, or updates the display list. void GenList(); /// Change name for this map void SetName(const string &name); /// Name for this map const string &GetName()const; /// Change the color. void SetColour(const float r=1.0,const float g=0.0,const float b=0.0, const float t=1.0); /// Get the color, as a float[4] array const float* GetColour()const; /// Toggle show Wire/Filled void ToggleShowWire(); /// Show Wire/Filled ? bool ShowWire()const; /// Perform the OpenGL drawing void Draw()const; /// Show this map ? void SetShow(bool show); /// Show this map ? bool Show()const; /// Change contour value void SetContour(float contour); /// Get contour value float GetContour()const; /// The Map const UnitCellMap & GetMap()const; private: /// The index of the OpenGL display list unsigned int mGLDisplayList; /// The color to display the map float mColour[4]; /// Show as wireframe (if true) or fill (if false). bool mShowWire; /// The name associated with this map display string mName; /// Show this ? bool mShow; /// The contour value float mContour; /// Corresponding UCMap const UnitCellMap *mpUCMap; /// Parent canvas for graphic context WXGLCrystalCanvas *mpParent; }; /// Class for 3D OpenGL display of Crystal structures class WXGLCrystalCanvas : public wxGLCanvas { public: WXGLCrystalCanvas(WXCrystal *wxcryst, wxFrame *parent, wxWindowID id=-1, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize); ~WXGLCrystalCanvas(); void OnExit(wxCommandEvent &event); void OnPaint(wxPaintEvent &event); //void OnSize(wxSizeEvent& event); void OnEraseBackground(wxEraseEvent& event); void OnKeyDown(wxKeyEvent& event); void OnKeyUp(wxKeyEvent& event); void OnEnterWindow( wxMouseEvent& event ); void OnMouse( wxMouseEvent& event ); /// This forces a new Display List (user-asked) void OnUpdate(wxCommandEvent & WXUNUSED(event)); /// This is called by the Crystal in WXCrystal::UpdateGL(). void CrystUpdate(); void OnChangeLimits(wxCommandEvent &event); /// Redraw the structure (special function to ensure complete redrawing under windows...) void OnUpdateUI(wxUpdateUIEvent& WXUNUSED(event)); void OnShowCrystal(wxCommandEvent & WXUNUSED(event)); void OnShowAtomLabel(wxCommandEvent & WXUNUSED(event)); void OnShowHydrogens(wxCommandEvent & WXUNUSED(event)); /// Access to mShowHydrogens bool GetShowHydrogens()const; void OnShowCursor(wxCommandEvent & WXUNUSED(event)); void OnSetCursor(wxCommandEvent & WXUNUSED(event)); /// Hide/show help text void OnShowHelp(wxCommandEvent & WXUNUSED(event)); /// Handle Fourier maps (display dialog, etc...) void OnFourier(wxCommandEvent &event); void OnLoadFourierGRD(wxCommandEvent & WXUNUSED(event)); void OnLoadFourierDSN6(wxCommandEvent & WXUNUSED(event)); void AddFourier(UnitCellMap*); void OnAddContour(wxCommandEvent & WXUNUSED(event)); void OnChangeContour(wxCommandEvent & WXUNUSED(event)); void OnShowFourier(wxCommandEvent & WXUNUSED(event)); void OnFourierChangeColour(wxColourPickerEvent & event); void OnUnloadFourier(wxCommandEvent & WXUNUSED(event)); void OnShowWire(wxCommandEvent & WXUNUSED(event)); void OnFourierChangeBbox(wxCommandEvent & WXUNUSED(event)); /// Save view as povray file void OnPOVRay(wxCommandEvent & WXUNUSED(event)); /// Save view as povray file void POVRayOutput(const std::string &filename); /// get bounding box for atoms display BBox GetCellBBox(); /// get bounding box for display of Fourier map BBox GetMapBBox(); /// Access to fade distance for 3D display REAL GetFadeDistance(); virtual void SetCurrent(); void NotifyDeleteFourierWin(); private: void InitGL(); /// Shows a dialog to choose a displayed fourier map from one of those /// available. int UserSelectUnitCellMapGLList()const; /// Shows a dialog to choose a fourier map from one of those /// available. int UserSelectUnitCellMap()const; /** Transform (x,y) window coordinates to (x,y,z) coordinates in the * Crystal's orthonormal frame (with the origin at the center of the Unit Cell). * * \param x,y: on input, these contain the mouse screen coordinates, * and in return these are the x and y coordinates in the Crystal orthonormal * frame. * \param z: ignored on input (the z coordinate taken is that of the * center of rotation). * * \note: this should be const, but we use SetCurrent() and build_rotmatrix( ,mQuat)... * which are not const-correct... */ void UnProject(REAL &x, REAL &y, REAL &z); /// Build the 96 display lists for the font void BuildGLFont(); /// Delete the 96 display lists for the font void DeleteGLFont()const; /// The parent wxFrame wxFrame* mpParentFrame; /// The owner WXCrystal WXCrystal* mpWXCrystal; /// The wxGLContext wxGLContext *mpwxGLContext; /// \internal bool mIsGLInit; /// quaternion for the orientation of the display float mQuat [4]; /// \internal float mTrackBallLastX,mTrackBallLastY; /// Distance from viewer to crystal (Z) float mDist; REAL mX0, mY0,mZ0; /// View Angle, in degrees float mViewAngle; /// Pop-up menu wxMenu* mpPopUpMenu; /// Display options bool mShowFourier, mShowCrystal, mShowAtomName, mShowHydrogens, mShowCursor, mSharpenMap, mShowHelp, mShowFullMolecule, mWhiteBackground; /// bounding box for atoms to be included BBox mcellbbox; /// bounding box for display of Fourier map BBox mmapbbox; /// position to use as center Triple mViewCntr; /** Fourier maps, imported or calculated. * * All diffraction data associated with this crystal will be listed here, for * the different maps possible (obs, calc, obs-calc). */ vector > mvpUnitCellMap; /** OpenGL display lists corresponding to Fourier maps. * */ vector > mvpUnitCellMapGLList; /// Display lists for the font used to display strings mutable bool mIsGLFontBuilt; mutable int mGLFontDisplayListBase; /// Window to list available Fourier maps class WXFourierMapList:public wxWindow { public: WXFourierMapList(WXGLCrystalCanvas *pGLCrystalCanvas,wxWindow *parent); ~WXFourierMapList(); wxCheckBox *mpWireFrame; wxCheckBox *mpShowFourier; wxCheckBox *mpSharpenMap; wxListBox *mpAvailableMapList; wxListBox *mpDisplayedMapList; wxStaticText *mpMapInfo; wxTextCtrl *mpNewContourValue; wxTextCtrl *mpContourValue; wxColourPickerCtrl *mpColourPicker; WXGLCrystalCanvas *mpGLCrystalCanvas; wxMutex mMutex; bool mIsUpdating; }; WXFourierMapList *mpFourierMapListWin; /// Fade distance to display transparent atoms/molecules beyond display limit. REAL mFadeDistance; DECLARE_EVENT_TABLE() }; #endif } //namespace #endif //_VFN_WX_CRYSTAL_H_ objcryst-2022.1/ObjCryst/wxCryst/wxDiffractionSingleCrystal.cpp000066400000000000000000000641031430515525000247040ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ //#include //for stringstream #include // wx headers, with or without precompilation #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "ObjCryst/wxCryst/wxDiffractionSingleCrystal.h" #include "ObjCryst/wxCryst/wxRadiation.h" //Fixes for Cygwin; where do those stupid macros come from ? Somewhere in wxMSW headers #ifdef max #undef max #endif #ifdef min #undef min #endif #ifdef DrawText #undef DrawText #endif namespace ObjCryst { //////////////////////////////////////////////////////////////////////// // // WXDiffractionSingleCrystalGraph // //////////////////////////////////////////////////////////////////////// /** Class to display Iobs and Icalc as a function of 1/d * */ class WXDiffractionSingleCrystalGraph:public WXMultiGraph { public: WXDiffractionSingleCrystalGraph(wxFrame *frame,WXDiffractionSingleCrystal *parent): WXMultiGraph(frame) { mpParent=parent; } virtual ~WXDiffractionSingleCrystalGraph() { mpParent->NotifyDeleteGraph(); } private: WXDiffractionSingleCrystal *mpParent; }; //////////////////////////////////////////////////////////////////////// // // WXDiffractionSingleCrystal // //////////////////////////////////////////////////////////////////////// static long ID_DIFFSINGLECRYST_MENU_SAVEHKLIOBSICALC= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_SAVEHKLFCALC= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_SIMULATE= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_IMPORT_HKLIOBS= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_IMPORT_HKLIOBSSIGMA= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_IMPORT_SHELXHKLF4= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_IMPORT_CIF= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_IMPORT_JANAM91= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_IMPORT_HKLIOBSGROUP= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_FITSCALE_R= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_FITSCALE_RW= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_WAVELENGTH= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_WAVELENGTH_XRAY= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_WAVELENGTH_NEUTRON= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_WAVELENGTH_ELECTRON= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_AG= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_MO= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_CU= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_FE= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_CO= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_CR= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_AGA1= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_MOA1= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_CUA1= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_FEA1= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_COA1= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_CRA1= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_CRYSTAL= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_DATA= WXCRYST_ID(); static long ID_DIFFSINGLECRYST_MENU_DATA_GRAPH= WXCRYST_ID(); BEGIN_EVENT_TABLE(WXDiffractionSingleCrystal, wxWindow) EVT_BUTTON(ID_WXOBJ_COLLAPSE, WXCrystObj::OnToggleCollapse) EVT_MENU(ID_REFOBJ_MENU_OBJ_SAVE, WXRefinableObj::OnMenuSave) EVT_MENU(ID_REFOBJ_MENU_OBJ_LOAD, WXRefinableObj::OnMenuLoad) EVT_MENU(ID_REFOBJ_MENU_PAR_FIXALL, WXRefinableObj::OnMenuFixAllPar) EVT_MENU(ID_REFOBJ_MENU_PAR_UNFIXALL, WXRefinableObj::OnMenuUnFixAllPar) EVT_MENU(ID_DIFFSINGLECRYST_MENU_SAVEHKLIOBSICALC, WXDiffractionSingleCrystal::OnMenuSaveHKLIobsIcalc) EVT_MENU(ID_DIFFSINGLECRYST_MENU_SAVEHKLFCALC, WXDiffractionSingleCrystal::OnMenuSaveHKLFcalc) EVT_MENU(ID_DIFFSINGLECRYST_MENU_SIMULATE, WXDiffractionSingleCrystal::OnMenuSimulate) EVT_MENU(ID_DIFFSINGLECRYST_MENU_IMPORT_HKLIOBS, WXDiffractionSingleCrystal::OnMenuImport) EVT_MENU(ID_DIFFSINGLECRYST_MENU_IMPORT_HKLIOBSSIGMA,WXDiffractionSingleCrystal::OnMenuImport) EVT_MENU(ID_DIFFSINGLECRYST_MENU_IMPORT_SHELXHKLF4, WXDiffractionSingleCrystal::OnMenuImport) EVT_MENU(ID_DIFFSINGLECRYST_MENU_IMPORT_CIF , WXDiffractionSingleCrystal::OnMenuImport) EVT_MENU(ID_DIFFSINGLECRYST_MENU_IMPORT_JANAM91, WXDiffractionSingleCrystal::OnMenuImport) EVT_MENU(ID_DIFFSINGLECRYST_MENU_IMPORT_HKLIOBSGROUP,WXDiffractionSingleCrystal::OnMenuImport) EVT_BUTTON(ID_DIFFSINGLECRYST_CRYSTAL, WXDiffractionSingleCrystal::OnChangeCrystal) //EVT_MENU(ID_DIFFSINGLECRYST_MENU_FITSCALE_R, WXDiffractionSingleCrystal::OnMenuFitScaleForR) //EVT_MENU(ID_DIFFSINGLECRYST_MENU_FITSCALE_RW, WXDiffractionSingleCrystal::OnMenuFitScaleForRw) EVT_MENU(ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET, WXDiffractionSingleCrystal::OnMenuSetWavelength) EVT_MENU(ID_DIFFSINGLECRYST_MENU_WAVELENGTH_XRAY, WXDiffractionSingleCrystal::OnMenuSetWavelength) EVT_MENU(ID_DIFFSINGLECRYST_MENU_WAVELENGTH_NEUTRON, WXDiffractionSingleCrystal::OnMenuSetWavelength) EVT_MENU(ID_DIFFSINGLECRYST_MENU_WAVELENGTH_ELECTRON,WXDiffractionSingleCrystal::OnMenuSetWavelength) EVT_MENU(ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_AG, WXDiffractionSingleCrystal::OnMenuSetWavelength) EVT_MENU(ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_MO, WXDiffractionSingleCrystal::OnMenuSetWavelength) EVT_MENU(ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_CU, WXDiffractionSingleCrystal::OnMenuSetWavelength) EVT_MENU(ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_FE, WXDiffractionSingleCrystal::OnMenuSetWavelength) EVT_MENU(ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_CO, WXDiffractionSingleCrystal::OnMenuSetWavelength) EVT_MENU(ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_CR, WXDiffractionSingleCrystal::OnMenuSetWavelength) EVT_MENU(ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_AGA1,WXDiffractionSingleCrystal::OnMenuSetWavelength) EVT_MENU(ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_MOA1,WXDiffractionSingleCrystal::OnMenuSetWavelength) EVT_MENU(ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_CUA1,WXDiffractionSingleCrystal::OnMenuSetWavelength) EVT_MENU(ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_FEA1,WXDiffractionSingleCrystal::OnMenuSetWavelength) EVT_MENU(ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_COA1,WXDiffractionSingleCrystal::OnMenuSetWavelength) EVT_MENU(ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_CRA1,WXDiffractionSingleCrystal::OnMenuSetWavelength) EVT_MENU(ID_DIFFSINGLECRYST_MENU_DATA_GRAPH, WXDiffractionSingleCrystal::OnMenuShowGraph) EVT_UPDATE_UI(ID_CRYST_UPDATEUI, WXRefinableObj::OnUpdateUI) END_EVENT_TABLE() WXDiffractionSingleCrystal::WXDiffractionSingleCrystal(wxWindow *parent, DiffractionDataSingleCrystal* data): WXRefinableObj(parent,data),mpData(data),mpGraph(0),mGrapIdObs(0),mGrapIdCalc(0) { VFN_DEBUG_MESSAGE("WXDiffractionSingleCrystal::WXDiffractionSingleCrystal()",6) mpWXTitle->SetForegroundColour(wxColour(255,0,0)); mpWXTitle->SetSize(400,-1); // Menu mpMenuBar->AddMenu("File",ID_REFOBJ_MENU_OBJ); //:TODO: reactivate & test those menus //mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_REFOBJ_MENU_OBJ_SAVE,"Save"); //mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_REFOBJ_MENU_OBJ_LOAD,"Load"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_DIFFSINGLECRYST_MENU_SAVEHKLIOBSICALC, "Save HKL Iobs Icalc (text)"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_DIFFSINGLECRYST_MENU_SAVEHKLFCALC, "Save HKL Fcalc (text)"); mpMenuBar->GetMenu(ID_REFOBJ_MENU_OBJ).AppendSeparator(); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_DIFFSINGLECRYST_MENU_SIMULATE, "Simulation mode (generate HKL list)"); mpMenuBar->GetMenu(ID_REFOBJ_MENU_OBJ).AppendSeparator(); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_DIFFSINGLECRYST_MENU_IMPORT_HKLIOBS, "Import HKL Iobs"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_DIFFSINGLECRYST_MENU_IMPORT_HKLIOBSSIGMA, "Import HKL Iobs Sigma (space or tab-separated)"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_DIFFSINGLECRYST_MENU_IMPORT_SHELXHKLF4, "Import HKL Iobs Sigma (HKLF 4 Shelx format)"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_DIFFSINGLECRYST_MENU_IMPORT_CIF, "Import CIF single crystal data"); //mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_DIFFSINGLECRYST_MENU_IMPORT_JANAM91, // "Import Jana M91"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_DIFFSINGLECRYST_MENU_IMPORT_HKLIOBSGROUP, "Import Reflections with group intensity"); mpMenuBar->AddMenu("Radiation",ID_DIFFSINGLECRYST_MENU_WAVELENGTH); mpMenuBar->AddMenuItem(ID_DIFFSINGLECRYST_MENU_WAVELENGTH, ID_DIFFSINGLECRYST_MENU_WAVELENGTH_NEUTRON, "Neutron"); mpMenuBar->AddMenuItem(ID_DIFFSINGLECRYST_MENU_WAVELENGTH, ID_DIFFSINGLECRYST_MENU_WAVELENGTH_XRAY, "X-Ray"); mpMenuBar->AddMenuItem(ID_DIFFSINGLECRYST_MENU_WAVELENGTH, ID_DIFFSINGLECRYST_MENU_WAVELENGTH_ELECTRON, "Electron"); mpMenuBar->AddMenuItem(ID_DIFFSINGLECRYST_MENU_WAVELENGTH, ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET, "Monochromatic Wavelength"); mpMenuBar->AddMenuItem(ID_DIFFSINGLECRYST_MENU_WAVELENGTH, ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_AG, "X-Ray Tube Ag Ka12"); mpMenuBar->AddMenuItem(ID_DIFFSINGLECRYST_MENU_WAVELENGTH, ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_AGA1, "X-Ray Tube Ag Ka1"); mpMenuBar->AddMenuItem(ID_DIFFSINGLECRYST_MENU_WAVELENGTH, ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_MO, "X-Ray Tube Mo Ka12"); mpMenuBar->AddMenuItem(ID_DIFFSINGLECRYST_MENU_WAVELENGTH, ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_MOA1, "X-Ray Tube Mo Ka1"); mpMenuBar->AddMenuItem(ID_DIFFSINGLECRYST_MENU_WAVELENGTH, ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_CU, "X-Ray Tube Cu Ka12"); mpMenuBar->AddMenuItem(ID_DIFFSINGLECRYST_MENU_WAVELENGTH, ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_CUA1, "X-Ray Tube Cu Ka1"); mpMenuBar->AddMenuItem(ID_DIFFSINGLECRYST_MENU_WAVELENGTH, ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_FE, "X-Ray Tube Fe Ka12"); mpMenuBar->AddMenuItem(ID_DIFFSINGLECRYST_MENU_WAVELENGTH, ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_FEA1, "X-Ray Tube Fe Ka1"); mpMenuBar->AddMenuItem(ID_DIFFSINGLECRYST_MENU_WAVELENGTH, ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_CO, "X-Ray Tube Co Ka12"); mpMenuBar->AddMenuItem(ID_DIFFSINGLECRYST_MENU_WAVELENGTH, ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_COA1, "X-Ray Tube Co Ka1"); mpMenuBar->AddMenuItem(ID_DIFFSINGLECRYST_MENU_WAVELENGTH, ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_CR, "X-Ray Tube Cr Ka12"); mpMenuBar->AddMenuItem(ID_DIFFSINGLECRYST_MENU_WAVELENGTH, ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_CRA1, "X-Ray Tube Cr Ka1"); //mpMenuBar->AddMenu("Compute",ID_CRYSTAL_MENU_DISPLAY); // mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_DISPLAY,ID_DIFFSINGLECRYST_MENU_FITSCALE_R, // "Fit Scale for R"); // mpMenuBar->AddMenuItem(ID_CRYSTAL_MENU_DISPLAY,ID_DIFFSINGLECRYST_MENU_FITSCALE_RW, // "Fit Scale for Rw"); mpMenuBar->AddMenu("Data",ID_DIFFSINGLECRYST_MENU_DATA); mpMenuBar->AddMenuItem(ID_DIFFSINGLECRYST_MENU_DATA,ID_DIFFSINGLECRYST_MENU_DATA_GRAPH, "Show Graph"); //mpSizer->SetItemMinSize(mpMenuBar, // mpMenuBar->GetSize().GetWidth(), // mpMenuBar->GetSize().GetHeight()); //Radiation mpSizer->Add(mpData->mRadiation.WXCreate(this),0); mList.Add(mpData->mRadiation.WXGet()); // Crystal mpFieldCrystal=new WXFieldChoice(this,ID_DIFFSINGLECRYST_CRYSTAL,"Crystal:",300); mpSizer->Add(mpFieldCrystal,0,wxALIGN_LEFT); mList.Add(mpFieldCrystal); // Max Sin(theta/Lambda) WXFieldPar *maxSiThOvLa= new WXFieldPar(this,"Max Sin(theta)/lambda:",-1,&(mpData->mMaxSinThetaOvLambda)); mpSizer->Add(maxSiThOvLa,0,wxALIGN_LEFT); mList.Add(maxSiThOvLa); // Statistics wxBoxSizer* pStats=new wxBoxSizer(wxHORIZONTAL); WXFieldPar *pWXFieldChi2=new WXFieldPar(this,"Chi^2",-1,&mChi2,100); pStats->Add(pWXFieldChi2 ,0,wxALIGN_CENTER); mList.Add(pWXFieldChi2); WXFieldPar *pWXFieldGof=new WXFieldPar(this,"GoF",-1,&mGoF,70); pStats->Add(pWXFieldGof ,0,wxALIGN_CENTER); mList.Add(pWXFieldGof); WXFieldPar *pWXFieldRwp=new WXFieldPar(this,"Rwp",-1,&mRwp,70); pStats->Add(pWXFieldRwp ,0,wxALIGN_CENTER); mList.Add(pWXFieldRwp); WXFieldPar *pWXFieldRp=new WXFieldPar(this,"Rp",-1,&mRp,70); pStats->Add(pWXFieldRp ,0,wxALIGN_CENTER); mList.Add(pWXFieldRp); mpSizer->Add(pStats); this->CrystUpdate(true); VFN_DEBUG_MESSAGE("WXDiffractionSingleCrystal::WXDiffractionSingleCrystal():End",6) } void WXDiffractionSingleCrystal::CrystUpdate(const bool uui,const bool lock) { VFN_DEBUG_ENTRY("WXDiffractionSingleCrystal::CrystUpdate()",6) if(lock) mMutex.Lock(); WXCrystValidateAllUserInput(); mChi2=mpData->GetChi2(); if(0==mpData->GetIobs().numElements()) mGoF=0; else mGoF=mpData->GetChi2()/mpData->GetIobs().numElements(); mRwp=mpData->GetRw(); mRp=mpData->GetR(); if(mpGraph!=0) { const CrystVector_REAL *mpCalc=&(mpData->GetIcalc()); const CrystVector_REAL *mpObs =&(mpData->GetIobs()); const CrystVector_REAL *mpSinThetaOverLambda=&(mpData->GetSinThetaOverLambda()); const unsigned long nb=mpCalc->numElements(); mX .resize(nb); mIobs .resize(nb); mIcalc.resize(nb); for(unsigned long i=0;iWXRefinableObj::CrystUpdate(uui,lock); VFN_DEBUG_EXIT("WXDiffractionSingleCrystal::CrystUpdate()",6) } void WXDiffractionSingleCrystal::NotifyDeleteGraph() { mpGraph=0; } void WXDiffractionSingleCrystal::OnMenuSimulate(wxCommandEvent & WXUNUSED(event)) { WXCrystValidateAllUserInput(); double theta; { wxTextEntryDialog dialog(this,_T("Theta Max"), _T("Enter maximum Theta (degrees)"),_T("50"),wxOK | wxCANCEL); dialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=dialog.ShowModal()) { VFN_DEBUG_EXIT("WXDiffractionSingleCrystal::OnMenuSimulate():Cancelled",6) return; } dialog.GetValue().ToDouble(&theta); } wxString choices[2]; choices[0]=_T("all reflections (keep Friedel&Bijvoet mates)"); choices[1]=_T("only unique reflections"); wxSingleChoiceDialog dialog(this,_T("Choose method"), _T("Choose method for Reflection generation"), 2,choices,(void **)NULL,wxOK | wxCANCEL); if(wxID_OK!=dialog.ShowModal()) return; const int choice=dialog.GetSelection(); if(0==choice) mpData->GenHKLFullSpace(theta*DEG2RAD,false); else mpData->GenHKLFullSpace(theta*DEG2RAD,true); } void WXDiffractionSingleCrystal::OnMenuImport(wxCommandEvent & event) { if(event.GetId()== ID_DIFFSINGLECRYST_MENU_IMPORT_HKLIOBS) { wxFileDialog open(this,_T("Choose file to import from"), _T(""),_T(""),_T("*.*"),wxFD_OPEN | wxFD_FILE_MUST_EXIST); if(open.ShowModal() != wxID_OK) return; long nb=0; { wxTextEntryDialog dialog(this,_T("Number of reflections"), _T("Enter The number of reflections to import"),_T("50"), wxOK | wxCANCEL); dialog.SetTextValidator(wxTextValidator(wxFILTER_DIGITS)); if(wxID_OK!=dialog.ShowModal()) { VFN_DEBUG_EXIT("WXDiffractionSingleCrystal))OnMenuImport())Cancelled",6) return; } dialog.GetValue().ToLong(&nb); } mpData->ImportHklIobs(string(open.GetPath().ToAscii()),nb); mpData->UpdateDisplay(); return; } if(event.GetId()== ID_DIFFSINGLECRYST_MENU_IMPORT_HKLIOBSSIGMA) { wxFileDialog open(this,_T("Choose file to import from"), _T(""),_T(""),_T("*.*"),wxFD_OPEN | wxFD_FILE_MUST_EXIST); if(open.ShowModal() != wxID_OK) return; long nb=0; { wxTextEntryDialog dialog(this,_T("Number of reflections"), _T("Enter The number of reflections to import"),_T("50"), wxOK | wxCANCEL); dialog.SetTextValidator(wxTextValidator(wxFILTER_DIGITS)); if(wxID_OK!=dialog.ShowModal()) { VFN_DEBUG_EXIT("WXDiffractionSingleCrystal))OnMenuImport())Cancelled",6) return; } dialog.GetValue().ToLong(&nb); } mpData->ImportHklIobsSigma(string(open.GetPath().ToAscii()),nb); mpData->UpdateDisplay(); return; } if(event.GetId()== ID_DIFFSINGLECRYST_MENU_IMPORT_SHELXHKLF4) { wxFileDialog open(this,_T("Choose Shelx file to import from"), _T(""),_T(""),_T("*.hkl"),wxFD_OPEN | wxFD_FILE_MUST_EXIST); if(open.ShowModal() != wxID_OK) return; mpData->ImportShelxHKLF4(string(open.GetPath().ToAscii())); mpData->UpdateDisplay(); return; } if(event.GetId()== ID_DIFFSINGLECRYST_MENU_IMPORT_CIF) { wxFileDialog open(this,_T("Choose CIF file to import from"), _T(""),_T(""),_T("*.cif"),wxFD_OPEN | wxFD_FILE_MUST_EXIST); if(open.ShowModal() != wxID_OK) return; mpData->ImportCIF(string(open.GetPath().ToAscii())); mpData->UpdateDisplay(); return; } if(event.GetId()== ID_DIFFSINGLECRYST_MENU_IMPORT_HKLIOBSGROUP) { wxFileDialog open(this,_T("Choose data file"), _T(""),_T(""),_T("*.*"),wxFD_OPEN | wxFD_FILE_MUST_EXIST); if(open.ShowModal() != wxID_OK) return; mpData->ImportHklIobsGroup(string(open.GetPath().ToAscii())); mpData->UpdateDisplay(); return; } if(event.GetId()== ID_DIFFSINGLECRYST_MENU_IMPORT_JANAM91) { wxFileDialog open(this,_T("Choose data file"), _T(""),_T(""),_T("*.*"),wxFD_OPEN | wxFD_FILE_MUST_EXIST); if(open.ShowModal() != wxID_OK) return; mpData->ImportHklIobsSigmaJanaM91(string(open.GetPath().ToAscii())); mpData->UpdateDisplay(); return; } } void WXDiffractionSingleCrystal::OnMenuSaveHKLIobsIcalc(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_MESSAGE("WXDiffractionSingleCrystal::OnMenuSaveHKLIobsIcalc()",6) WXCrystValidateAllUserInput(); wxFileDialog save(this,_T("Choose a file"),_T(""),_T(""),_T("*.txt"),wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if(save.ShowModal() != wxID_OK) return; mpData->SaveHKLIobsIcalc(string(save.GetPath().ToAscii())); } void WXDiffractionSingleCrystal::OnMenuSaveHKLFcalc(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_MESSAGE("WXDiffractionSingleCrystal::OnMenuSaveHKLFcalc()",6) WXCrystValidateAllUserInput(); wxFileDialog save(this,_T("Choose a file"),_T(""),_T(""),_T("*.txt"),wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if(save.ShowModal() != wxID_OK) return; ofstream os(save.GetPath().ToAscii()); mpData->PrintFhklCalcDetail(os); os.close(); mpData->GetCrystal().GetScatteringComponentList().Print(); } void WXDiffractionSingleCrystal::OnMenuSetWavelength(wxCommandEvent &event) { WXCrystValidateAllUserInput(); //:TODO: Use wxRadiation instead if(event.GetId()== ID_DIFFSINGLECRYST_MENU_WAVELENGTH_XRAY) mpData->SetRadiationType(RAD_XRAY); if(event.GetId()== ID_DIFFSINGLECRYST_MENU_WAVELENGTH_NEUTRON) mpData->SetRadiationType(RAD_NEUTRON); if(event.GetId()== ID_DIFFSINGLECRYST_MENU_WAVELENGTH_ELECTRON) mpData->SetRadiationType(RAD_ELECTRON); if(event.GetId()== ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET) { double lambda; wxTextEntryDialog dialog(this,_T("new Wavelength)"), _T("Enter new Wavelength (Angstroems)"),_T("1"),wxOK | wxCANCEL); dialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=dialog.ShowModal()) { VFN_DEBUG_EXIT("WXDiffractionSingleCrystal))OnMenuSetWavelength())Monochromatic)Cancelled",6) return; } dialog.GetValue().ToDouble(&lambda); mpData->SetWavelength(lambda); } if(event.GetId()== ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_AG) mpData->SetWavelength("Ag"); if(event.GetId()== ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_MO) mpData->SetWavelength("Mo"); if(event.GetId()== ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_CU) mpData->SetWavelength("Cu"); if(event.GetId()== ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_FE) mpData->SetWavelength("Fe"); if(event.GetId()== ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_CO) mpData->SetWavelength("Co"); if(event.GetId()== ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_CR) mpData->SetWavelength("Cr"); if(event.GetId()== ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_AGA1) mpData->SetWavelength("AgA1"); if(event.GetId()== ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_MOA1) mpData->SetWavelength("MoA1"); if(event.GetId()== ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_CUA1) mpData->SetWavelength("CuA1"); if(event.GetId()== ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_FEA1) mpData->SetWavelength("FeA1"); if(event.GetId()== ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_COA1) mpData->SetWavelength("CoA1"); if(event.GetId()== ID_DIFFSINGLECRYST_MENU_WAVELENGTH_SET_CRA1) mpData->SetWavelength("CrA1"); this->CrystUpdate(true,true); } void WXDiffractionSingleCrystal::OnMenuShowGraph(wxCommandEvent &event) { VFN_DEBUG_MESSAGE("WXDiffractionSingleCrystal::OnMenuShowGraph()"<GetNbRefl()<=0) return; WXCrystValidateAllUserInput(); std::string s=mpData->GetName(); if(s.size()==0) s=mpData->GetCrystal().GetName(); s="Single Crystal data:"+s; wxFrame *frame= new wxFrame(this,-1,wxString::FromAscii(s.c_str()), wxDefaultPosition, wxSize(500, 300), wxCLOSE_BOX | wxRESIZE_BORDER | wxCAPTION | wxMINIMIZE_BOX | wxMAXIMIZE_BOX);//wxFRAME_FLOAT_ON_PARENT frame->CreateStatusBar(1); mpGraph = new WXDiffractionSingleCrystalGraph(frame,this); mpGraph->SetXLabel(_T("1/d (A)")); mpGraph->SetYLabel(_T("Intensity")); mGrapIdObs =mpGraph->AddGraph("Iobs"); mGrapIdCalc=mpGraph->AddGraph("Icalc"); wxSizer *ps=new wxBoxSizer(wxHORIZONTAL); ps->Add(mpGraph,1,wxEXPAND); frame->SetSizer(ps); frame->SetAutoLayout(true); //frame->CreateStatusBar(2); frame->Show(true); frame->Raise(); this->CrystUpdate(true); } void WXDiffractionSingleCrystal::OnChangeCrystal(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_MESSAGE("WXDiffractionSingleCrystal::OnChangeCrystal()",6) WXCrystValidateAllUserInput(); int choice; Crystal *cryst=dynamic_cast (WXDialogChooseFromRegistry(gCrystalRegistry,(wxWindow*)this, "Choose a Crystal Structure:",choice)); if(0==cryst) return; mpData->SetCrystal(*cryst); this->CrystUpdate(true,true); } void WXDiffractionSingleCrystal::UpdateUI(const bool lock) { if(lock) mMutex.Lock(); if(mpData->HasCrystal()) mpFieldCrystal->SetValue(mpData->GetCrystal().GetName()); if(mpGraph!=0) { mpGraph->SetGraphData(mGrapIdObs,mX,mIobs); mpGraph->SetGraphData(mGrapIdCalc,mX,mIcalc); mpGraph->UpdateDisplay(); } this->WXRefinableObj::UpdateUI(false); if(lock) mMutex.Unlock(); } }//namespace objcryst-2022.1/ObjCryst/wxCryst/wxDiffractionSingleCrystal.h000066400000000000000000000046211430515525000243500ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _VFN_WX_DIFFRACTIONSINGLECRYSTAL_H_ #define _VFN_WX_DIFFRACTIONSINGLECRYSTAL_H_ #include "ObjCryst/ObjCryst/DiffractionDataSingleCrystal.h" #include "ObjCryst/wxCryst/wxRefinableObj.h" #include "ObjCryst/wxCryst/wxMultiGraph.h" namespace ObjCryst { /** WX Class for DiffractionDataSingleCrystal objects * * */ class WXDiffractionSingleCrystal: public WXRefinableObj { public: WXDiffractionSingleCrystal(wxWindow *parent, DiffractionDataSingleCrystal*); virtual void CrystUpdate(const bool updateUI=false,const bool mutexlock=false); virtual void UpdateUI(const bool mutexlock=false); /// For the mpGraph to tell its owner it was deleted void NotifyDeleteGraph(); private: void OnMenuSimulate(wxCommandEvent & WXUNUSED(event)); void OnMenuImport(wxCommandEvent & event); void OnMenuSaveHKLIobsIcalc(wxCommandEvent & WXUNUSED(event)); void OnMenuSaveHKLFcalc(wxCommandEvent & WXUNUSED(event)); void OnMenuSetWavelength(wxCommandEvent &event); void OnMenuShowGraph(wxCommandEvent &event); void OnChangeCrystal(wxCommandEvent & WXUNUSED(event)); WXFieldChoice* mpFieldCrystal; DiffractionDataSingleCrystal *mpData; // Store statistics for display REAL mChi2; REAL mGoF; REAL mRwp; REAL mRp; WXMultiGraph *mpGraph; unsigned long mGrapIdObs; unsigned long mGrapIdCalc; /// Copy of the data for graph display valarray mIobs,mIcalc,mX; DECLARE_EVENT_TABLE() }; }//namespace #endif objcryst-2022.1/ObjCryst/wxCryst/wxGlobalOptimObj.cpp000066400000000000000000000640041430515525000226140ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ //#include //for stringstream #include // wx headers, with or without precompilation #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "wx/progdlg.h" #include "ObjCryst/wxCryst/wxGlobalOptimObj.h" #include "ObjCryst/ObjCryst/IO.h" // Next two just to fix some parameters during global optimization #include "ObjCryst/ObjCryst/Crystal.h" #include "ObjCryst/ObjCryst/ScatteringData.h" //Fixes for Cygwin; where do those stupid macros come from ? Somewhere in wxMSW headers #ifdef max #undef max #endif #ifdef min #undef min #endif #ifdef DrawText #undef DrawText #endif namespace ObjCryst { //////////////////////////////////////////////////////////////////////// // // WXOptimizationObj // //////////////////////////////////////////////////////////////////////// static long ID_GLOBALOPT_MENU_OBJECTS= WXCRYST_ID(); static long ID_GLOBALOPT_MENU_OBJECTS_ADDOBJ= WXCRYST_ID(); static long ID_GLOBALOPT_MENU_OBJECTS_REMOVEOBJ= WXCRYST_ID(); static long ID_GLOBALOPT_MENU_OBJECTS_ADDCOSTFUNC= WXCRYST_ID(); static long ID_GLOBALOPT_MENU_OBJECTS_REMOVECOSTFUNC=WXCRYST_ID(); static long ID_GLOBALOPT_MENU_OPT= WXCRYST_ID(); static long ID_GLOBALOPT_MENU_OPT_RUN= WXCRYST_ID(); static long ID_GLOBALOPT_MENU_OPT_RUN_MULTIPLE= WXCRYST_ID(); static long ID_GLOBALOPT_MENU_OPT_STOP= WXCRYST_ID(); static long ID_GLOBALOPT_MENU_OPT_LSQ= WXCRYST_ID(); static long ID_GLOBALOPT_MENU_SOLUTIONS= WXCRYST_ID(); static long ID_GLOBALOPT_MENU_SOLUTIONS_BROWSE= WXCRYST_ID(); static long ID_BROWSE_WIN= WXCRYST_ID(); WXOptimizationObj::WXOptimizationObj(wxWindow* parent, OptimizationObj *obj): WXCrystObj(parent),mpGlobalOptimRunThread(0) { VFN_DEBUG_ENTRY("WXOptimizationObj::WXOptimizationObj(wxWindow*,GlobalOptimObj*,)",7) #ifdef VFN_CRYST_MUTEX cout <<"new CrystMutex("<<&mMutex<<")for WXOptimizationObj:"<GetName()<SetForegroundColour(wxColour(255,0,0)); mpWXTitle->SetLabel("Global Optimization:"); mpWXTitle->SetSize(400,-1); // Menu mpMenuBar=new WXCrystMenuBar(this,this); mpSizer->Add(mpMenuBar); mList.Add(mpMenuBar); //mpMenuBar->AddMenu("Object",ID_REFOBJ_MENU_OBJ); //mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_REFOBJ_MENU_OBJ_SAVE,"Save"); //mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_REFOBJ_MENU_OBJ_LOAD,"Load"); mpMenuBar->AddMenu("Optimized Objects",ID_GLOBALOPT_MENU_OBJECTS); mpMenuBar->AddMenuItem(ID_GLOBALOPT_MENU_OBJECTS,ID_GLOBALOPT_MENU_OBJECTS_ADDOBJ, "Add object to optimize"); mpMenuBar->AddMenu("Run/Stop",ID_GLOBALOPT_MENU_OPT); mpMenuBar->AddMenuItem(ID_GLOBALOPT_MENU_OPT, ID_GLOBALOPT_MENU_OPT_RUN_MULTIPLE,"Multiple Runs"); mpMenuBar->AddMenuItem(ID_GLOBALOPT_MENU_OPT, ID_GLOBALOPT_MENU_OPT_RUN,"Single Run"); mpMenuBar->AddMenuItem(ID_GLOBALOPT_MENU_OPT, ID_GLOBALOPT_MENU_OPT_STOP,"Stop Optimization"); mpMenuBar->GetMenu(ID_GLOBALOPT_MENU_OPT).AppendSeparator(); mpMenuBar->AddMenuItem(ID_GLOBALOPT_MENU_OPT, ID_GLOBALOPT_MENU_OPT_LSQ,"Least Squares Fit"); mpMenuBar->AddMenu("Solutions",ID_GLOBALOPT_MENU_SOLUTIONS); mpMenuBar->AddMenuItem(ID_GLOBALOPT_MENU_SOLUTIONS, ID_GLOBALOPT_MENU_SOLUTIONS_BROWSE,"Browse Solutions"); mpMenuBar->Layout(); //mpSizer->SetItemMinSize(mpMenuBar, // mpMenuBar->GetSize().GetWidth(), // mpMenuBar->GetSize().GetHeight()); //Refined Objects for(int i=0;imRefinedObjList.GetNb();i++) { WXFieldName *refobj=new WXFieldName(this,"Optimized object:",this,-1,300,false); refobj->SetValue(obj->mRefinedObjList.GetObj(i).GetClassName() +":"+obj->mRefinedObjList.GetObj(i).GetName()); mpSizer->Add(refobj); mList.Add(refobj); } // This will be done later //this->CrystUpdate(); VFN_DEBUG_EXIT("WXOptimizationObj::WXOptimizationObj(wxWindow*,GlobalOptimObj*,)",7) } void WXOptimizationObj::CrystUpdate(const bool uui,const bool lock) { VFN_DEBUG_ENTRY("WXOptimizationObj::CrystUpdate("<WXCrystObj::CrystUpdate(uui,lock); if(uui) { if(true==wxThread::IsMain()) this->UpdateUI(lock); else { wxUpdateUIEvent event(ID_CRYST_UPDATEUI); wxPostEvent(this,event); } } VFN_DEBUG_EXIT("WXOptimizationObj::CrystUpdate("<GetOptimizationObj().SetName(mpWXTitle->GetValue()); return true; } return false; } void WXOptimizationObj::OnSave(){} void WXOptimizationObj::OnLoad(){} void WXOptimizationObj::OnAddRefinedObject(wxCommandEvent & WXUNUSED(event)) { WXCrystValidateAllUserInput(); int choice; RefinableObj *obj= WXDialogChooseFromRegistry(gTopRefinableObjRegistry,this, "Choose object to optimize:",choice); if(0==obj) return; this->GetOptimizationObj().AddRefinableObj(*obj); } void WXOptimizationObj::AddRefinedObject(RefinableObj &obj) { WXCrystValidateAllUserInput(); WXFieldName *refobj=new WXFieldName(this,"Optimized object:",this,-1,300,false); refobj->SetValue(obj.GetClassName()+":"+obj.GetName()); mpSizer->Add(refobj); mList.Add(refobj); wxTheApp->GetTopWindow()->Layout(); wxTheApp->GetTopWindow()->SendSizeEvent(); refobj->UpdateUI(true); } void WXOptimizationObj::OnRemoveRefinedObject(wxCommandEvent & WXUNUSED(event)) { } void WXOptimizationObj::OnStopOptimization(wxCommandEvent & WXUNUSED(event)) { if(0!=mpGlobalOptimRunThread) { if(mpGlobalOptimRunThread->IsAlive()) { (*fpObjCrystInformUser)("Waiting for global optimization to stop..."); this->GetOptimizationObj().StopAfterCycle(); mpGlobalOptimRunThread->Wait(wxTHREAD_WAIT_YIELD); this->GetOptimizationObj().UpdateDisplay(); (*fpObjCrystInformUser)("Global optimization halted..."); } delete mpGlobalOptimRunThread; mpGlobalOptimRunThread=0; } } void WXOptimizationObj::OnUpdateUI(wxUpdateUIEvent& event) { VFN_DEBUG_ENTRY("WXOptimizationObj::OnUpdateUI()",5) this->UpdateUI(true); event.Skip(); VFN_DEBUG_EXIT("WXOptimizationObj::OnUpdateUI()",5) } void WXOptimizationObj::UpdateUI(const bool lock) { VFN_DEBUG_ENTRY("WXOptimizationObj::UpdateUI()",5) if(lock) mMutex.Lock(); mpWXTitle->SetValue(this->GetOptimizationObj().GetName()); mpWXTitle->UpdateUI(false); this->WXCrystObj::UpdateUI(false); if(lock) mMutex.Unlock(); VFN_DEBUG_EXIT("WXOptimizationObj::UpdateUI()",5) } void WXOptimizationObj::OnBrowseParamSet(wxCommandEvent & WXUNUSED(event)) { if(this->GetOptimizationObj().IsOptimizing()) { wxMessageDialog dumbUser(this,_T("Cannot browse during Optimisation !"), _T("Cannot browse during Optimisation!"),wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); return; } wxFrame *frame= new wxFrame(this,-1,_T("Stored Configurations"), wxDefaultPosition,wxSize(250,200)); const long nb=this->GetOptimizationObj().mvSavedParamSet.size(); wxArrayString choices; mpwxParamSetList=new wxListBox(frame, ID_BROWSE_WIN, wxDefaultPosition, wxDefaultSize, choices, wxLB_SINGLE|wxLB_NEEDED_SB, wxDefaultValidator, _T("listBox")); for(int i=0;iGetOptimizationObj().mRefParList.GetParamSetName (this->GetOptimizationObj().mvSavedParamSet[i].first).c_str()); mpwxParamSetList->Append(wxString::Format(_T("%d, cost= %f, %s"),i, this->GetOptimizationObj().mvSavedParamSet[i].second,tmpname.c_str())); } //mpwxParamSetList->SetEventHandler(this); mClockParamSetWindow.Click(); frame->Show(true); } void WXOptimizationObj::OnSelectParamSet(wxCommandEvent &event) { if(this->GetOptimizationObj().IsOptimizing()) { wxMessageDialog dumbUser(this,_T("Cannot browse during Optimisation !"), _T("Cannot browse during Optimisation!"),wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); return; } const long n=event.GetSelection(); if(n>=0) {// n=-1 when window is closed ? // Window is alive, check the number of browsable parameters is unchanged if(mpwxParamSetList->GetCount()!=this->GetOptimizationObj().mvSavedParamSet.size()) { const long nb=this->GetOptimizationObj().mvSavedParamSet.size(); wxArrayString choices; for(int i=0;iGetOptimizationObj().mRefParList.GetParamSetName (this->GetOptimizationObj().mvSavedParamSet[i].first).c_str()); choices.Add(wxString::Format(_T("%d, cost= %f, %s"),i, this->GetOptimizationObj().mvSavedParamSet[i].second,tmpname.c_str())); } mpwxParamSetList->Set(choices); mClockParamSetWindow.Click(); //wxMessageDialog bad(mpwxParamSetList,_T("The list has changed. Updating"), // _T("The list has changed. Updating"),wxOK|wxSTAY_ON_TOP); //bad.ShowModal(); return; } if(mClockParamSetWindow>this->GetOptimizationObj().mRefParList.GetRefParListClock()) { try { this->GetOptimizationObj().mRefParList .RestoreParamSet(this->GetOptimizationObj().mvSavedParamSet[n].first); } catch(const ObjCrystException &except) { wxMessageDialog bad(this,_T("Impossible ! Model has been altered !"), _T("Impossible ! Model has been altered !"),wxOK|wxICON_EXCLAMATION); mpwxParamSetList->GetParent()->Close(); mpwxParamSetList=0; } this->GetOptimizationObj().UpdateDisplay(); cout <<"Param set #"<GetOptimizationObj().mvSavedParamSet[n].first<<", cost=" <GetOptimizationObj().mvSavedParamSet[n].second <<", now cost="<GetOptimizationObj().GetLogLikelihood()<MultiRunOptimize(*mpNbRun,*mpNbTrial,false,mFinalCost); else mpGlobalOptObj->Optimize(*mpNbTrial,false,mFinalCost); (*fpObjCrystInformUser)("Finished global optimization"); } catch(...){cout<<"Unhandled exception in WXGlobalOptimRunThread::Entry() ?"<mGlobalOptimType)); mpSizer->Add(opt,0,wxALIGN_LEFT); mList.Add(opt); opt=new WXFieldOption(this,-1,&(mpMonteCarloObj->mAnnealingScheduleTemp)); mpSizer->Add(opt,0,wxALIGN_LEFT); mList.Add(opt); wxBoxSizer *sizerTemp=new wxBoxSizer(wxHORIZONTAL); WXFieldPar *tempMax= new WXFieldPar(this,"Temperature Max:",-1,&(mpMonteCarloObj->mTemperatureMax)); WXFieldPar *tempMin= new WXFieldPar(this,"Temperature Min:",-1,&(mpMonteCarloObj->mTemperatureMin)); WXFieldPar *tempGamma= new WXFieldPar(this,"Gamma:",-1,&(mpMonteCarloObj->mTemperatureGamma)); sizerTemp->Add(tempMax); sizerTemp->Add(tempMin); sizerTemp->Add(tempGamma); mpSizer->Add(sizerTemp); mList.Add(tempMax); mList.Add(tempMin); mList.Add(tempGamma); tempMax->SetFormat(_T("%8f")); tempMin->SetFormat(_T("%8f")); tempGamma->SetFormat(_T("%8f")); opt=new WXFieldOption(this,-1,&(mpMonteCarloObj->mAnnealingScheduleMutation)); mpSizer->Add(opt,0,wxALIGN_LEFT); mList.Add(opt); wxBoxSizer *sizerAmp=new wxBoxSizer(wxHORIZONTAL); WXFieldPar *ampMax= new WXFieldPar(this,"Amplitude Max:",-1,&(mpMonteCarloObj->mMutationAmplitudeMax)); WXFieldPar *ampMin= new WXFieldPar(this,"Amplitude Min:",-1,&(mpMonteCarloObj->mMutationAmplitudeMin)); WXFieldPar *ampGamma= new WXFieldPar(this,"Gamma:",-1,&(mpMonteCarloObj->mMutationAmplitudeGamma)); sizerAmp->Add(ampMax); sizerAmp->Add(ampMin); sizerAmp->Add(ampGamma); mpSizer->Add(sizerAmp); mList.Add(ampMax); mList.Add(ampMin); mList.Add(ampGamma); ampMax->SetFormat(_T("%8f")); ampMin->SetFormat(_T("%8f")); ampGamma->SetFormat(_T("%8f")); opt=new WXFieldOption(this,-1,&(mpMonteCarloObj->mSaveTrackedData)); mpSizer->Add(opt,0,wxALIGN_LEFT); mList.Add(opt); opt->SetToolTip(_T("Saved Tracked values (costs, Chi^2, parameters...)\n\n") _T("This is only useful for Test purposes.\n") _T("Data is saved in the file (Name)-Tracker(-Run#).dat")); opt=new WXFieldOption(this,-1,&(mpMonteCarloObj->mXMLAutoSave)); mpSizer->Add(opt,0,wxALIGN_LEFT); mList.Add(opt); opt->SetToolTip(_T("Periodically save the best configuration\n\n") _T("Recommended choice is : After Each Run\n") _T("File name is: (name)-(date)-(Run#)-cost.xml\n\n") _T("For Multiple Runs, Note that all choices\n") _T("save the *best* configuration overall, except for\n") _T("'After Each Run', for which the configuration\n") _T("saved are the best for each run.")); opt=new WXFieldOption(this,-1,&(mpMonteCarloObj->mAutoLSQ)); mpSizer->Add(opt,0,wxALIGN_LEFT); mList.Add(opt); opt->SetToolTip(_T("Least squares refinement can be run:\n\n") _T(" - at the end of each run\n") _T(" - perdiodically during the optimization\n\n") _T(" This allows to find the global minimum\n") _T("much faster\n") _T(" Note that if a LSQ refinement is run but does\n") _T("not reach the real global minimum, the returned\n") _T("structure can be very distorted, but this is\n") _T("harmless (restraints will bring back a correct \n") _T("conformation after a few thousand tests)")); // Number of trials to go mpWXFieldNbTrial=new WXFieldPar(this,"Number of trials per run:",-1,&(mpMonteCarloObj->NbTrialPerRun()),70); mpSizer->Add(mpWXFieldNbTrial); mList.Add(mpWXFieldNbTrial); mpWXFieldNbTrial->SetFormat(_T("%ld")); mpWXFieldNbTrial->SetToolTip(_T("Number of triels per run.\n") _T("This number will be updated during the optimization.\n\n") _T("Using Multiple Runs:\n") _T(" For simple problems (e.g. PbSO4), use 200 000\n") _T(" For larger problems (e.g. Cimetidine), use 2 000 000\n") _T(" For much larger problems, use 10 000 000\n\n") _T("For a single run using Parallel Tempering, use a large number (100 000 000:\n")); // Number of cycles (-1=run indefinitely) WXFieldPar *pWXFieldNbRun=new WXFieldPar(this,"Number of Runs to perform:",-1,&mNbRun,40); mpSizer->Add(pWXFieldNbRun); mList.Add(pWXFieldNbRun); pWXFieldNbRun->SetFormat(_T("%ld")); pWXFieldNbRun->SetToolTip(_T("Number of runs to perform (for Multiple Runs).\n") _T("Use -1 (the default) to run an infinite number of Runs.\n\n") _T("The model will be randomized at the beginning of each run.\n")); // Best cost so far WXFieldPar *pWXFieldBestCost=new WXFieldPar(this,"Overall Best Cost:",-1,&(mpMonteCarloObj->GetBestCost()),130); mpSizer->Add(pWXFieldBestCost); mList.Add(pWXFieldBestCost); pWXFieldBestCost->SetFormat(_T("%12.2f")); pWXFieldBestCost->SetToolTip(_T("Overall (all runs) Best Cost")); this->CrystUpdate(true); VFN_DEBUG_EXIT("WXMonteCarloObj::WXMonteCarloObj()",7) } WXMonteCarloObj::~WXMonteCarloObj() { if(0!=mpGlobalOptimRunThread) { if(mpGlobalOptimRunThread->IsAlive()) { (*fpObjCrystInformUser)("Waiting for global optimization to stop..."); this->GetOptimizationObj().StopAfterCycle(); mpGlobalOptimRunThread->Wait(wxTHREAD_WAIT_BLOCK); (*fpObjCrystInformUser)("Global optimization halted..."); } delete mpGlobalOptimRunThread; mpGlobalOptimRunThread=0; } } void WXMonteCarloObj::OnRunOptimization(wxCommandEvent & event) { VFN_DEBUG_ENTRY("WXMonteCarloObj::OnRunOptimization()",6) WXCrystValidateAllUserInput(); if(true==this->GetOptimizationObj().IsOptimizing()) { wxMessageDialog dumbUser(this,_T("The optimization is already running !"),_T("Huh ?"), wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); VFN_DEBUG_EXIT("WXMonteCarloObj::OnRunOptimization()",6) return; } (*fpObjCrystInformUser)("Beginning global optimization"); //Fix parameters than really should not be global-optimized mpMonteCarloObj->SetParIsFixed(gpRefParTypeUnitCell,true); mpMonteCarloObj->SetParIsFixed(gpRefParTypeScattDataScale,true); mpMonteCarloObj->SetParIsFixed(gpRefParTypeScattDataProfile,true); mpMonteCarloObj->SetParIsFixed(gpRefParTypeScattDataCorrIntAbsorp,true); mpMonteCarloObj->SetParIsFixed(gpRefParTypeScattDataCorrIntPolar,true); mpMonteCarloObj->SetParIsFixed(gpRefParTypeScattDataCorrIntExtinc,true); mpMonteCarloObj->SetParIsFixed(gpRefParTypeScattDataCorrPos,true); mpMonteCarloObj->SetParIsFixed(gpRefParTypeScattDataBackground,true); mpMonteCarloObj->SetParIsFixed(gpRefParTypeRadiation,true); mpMonteCarloObj->UpdateDisplay(); double finalCost=0; if(mpMonteCarloObj->NbTrialPerRun()<0) { mpMonteCarloObj->NbTrialPerRun() = - mpMonteCarloObj->NbTrialPerRun(); wxTextEntryDialog costDialog(this,_T("Enter desired cost for the optimization to stop"), _T("Goal Cost"),_T(".20"),wxOK | wxCANCEL); costDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK==costDialog.ShowModal()) costDialog.GetValue().ToDouble(&finalCost); } if(0!=mpGlobalOptimRunThread) delete mpGlobalOptimRunThread; if(event.GetId()==ID_GLOBALOPT_MENU_OPT_RUN_MULTIPLE) mpGlobalOptimRunThread = new WXGlobalOptimRunThread(this->GetOptimizationObj(), mpMonteCarloObj->NbTrialPerRun(),finalCost,mNbRun,true); else mpGlobalOptimRunThread = new WXGlobalOptimRunThread(this->GetOptimizationObj(), mpMonteCarloObj->NbTrialPerRun(),finalCost,mNbRun,false); // Tracker window if(this->GetOptimizationObj().GetMainTracker().WXGet()==0) { wxFrame *frame= new wxFrame(this,-1,_T("Tracked data"), wxDefaultPosition,wxSize(300,200)); wxWindow* pwxTrackerGraph = this->GetOptimizationObj().GetMainTracker().WXCreate(frame); wxSizer *ps=new wxBoxSizer(wxHORIZONTAL); ps->Add(pwxTrackerGraph,1,wxEXPAND); frame->CreateStatusBar(2); frame->SetSizer(ps); frame->SetAutoLayout(true); frame->Show(true); } if(mpGlobalOptimRunThread->Create() != wxTHREAD_NO_ERROR) wxLogError(_T("Can't create optimization thread")); else mpGlobalOptimRunThread->Run(); VFN_DEBUG_EXIT("WXMonteCarloObj::OnRunOptimization()",6) } void WXMonteCarloObj::OnLSQRefine(wxCommandEvent &event) { WXCrystValidateAllUserInput(); if(true==this->GetOptimizationObj().IsOptimizing()) { wxMessageDialog dumbUser(this,_T("An optimization is already running !"),_T("Huh ?"), wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); return; } char buf[200]; mpMonteCarloObj->BeginOptimization(); mpMonteCarloObj->PrepareRefParList(); mpMonteCarloObj->InitLSQ(true); sprintf(buf,"LSQ: start"); REAL cost=mpMonteCarloObj->GetLogLikelihood(); mpMonteCarloObj->mvSavedParamSet.push_back(make_pair(mpMonteCarloObj->mRefParList.CreateParamSet(buf),cost)); wxProgressDialog dlgProgress(_T("Least Squares refinement"),wxString::Format(_T("Least Squares refinement, cycle #%02d/20, Chi^2=%012.2f"),0,cost), 19,this,wxPD_AUTO_HIDE|wxPD_ELAPSED_TIME|wxPD_CAN_ABORT); (*fpObjCrystInformUser)(std::string(wxString::Format(_T("Least Squares refinement, cycle #%02d/20, Chi^2=%012.2f"),0,cost))); for(unsigned i=0;i<20;++i) { try {mpMonteCarloObj->GetLSQObj().Refine(1,true,false,false);} catch(const ObjCrystException &except){}; mpMonteCarloObj->UpdateDisplay(); sprintf(buf,"LSQ: cycle #%02d",i); cost=mpMonteCarloObj->GetLogLikelihood(); mpMonteCarloObj->mvSavedParamSet.push_back(make_pair(mpMonteCarloObj->mRefParList.CreateParamSet(buf),cost)); (*fpObjCrystInformUser)(std::string(wxString::Format(_T("Least Squares refinement, cycle #%02d/20, Chi^2=%012.2f"),i,cost))); if(dlgProgress.Update(i,wxString::Format(_T("Least Squares refinement, cycle #%02d/20, Chi^2=%012.2f"),i,cost))==false) break; } mpMonteCarloObj->EndOptimization(); } void WXMonteCarloObj::UpdateDisplayNbTrial() { VFN_DEBUG_MESSAGE("WXMonteCarloObj::UpdateDisplayNbTrial()",5) mMutex.Lock(); mList.CrystUpdate(false); mMutex.Unlock(); wxUpdateUIEvent event(ID_CRYST_UPDATEUI); wxPostEvent(this,event); } OptimizationObj & WXMonteCarloObj::GetOptimizationObj() { VFN_DEBUG_MESSAGE("WXMonteCarloObj::GetOptimizationObj()",2) return *mpMonteCarloObj; } const OptimizationObj & WXMonteCarloObj::GetOptimizationObj()const { VFN_DEBUG_MESSAGE("WXMonteCarloObj::GetOptimizationObj() const",2) return *mpMonteCarloObj; } }// namespace objcryst-2022.1/ObjCryst/wxCryst/wxGlobalOptimObj.h000066400000000000000000000107641430515525000222650ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _VFN_WX_GLOBALOPTIM_OBJ_H_ #define _VFN_WX_GLOBALOPTIM_OBJ_H_ #include "ObjCryst/wxCryst/wxCryst.h" #include "ObjCryst/wxCryst/wxMultiGraph.h" namespace ObjCryst { class WXOptimizationObj; class WXMonteCarloObj; } #include "ObjCryst/RefinableObj/GlobalOptimObj.h" namespace ObjCryst { class WXGlobalOptimRunThread; /// WX Class for a Global Optimization objects class WXOptimizationObj: public WXCrystObj { public: WXOptimizationObj(wxWindow *parent, OptimizationObj*); virtual void CrystUpdate(const bool updateUI=false,const bool mutexlock=false); virtual bool OnChangeName(const int id); virtual void OnSave(); virtual void OnLoad(); /// From the menu virtual void OnAddRefinedObject(wxCommandEvent & WXUNUSED(event)); /// Added by the library virtual void AddRefinedObject(RefinableObj &obj); /// From the menu virtual void OnRemoveRefinedObject(wxCommandEvent & WXUNUSED(event)); /// Launches the optimization run virtual void OnRunOptimization(wxCommandEvent & WXUNUSED(event))=0; virtual void OnStopOptimization(wxCommandEvent & WXUNUSED(event)); virtual OptimizationObj & GetOptimizationObj()=0; virtual const OptimizationObj & GetOptimizationObj()const=0; virtual void OnUpdateUI(wxUpdateUIEvent& event); virtual void UpdateUI(const bool mutexlock=false); /// Opens a window where the stored parameter set can be selected virtual void OnBrowseParamSet(wxCommandEvent & WXUNUSED(event)); /// Restore one parameter set virtual void OnSelectParamSet(wxCommandEvent & WXUNUSED(event)); protected: WXCrystMenuBar* mpMenuBar; WXGlobalOptimRunThread *mpGlobalOptimRunThread; WXFieldPar *mpWXFieldNbTrial; /// Record when the window giving the list of recorded parameter set was created. RefinableObjClock mClockParamSetWindow; /// Window giving the list of recorded parameter sets wxListBox *mpwxParamSetList; }; /// Class for a GlobalOptimization thread class WXGlobalOptimRunThread: public wxThread { public: WXGlobalOptimRunThread(OptimizationObj &globalOptObj,long &nbTrial, const REAL finalCost,long &nbRun,const bool multiple=true); virtual void *Entry(); virtual void OnExit(); private: OptimizationObj *mpGlobalOptObj; ///This points to OptimizationObj::mNbTrialPerRun long *mpNbTrial; ///This points to the mNbRun member in WXOptimizationObj long *mpNbRun; /// The value of the cost below which the optimization should stop /// (0 by default) even if the desired number pf trial has not been reached. const REAL mFinalCost; /// Use multiple Runs ? const bool mDoMultiple; }; /** Class for Graphical interface to Monte-Carlo objects * (Simulated Annealing, Parallel Tempering) * */ class WXMonteCarloObj: public WXOptimizationObj { public: WXMonteCarloObj(wxWindow *parent, MonteCarloObj*); ~WXMonteCarloObj(); //virtual void CrystUpdate(); virtual void OnRunOptimization(wxCommandEvent &event); /// Called during optimization, to show the user something's still going on... void UpdateDisplayNbTrial(); virtual OptimizationObj & GetOptimizationObj(); virtual const OptimizationObj & GetOptimizationObj()const; void OnLSQRefine(wxCommandEvent &event); protected: /// The algorithm object MonteCarloObj *mpMonteCarloObj; /// The number of cycles long mNbRun; WXFieldPar *mpWXFieldNbTrial; DECLARE_EVENT_TABLE() }; } //namespace #endif //_VFN_WX_GLOBALOPTIM_OBJ_H_ objcryst-2022.1/ObjCryst/wxCryst/wxLSQ.cpp000066400000000000000000000031271430515525000204060ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2008 Vincent Favre-Nicolin vincefn@users.sourceforge.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * code file for the wxLSQ class * */ #include "ObjCryst/wxCryst/wxLSQ.h" namespace ObjCryst { BEGIN_EVENT_TABLE(WXLSQ, wxWindow) END_EVENT_TABLE() WXLSQ::WXLSQ(wxWindow *parent, LSQNumObj*p): WXCrystObj(parent, wxVERTICAL, false),mpLSQ(p) { // Add all individual refinable parameters for(unsigned int i=0;iGetCompiledRefinedObj().GetNbPar();++i) { if(mpLSQ->GetCompiledRefinedObj().GetPar(i).IsUsed()) { WXCrystObjBasic* pRefPar=mpLSQ->GetCompiledRefinedObj().GetPar(i).WXCreate(this); mpSizer->Add(pRefPar, 1, wxALIGN_RIGHT); mList.Add(pRefPar); } } this->CrystUpdate(true,true); } WXLSQ::~WXLSQ(){mpLSQ->WXNotifyDelete();} bool WXLSQ::OnChangeName(const int id) { return false; } } //namespace objcryst-2022.1/ObjCryst/wxCryst/wxLSQ.h000066400000000000000000000024301430515525000200470ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2008 Vincent Favre-Nicolin vincefn@users.sourceforge.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * header file for the wxLSQ class * */ #ifndef _VFN_WX_LSQ_H_ #define _VFN_WX_LSQ_H_ #include "ObjCryst/RefinableObj/LSQNumObj.h" #include "ObjCryst/wxCryst/wxCryst.h" namespace ObjCryst { class WXLSQ: public WXCrystObj { public: WXLSQ(wxWindow *parent, LSQNumObj*); virtual ~WXLSQ(); virtual bool OnChangeName(const int id); private: LSQNumObj* mpLSQ; DECLARE_EVENT_TABLE() }; } //namespace #endif //_VFN_WX_ATOM_H_ objcryst-2022.1/ObjCryst/wxCryst/wxMolecule.cpp000066400000000000000000003621711430515525000215230ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // wx headers, with or without precompilation #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "wx/notebook.h" #include "wx/minifram.h" #include #include "wx/progdlg.h" #include #include #include #include "ObjCryst/wxCryst/wxMolecule.h" #include "ObjCryst/RefinableObj/LSQNumObj.h" #include "ObjCryst/Quirks/Chronometer.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" namespace ObjCryst { //:TODO: Move this to wxCryst.h template T const* WXDialogChooseFromVector(const vector ®,wxWindow*parent, const string &message,int &choice) { wxString *choices = new wxString[reg.size()]; for(unsigned int i=0;iGetName()).c_str()); wxSingleChoiceDialog dialog (parent,message.c_str(),"Choose",reg.size(),choices,NULL,wxOK | wxCANCEL); dialog.SetSize(300,300); if(wxID_OK!=dialog.ShowModal()) return 0; choice=dialog.GetSelection(); delete[] choices; return reg[choice]; } template T * WXDialogChooseFromVector(vector ®,wxWindow*parent, const string &message,int &choice) { wxString *choices = new wxString[reg.size()]; for(unsigned int i=0;iGetName()).c_str()); #if wxCHECK_VERSION( 2, 9, 4 ) wxSingleChoiceDialog dialog (parent, wxString::FromAscii(message.c_str()),_T("Choose"),reg.size(),choices,(void**)NULL,wxOK | wxCANCEL); #else wxSingleChoiceDialog dialog (parent, wxString::FromAscii(message.c_str()),_T("Choose"),reg.size(),choices,NULL,wxOK | wxCANCEL); #endif dialog.SetSize(300,300); if(wxID_OK!=dialog.ShowModal()) return 0; choice=dialog.GetSelection(); delete[] choices; return reg[choice]; } template list WXDialogChooseMultipleFromVector(vector ®,wxWindow*parent, const string &message) { wxString *choices = new wxString[reg.size()]; for(unsigned int i=0;iGetName()).c_str()); wxMultiChoiceDialog_ListBox dialog (parent, wxString::FromAscii(message.c_str()),_T("Choose"),reg.size(),choices); dialog.ShowModal(); wxArrayInt choice=dialog.GetSelections(); list vChoice; for(unsigned int i=0;i list WXDialogChooseMultipleFromVector(const vector ®,wxWindow*parent, const string &message) { wxString *choices = new wxString[reg.size()]; for(unsigned int i=0;iGetName()).c_str()); wxMultiChoiceDialog_ListBox dialog (parent, wxString::FromAscii(message.c_str()),_T("Choose"),reg.size(),choices); dialog.ShowModal(); wxArrayInt choice=dialog.GetSelections(); list vChoice; for(unsigned int i=0;i SplitString(const string &str, const string &separator) { string::size_type idx0=(string::size_type) 0; string::size_type idx1=(string::size_type) 0; list l; while((idx1!=string::npos)&&(idx0idx0) l.push_back(str.substr(idx0,idx1-idx0)); idx0=idx1+1; } //for(list::const_iterator pos=l.begin();pos!=l.end();++pos) cout <<*pos<<" / "; //cout<NotifyDeleteListWin(this); } //////////////////////////////////////////////////////////////////////// // // WXMolAtom // //////////////////////////////////////////////////////////////////////// static const long ID_MOLATOM_SCATTPOW=WXCRYST_ID(); static const long ID_MOLATOM_NAME=WXCRYST_ID(); BEGIN_EVENT_TABLE(WXMolAtom,wxWindow) EVT_BUTTON(ID_MOLATOM_SCATTPOW, WXMolAtom::OnChangeScattPow) END_EVENT_TABLE() WXMolAtom::WXMolAtom(wxWindow *parent, MolAtom*obj): WXCrystObjBasic(parent),mpMolAtom(obj) { VFN_DEBUG_ENTRY("WXMolAtom::WXMolAtom():"<GetName(),6) mpSizer=new wxBoxSizer(wxHORIZONTAL); wxStaticText* label=new wxStaticText(this,-1,_T("Atom")); mpSizer->Add(label); { mpFieldName=new WXFieldString(this, mpMolAtom->GetName(),ID_MOLATOM_NAME,80,true); mpSizer->Add(mpFieldName,0,wxALIGN_CENTER); mpFieldScattPower=new WXFieldChoice(this,ID_MOLATOM_SCATTPOW,"Type:",60); mpSizer->Add(mpFieldScattPower,0,wxALIGN_CENTER); mList.Add(mpFieldScattPower); if(mpMolAtom->IsDummy()) mpFieldScattPower->SetValue("Dummy"); else mpFieldScattPower->SetValue(mpMolAtom->GetScatteringPower().GetName()); } { WXCrystObjBasic* pFieldX=mpMolAtom->GetMolecule().GetPar(&(mpMolAtom->X())).WXCreate(this); mpSizer->Add(pFieldX,0,wxALIGN_CENTER); mList.Add(pFieldX); } { WXCrystObjBasic* pFieldY=mpMolAtom->GetMolecule().GetPar(&(mpMolAtom->Y())).WXCreate(this); mpSizer->Add(pFieldY,0,wxALIGN_CENTER); mList.Add(pFieldY); } { WXCrystObjBasic* pFieldZ=mpMolAtom->GetMolecule().GetPar(&(mpMolAtom->Z())).WXCreate(this); mpSizer->Add(pFieldZ,0,wxALIGN_CENTER); mList.Add(pFieldZ); } this->SetSizer(mpSizer); this->Layout(); this->CrystUpdate(true); VFN_DEBUG_EXIT("WXMolAtom::WXMolAtom():"<GetName(),6) } WXMolAtom::~WXMolAtom() { mpMolAtom->WXNotifyDelete(); } void WXMolAtom::CrystUpdate(const bool uui,const bool lock) { VFN_DEBUG_ENTRY("WXMolAtom::CrystUpdate()",5) if(lock) mMutex.Lock(); mList.CrystUpdate(uui,false); if(lock) mMutex.Unlock(); VFN_DEBUG_EXIT("WXMolAtom::CrystUpdate()",5) } void WXMolAtom::UpdateUI(const bool lock) { VFN_DEBUG_ENTRY("WXMolAtom::UpdateUI()",5) if(lock) mMutex.Lock(); mList.UpdateUI(false); mpFieldName->SetValue(mpMolAtom->GetName().c_str()); if(mpMolAtom->IsDummy()) mpFieldScattPower->SetValue("Dummy"); else mpFieldScattPower->SetValue(mpMolAtom->GetScatteringPower().GetName()); if(lock) mMutex.Unlock(); VFN_DEBUG_EXIT("WXMolAtom::UpdateUI()",5) } void WXMolAtom::OnChangeScattPow(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXMolAtom::OnChangeScattPow()",6) WXCrystValidateAllUserInput(); int choice; const ScatteringPower *scatt=WXDialogChooseFromRegistry( mpMolAtom->GetMolecule().GetCrystal().GetScatteringPowerRegistry(), (wxWindow*)this,"Choose a new Scattering Power",choice); if(0==scatt) return; mpMolAtom->SetScatteringPower(*scatt); this->CrystUpdate(true); this->UpdateUI(true); VFN_DEBUG_EXIT("WXMolAtom::OnChangeScattPow()",6) } //////////////////////////////////////////////////////////////////////// // // WXMolBond // //////////////////////////////////////////////////////////////////////// WXCRYST_ID ID_MOLBOND_ATOM1; WXCRYST_ID ID_MOLBOND_ATOM2; WXCRYST_ID ID_MOLBOND_FREEBUTTON; BEGIN_EVENT_TABLE(WXMolBond,wxWindow) EVT_BUTTON(ID_MOLBOND_ATOM1, WXMolBond::OnChangeAtom) EVT_BUTTON(ID_MOLBOND_ATOM2, WXMolBond::OnChangeAtom) EVT_CHECKBOX(ID_MOLBOND_FREEBUTTON, WXMolBond::OnToggleFree) END_EVENT_TABLE() WXMolBond::WXMolBond(wxWindow *parent, MolBond*obj): WXCrystObjBasic(parent),mpMolBond(obj),mpButtonFree(0) { VFN_DEBUG_ENTRY("WXMolBond::WXMolBond():"<GetName(),6) mpSizer=new wxBoxSizer(wxHORIZONTAL); #if 1 mpButtonFree=new wxCheckBox(this,ID_MOLBOND_FREEBUTTON,_T(""),wxDefaultPosition, wxDefaultSize); mpButtonFree->Fit(); mpSizer->Add(mpButtonFree,0,wxALIGN_CENTER); #endif mpFieldAtom1=new WXFieldChoice(this,ID_MOLBOND_ATOM1,"Bond:",60); mpFieldAtom1->SetValue(mpMolBond->GetAtom1().GetName()); mpSizer->Add(mpFieldAtom1,0,wxALIGN_CENTER); mList.Add(mpFieldAtom1); mpFieldAtom2=new WXFieldChoice(this,ID_MOLBOND_ATOM2,"-",60); mpFieldAtom2->SetValue(mpMolBond->GetAtom2().GetName()); mpSizer->Add(mpFieldAtom2,0,wxALIGN_CENTER); mList.Add(mpFieldAtom2); WXFieldPar *value= new WXFieldPar(this,"Length=",-1,&mValue); mpSizer->Add(value,0,wxALIGN_CENTER); mList.Add(value); WXFieldPar *length= new WXFieldPar(this,",Restraint=",-1,&(mpMolBond->Length0())); mpSizer->Add(length,0,wxALIGN_CENTER); mList.Add(length); WXFieldPar *delta= new WXFieldPar(this,",delta=",-1,&(mpMolBond->LengthDelta())); mpSizer->Add(delta,0,wxALIGN_CENTER); mList.Add(delta); WXFieldPar *sigma= new WXFieldPar(this,",sigma=",-1,&(mpMolBond->LengthSigma())); mpSizer->Add(sigma,0,wxALIGN_CENTER); mList.Add(sigma); this->SetSizer(mpSizer); this->Layout(); this->CrystUpdate(true,true); VFN_DEBUG_EXIT("WXMolBond::WXMolBond():"<GetName(),6) } WXMolBond::~WXMolBond() { mpMolBond->WXNotifyDelete(); } void WXMolBond::CrystUpdate(const bool uui,const bool lock) { VFN_DEBUG_ENTRY("WXMolBond::CrystUpdate()",5) if(lock) mMutex.Lock(); mValue=mpMolBond->GetLength(); mList.CrystUpdate(uui,false); if(lock) mMutex.Unlock(); VFN_DEBUG_EXIT("WXMolBond::CrystUpdate()",5) } void WXMolBond::UpdateUI(const bool lock) { VFN_DEBUG_ENTRY("WXMolBond::UpdateUI()",5) if(lock) mMutex.Lock(); if(0!=mpButtonFree) mpButtonFree->SetValue(mpMolBond->IsFreeTorsion()); mList.UpdateUI(false); mpFieldAtom1->SetValue(mpMolBond->GetAtom1().GetName().c_str()); mpFieldAtom2->SetValue(mpMolBond->GetAtom2().GetName().c_str()); if(lock) mMutex.Unlock(); VFN_DEBUG_EXIT("WXMolBond::UpdateUI()",5) } void WXMolBond::OnChangeAtom(wxCommandEvent &event) { VFN_DEBUG_ENTRY("WXMolBond::OnChangeAtom()",6) WXCrystValidateAllUserInput(); int choice; MolAtom *const at=WXDialogChooseFromVector(mpMolBond->GetMolecule().GetAtomList(), (wxWindow*)this,"Choose a new Atom",choice); if(0==at) return; if((long)ID_MOLBOND_ATOM1==event.GetId()) { if(at==&(mpMolBond->GetAtom2())) { wxMessageDialog dumbUser(this,_T("The two atoms must be different !"), _T("Whooops"),wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); return; } mpMolBond->SetAtom1(*at); } if((long)ID_MOLBOND_ATOM2==event.GetId()) { if(at==&(mpMolBond->GetAtom1())) { wxMessageDialog dumbUser(this,_T("The two atoms must be different !"), _T("Whooops"),wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); return; } mpMolBond->SetAtom2(*at); } this->CrystUpdate(true); this->UpdateUI(true); VFN_DEBUG_EXIT("WXMolBond::OnChangeScattPow()",6) } void WXMolBond::OnToggleFree(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_MESSAGE("WXMolBond::OnToggleFree()",6) if(0!=mpButtonFree) mpMolBond->SetFreeTorsion(mpButtonFree->GetValue()); } //////////////////////////////////////////////////////////////////////// // // WXMolBondAngle // //////////////////////////////////////////////////////////////////////// WXCRYST_ID ID_MOLBONDANGLE_ATOM1; WXCRYST_ID ID_MOLBONDANGLE_ATOM2; WXCRYST_ID ID_MOLBONDANGLE_ATOM3; BEGIN_EVENT_TABLE(WXMolBondAngle,wxWindow) EVT_BUTTON(ID_MOLBONDANGLE_ATOM1, WXMolBondAngle::OnChangeAtom) EVT_BUTTON(ID_MOLBONDANGLE_ATOM2, WXMolBondAngle::OnChangeAtom) EVT_BUTTON(ID_MOLBONDANGLE_ATOM3, WXMolBondAngle::OnChangeAtom) END_EVENT_TABLE() WXMolBondAngle::WXMolBondAngle(wxWindow *parent, MolBondAngle*obj): WXCrystObjBasic(parent),mpMolBondAngle(obj) { VFN_DEBUG_ENTRY("WXMolBondAngle::WXMolBond():"<GetName(),6) mpSizer=new wxBoxSizer(wxHORIZONTAL); mpFieldAtom1=new WXFieldChoice(this,ID_MOLBONDANGLE_ATOM1,"Bond Angle:",60); mpFieldAtom1->SetValue(mpMolBondAngle->GetAtom1().GetName()); mpSizer->Add(mpFieldAtom1,0,wxALIGN_CENTER); mList.Add(mpFieldAtom1); mpFieldAtom2=new WXFieldChoice(this,ID_MOLBONDANGLE_ATOM2,"-",60); mpFieldAtom2->SetValue(mpMolBondAngle->GetAtom2().GetName()); mpSizer->Add(mpFieldAtom2,0,wxALIGN_CENTER); mList.Add(mpFieldAtom2); mpFieldAtom3=new WXFieldChoice(this,ID_MOLBONDANGLE_ATOM3,"-",60); mpFieldAtom3->SetValue(mpMolBondAngle->GetAtom3().GetName()); mpSizer->Add(mpFieldAtom3,0,wxALIGN_CENTER); mList.Add(mpFieldAtom3); WXFieldPar *value= new WXFieldPar(this,"Angle=",-1,&mValue); value->SetHumanValueScale(RAD2DEG); mpSizer->Add(value,0,wxALIGN_CENTER); mList.Add(value); WXFieldPar *angle= new WXFieldPar(this,",Restraint=",WXCRYST_ID(),&(mpMolBondAngle->Angle0())); angle->SetHumanValueScale(RAD2DEG); mpSizer->Add(angle,0,wxALIGN_CENTER); mList.Add(angle); WXFieldPar *delta= new WXFieldPar(this,",delta=",WXCRYST_ID(),&(mpMolBondAngle->AngleDelta())); delta->SetHumanValueScale(RAD2DEG); mpSizer->Add(delta,0,wxALIGN_CENTER); mList.Add(delta); WXFieldPar *sigma= new WXFieldPar(this,",sigma=",WXCRYST_ID(),&(mpMolBondAngle->AngleSigma())); sigma->SetHumanValueScale(RAD2DEG); mpSizer->Add(sigma,0,wxALIGN_CENTER); mList.Add(sigma); this->SetSizer(mpSizer); this->Layout(); this->CrystUpdate(true,true); VFN_DEBUG_EXIT("WXMolBondAngle::WXMolBond():"<GetName(),6) } WXMolBondAngle::~WXMolBondAngle() { mpMolBondAngle->WXNotifyDelete(); } void WXMolBondAngle::CrystUpdate(const bool uui,const bool lock) { VFN_DEBUG_ENTRY("WXMolBondAngle::CrystUpdate()",5) if(lock) mMutex.Lock(); mValue=mpMolBondAngle->GetAngle(); mList.CrystUpdate(uui,false); if(lock) mMutex.Unlock(); VFN_DEBUG_EXIT("WXMolBondAngle::CrystUpdate()",5) } void WXMolBondAngle::UpdateUI(const bool lock) { VFN_DEBUG_ENTRY("WXMolBondAngle::UpdateUI()",5) if(lock) mMutex.Lock(); mList.UpdateUI(false); mpFieldAtom1->SetValue(mpMolBondAngle->GetAtom1().GetName().c_str()); mpFieldAtom2->SetValue(mpMolBondAngle->GetAtom2().GetName().c_str()); mpFieldAtom3->SetValue(mpMolBondAngle->GetAtom3().GetName().c_str()); if(lock) mMutex.Unlock(); VFN_DEBUG_EXIT("WXMolBondAngle::UpdateUI()",5) } void WXMolBondAngle::OnChangeAtom(wxCommandEvent &event) { VFN_DEBUG_ENTRY("WXMolBondAngle::OnChangeAtom()",6) WXCrystValidateAllUserInput(); int choice; MolAtom *const at=WXDialogChooseFromVector(mpMolBondAngle->GetMolecule().GetAtomList(), (wxWindow*)this,"Choose a new Atom",choice); if(0==at) return; if((long)ID_MOLBONDANGLE_ATOM1==event.GetId()) { if((at==&(mpMolBondAngle->GetAtom2()) )||(at==&(mpMolBondAngle->GetAtom3())) ) { wxMessageDialog dumbUser(this,_T("The three atoms must be different !"), _T("Whooops"),wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); return; } mpMolBondAngle->SetAtom1(*at); } if((long)ID_MOLBONDANGLE_ATOM2==event.GetId()) { if((at==&(mpMolBondAngle->GetAtom1()) )||(at==&(mpMolBondAngle->GetAtom3())) ) { wxMessageDialog dumbUser(this,_T("The three atoms must be different !"), _T("Whooops"),wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); return; } mpMolBondAngle->SetAtom2(*at); } if((long)ID_MOLBONDANGLE_ATOM3==event.GetId()) { if((at==&(mpMolBondAngle->GetAtom1()) )||(at==&(mpMolBondAngle->GetAtom2())) ) { wxMessageDialog dumbUser(this,_T("The three atoms must be different !"), _T("Whooops"),wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); return; } mpMolBondAngle->SetAtom3(*at); } this->CrystUpdate(true); this->UpdateUI(true); VFN_DEBUG_EXIT("WXMolBondAngle::OnChangeScattPow()",6) } //////////////////////////////////////////////////////////////////////// // // WXMolDihedralAngle // //////////////////////////////////////////////////////////////////////// WXCRYST_ID ID_MOLDIHEDRALANGLE_ATOM1; WXCRYST_ID ID_MOLDIHEDRALANGLE_ATOM2; WXCRYST_ID ID_MOLDIHEDRALANGLE_ATOM3; WXCRYST_ID ID_MOLDIHEDRALANGLE_ATOM4; BEGIN_EVENT_TABLE(WXMolDihedralAngle,wxWindow) EVT_BUTTON(ID_MOLDIHEDRALANGLE_ATOM1, WXMolDihedralAngle::OnChangeAtom) EVT_BUTTON(ID_MOLDIHEDRALANGLE_ATOM2, WXMolDihedralAngle::OnChangeAtom) EVT_BUTTON(ID_MOLDIHEDRALANGLE_ATOM3, WXMolDihedralAngle::OnChangeAtom) EVT_BUTTON(ID_MOLDIHEDRALANGLE_ATOM4, WXMolDihedralAngle::OnChangeAtom) END_EVENT_TABLE() WXMolDihedralAngle::WXMolDihedralAngle(wxWindow *parent, MolDihedralAngle*obj): WXCrystObjBasic(parent),mpMolDihedralAngle(obj) { VFN_DEBUG_ENTRY("WXMolDihedralAngle::WXMolBond()",6) mpSizer=new wxBoxSizer(wxHORIZONTAL); mpFieldAtom1=new WXFieldChoice(this,ID_MOLDIHEDRALANGLE_ATOM1,"Dihedral Angle:",60); mpFieldAtom1->SetValue(mpMolDihedralAngle->GetAtom1().GetName()); mpSizer->Add(mpFieldAtom1,0,wxALIGN_CENTER); mList.Add(mpFieldAtom1); mpFieldAtom2=new WXFieldChoice(this,ID_MOLDIHEDRALANGLE_ATOM2,"-",60); mpFieldAtom2->SetValue(mpMolDihedralAngle->GetAtom2().GetName()); mpSizer->Add(mpFieldAtom2,0,wxALIGN_CENTER); mList.Add(mpFieldAtom2); mpFieldAtom3=new WXFieldChoice(this,ID_MOLDIHEDRALANGLE_ATOM3,"-",60); mpFieldAtom3->SetValue(mpMolDihedralAngle->GetAtom3().GetName()); mpSizer->Add(mpFieldAtom3,0,wxALIGN_CENTER); mList.Add(mpFieldAtom3); mpFieldAtom4=new WXFieldChoice(this,ID_MOLDIHEDRALANGLE_ATOM4,"-",60); mpFieldAtom4->SetValue(mpMolDihedralAngle->GetAtom4().GetName()); mpSizer->Add(mpFieldAtom4,0,wxALIGN_CENTER); mList.Add(mpFieldAtom4); WXFieldPar *value= new WXFieldPar(this,"Angle=",-1,&mValue); value->SetHumanValueScale(RAD2DEG); mpSizer->Add(value,0,wxALIGN_CENTER); mList.Add(value); WXFieldPar *angle= new WXFieldPar(this,"Restraint:",-1,&(mpMolDihedralAngle->Angle0())); angle->SetHumanValueScale(RAD2DEG); mpSizer->Add(angle,0,wxALIGN_CENTER); mList.Add(angle); WXFieldPar *delta= new WXFieldPar(this,",delta=",-1,&(mpMolDihedralAngle->AngleDelta())); delta->SetHumanValueScale(RAD2DEG); mpSizer->Add(delta,0,wxALIGN_CENTER); mList.Add(delta); WXFieldPar *sigma= new WXFieldPar(this,",sigma=",-1,&(mpMolDihedralAngle->AngleSigma())); sigma->SetHumanValueScale(RAD2DEG); mpSizer->Add(sigma,0,wxALIGN_CENTER); mList.Add(sigma); this->SetSizer(mpSizer); this->Layout(); this->CrystUpdate(true); VFN_DEBUG_EXIT("WXMolDihedralAngle::WXMolBond():"<GetName(),6) } WXMolDihedralAngle::~WXMolDihedralAngle() { mpMolDihedralAngle->WXNotifyDelete(); } void WXMolDihedralAngle::CrystUpdate(const bool uui,const bool lock) { VFN_DEBUG_ENTRY("WXMolDihedralAngle::CrystUpdate()",5) if(lock) mMutex.Lock(); mValue=mpMolDihedralAngle->GetAngle(); mList.CrystUpdate(uui,false); if(lock) mMutex.Unlock(); VFN_DEBUG_EXIT("WXMolDihedralAngle::CrystUpdate()",5) } void WXMolDihedralAngle::UpdateUI(const bool lock) { VFN_DEBUG_ENTRY("WXMolDihedralAngle::UpdateUI()",5) if(lock) mMutex.Lock(); mList.UpdateUI(false); mpFieldAtom1->SetValue(mpMolDihedralAngle->GetAtom1().GetName().c_str()); mpFieldAtom2->SetValue(mpMolDihedralAngle->GetAtom2().GetName().c_str()); mpFieldAtom3->SetValue(mpMolDihedralAngle->GetAtom3().GetName().c_str()); if(lock) mMutex.Unlock(); VFN_DEBUG_EXIT("WXMolDihedralAngle::UpdateUI()",5) } void WXMolDihedralAngle::OnChangeAtom(wxCommandEvent &event) { VFN_DEBUG_ENTRY("WXMolDihedralAngle::OnChangeAtom()",6) WXCrystValidateAllUserInput(); int choice; MolAtom *const at=WXDialogChooseFromVector(mpMolDihedralAngle->GetMolecule().GetAtomList(), (wxWindow*)this,"Choose a new Atom",choice); if(0==at) return; if((long)ID_MOLDIHEDRALANGLE_ATOM1==event.GetId()) { if( (at==&(mpMolDihedralAngle->GetAtom2())) ||(at==&(mpMolDihedralAngle->GetAtom3())) ||(at==&(mpMolDihedralAngle->GetAtom4())) ) { wxMessageDialog dumbUser(this,_T("The four atoms must be different !"), _T("Whooops"),wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); return; } mpMolDihedralAngle->SetAtom1(*at); } if((long)ID_MOLDIHEDRALANGLE_ATOM2==event.GetId()) { if( (at==&(mpMolDihedralAngle->GetAtom1())) ||(at==&(mpMolDihedralAngle->GetAtom3())) ||(at==&(mpMolDihedralAngle->GetAtom4())) ) { wxMessageDialog dumbUser(this,_T("The four atoms must be different !"), _T("Whooops"),wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); return; } mpMolDihedralAngle->SetAtom2(*at); } if((long)ID_MOLDIHEDRALANGLE_ATOM3==event.GetId()) { if( (at==&(mpMolDihedralAngle->GetAtom1())) ||(at==&(mpMolDihedralAngle->GetAtom2())) ||(at==&(mpMolDihedralAngle->GetAtom4())) ) { wxMessageDialog dumbUser(this,_T("The four atoms must be different !"), _T("Whooops"),wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); return; } mpMolDihedralAngle->SetAtom3(*at); } if((long)ID_MOLDIHEDRALANGLE_ATOM4==event.GetId()) { if( (at==&(mpMolDihedralAngle->GetAtom1())) ||(at==&(mpMolDihedralAngle->GetAtom2())) ||(at==&(mpMolDihedralAngle->GetAtom3())) ) { wxMessageDialog dumbUser(this,_T("The four atoms must be different !"), _T("Whooops"),wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); return; } mpMolDihedralAngle->SetAtom4(*at); } this->CrystUpdate(true); this->UpdateUI(true); VFN_DEBUG_EXIT("WXMolDihedralAngle::OnChangeScattPow()",6) } //////////////////////////////////////////////////////////////////////// // // WXMolecule Grid objects // //////////////////////////////////////////////////////////////////////// WXMolecule::CellAtom::CellAtom(): mpAtom(0),mName(""),mpScatteringPower(0),mX(0),mY(0),mZ(0),mNeedUpdateUI(true) {} WXMolecule::CellBond::CellBond(): mpBond(0),mAtom1(""),mAtom2(""), mLength(0),mLength0(0),mSigma(0),mDelta(0),mNeedUpdateUI(true) {} WXMolecule::CellBondAngle::CellBondAngle(): mpBondAngle(0),mAtom1(""),mAtom2(""),mAtom3(""), mAngle(0),mAngle0(0),mSigma(0),mDelta(0),mNeedUpdateUI(true) {} WXMolecule::CellDihedralAngle::CellDihedralAngle(): mpDihedralAngle(0),mAtom1(""),mAtom2(""),mAtom3(""),mAtom4(""), mAngle(0),mAngle0(0),mSigma(0),mDelta(0),mNeedUpdateUI(true) {} WXMolecule::CellRigidGroup::CellRigidGroup(): mpGroup(0),mNeedUpdateUI(false) {} //////////////////////////////////////////////////////////////////////// // // WXMolecule // //////////////////////////////////////////////////////////////////////// WXCRYST_ID ID_MENU_OPTIMIZECONFORMATION; WXCRYST_ID ID_MENU_SETLIMITS; WXCRYST_ID ID_MOLECULE_MENU_FILE; WXCRYST_ID ID_MOLECULE_MENU_FILE_2ZMATRIX; WXCRYST_ID ID_MOLECULE_MENU_FILE_2ZMATRIXNAMED; WXCRYST_ID ID_MOLECULE_MENU_PAR_MDTEST; WXCRYST_ID ID_MOLECULE_MENU_FORMULA; WXCRYST_ID ID_MOLECULE_MENU_FORMULA_OPTIMIZECONFORMATION; WXCRYST_ID ID_MOLECULE_MENU_FORMULA_STATUS; WXCRYST_ID ID_MOLECULE_MENU_EXPORT_RESTRAINTS; WXCRYST_ID ID_MOLECULE_MENU_FORMULA_ADD_ATOM; WXCRYST_ID ID_MOLECULE_MENU_FORMULA_ADD_BOND; WXCRYST_ID ID_MOLECULE_MENU_FORMULA_ADD_ANGLE; WXCRYST_ID ID_MOLECULE_MENU_FORMULA_ADD_DIHEDRAL; WXCRYST_ID ID_MOLECULE_MENU_FORMULA_ADD_RIGID_GROUP; WXCRYST_ID ID_MOLECULE_MENU_FORMULA_ADD_NONFLIP_ATOM; WXCRYST_ID ID_MOLECULE_MENU_FORMULA_RIGIDIFY_WITH_DIHEDRALANGLES; WXCRYST_ID ID_MOLECULE_MENU_FORMULA_TEST; WXCRYST_ID ID_MOLECULE_MENU_FORMULA_REMOVE_ATOM; WXCRYST_ID ID_MOLECULE_MENU_FORMULA_REMOVE_BOND; WXCRYST_ID ID_MOLECULE_MENU_FORMULA_REMOVE_ANGLE; WXCRYST_ID ID_MOLECULE_MENU_FORMULA_REMOVE_DIHEDRAL; WXCRYST_ID ID_MOLECULE_MENU_FORMULA_REMOVE_RIGID_GROUP; WXCRYST_ID ID_MOLECULE_MENU_FORMULA_REMOVE_NONFLIPATOM; WXCRYST_ID ID_MOLECULE_MENU_FORMULA_SHOW_RESTRAINT; WXCRYST_ID ID_MOLECULE_MENU_FORMULA_SET_DELTA_SIGMA; WXCRYST_ID ID_MOLECULE_MENU_GEOMETRY; WXCRYST_ID ID_MOLECULE_MENU_GEOMETRY_ROTATE_BOND; WXCRYST_ID ID_MOLECULE_MENU_GEOMETRY_ROTATE_DIHED; WXCRYST_ID ID_MOLECULE_CHANGE_CENTER_ATOM; WXCRYST_ID ID_WINDOW_ATOM; WXCRYST_ID ID_WINDOW_BONDLENGTH; WXCRYST_ID ID_WINDOW_BONDANGLE; WXCRYST_ID ID_WINDOW_DIHEDRALANGLE; WXCRYST_ID ID_WINDOW_RIGIDGROUP; WXCRYST_ID ID_WINDOW_NONFLIPATOM; BEGIN_EVENT_TABLE(WXMolecule,wxWindow) EVT_BUTTON(ID_WXOBJ_COLLAPSE, WXCrystObj::OnToggleCollapse) EVT_MENU(ID_REFOBJ_MENU_PAR_FIXALL, WXRefinableObj::OnMenuFixAllPar) EVT_MENU(ID_REFOBJ_MENU_PAR_UNFIXALL, WXRefinableObj::OnMenuUnFixAllPar) EVT_MENU(ID_REFOBJ_MENU_PAR_RANDOMIZE, WXRefinableObj::OnMenuParRandomize) EVT_MENU(ID_MOLECULE_MENU_PAR_MDTEST, WXMolecule::OnMenuMDTest) EVT_MENU(ID_MOLECULE_MENU_FORMULA_OPTIMIZECONFORMATION,WXMolecule::OnMenuOptimizeConformation) EVT_MENU(ID_MOLECULE_MENU_FORMULA_STATUS, WXMolecule::OnMenuPrintRestraintStatus) EVT_MENU(ID_MOLECULE_MENU_EXPORT_RESTRAINTS, WXMolecule::OnMenuExportRestraints) EVT_MENU(ID_MOLECULE_MENU_FORMULA_ADD_ATOM, WXMolecule::OnMenuAddAtom) EVT_MENU(ID_MOLECULE_MENU_FORMULA_ADD_BOND, WXMolecule::OnMenuAddBond) EVT_MENU(ID_MOLECULE_MENU_FORMULA_ADD_ANGLE, WXMolecule::OnMenuAddAngle) EVT_MENU(ID_MOLECULE_MENU_FORMULA_ADD_DIHEDRAL, WXMolecule::OnMenuAddDihedralAngle) EVT_MENU(ID_MOLECULE_MENU_FORMULA_ADD_RIGID_GROUP, WXMolecule::OnMenuAddRigidGroup) EVT_MENU(ID_MOLECULE_MENU_FORMULA_ADD_NONFLIP_ATOM, WXMolecule::OnMenuAddNonFlipAtom) EVT_MENU(ID_MOLECULE_MENU_FORMULA_RIGIDIFY_WITH_DIHEDRALANGLES,WXMolecule::OnMenuRigidfyWithDihedralAngles) EVT_MENU(ID_MOLECULE_MENU_FORMULA_REMOVE_ATOM, WXMolecule::OnMenuRemoveAtom) EVT_MENU(ID_MOLECULE_MENU_FORMULA_REMOVE_BOND, WXMolecule::OnMenuRemoveBond) EVT_MENU(ID_MOLECULE_MENU_FORMULA_REMOVE_ANGLE, WXMolecule::OnMenuRemoveAngle) EVT_MENU(ID_MOLECULE_MENU_FORMULA_REMOVE_DIHEDRAL, WXMolecule::OnMenuRemoveDihedralAngle) EVT_MENU(ID_MOLECULE_MENU_FORMULA_REMOVE_RIGID_GROUP, WXMolecule::OnMenuRemoveRigidGroup) EVT_MENU(ID_MOLECULE_MENU_FORMULA_REMOVE_NONFLIPATOM, WXMolecule::OnMenuRemoveNonFlipAtom) EVT_MENU(ID_MOLECULE_MENU_FORMULA_TEST , WXMolecule::OnMenuTest) EVT_MENU(ID_MENU_SETLIMITS, WXMolecule::OnMenuSetLimits) EVT_MENU(ID_MOLECULE_MENU_FORMULA_SHOW_RESTRAINT, WXMolecule::OnMenuShowRestraintWindow) EVT_MENU(ID_MOLECULE_MENU_FORMULA_SET_DELTA_SIGMA ,WXMolecule::OnMenuSetDeltaSigma) EVT_MENU(ID_MOLECULE_MENU_FILE_2ZMATRIX, WXMolecule::OnMenuExport2ZMatrix) EVT_MENU(ID_MOLECULE_MENU_FILE_2ZMATRIXNAMED, WXMolecule::OnMenuExport2ZMatrix) EVT_MENU(ID_MOLECULE_MENU_GEOMETRY_ROTATE_BOND, WXMolecule::OnMenuRotate) EVT_MENU(ID_MOLECULE_MENU_GEOMETRY_ROTATE_DIHED, WXMolecule::OnMenuRotate) EVT_GRID_CMD_CELL_CHANGED(ID_WINDOW_ATOM, WXMolecule::OnEditGridAtom) EVT_GRID_CMD_CELL_CHANGED(ID_WINDOW_BONDLENGTH, WXMolecule::OnEditGridBondLength) EVT_GRID_CMD_CELL_CHANGED(ID_WINDOW_BONDANGLE, WXMolecule::OnEditGridBondAngle) EVT_GRID_CMD_CELL_CHANGED(ID_WINDOW_DIHEDRALANGLE, WXMolecule::OnEditGridDihedralAngle) EVT_GRID_CMD_CELL_CHANGED(ID_WINDOW_RIGIDGROUP, WXMolecule::OnEditGridRigidGroup) EVT_BUTTON(ID_MOLECULE_CHANGE_CENTER_ATOM, WXMolecule::OnChangeCenterAtom) END_EVENT_TABLE() WXMolecule::WXMolecule(wxWindow *parent, Molecule *mol): WXScatterer(parent,mol),mpMolecule(mol), mpBondWin(0),mpAngleWin(0),mpDihedralAngleWin(0),mpRigidGroupWin(0),mpNonFlipAtomWin(0),mIsSelfUpdating(false) { VFN_DEBUG_ENTRY("WXMolecule::WXMolecule():"<GetName(),6) //Menus mpMenuBar->AddMenu("File",ID_MOLECULE_MENU_FILE); mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FILE,ID_MOLECULE_MENU_FILE_2ZMATRIX,"Export to Fenske-Hall Z-Matrix"); mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FILE,ID_MOLECULE_MENU_FILE_2ZMATRIXNAMED,"Export to Z-Matrix with atom names"); mpMenuBar->AddMenu("Parameters",ID_REFOBJ_MENU_PAR); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_FIXALL,"Fix all"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_UNFIXALL,"Unfix all"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_RANDOMIZE, "Randomize Configuration"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_MOLECULE_MENU_PAR_MDTEST, "Test Molecular Dynamics moves for 30s"); mpMenuBar->AddMenu("Formula && Restraints",ID_MOLECULE_MENU_FORMULA); mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_OPTIMIZECONFORMATION, "Optimize Starting Conformation"); mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_SET_DELTA_SIGMA, "Set Restraints delta && sigma for all bonds && angles"); mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_STATUS, "Print Detailed Restraint Values"); mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_EXPORT_RESTRAINTS, "Export Restraints in CVS File format"); mpMenuBar->GetMenu(ID_MOLECULE_MENU_FORMULA).AppendSeparator(); mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_ADD_ATOM, "Add an Atom"); mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_ADD_BOND, "Add Bond Restraint"); mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_ADD_ANGLE, "Add Bond Angle Restraint"); mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_ADD_DIHEDRAL, "Add Dihedral Angle Restraint"); mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_ADD_RIGID_GROUP, "Add Rigid Group"); mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_ADD_NONFLIP_ATOM, "Add Non-Flip (optically active) Atom"); mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_RIGIDIFY_WITH_DIHEDRALANGLES, "Rigidify with Dihedral Angles"); mpMenuBar->GetMenu(ID_MOLECULE_MENU_FORMULA).AppendSeparator(); mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_REMOVE_ATOM, "Remove an Atom"); mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_REMOVE_BOND, "Remove a Bond Restraint"); mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_REMOVE_ANGLE, "Remove a Bond Angle Restraint"); mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_REMOVE_DIHEDRAL, "Remove a Dihedral Angle Restraint"); mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_REMOVE_RIGID_GROUP, "Remove Rigid Group"); mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_REMOVE_NONFLIPATOM, "Remove Non-Flip (optically active) Atom"); mpMenuBar->GetMenu(ID_MOLECULE_MENU_FORMULA).AppendSeparator(); mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_SHOW_RESTRAINT, "Show Restraint Window"); //#ifdef __DEBUG__ mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_TEST,"Debug Test"); //#endif mpMenuBar->AddMenu("Manipulate Geometry",ID_MOLECULE_MENU_GEOMETRY); mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_GEOMETRY,ID_MOLECULE_MENU_GEOMETRY_ROTATE_BOND, "Rotate around bond"); mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_GEOMETRY,ID_MOLECULE_MENU_GEOMETRY_ROTATE_DIHED, "Set dihedral angle"); //mpSizer->SetItemMinSize(mpMenuBar, // mpMenuBar->GetSize().GetWidth(), // mpMenuBar->GetSize().GetHeight()); WXFieldPar *pLLKScale= new WXFieldPar(this,"Log(likelihood) scale",-1,&(mpMolecule->mLogLikelihoodScale)); mList.Add(pLLKScale); mpSizer->Add(pLLKScale,0,wxALIGN_LEFT); pLLKScale->SetToolTip(_T("The log(likelihood) of the molecule, i.e. the sum\n") _T("of the restraints costs for all bonds and angles \n") _T("are multiplied by this scale.\n\n") _T("The default value is 1.\n\n") _T("Multiplying this value by 4 is equivalent to dividing the\n") _T("sigma of all bonds and angles by a factor 2.\n") _T("This can be increased if the molecule presents too\n") _T("much distortion.\n\n") _T("Note that a too large value (e.g.>100) will decrease the\n") _T("convergence speed of the algorithm, as distortion of the\n") _T("structure is necessary for an efficient minimisation.")); // Molecular Dynamics move parameters wxBoxSizer* pMDSizer=new wxBoxSizer(wxHORIZONTAL); WXFieldPar *pWXFieldMDEnergy= new WXFieldPar(this,"MD moves Energy",-1,&(mpMolecule->mMDMoveEnergy)); WXFieldPar *pWXFieldMDFrequency= new WXFieldPar(this,"MD moves frequency",-1,&(mpMolecule->mMDMoveFreq)); pMDSizer->Add(pWXFieldMDFrequency); pMDSizer->Add(pWXFieldMDEnergy); mpSizer->Add(pMDSizer,0,wxALIGN_LEFT); mList.Add(pWXFieldMDEnergy); mList.Add(pWXFieldMDFrequency); pWXFieldMDFrequency->SetToolTip(_T("Frequency of Molecular Dynamics Moves (0.0-1.0)\n\n") _T("MD moves are used to alter the conformation of atom groups \n") _T("which cannot be changed by simple bond distance\n") _T("or bond angle changes.\n\n") _T("MD moves are CPU intensive, so a slow value (0.05) is recommended\n") _T("Larger frequencies can be used for constrained molecules,\n") _T("e.g. with large, flexible cycles.")); pWXFieldMDEnergy->SetToolTip(_T("Energy of Molecule for Molecular Dynamics Moves\n\n") _T("Standard amplitude=40. \n") _T("Small amplitude=10. (small distortion of the Molecule)\n") _T("Large amplitude=400. (large distortion of the Molecule)")); //Center atom mpFieldCenterAtom=new WXFieldChoice(this,ID_MOLECULE_CHANGE_CENTER_ATOM,"Center Atom:",240); if(mpMolecule->GetCenterAtom()!=0) mpFieldCenterAtom->SetValue(mpMolecule->GetCenterAtom()->GetName()); else mpFieldCenterAtom->SetValue("Click to choose an atom !"); mpSizer->Add(mpFieldCenterAtom,0,wxALIGN_LEFT); mList.Add(mpFieldCenterAtom); // Atom list wxGridCellAttr* cellAttrName = new wxGridCellAttr; cellAttrName->SetRenderer(new wxGridCellStringRenderer); cellAttrName->SetEditor(new wxGridCellTextEditor); wxGridCellAttr* cellAttrFloat = new wxGridCellAttr; cellAttrFloat->SetRenderer(new wxGridCellFloatRenderer(6,3)); cellAttrFloat->SetEditor(new wxGridCellFloatEditor(6,3)); mpAtomWin= new WXMolScrolledWindow(this,this,ID_WINDOW_ATOM); //mpAtomWin->SetSize(800,300); mpAtomWin->EnableScrolling(true,true); //mpAtomWin->SetSizeHints(-1,300,-1,300); mpAtomWin->CreateGrid(0,6); mpAtomWin->SetRowLabelSize(40); mpAtomWin->SetDefaultColSize(60); mpAtomWin->SetColAttr(0,cellAttrName); mpAtomWin->SetColAttr(1,cellAttrName->Clone()); mpAtomWin->SetColAttr(2,cellAttrFloat); mpAtomWin->SetColAttr(3,cellAttrFloat->Clone()); mpAtomWin->SetColAttr(4,cellAttrFloat->Clone()); mpAtomWin->SetColAttr(5,cellAttrFloat->Clone()); mpAtomWin->SetColLabelValue(0,_T("Name")); mpAtomWin->SetColLabelValue(1,_T("Type")); mpAtomWin->SetColLabelValue(2,_T("X")); mpAtomWin->SetColLabelValue(3,_T("Y")); mpAtomWin->SetColLabelValue(4,_T("Z")); mpAtomWin->SetColLabelValue(5,_T("Occup")); mpAtomWin->AutoSizeRows(); mpSizer->Add(mpAtomWin,0,wxALIGN_LEFT); this->CrystUpdate(true); VFN_DEBUG_EXIT("WXMolecule::WXMolecule():"<GetName(),6) } WXMolecule::~WXMolecule() { VFN_DEBUG_ENTRY("WXMolecule::~WXMolecule()",10) if(0!=mpBondWin) mpBondWin->GetParent()->Destroy(); VFN_DEBUG_EXIT("WXMolecule::~WXMolecule()",10) } void WXMolecule::OnMenuOptimizeConformation(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXMolecule::OnMenuOptimizeConformation()",5) WXCrystValidateAllUserInput(); mpMolecule->OptimizeConformation(20000,mpMolecule->GetAtomList().size()); mpMolecule->OptimizeConformationSteepestDescent(0.01,100); mpMolecule->RestraintStatus(cout); LSQNumObj lsq; lsq.SetRefinedObj(*mpMolecule); lsq.PrepareRefParList(true); lsq.SetParIsUsed(gpRefParTypeObjCryst,false); lsq.SetParIsUsed(gpRefParTypeScattConform,true); try {lsq.Refine(10,true,false);} catch(const ObjCrystException &except){} mpMolecule->GetCrystal().UpdateDisplay(); mpMolecule->RestraintStatus(cout); mpMolecule->GetCrystal().UpdateDisplay(); VFN_DEBUG_EXIT("WXMolecule::OnMenuOptimizeConformation()",5) } void WXMolecule::OnMenuExportRestraints(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXMolecule::OnMenuExportRestraints()",5) WXCrystValidateAllUserInput(); stringstream ss; mpMolecule->RestraintExport(ss); wxFileDialog open(this,_T("Choose File to save restraints:"), _T(""),_T(""),_T("*.csv"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if(open.ShowModal() != wxID_OK) return; wxString name=open.GetPath(); if(name.substr(name.size()-4,4)!=_T(".csv")) { cout< "<RestraintStatus(cout); VFN_DEBUG_EXIT("WXMolecule::OnMenuPrintRestraintStatus()",5) } void WXMolecule::OnMenuAddAtom(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXMolecule::OnMenuAddAtom()",6) WXCrystValidateAllUserInput(); int choice; const ScatteringPower *scatt=WXDialogChooseFromRegistry( mpMolecule->GetCrystal().GetScatteringPowerRegistry(), (wxWindow*)this,"Choose a new Scattering Power",choice); if(0==scatt) return; long num=mpMolecule->GetAtomList().size(); if(num>0) { wxString lastAtom=wxString::FromAscii(mpMolecule->GetAtom(num-1).GetName().c_str()); for(;;) { if(lastAtom.size()==0) break; if(lastAtom.IsNumber()) { lastAtom.ToLong(&num); break; } lastAtom.erase(0,1); } } stringstream st; st<AddAtom(0.,0.,0.,scatt,scatt->GetName()+st.str()); VFN_DEBUG_EXIT("WXMolecule::OnMenuAddAtom()",6) } void WXMolecule::OnMenuAddBond(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXMolecule::OnMenuAddBond()",6) WXCrystValidateAllUserInput(); int choice; vector v=mpMolecule->GetAtomList(); MolAtom *at1=WXDialogChooseFromVector(v, (wxWindow*)this,"Choose the first Atom",choice); if(0==at1) return; MolAtom *at2=WXDialogChooseFromVector(v, (wxWindow*)this,"Choose the second Atom",choice); if(0==at2) return; if(at1==at2) { wxMessageDialog dumbUser(this,_T("The two atoms must be different !"), _T("Whooops"),wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); return; } static double d=1.5;//static so that last entered value will be used next time wxString s; s.Printf(_T("%6.3f"),d); // if((at1->IsDummy())||(at2->IsDummy())) d=1.5; // else d= (at1->GetScatteringPower().GetRadius()+at2->GetScatteringPower().GetRadius())*0.9; string mes="Enter bond distance (Angstroems) for "+at1->GetName()+"-"+at2->GetName(); wxTextEntryDialog dialog(this,wxString::FromAscii(mes.c_str()), _T("Bond distance"),s,wxOK | wxCANCEL); dialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=dialog.ShowModal()) { VFN_DEBUG_EXIT("WXMolecule::OnMenuAddBond():Canceled",6) return; } dialog.GetValue().ToDouble(&d); mpMolecule->AddBond(*at1,*at2,d,.01,.02,1.); VFN_DEBUG_EXIT("WXMolecule::OnMenuAddBond()",6) } void WXMolecule::OnMenuAddAngle(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXMolecule::OnMenuAddBond()",6) WXCrystValidateAllUserInput(); int choice; vector v=mpMolecule->GetAtomList(); MolAtom *at1=WXDialogChooseFromVector(v, (wxWindow*)this,"Choose the first Atom",choice); if(0==at1) return; MolAtom *at2=WXDialogChooseFromVector(v, (wxWindow*)this,"Choose the second Atom",choice); if(0==at2) return; MolAtom *at3=WXDialogChooseFromVector(v, (wxWindow*)this,"Choose the third Atom",choice); if(0==at2) return; if( (at1==at2) || (at1==at3) ||(at2==at3)) { wxMessageDialog dumbUser(this,_T("The three atoms must be different !"), _T("Whooops"),wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); return; } static double a=109.5;//static so that last entered value will be used next time wxString s; s.Printf(_T("%6.2f"),a); string mes="Enter bond angle (degrees) for "+at1->GetName() +"-"+at2->GetName() +"-"+at3->GetName(); wxTextEntryDialog dialog(this,wxString::FromAscii(mes.c_str()), _T("Bond angle"),s,wxOK | wxCANCEL); dialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=dialog.ShowModal()) { VFN_DEBUG_EXIT("WXMolecule::OnMenuAddAngle():Canceled",6) return; } dialog.GetValue().ToDouble(&a); mpMolecule->AddBondAngle(*at1,*at2,*at3,a*DEG2RAD,.01,0.02); VFN_DEBUG_EXIT("WXMolecule::OnMenuAddBond()",6) } void WXMolecule::OnMenuAddDihedralAngle(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXMolecule::OnMenuAddDihedralAngle()",6) WXCrystValidateAllUserInput(); int choice; vector v=mpMolecule->GetAtomList(); MolAtom *at1=WXDialogChooseFromVector(v, (wxWindow*)this,"Choose the first Atom",choice); if(0==at1) return; MolAtom *at2=WXDialogChooseFromVector(v, (wxWindow*)this,"Choose the second Atom",choice); if(0==at2) return; MolAtom *at3=WXDialogChooseFromVector(v, (wxWindow*)this,"Choose the third Atom",choice); if(0==at3) return; MolAtom *at4=WXDialogChooseFromVector(v, (wxWindow*)this,"Choose the fourth Atom",choice); if(0==at4) return; if( (at1==at2) || (at1==at3) || (at1==at4) || (at2==at3) || (at2==at4) || (at3==at4)) { wxMessageDialog dumbUser(this,_T("The atoms must be different !"), _T("Whooops"),wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); return; } static double a=180; wxString s; s.Printf(_T("%6.2f"),a); string mes="Enter dihedral angle (degrees) for "+at1->GetName() +"-"+at2->GetName() +"-"+at3->GetName() +"-"+at4->GetName(); wxTextEntryDialog dialog(this,_T("Enter dihedral angle (degrees)"), _T("Bond angle"),s,wxOK | wxCANCEL); dialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=dialog.ShowModal()) { VFN_DEBUG_EXIT("WXMolecule::OnMenuAddDihedralAngle():Canceled",6) return; } dialog.GetValue().ToDouble(&a); mpMolecule->AddDihedralAngle(*at1,*at2,*at3,*at4,a*DEG2RAD,.01,.02); VFN_DEBUG_EXIT("WXMolecule::OnMenuAddDihedralAngle()",6) } void WXMolecule::OnMenuAddRigidGroup(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXMolecule::OnMenuAddRigidGroup()",6) WXCrystValidateAllUserInput(); list l=WXDialogChooseMultipleFromVector(mpMolecule->GetAtomList(),this, "Choose atoms in the rigid group"); RigidGroup s; for(list::const_iterator pos=l.begin();pos!=l.end();++pos) s.insert(*pos); mpMolecule->AddRigidGroup(s); VFN_DEBUG_EXIT("WXMolecule::OnMenuAddRigidGroup()",6) } void WXMolecule::OnMenuAddNonFlipAtom(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXMolecule::OnMenuAddNonFlipAtom()",6) WXCrystValidateAllUserInput(); int choice; vector v; for(vector::const_iterator pos=mpMolecule->GetAtomList().begin();pos!=mpMolecule->GetAtomList().end();++pos) { if((*pos)->IsNonFlipAtom()==false) v.push_back(*pos); } MolAtom *at1=WXDialogChooseFromVector(v, (wxWindow*)this,"Choose the Optically active Atom",choice); if(0==at1) { wxMessageDialog dumbUser(this,_T("No atom selected !"), _T("Whooops"),wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); return; } at1->SetNonFlipAtom(true); this->CrystUpdate(true); VFN_DEBUG_EXIT("WXMolecule::OnMenuAddNonFlipAtom()",6) } void WXMolecule::OnMenuRemoveAtom(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXMolecule::OnMenuRemoveAtom()",6) WXCrystValidateAllUserInput(); vector v=mpMolecule->GetAtomList(); list vAt=WXDialogChooseMultipleFromVector(v,(wxWindow*)this, "Choose the Atom(s) to be removed"); if(0==vAt.size()) return; for(list::iterator pos=vAt.begin();pos!=vAt.end();++pos) mpMolecule->RemoveAtom(**pos); this->CrystUpdate(true); VFN_DEBUG_EXIT("WXMolecule::OnMenuRemoveAtom()",6) } void WXMolecule::OnMenuRemoveBond(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXMolecule::OnMenuRemoveBond()",6) WXCrystValidateAllUserInput(); vector v=mpMolecule->GetBondList(); list vBond=WXDialogChooseMultipleFromVector(v,(wxWindow*)this, "Choose the Bond(s) to be removed"); if(0==vBond.size()) return; const int answer =wxMessageBox (_T("Remove Bond and Dihedral Angles involving the deleted Bond(s) (if any) ?"), _T("Delete related Restraints ?"),wxYES_NO, this); for(list::iterator pos=vBond.begin();pos!=vBond.end();++pos) { if(answer==wxYES) { const MolAtom *pAtom1= &((*pos)->GetAtom1()); const MolAtom *pAtom2= &((*pos)->GetAtom2()); for(vector::iterator posb=mpMolecule->GetBondAngleList().begin(); posb!=mpMolecule->GetBondAngleList().end();) { if( ( (pAtom1==&((*posb)->GetAtom1())) && (pAtom2==&((*posb)->GetAtom2())) ) ||( (pAtom1==&((*posb)->GetAtom2())) && (pAtom2==&((*posb)->GetAtom1())) ) ||( (pAtom1==&((*posb)->GetAtom2())) && (pAtom2==&((*posb)->GetAtom3())) ) ||( (pAtom1==&((*posb)->GetAtom3())) && (pAtom2==&((*posb)->GetAtom2())) )) posb=mpMolecule->RemoveBondAngle(**posb); else ++posb; } for(vector::iterator posb=mpMolecule->GetDihedralAngleList().begin(); posb!=mpMolecule->GetDihedralAngleList().end();) { if( ( (pAtom1==&((*posb)->GetAtom1())) && (pAtom2==&((*posb)->GetAtom2())) ) ||( (pAtom1==&((*posb)->GetAtom2())) && (pAtom2==&((*posb)->GetAtom1())) ) ||( (pAtom1==&((*posb)->GetAtom2())) && (pAtom2==&((*posb)->GetAtom3())) ) ||( (pAtom1==&((*posb)->GetAtom3())) && (pAtom2==&((*posb)->GetAtom2())) ) ||( (pAtom1==&((*posb)->GetAtom3())) && (pAtom2==&((*posb)->GetAtom4())) ) ||( (pAtom1==&((*posb)->GetAtom4())) && (pAtom2==&((*posb)->GetAtom3())) )) posb=mpMolecule->RemoveDihedralAngle(**posb); else ++posb; } } mpMolecule->RemoveBond(**pos); } this->CrystUpdate(true); VFN_DEBUG_EXIT("WXMolecule::OnMenuRemoveBond()",6) } void WXMolecule::OnMenuRemoveAngle(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXMolecule::OnMenuRemoveAngle()",6) WXCrystValidateAllUserInput(); vector v=mpMolecule->GetBondAngleList(); list vAngle=WXDialogChooseMultipleFromVector(v,(wxWindow*)this, "Choose the Bond Angle(s) to be removed"); if(0==vAngle.size()) return; for(list::iterator pos=vAngle.begin();pos!=vAngle.end();++pos) mpMolecule->RemoveBondAngle(**pos); this->CrystUpdate(true); VFN_DEBUG_EXIT("WXMolecule::OnMenuRemoveAngle()",6) } void WXMolecule::OnMenuRemoveDihedralAngle(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXMolecule::OnMenuRemoveDihedralAngle()",6) WXCrystValidateAllUserInput(); vector v=mpMolecule->GetDihedralAngleList(); list vAngle=WXDialogChooseMultipleFromVector(v,(wxWindow*)this, "Choose the Dihedral Angle(s) to be removed"); if(0==vAngle.size()) return; for(list::iterator pos=vAngle.begin();pos!=vAngle.end();++pos) mpMolecule->RemoveDihedralAngle(**pos); this->CrystUpdate(true); VFN_DEBUG_EXIT("WXMolecule::OnMenuRemoveDihedralAngle()",6) } void WXMolecule::OnMenuRemoveNonFlipAtom(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXMolecule::OnMenuRemoveNonFlipAtom()",6) WXCrystValidateAllUserInput(); int choice; vector v; for(vector::const_iterator pos=mpMolecule->GetAtomList().begin();pos!=mpMolecule->GetAtomList().end();++pos) { if((*pos)->IsNonFlipAtom()) v.push_back(*pos); } if(v.size()==0) { wxMessageDialog dumbUser(this,_T("The list of optically active atoms is empty !"), _T("Whooops"),wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); return; } MolAtom *at1=WXDialogChooseFromVector(v, (wxWindow*)this,"Choose the Optically active Atom to be removed",choice); if(0==at1) { wxMessageDialog dumbUser(this,_T("No atom selected !"), _T("Whooops"),wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); return; } at1->SetNonFlipAtom(false); this->CrystUpdate(true); VFN_DEBUG_EXIT("WXMolecule::OnMenuRemoveNonFlipAtom()",6) } void WXMolecule::OnMenuRemoveRigidGroup(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXMolecule::OnMenuRemoveRigidGroup()",6) WXCrystValidateAllUserInput(); vector v=mpMolecule->GetRigidGroupList(); list vGroup=WXDialogChooseMultipleFromVector(v,(wxWindow*)this, "Choose the Rigid Group(s) to be removed"); if(0==vGroup.size()) return; for(list::iterator pos=vGroup.begin();pos!=vGroup.end();++pos) mpMolecule->RemoveRigidGroup(**pos); this->CrystUpdate(true); VFN_DEBUG_EXIT("WXMolecule::OnMenuRemoveRigidGroup()",6) } /* void WXMolecule::OnMenuRemoveFlipGroup(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXMolecule::OnMenuRemoveFlipGroup()",6) WXCrystValidateAllUserInput(); mpMolecule->BuildFlipGroup(); list v = mpMolecule->GetFlipGroupList(); wxString *choices = new wxString[v.size()]; int i=0; for(list::iterator pos=v.begin();pos!=v.end();++pos) { if(pos->mvRotatedChainList.begin()->first==pos->mpAtom0) { choices[i] = pos->mpAtom0->GetName(); choices[i] += ": "; choices[i] += pos->mpAtom1->GetName(); choices[i] += " <-> "; choices[i] += pos->mpAtom2->GetName(); } else { choices[i] = pos->mpAtom0->GetName(); for(list > >::const_iterator chain=pos->mvRotatedChainList.begin(); chain!=pos->mvRotatedChainList.end();++chain) { choices[i] += chain->first->GetName(); choices[i] += " <-> "; } choices[i].Remove(choices[i].size()-5, choices[i].size()); } i++; } wxMultiChoiceDialog_ListBox dialog ((wxWindow*)this, "Choose the Flip Group(s) to be removed",_T("Choose"),v.size(),choices); dialog.ShowModal(); wxArrayInt choice=dialog.GetSelections(); delete[] choices; this->CrystUpdate(true); VFN_DEBUG_EXIT("WXMolecule::OnMenuRemoveFlipGroup()",6) } */ void WXMolecule::OnEditGridAtom(wxGridEvent &e) { if(mIsSelfUpdating) return; VFN_DEBUG_ENTRY("WXMolecule::OnEditGridAtom():"<GetCellValue(r,c); if(s!=_T("")) mpMolecule->GetAtomList()[r]->SetName(string(s.ToAscii())); } if(c==1) { wxString s=mpAtomWin->GetCellValue(r,c); if(s!=_T("")) { try { long p=mpMolecule->GetCrystal().GetScatteringPowerRegistry().Find(string(s.ToAscii())); if(p>=0) mpMolecule->GetAtomList()[r]->SetScatteringPower( mpMolecule->GetCrystal().GetScatteringPowerRegistry().GetObj(p)); } catch(ObjCrystException){}; } } if(c==2) { wxString s=mpAtomWin->GetCellValue(r,c); if(s!=_T("")) { double d; if(s.ToDouble(&d)) mpMolecule->GetAtomList()[r]->SetX(d); } } if(c==3) { wxString s=mpAtomWin->GetCellValue(r,c); if(s!=_T("")) { double d; if(s.ToDouble(&d)) mpMolecule->GetAtomList()[r]->SetY(d); } } if(c==4) { wxString s=mpAtomWin->GetCellValue(r,c); if(s!=_T("")) { double d; if(s.ToDouble(&d)) mpMolecule->GetAtomList()[r]->SetZ(d); } } if(c==5) { wxString s=mpAtomWin->GetCellValue(r,c); if(s!=_T("")) { double d; if(s.ToDouble(&d)) { if(d>1)d=1; else if(d<0)d=0; mpMolecule->GetAtomList()[r]->SetOccupancy(d); } } } mpMolecule->GetCrystal().UpdateDisplay(); VFN_DEBUG_EXIT("WXMolecule::OnEditGridAtom():"<GetCellValue(r,c); vector::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii())); if(at!=mpMolecule->GetAtomList().rend()) { if(*at!=&(mpMolecule->GetBondList()[r]->GetAtom2())) mpMolecule->GetBondList()[r]->SetAtom1(**at); else mpBondWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondList()[r]->GetAtom1().GetName().c_str())); } else mpBondWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondList()[r]->GetAtom1().GetName().c_str())); } if(c==1) { wxString s=mpBondWin->GetCellValue(r,c); vector::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii())); if(at!=mpMolecule->GetAtomList().rend()) { if(*at!=&(mpMolecule->GetBondList()[r]->GetAtom1())) mpMolecule->GetBondList()[r]->SetAtom2(**at); else mpBondWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondList()[r]->GetAtom2().GetName().c_str())); } else mpBondWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondList()[r]->GetAtom2().GetName().c_str())); } if(c==3) { wxString s=mpBondWin->GetCellValue(r,c); if(s!=_T("")) { double d; if(s.ToDouble(&d)) if(d>0) mpMolecule->GetBondList()[r]->SetLength0(d); } } if(c==4) { wxString s=mpBondWin->GetCellValue(r,c); if(s!=_T("")) { double d; if(s.ToDouble(&d)) if(d>0) mpMolecule->GetBondList()[r]->SetLengthSigma(d); } } if(c==5) { wxString s=mpBondWin->GetCellValue(r,c); if(s!=_T("")) { double d; if(s.ToDouble(&d)) if(d>0) mpMolecule->GetBondList()[r]->SetLengthDelta(d); } } this->CrystUpdate(true); VFN_DEBUG_EXIT("WXMolecule::OnEditGridBondLength():"<GetCellValue(r,c); vector::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii())); if(at!=mpMolecule->GetAtomList().rend()) { if( (*at!=&(mpMolecule->GetBondAngleList()[r]->GetAtom2())) &&(*at!=&(mpMolecule->GetBondAngleList()[r]->GetAtom3()))) mpMolecule->GetBondAngleList()[r]->SetAtom1(**at); else mpAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondAngleList()[r]->GetAtom1().GetName().c_str())); } else mpAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondAngleList()[r]->GetAtom1().GetName().c_str())); } if(c==1) { wxString s=mpAngleWin->GetCellValue(r,c); vector::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii())); if(at!=mpMolecule->GetAtomList().rend()) { if( (*at!=&(mpMolecule->GetBondAngleList()[r]->GetAtom1())) &&(*at!=&(mpMolecule->GetBondAngleList()[r]->GetAtom3()))) mpMolecule->GetBondAngleList()[r]->SetAtom2(**at); else mpAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondAngleList()[r]->GetAtom2().GetName().c_str())); } else mpAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondAngleList()[r]->GetAtom2().GetName().c_str())); } if(c==2) { wxString s=mpAngleWin->GetCellValue(r,c); vector::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii())); if(at!=mpMolecule->GetAtomList().rend()) { if( (*at!=&(mpMolecule->GetBondAngleList()[r]->GetAtom1())) &&(*at!=&(mpMolecule->GetBondAngleList()[r]->GetAtom2()))) mpMolecule->GetBondAngleList()[r]->SetAtom3(**at); else mpAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondAngleList()[r]->GetAtom3().GetName().c_str())); } else mpAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondAngleList()[r]->GetAtom2().GetName().c_str())); } if(c==4) { wxString s=mpAngleWin->GetCellValue(r,c); if(s!=_T("")) { double d; if(s.ToDouble(&d)) if(d>0) mpMolecule->GetBondAngleList()[r]->SetAngle0(d*DEG2RAD); } } if(c==5) { wxString s=mpAngleWin->GetCellValue(r,c); if(s!=_T("")) { double d; if(s.ToDouble(&d)) if(d>0) mpMolecule->GetBondAngleList()[r]->SetAngleSigma(d*DEG2RAD); } } if(c==6) { wxString s=mpAngleWin->GetCellValue(r,c); if(s!=_T("")) { double d; if(s.ToDouble(&d)) if(d>0) mpMolecule->GetBondAngleList()[r]->SetAngleDelta(d*DEG2RAD); } } this->CrystUpdate(true); VFN_DEBUG_EXIT("WXMolecule::OnEditGridBondAngle():"<GetCellValue(r,c); vector::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii())); if(at!=mpMolecule->GetAtomList().rend()) { if( (*at!=&(mpMolecule->GetDihedralAngleList()[r]->GetAtom2())) &&(*at!=&(mpMolecule->GetDihedralAngleList()[r]->GetAtom3()))) mpMolecule->GetDihedralAngleList()[r]->SetAtom1(**at); else mpDihedralAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetDihedralAngleList()[r]->GetAtom1().GetName().c_str())); } else mpDihedralAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetDihedralAngleList()[r]->GetAtom1().GetName().c_str())); } if(c==1) { wxString s=mpDihedralAngleWin->GetCellValue(r,c); vector::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii())); if(at!=mpMolecule->GetAtomList().rend()) { if( (*at!=&(mpMolecule->GetDihedralAngleList()[r]->GetAtom1())) &&(*at!=&(mpMolecule->GetDihedralAngleList()[r]->GetAtom3()))) mpMolecule->GetDihedralAngleList()[r]->SetAtom2(**at); else mpDihedralAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetDihedralAngleList()[r]->GetAtom2().GetName().c_str())); } else mpDihedralAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetDihedralAngleList()[r]->GetAtom2().GetName().c_str())); } if(c==2) { wxString s=mpDihedralAngleWin->GetCellValue(r,c); vector::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii())); if(at!=mpMolecule->GetAtomList().rend()) { if( (*at!=&(mpMolecule->GetDihedralAngleList()[r]->GetAtom1())) &&(*at!=&(mpMolecule->GetDihedralAngleList()[r]->GetAtom2()))) mpMolecule->GetDihedralAngleList()[r]->SetAtom3(**at); else mpDihedralAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetDihedralAngleList()[r]->GetAtom3().GetName().c_str())); } else mpDihedralAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetDihedralAngleList()[r]->GetAtom3().GetName().c_str())); } if(c==3) { wxString s=mpDihedralAngleWin->GetCellValue(r,c); vector::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii())); if(at!=mpMolecule->GetAtomList().rend()) { if( (*at!=&(mpMolecule->GetDihedralAngleList()[r]->GetAtom1())) &&(*at!=&(mpMolecule->GetDihedralAngleList()[r]->GetAtom2()))) mpMolecule->GetDihedralAngleList()[r]->SetAtom4(**at); else mpDihedralAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetDihedralAngleList()[r]->GetAtom4().GetName().c_str())); } else mpDihedralAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetDihedralAngleList()[r]->GetAtom4().GetName().c_str())); } if(c==5) { wxString s=mpDihedralAngleWin->GetCellValue(r,c); if(s!=_T("")) { double d; if(s.ToDouble(&d)) mpMolecule->GetDihedralAngleList()[r]->SetAngle0(d*DEG2RAD); } } if(c==6) { wxString s=mpDihedralAngleWin->GetCellValue(r,c); if(s!=_T("")) { double d; if(s.ToDouble(&d)) if(d>0) mpMolecule->GetDihedralAngleList()[r]->SetAngleSigma(d*DEG2RAD); } } if(c==7) { wxString s=mpDihedralAngleWin->GetCellValue(r,c); if(s!=_T("")) { double d; if(s.ToDouble(&d)) if(d>0) mpMolecule->GetDihedralAngleList()[r]->SetAngleDelta(d*DEG2RAD); } } this->CrystUpdate(true); VFN_DEBUG_EXIT("WXMolecule::OnEditGridDihedralAngle():"<GetCellValue(r,c); list l=SplitString(CompressString(string(s.ToAscii())," "),","); RigidGroup rg; for(list::const_iterator pos=l.begin();pos!=l.end();++pos) { vector::reverse_iterator rpos=mpMolecule->FindAtom(*pos); if(rpos!=mpMolecule->GetAtomList().rend()) rg.insert(*rpos); else cout<<*pos<<" : NOT FOUND"< *pold=(set*) mpMolecule->GetRigidGroupList()[r]; set *pnew=(set*) &rg; if( *pold != *pnew) { *pold = *pnew; mpMolecule->GetRigidGroupClock().Click(); } this->CrystUpdate(true); VFN_DEBUG_EXIT("WXMolecule::OnEditGridRigidGroup():"< *pz=&(mpMolecule->AsZMatrix(true)); if(event.GetId()==ID_MOLECULE_MENU_FILE_2ZMATRIX) { wxFileDialog open(this,_T("Choose a file to save the Z-matrix to"),_T(""),_T(""),_T("*.fhz"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if(open.ShowModal() != wxID_OK) return; ofstream fout (open.GetPath().ToAscii()); fout.imbue(std::locale::classic()); if(fout) { wxString tmp; fout<GetName()<size()<::const_iterator pos=pz->begin();pos!=pz->end();++pos) { tmp.Printf(_T("%-2s %2lu"),pos->mpPow->GetSymbol().c_str(),pos->mBondAtom+1); fout<0) { fout<mBondLength,6,3);; if(i>1) { tmp.Printf(_T(" %2lu"),pos->mBondAngleAtom+1); fout<mBondAngle*RAD2DEG,8,3);; if(i>2) { fout<<" "<mDihedralAtom+1,2)<mDihedralAngle*RAD2DEG,8,3); } } } fout<::const_iterator pos=mpMolecule->GetAtomList().begin(); pos!=mpMolecule->GetAtomList().end();++pos) if(nbchar<(*pos)->GetName().size()) nbchar=(*pos)->GetName().size(); ofstream fout (open.GetPath().ToAscii()); fout.imbue(std::locale::classic()); if(fout) { wxString tmp; fout<GetName()<size()<::const_iterator pos=pz->begin();pos!=pz->end();++pos) { fout.width(nbchar); fout<GetAtomList()[i]->GetName(); tmp.Printf(_T(" %2s "),pos->mpPow->GetSymbol().c_str()); fout<GetAtomList()[pos->mBondAtom]->GetName()<<" "; if(i>0) { fout<mBondLength,6,3)<<" "; if(i>1) { fout.width(nbchar); fout<GetAtomList()[pos->mBondAngleAtom]->GetName(); fout<<" "<mBondAngle*RAD2DEG,8,3)<<" "; if(i>2) { fout.width(nbchar); fout<GetAtomList()[pos->mDihedralAtom]->GetName(); fout<<" "<mDihedralAngle*RAD2DEG,8,3)<<" "; } } } fout<BuildRingList(); mpMolecule->BuildStretchModeBondLength(); mpMolecule->BuildStretchModeBondAngle(); mpMolecule->BuildStretchModeTorsion(); mpMolecule->BuildStretchModeTwist(); //mpMolecule->BuildRotorGroup(); mpMolecule->BuildFlipGroup(); mpMolecule->TuneGlobalOptimRotationAmplitude(); //mpMolecule->FlipAtomGroup(*(mpMolecule->mvFlipGroup.begin())); //mpMolecule->GlobalOptRandomMove(0.1,gpRefParTypeObjCryst); mpMolecule->BuildStretchModeGroups(); #else for(list::iterator pos=mpMolecule->GetStretchModeTorsionList().begin(); pos!=mpMolecule->GetStretchModeTorsionList().end();++pos) { if((pos->mpAtom1->GetName()=="C12")&&(pos->mpAtom2->GetName()=="N13")) { //mpMolecule->DihedralAngleRandomChange(*pos,0.01,true); cout<mpDihedralAngle->GetAngle()*RAD2DEG; mpMolecule->RotateAtomGroup(*(pos->mpAtom1),*(pos->mpAtom2),pos->mvRotatedAtomList,2*M_PI/10,true); cout<<" -> "<mpDihedralAngle->GetAngle()*RAD2DEG <<", llk="<mpDihedralAngle->GetLogLikelihood()<GetCrystal().UpdateDisplay(); #endif #if 0 mpMolecule->BeginOptimization(true); for(REAL amplitude=0.1;amplitude<10;amplitude*=1.5) { REAL maxLLK=0,llk,ave=0.0; for(unsigned long i=0;i<1000;i++) { mpMolecule->BeginGlobalOptRandomMove(); mpMolecule->GlobalOptRandomMove(amplitude,gpRefParTypeObjCryst); llk=mpMolecule->GetLogLikelihood(); //cout<<" "<maxLLK) maxLLK=llk; ave+=llk; mpMolecule->GetCrystal().UpdateDisplay(); } cout<<"Amplitude="<= "< > *pConnect=&(mpMolecule-> GetConnectivityTable()); Chronometer chrono; float dt0=chrono.seconds(); unsigned long ct=0; while(chrono.seconds()<30) { cout<<"MD Test, cycle #"<mvMDFullAtomGroup.begin())->GetX(); REAL xmax=(*mpMolecule->mvMDFullAtomGroup.begin())->GetX(); REAL ymin=(*mpMolecule->mvMDFullAtomGroup.begin())->GetY(); REAL ymax=(*mpMolecule->mvMDFullAtomGroup.begin())->GetY(); REAL zmin=(*mpMolecule->mvMDFullAtomGroup.begin())->GetZ(); REAL zmax=(*mpMolecule->mvMDFullAtomGroup.begin())->GetZ(); for(set::iterator at=mpMolecule->mvMDFullAtomGroup.begin();at!=mpMolecule->mvMDFullAtomGroup.end();++at) { if((*at)->GetX()GetX(); if((*at)->GetX()>xmax) xmax=(*at)->GetX(); if((*at)->GetY()GetY(); if((*at)->GetY()>ymax) ymax=(*at)->GetY(); if((*at)->GetZ()GetZ(); if((*at)->GetZ()>zmax) zmax=(*at)->GetZ(); } // Apply a gaussian impulsion to part of the atom group (FWHM=1/5 of group size) REAL dx=(xmax-xmin)/5.,dy=(ymax-ymin)/5.,dz=(zmax-zmin)/5.; if(dx<2) dx=2; if(dy<2) dy=2; if(dz<2) dz=2; const REAL xc=xmin+rand()/(REAL)RAND_MAX*(xmax-xmin); const REAL yc=ymin+rand()/(REAL)RAND_MAX*(ymax-ymin); const REAL zc=zmin+rand()/(REAL)RAND_MAX*(zmax-zmin); map v0; const REAL ax=-4.*log(2.)/(dx*dx); const REAL ay=-4.*log(2.)/(dy*dy); const REAL az=-4.*log(2.)/(dz*dz); REAL ux,uy,uz,n=0; while(n<1) { ux=REAL(rand()-RAND_MAX/2); uy=REAL(rand()-RAND_MAX/2); uz=REAL(rand()-RAND_MAX/2); n=sqrt(ux*ux+uy*uy+uz*uz); } ux=ux/n;uy=uy/n;uz=uz/n; if(rand()%2==0) for(set::iterator at=mpMolecule->mvMDFullAtomGroup.begin();at!=mpMolecule->mvMDFullAtomGroup.end();++at) v0[*at]=XYZ(ux*exp(ax*((*at)->GetX()-xc)*((*at)->GetX()-xc)), uy*exp(ay*((*at)->GetY()-yc)*((*at)->GetY()-yc)), uz*exp(az*((*at)->GetZ()-zc)*((*at)->GetZ()-zc))); else for(set::iterator at=mpMolecule->mvMDFullAtomGroup.begin();at!=mpMolecule->mvMDFullAtomGroup.end();++at) v0[*at]=XYZ(((*at)->GetX()-xc)*ux*exp(ax*((*at)->GetX()-xc)*((*at)->GetX()-xc)), ((*at)->GetY()-yc)*uy*exp(ay*((*at)->GetY()-yc)*((*at)->GetY()-yc)), ((*at)->GetZ()-zc)*uz*exp(az*((*at)->GetZ()-zc)*((*at)->GetZ()-zc))); #else map v0; // Use one atom for the center of the impulsion, 'push' atoms depending on distance & connectivity table for(set::iterator at=mpMolecule->mvMDFullAtomGroup.begin();at!=mpMolecule->mvMDFullAtomGroup.end();++at) v0[*at]=XYZ(0,0,0); map pushedAtoms; unsigned long idx=rand()%v0.size(); set::iterator at0=mpMolecule->mvMDFullAtomGroup.begin(); for(unsigned int i=0;iGetX(); const REAL yc=(*at0)->GetY(); const REAL zc=(*at0)->GetZ(); ExpandAtomGroupRecursive(*at0,*pConnect,pushedAtoms,3); REAL ux,uy,uz,n=0; while(n<1) { ux=REAL(rand()-RAND_MAX/2); uy=REAL(rand()-RAND_MAX/2); uz=REAL(rand()-RAND_MAX/2); n=sqrt(ux*ux+uy*uy+uz*uz); } ux=ux/n;uy=uy/n;uz=uz/n; const REAL a=-4.*log(2.)/(2*2);//FWHM=2 Angstroems if(rand()%2==0) for(map::iterator at=pushedAtoms.begin() ;at!=pushedAtoms.end();++at) v0[at->first]=XYZ(ux*exp(a*(at->first->GetX()-xc)*(at->first->GetX()-xc)), uy*exp(a*(at->first->GetY()-yc)*(at->first->GetY()-yc)), uz*exp(a*(at->first->GetZ()-zc)*(at->first->GetZ()-zc))); else for(map::iterator at=pushedAtoms.begin() ;at!=pushedAtoms.end();++at) v0[at->first]=XYZ((at->first->GetX()-xc)*ux*exp(a*(at->first->GetX()-xc)*(at->first->GetX()-xc)), (at->first->GetY()-yc)*uy*exp(a*(at->first->GetY()-yc)*(at->first->GetY()-yc)), (at->first->GetZ()-zc)*uz*exp(a*(at->first->GetZ()-zc)*(at->first->GetZ()-zc))); #endif const REAL nrj0=40*( mpMolecule->GetBondList().size() +mpMolecule->GetBondAngleList().size() +mpMolecule->GetDihedralAngleList().size()); map > vr; mpMolecule->MolecularDynamicsEvolve(v0, 200,0.004, mpMolecule->GetBondList(), mpMolecule->GetBondAngleList(), mpMolecule->GetDihedralAngleList(), vr,nrj0); // Display wxMilliSleep(1);// Slow down display for simple structures if((chrono.seconds()-dt0)>0.05) {mpMolecule->GetCrystal().UpdateDisplay();dt0=chrono.seconds();} } return NULL; }; virtual void OnExit() { cout <BuildFlipGroup(); dlgProgress.Update(0,_T("Build Ring List")) ; mpMolecule->BuildRingList(); dlgProgress.Update(1,_T("Build Stretch Modes: Bond Length")) ; mpMolecule->BuildStretchModeBondLength(); dlgProgress.Update(2,_T("Build Stretch Modes: Bond Angle")) ; mpMolecule->BuildStretchModeBondAngle(); dlgProgress.Update(3,_T("Build Stretch Modes: Torsion")) ; mpMolecule->BuildStretchModeTorsion(); //mpMolecule->BuildStretchModeTwist(); dlgProgress.Update(4,_T("Build Stretch Modes: Optimize Rotation Amplitudes")) ; mpMolecule->TuneGlobalOptimRotationAmplitude(); dlgProgress.Update(5,_T("Build Stretch Modes Groups")) ; mpMolecule->BuildStretchModeGroups(); dlgProgress.Update(6,_T("Build MD Atom Groups")) ; mpMolecule->BuildMDAtomGroups(); } MoleculeMDTestThread *pTest = new MoleculeMDTestThread(*mpMolecule,30); if(pTest->Create() != wxTHREAD_NO_ERROR) wxLogError(_T("Can't create test optimization thread")); else pTest->Run(); VFN_DEBUG_EXIT("WXMolecule::OnMenuMDTest()",6) } static const long ID_MOLECULE_ROTATE_BOND_GO =WXCRYST_ID(); static const long ID_MOLECULE_ROTATE_BOND_ATOMS=WXCRYST_ID(); class WXMoleculeRotation:public wxWindow { public: WXMoleculeRotation(wxWindow *parent, Molecule &mol): wxWindow(parent,-1),mBondListClock(mol.GetBondListClock()),mpMol(&mol) { VFN_DEBUG_ENTRY("WXMoleculeRotation::WXMoleculeRotation()",10) this->SetFont(wxFont(8,wxTELETYPE,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL)); wxArrayString choices; for(vector::const_iterator pos=mol.GetBondList().begin();pos!=mol.GetBondList().end();++pos) choices.Add(wxString::FromAscii((*pos)->GetName().c_str())); wxBoxSizer* pSizer=new wxBoxSizer(wxHORIZONTAL); wxBoxSizer* pSizer1=new wxBoxSizer(wxVERTICAL); pSizer1->Add(new wxStaticText(this,-1,_T("Select bond:")),0,wxALIGN_CENTER); mpBond= new wxChoice(this,ID_MOLECULE_ROTATE_BOND_ATOMS,wxDefaultPosition,wxDefaultSize,choices); mpBond->SetSelection(0); pSizer1->Add(mpBond,0,wxALIGN_CENTER); pSizer->Add(pSizer1,0,wxALIGN_CENTER); wxBoxSizer* pSizer2=new wxBoxSizer(wxVERTICAL); pSizer2->Add(new wxStaticText(this,-1,_T("Atoms to rotate:")),0,wxALIGN_CENTER); mpRotatedAtoms= new wxListBox(this,-1,wxDefaultPosition,wxSize(150,60)); pSizer2->Add(mpRotatedAtoms,0,wxALIGN_CENTER); pSizer->Add(pSizer2,0,wxALIGN_CENTER); wxBoxSizer* pSizer3=new wxBoxSizer(wxVERTICAL); pSizer3->Add(new wxStaticText(this,-1,_T("Amplitude:")),0,wxALIGN_CENTER); mpAngle=new wxTextCtrl(this,-1,_T("10"), wxDefaultPosition, wxDefaultSize, 0, wxTextValidator(wxFILTER_NUMERIC)); pSizer3->Add(mpAngle,0,wxALIGN_CENTER); pSizer->Add(pSizer3,0,wxALIGN_CENTER); wxButton *pButtonRotate=new wxButton(this,ID_MOLECULE_ROTATE_BOND_GO,_T("Rotate !")); pSizer->Add(pButtonRotate,0,wxALIGN_CENTER); this->SetSizer(pSizer); this->SetAutoLayout(true); pSizer->SetSizeHints(this); pSizer->SetSizeHints(parent); this->Layout(); wxCommandEvent ev(wxEVT_COMMAND_CHOICE_SELECTED,ID_MOLECULE_ROTATE_BOND_ATOMS); wxPostEvent(this,ev); VFN_DEBUG_EXIT("WXMoleculeRotation::WXMoleculeRotation()",10) } void OnRotate(wxCommandEvent &event) { if(mBondListClockGetBondListClock()) { cout<<" The bond list has changed !"<GetParent()->Destroy(); return; } VFN_DEBUG_MESSAGE("WXMoleculeRotation::OnRotate()",10) WXCrystValidateAllUserInput(); unsigned int bond=mpBond->GetSelection(); unsigned int choice=mpRotatedAtoms->GetSelection(); double angle; mpAngle->GetValue().ToDouble(&angle); mpMol->RotateAtomGroup(mpMol->GetBondList()[bond]->GetAtom1(), mpMol->GetBondList()[bond]->GetAtom2(), mvpRotatedAtoms[choice], angle*DEG2RAD, true); mpMol->GetCrystal().UpdateDisplay(); } void OnSelectBond(wxCommandEvent &event) { if(mBondListClockGetBondListClock()) { cout<<" The bond list has changed !"<GetParent()->Destroy(); return; } VFN_DEBUG_MESSAGE("WXMoleculeRotation::OnSelectBond()",10) WXCrystValidateAllUserInput(); const unsigned int choice=mpBond->GetSelection(); MolAtom *pAt1=&(mpMol->GetBondList()[choice]->GetAtom1()); MolAtom *pAt2=&(mpMol->GetBondList()[choice]->GetAtom2()); mpMol->BuildConnectivityTable(); mvpRotatedAtoms.clear(); mvpRotatedAtoms.resize(2); mvpRotatedAtoms[0].insert(pAt1); ExpandAtomGroupRecursive(pAt2,mpMol->GetConnectivityTable(),mvpRotatedAtoms[0]); mvpRotatedAtoms[1].insert(pAt2); ExpandAtomGroupRecursive(pAt1,mpMol->GetConnectivityTable(),mvpRotatedAtoms[1]); wxArrayString choices; set::const_iterator pos=mvpRotatedAtoms[0].begin(); wxString choice1(wxString::FromAscii((*pos++)->GetName().c_str())); for(;pos!=mvpRotatedAtoms[0].end();++pos) choice1 +=_T("-")+wxString::FromAscii((*pos)->GetName().c_str()); choices.Add(choice1); pos=mvpRotatedAtoms[1].begin(); wxString choice2(wxString::FromAscii((*pos++)->GetName().c_str())); for(;pos!=mvpRotatedAtoms[1].end();++pos) choice2 +=_T("-")+wxString::FromAscii((*pos)->GetName().c_str()); choices.Add(choice2); mpRotatedAtoms->Set(choices); mpRotatedAtoms->SetSelection(0); } private: /// Record the last time the bond list was changed const RefinableObjClock& mBondListClock; Molecule *mpMol; wxChoice *mpBond; wxListBox *mpRotatedAtoms; vector > mvpRotatedAtoms; wxTextCtrl *mpAngle; DECLARE_EVENT_TABLE() }; BEGIN_EVENT_TABLE(WXMoleculeRotation,wxWindow) EVT_BUTTON(ID_MOLECULE_ROTATE_BOND_GO, WXMoleculeRotation::OnRotate) EVT_CHOICE(ID_MOLECULE_ROTATE_BOND_ATOMS, WXMoleculeRotation::OnSelectBond) END_EVENT_TABLE() static const long ID_MOLECULE_ROTATE_DIHED_GO =WXCRYST_ID(); static const long ID_MOLECULE_ROTATE_DIHED_ATOMS=WXCRYST_ID(); class WXMoleculeRotationDihed:public wxWindow { public: WXMoleculeRotationDihed(wxWindow *parent, Molecule &mol): wxWindow(parent,-1),mBondListClock(mol.GetBondListClock()),mpMol(&mol) { VFN_DEBUG_ENTRY("WXMoleculeRotationDihed::WXMoleculeRotationDihed()",10) this->SetFont(wxFont(8,wxTELETYPE,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL)); wxArrayString choices; // Use existing angle restraints to generate dihedral angles for(vector::const_iterator pos=mol.GetBondAngleList().begin();pos!=mol.GetBondAngleList().end();++pos) { MolAtom *pAt1=&((*pos)->GetAtom1()); MolAtom *pAt2=&((*pos)->GetAtom2()); MolAtom *pAt3=&((*pos)->GetAtom3()); const set *pConn=&(mpMol->GetConnectivityTable().find(pAt3)->second); for(set::const_iterator neigh=pConn->begin();neigh!=pConn->end();++neigh) { if( (*neigh==pAt1) || (*neigh==pAt2) ) continue; mvDihed.push_back(MolDihedralAngle(*pAt1,*pAt2,*pAt3,**neigh,0,.001,.001,*mpMol)); choices.Add(wxString::FromAscii(mvDihed.back().GetName().c_str())); } } wxBoxSizer* pSizer=new wxBoxSizer(wxHORIZONTAL); wxBoxSizer* pSizer1=new wxBoxSizer(wxVERTICAL); pSizer1->Add(new wxStaticText(this,-1,_T("Dihedral Angle:")),0,wxALIGN_CENTER); mpDihed= new wxChoice(this,ID_MOLECULE_ROTATE_DIHED_ATOMS,wxDefaultPosition,wxDefaultSize,choices); mpDihed->SetSelection(0); pSizer1->Add(mpDihed,0,wxALIGN_CENTER); pSizer->Add(pSizer1,0,wxALIGN_CENTER); wxBoxSizer* pSizer2=new wxBoxSizer(wxVERTICAL); pSizer2->Add(new wxStaticText(this,-1,_T("Atoms to rotate:")),0,wxALIGN_CENTER); mpRotatedAtoms= new wxListBox(this,-1,wxDefaultPosition,wxSize(150,60)); pSizer2->Add(mpRotatedAtoms,0,wxALIGN_CENTER); pSizer->Add(pSizer2,0,wxALIGN_CENTER); wxBoxSizer* pSizer3=new wxBoxSizer(wxVERTICAL); pSizer3->Add(new wxStaticText(this,-1,_T("Angle:")),0,wxALIGN_CENTER); mpAngle=new wxTextCtrl(this,-1,_T("10"), wxDefaultPosition, wxDefaultSize, 0, wxTextValidator(wxFILTER_NUMERIC)); pSizer3->Add(mpAngle,0,wxALIGN_CENTER); pSizer->Add(pSizer3,0,wxALIGN_CENTER); wxButton *pButtonRotate=new wxButton(this,ID_MOLECULE_ROTATE_DIHED_GO,_T("Set angle !")); pSizer->Add(pButtonRotate,0,wxALIGN_CENTER); this->SetSizer(pSizer); this->SetAutoLayout(true); pSizer->SetSizeHints(this); pSizer->SetSizeHints(parent); this->Layout(); wxCommandEvent ev(wxEVT_COMMAND_CHOICE_SELECTED,ID_MOLECULE_ROTATE_DIHED_ATOMS); wxPostEvent(this,ev); VFN_DEBUG_EXIT("WXMoleculeRotationDihed::WXMoleculeRotationDihed()",10) } void OnRotate(wxCommandEvent &event) { if(mBondListClockGetBondListClock()) { cout<<" The bond list has changed !"<GetParent()->Destroy(); return; } VFN_DEBUG_MESSAGE("WXMoleculeRotationDihed::OnRotate()",10) WXCrystValidateAllUserInput(); MolDihedralAngle *pDihed=&mvDihed[mpDihed->GetSelection()]; unsigned int choice=mpRotatedAtoms->GetSelection(); double angle; mpAngle->GetValue().ToDouble(&angle); angle*=DEG2RAD; angle-=pDihed->GetAngle(); if(mvpRotatedAtoms[choice].find(&(pDihed->GetAtom1()))!=mvpRotatedAtoms[choice].end()) angle*=-1; mpMol->RotateAtomGroup(pDihed->GetAtom2(), pDihed->GetAtom3(), mvpRotatedAtoms[choice], angle, true); mpMol->GetCrystal().UpdateDisplay(); } void OnSelectDihed(wxCommandEvent &event) { if(mBondListClockGetBondListClock()) { cout<<" The bond list has changed !"<GetParent()->Destroy(); return; } VFN_DEBUG_MESSAGE("WXMoleculeRotationDihed::OnSelectBond()",10) WXCrystValidateAllUserInput(); MolDihedralAngle *pDihed=&mvDihed[mpDihed->GetSelection()]; MolAtom *pAt1=&(pDihed->GetAtom1()); MolAtom *pAt2=&(pDihed->GetAtom2()); MolAtom *pAt3=&(pDihed->GetAtom3()); MolAtom *pAt4=&(pDihed->GetAtom4()); mpMol->BuildConnectivityTable(); mvpRotatedAtoms.clear(); mvpRotatedAtoms.resize(2); mvpRotatedAtoms[0].insert(pAt1); mvpRotatedAtoms[0].insert(pAt2); ExpandAtomGroupRecursive(pAt3,mpMol->GetConnectivityTable(),mvpRotatedAtoms[0]); mvpRotatedAtoms[0].erase(pAt1); mvpRotatedAtoms[0].erase(pAt2); mvpRotatedAtoms[1].insert(pAt4); mvpRotatedAtoms[1].insert(pAt3); ExpandAtomGroupRecursive(pAt2,mpMol->GetConnectivityTable(),mvpRotatedAtoms[1]); mvpRotatedAtoms[1].erase(pAt4); mvpRotatedAtoms[1].erase(pAt3); wxArrayString choices; set::const_iterator pos=mvpRotatedAtoms[0].begin(); wxString choice1(wxString::FromAscii((*pos++)->GetName().c_str())); for(;pos!=mvpRotatedAtoms[0].end();++pos) choice1 +=_T("-")+wxString::FromAscii((*pos)->GetName().c_str()); choices.Add(choice1); pos=mvpRotatedAtoms[1].begin(); wxString choice2(wxString::FromAscii((*pos++)->GetName().c_str())); for(;pos!=mvpRotatedAtoms[1].end();++pos) choice2 +=_T("-")+wxString::FromAscii((*pos)->GetName().c_str()); choices.Add(choice2); mpRotatedAtoms->Set(choices); mpRotatedAtoms->SetSelection(0); mpAngle->SetValue(wxString::Format(_T("%6.2f"),pDihed->GetAngle()*RAD2DEG)); } private: /// Record the last time the bond list was changed const RefinableObjClock& mBondListClock; Molecule *mpMol; vector mvDihed; wxChoice *mpDihed; wxListBox *mpRotatedAtoms; vector > mvpRotatedAtoms; wxTextCtrl *mpAngle; DECLARE_EVENT_TABLE() }; BEGIN_EVENT_TABLE(WXMoleculeRotationDihed,wxWindow) EVT_BUTTON(ID_MOLECULE_ROTATE_DIHED_GO, WXMoleculeRotationDihed::OnRotate) EVT_CHOICE(ID_MOLECULE_ROTATE_DIHED_ATOMS, WXMoleculeRotationDihed::OnSelectDihed) END_EVENT_TABLE() void WXMolecule::OnMenuRotate(wxCommandEvent &event) { VFN_DEBUG_ENTRY("WXMolecule::OnMenuRotate()",10) WXCrystValidateAllUserInput(); if(event.GetId()==ID_MOLECULE_MENU_GEOMETRY_ROTATE_BOND) { #ifdef __WXGTK__ wxFrame *frame= new wxMiniFrame(this,-1,_T("Rotate around bond"),wxDefaultPosition, wxDefaultSize,wxCLOSE_BOX|wxSTAY_ON_TOP|wxCAPTION); #else wxFrame *frame= new wxFrame(this,-1,_T("Rotate around bond"),wxDefaultPosition, wxDefaultSize); #endif WXMoleculeRotation * wxMolRot; wxMolRot=new WXMoleculeRotation(frame,*mpMolecule); frame->Show(true); } if(event.GetId()==ID_MOLECULE_MENU_GEOMETRY_ROTATE_DIHED) { #ifdef __WXGTK__ wxFrame *frame= new wxMiniFrame(this,-1,_T("Change dihedral angle"),wxDefaultPosition, wxDefaultSize,wxCLOSE_BOX|wxSTAY_ON_TOP|wxCAPTION); #else wxFrame *frame= new wxFrame(this,-1,_T("Change dihedral angle"),wxDefaultPosition, wxDefaultSize); #endif WXMoleculeRotationDihed * wxMolRot; wxMolRot=new WXMoleculeRotationDihed(frame,*mpMolecule); frame->Show(true); } VFN_DEBUG_EXIT("WXMolecule::OnMenuRotate()",10) } void WXMolecule::OnMenuSetLimits(wxCommandEvent &event) { } void WXMolecule::CrystUpdate(const bool uui,const bool lock) { VFN_DEBUG_ENTRY("WXMolecule::CrystUpdate()",6) if(lock) mMutex.Lock(); if(false==mpMolecule->IsBeingRefined()) { //Remove any atom, bond, bond angle or dihedral angle that could have been removed { unsigned long i=0; for(list::iterator pos=mvpAtom.begin();pos!=mvpAtom.end();) { if(i>=mpMolecule->GetAtomList().size()) { pos=mvpAtom.erase(pos); mpAtomWin->DeleteRows(i); } else { if(pos->mpAtom!=mpMolecule->GetAtomList()[i]) { pos=mvpAtom.erase(pos); mpAtomWin->DeleteRows(i); } else { ++pos; ++i; } } } } if(0!=mpBondWin) { unsigned long i=0; for(list::iterator pos=mvpBond.begin();pos!=mvpBond.end();) { if(i>=mpMolecule->GetBondList().size()) { pos=mvpBond.erase(pos); mpBondWin->DeleteRows(i); } else { if(pos->mpBond!=mpMolecule->GetBondList()[i]) { pos=mvpBond.erase(pos); mpBondWin->DeleteRows(i); } else { ++pos; ++i; } } } } if(0!=mpAngleWin) { unsigned long i=0; for(list::iterator pos=mvpBondAngle.begin();pos!=mvpBondAngle.end();) { if(i>=mpMolecule->GetBondAngleList().size()) { pos=mvpBondAngle.erase(pos); mpAngleWin->DeleteRows(i); } else { if(pos->mpBondAngle!=mpMolecule->GetBondAngleList()[i]) { pos=mvpBondAngle.erase(pos); mpAngleWin->DeleteRows(i); } else { ++pos; ++i; } } } } if(0!=mpDihedralAngleWin) { unsigned long i=0; for(list::iterator pos=mvpDihedralAngle.begin();pos!=mvpDihedralAngle.end();) { if(i>=mpMolecule->GetDihedralAngleList().size()) { pos=mvpDihedralAngle.erase(pos); mpDihedralAngleWin->DeleteRows(i); } else { if(pos->mpDihedralAngle!=mpMolecule->GetDihedralAngleList()[i]) { pos=mvpDihedralAngle.erase(pos); mpDihedralAngleWin->DeleteRows(i); } else { ++pos; ++i; } } } } if(0!=mpRigidGroupWin) { unsigned long i=0; for(list::iterator pos=mvpRigidGroup.begin();pos!=mvpRigidGroup.end();) { if(i>=mpMolecule->GetRigidGroupList().size()) { pos=mvpRigidGroup.erase(pos); mpRigidGroupWin->DeleteRows(i); } else { if(pos->mpGroup!=mpMolecule->GetRigidGroupList()[i]) { pos=mvpRigidGroup.erase(pos); mpRigidGroupWin->DeleteRows(i); } else { ++pos; ++i; } } } } if(0!=mpNonFlipAtomWin) { if(mpNonFlipAtomWin->GetNumberRows()>0) mpNonFlipAtomWin->DeleteRows(0, mpNonFlipAtomWin->GetNumberRows(), true); } //Add any atom, bond, bond angle or dihedral angle that could have been added { bool needLayout=false; for(unsigned long i=mvpAtom.size();iGetAtomList().size();++i) { VFN_DEBUG_MESSAGE("WXMolecule::CrystUpdate():Atom not found",5) mpAtomWin->AppendRows(); mvpAtom.push_back(CellAtom()); mvpAtom.back().mpAtom=mpMolecule->GetAtomList()[i]; needLayout=true; } if(needLayout) { //mpAtomWin->Layout(); //mpAtomWin->SetScrollRate(20,20); mpAtomWin->FitInside(); //mpAtomWin->EnableScrolling(true,true); } } if(0!=mpBondWin) { for(unsigned long i=mvpBond.size();iGetBondList().size();++i) { VFN_DEBUG_MESSAGE("WXMolecule::CrystUpdate():Bond not found",5) mpBondWin->AppendRows(); mvpBond.push_back(CellBond()); mvpBond.back().mpBond=mpMolecule->GetBondList()[i]; } } if(0!=mpAngleWin) { for(unsigned long i=mvpBondAngle.size();iGetBondAngleList().size();++i) { VFN_DEBUG_MESSAGE("WXMolecule::CrystUpdate():Bond Angle not found",5) mpAngleWin->AppendRows(); mvpBondAngle.push_back(CellBondAngle()); mvpBondAngle.back().mpBondAngle=mpMolecule->GetBondAngleList()[i]; } } if(0!=mpDihedralAngleWin) { for(unsigned long i=mvpDihedralAngle.size();iGetDihedralAngleList().size();++i) { VFN_DEBUG_MESSAGE("WXMolecule::CrystUpdate():Dihedral Angle not found",5) mpDihedralAngleWin->AppendRows(); mvpDihedralAngle.push_back(CellDihedralAngle()); mvpDihedralAngle.back().mpDihedralAngle=mpMolecule->GetDihedralAngleList()[i]; } } if(0!=mpRigidGroupWin) { for(unsigned long i=mvpRigidGroup.size();iGetRigidGroupList().size();++i) { VFN_DEBUG_MESSAGE("WXMolecule::CrystUpdate():Rigid Group not found",5) mpRigidGroupWin->AppendRows(); mvpRigidGroup.push_back(CellRigidGroup()); mvpRigidGroup.back().mpGroup=mpMolecule->GetRigidGroupList()[i]; } // Update list of atoms, if necessary for(list::iterator pos=mvpRigidGroup.begin();pos!=mvpRigidGroup.end();++pos) { if(*(pos->mpGroup) != pos->mGroupCopy) { pos->mGroupCopy=*(pos->mpGroup); pos->mNeedUpdateUI=true; } } } if(0!=mpNonFlipAtomWin) { vector v = mpMolecule->GetAtomList(); unsigned int i=0; for(std::vector::const_iterator pos=mpMolecule->GetAtomList().begin();pos!=mpMolecule->GetAtomList().end();++pos) { if((*pos)->IsNonFlipAtom()) { mpNonFlipAtomWin->AppendRows(1, true); mpNonFlipAtomWin->SetCellValue(i, 0, (*pos)->GetName()); i++; } } } } // Update values { for(list::iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos) { const string name=pos->mpAtom->GetName(); const ScatteringPower* pow=&(pos->mpAtom->GetScatteringPower()); const REAL x=pos->mpAtom->X(); const REAL y=pos->mpAtom->Y(); const REAL z=pos->mpAtom->Z(); const REAL occ=pos->mpAtom->GetOccupancy(); if( (name !=pos->mName) ||(pow !=pos->mpScatteringPower) ||(x !=pos->mX) ||(y !=pos->mY) ||(z !=pos->mZ) ||(occ !=pos->mOcc)) { pos->mName =name; pos->mpScatteringPower =pow; pos->mX =x; pos->mY =y; pos->mZ =z; pos->mOcc =occ; pos->mNeedUpdateUI=true; } } } if(0!=mpBondWin) { for(list::iterator pos=mvpBond.begin();pos!=mvpBond.end();++pos) { const string atom1=pos->mpBond->GetAtom1().GetName(); const string atom2=pos->mpBond->GetAtom2().GetName(); const REAL length =pos->mpBond->GetLength(); const REAL length0 =pos->mpBond->GetLength0(); const REAL sigma =pos->mpBond->GetLengthSigma(); const REAL delta =pos->mpBond->GetLengthDelta(); if( (atom1 !=pos->mAtom1) ||(atom2 !=pos->mAtom2) ||(length !=pos->mLength) ||(length0!=pos->mLength0) ||(sigma !=pos->mSigma) ||(delta !=pos->mDelta)) { VFN_DEBUG_MESSAGE("WXMolecule::CrystUpdate():"<mAtom1 =atom1; pos->mAtom2 =atom2; pos->mLength =length; pos->mLength0=length0; pos->mSigma =sigma; pos->mDelta =delta; pos->mNeedUpdateUI=true; } } } if(0!=mpAngleWin) { for(list::iterator pos=mvpBondAngle.begin();pos!=mvpBondAngle.end();++pos) { const string atom1=pos->mpBondAngle->GetAtom1().GetName(); const string atom2=pos->mpBondAngle->GetAtom2().GetName(); const string atom3=pos->mpBondAngle->GetAtom3().GetName(); const REAL angle =pos->mpBondAngle->GetAngle(); const REAL angle0 =pos->mpBondAngle->GetAngle0(); const REAL sigma =pos->mpBondAngle->GetAngleSigma(); const REAL delta =pos->mpBondAngle->GetAngleDelta(); if( (atom1 !=pos->mAtom1) ||(atom2 !=pos->mAtom2) ||(atom3 !=pos->mAtom3) ||(angle !=pos->mAngle) ||(angle0!=pos->mAngle0) ||(sigma !=pos->mSigma) ||(delta !=pos->mDelta)) { pos->mAtom1 =atom1; pos->mAtom2 =atom2; pos->mAtom3 =atom3; pos->mAngle =angle; pos->mAngle0=angle0; pos->mSigma =sigma; pos->mDelta =delta; pos->mNeedUpdateUI=true; } } } if(0!=mpDihedralAngleWin) { for(list::iterator pos=mvpDihedralAngle.begin();pos!=mvpDihedralAngle.end();++pos) { const string atom1=pos->mpDihedralAngle->GetAtom1().GetName(); const string atom2=pos->mpDihedralAngle->GetAtom2().GetName(); const string atom3=pos->mpDihedralAngle->GetAtom3().GetName(); const string atom4=pos->mpDihedralAngle->GetAtom4().GetName(); const REAL angle =pos->mpDihedralAngle->GetAngle(); const REAL angle0 =pos->mpDihedralAngle->GetAngle0(); const REAL sigma =pos->mpDihedralAngle->GetAngleSigma(); const REAL delta =pos->mpDihedralAngle->GetAngleDelta(); if( (atom1 !=pos->mAtom1) ||(atom2 !=pos->mAtom2) ||(atom3 !=pos->mAtom3) ||(atom4 !=pos->mAtom4) ||(angle !=pos->mAngle) ||(angle0!=pos->mAngle0) ||(sigma !=pos->mSigma) ||(delta !=pos->mDelta)) { pos->mAtom1 =atom1; pos->mAtom2 =atom2; pos->mAtom3 =atom3; pos->mAtom4 =atom4; pos->mAngle =angle; pos->mAngle0=angle0; pos->mSigma =sigma; pos->mDelta =delta; pos->mNeedUpdateUI=true; } } } if(0!=mpNonFlipAtomWin) { } this->WXRefinableObj::CrystUpdate(uui,false); if(lock) mMutex.Unlock(); VFN_DEBUG_EXIT("WXMolecule::CrystUpdate()",6) } void WXMolecule::OnMenuShowRestraintWindow(wxCommandEvent &event) { if(0!=mpBondWin) return; // Frame with notebook wxFrame *frame= new wxFrame(this,-1,_T("Restraints for: ")+wxString::FromAscii(mpMolecule->GetName().c_str()), wxDefaultPosition,wxSize(800,300)); wxNotebook *notebook = new wxNotebook(frame, -1); // Bond lengths { wxGridCellAttr* cellAttrName = new wxGridCellAttr; cellAttrName->SetRenderer(new wxGridCellStringRenderer); cellAttrName->SetEditor(new wxGridCellTextEditor); wxGridCellAttr* cellAttrFloat = new wxGridCellAttr; cellAttrFloat->SetRenderer(new wxGridCellFloatRenderer(-1,3)); cellAttrFloat->SetEditor(new wxGridCellFloatEditor); wxGridCellAttr* cellAttrFloatReadOnly = new wxGridCellAttr; cellAttrFloatReadOnly->SetRenderer(new wxGridCellFloatRenderer(-1,3)); cellAttrFloatReadOnly->SetEditor(new wxGridCellFloatEditor); cellAttrFloatReadOnly->SetReadOnly(); mpBondWin = new WXMolScrolledWindow(notebook,this,ID_WINDOW_BONDLENGTH); notebook->AddPage(mpBondWin, _T("Bond Lengths"), true); mpBondWin->CreateGrid(0,6); mpBondWin->SetColSize(0,80); mpBondWin->SetColAttr(0,cellAttrName); mpBondWin->SetColAttr(1,cellAttrName->Clone()); mpBondWin->SetColAttr(2,cellAttrFloatReadOnly); mpBondWin->SetColAttr(3,cellAttrFloat); mpBondWin->SetColAttr(4,cellAttrFloat->Clone()); mpBondWin->SetColAttr(5,cellAttrFloat->Clone()); mpBondWin->SetColLabelValue(0,_T("Atom1")); mpBondWin->SetColLabelValue(1,_T("Atom2")); mpBondWin->SetColLabelValue(2,_T("Length")); mpBondWin->SetColLabelValue(3,_T("Restraint")); mpBondWin->SetColLabelValue(4,_T("Sigma")); mpBondWin->SetColLabelValue(5,_T("Delta")); mpBondWin->AutoSizeRows(); } // Bond angles { wxGridCellAttr* cellAttrName = new wxGridCellAttr; cellAttrName->SetRenderer(new wxGridCellStringRenderer); cellAttrName->SetEditor(new wxGridCellTextEditor); wxGridCellAttr* cellAttrFloat = new wxGridCellAttr; cellAttrFloat->SetRenderer(new wxGridCellFloatRenderer(-1,3)); cellAttrFloat->SetEditor(new wxGridCellFloatEditor); wxGridCellAttr* cellAttrFloatReadOnly = new wxGridCellAttr; cellAttrFloatReadOnly->SetRenderer(new wxGridCellFloatRenderer(-1,3)); cellAttrFloatReadOnly->SetEditor(new wxGridCellFloatEditor); cellAttrFloatReadOnly->SetReadOnly(); mpAngleWin = new WXMolScrolledWindow(notebook,this,ID_WINDOW_BONDANGLE); notebook->AddPage(mpAngleWin, _T("Bond Angles"), true); mpAngleWin->CreateGrid(0,7); mpAngleWin->SetColSize(0,80); mpAngleWin->SetColAttr(0,cellAttrName); mpAngleWin->SetColAttr(1,cellAttrName->Clone()); mpAngleWin->SetColAttr(2,cellAttrName->Clone()); mpAngleWin->SetColAttr(3,cellAttrFloatReadOnly); mpAngleWin->SetColAttr(4,cellAttrFloat); mpAngleWin->SetColAttr(5,cellAttrFloat->Clone()); mpAngleWin->SetColAttr(6,cellAttrFloat->Clone()); mpAngleWin->SetColLabelValue(0,_T("Atom1")); mpAngleWin->SetColLabelValue(1,_T("Atom2")); mpAngleWin->SetColLabelValue(2,_T("Atom3")); mpAngleWin->SetColLabelValue(3,_T("Angle")); mpAngleWin->SetColLabelValue(4,_T("Restraint")); mpAngleWin->SetColLabelValue(5,_T("Sigma")); mpAngleWin->SetColLabelValue(6,_T("Delta")); mpAngleWin->AutoSizeRows(); } // Dihedral angles { wxGridCellAttr* cellAttrName = new wxGridCellAttr; cellAttrName->SetRenderer(new wxGridCellStringRenderer); cellAttrName->SetEditor(new wxGridCellTextEditor); wxGridCellAttr* cellAttrFloat = new wxGridCellAttr; cellAttrFloat->SetRenderer(new wxGridCellFloatRenderer(-1,3)); cellAttrFloat->SetEditor(new wxGridCellFloatEditor); wxGridCellAttr* cellAttrFloatReadOnly = new wxGridCellAttr; cellAttrFloatReadOnly->SetRenderer(new wxGridCellFloatRenderer(-1,3)); cellAttrFloatReadOnly->SetEditor(new wxGridCellFloatEditor); cellAttrFloatReadOnly->SetReadOnly(); mpDihedralAngleWin = new WXMolScrolledWindow(notebook,this,ID_WINDOW_DIHEDRALANGLE); notebook->AddPage(mpDihedralAngleWin, _T("Dihedral Angles"), true); mpDihedralAngleWin->CreateGrid(0,8); mpDihedralAngleWin->SetColSize(0,80); mpDihedralAngleWin->SetColAttr(0,cellAttrName); mpDihedralAngleWin->SetColAttr(1,cellAttrName->Clone()); mpDihedralAngleWin->SetColAttr(2,cellAttrName->Clone()); mpDihedralAngleWin->SetColAttr(3,cellAttrName->Clone()); mpDihedralAngleWin->SetColAttr(4,cellAttrFloatReadOnly); mpDihedralAngleWin->SetColAttr(5,cellAttrFloat); mpDihedralAngleWin->SetColAttr(6,cellAttrFloat->Clone()); mpDihedralAngleWin->SetColAttr(7,cellAttrFloat->Clone()); mpDihedralAngleWin->SetColLabelValue(0,_T("Atom1")); mpDihedralAngleWin->SetColLabelValue(1,_T("Atom2")); mpDihedralAngleWin->SetColLabelValue(2,_T("Atom3")); mpDihedralAngleWin->SetColLabelValue(3,_T("Atom4")); mpDihedralAngleWin->SetColLabelValue(4,_T("Angle")); mpDihedralAngleWin->SetColLabelValue(5,_T("Restraint")); mpDihedralAngleWin->SetColLabelValue(6,_T("Sigma")); mpDihedralAngleWin->SetColLabelValue(7,_T("Delta")); mpDihedralAngleWin->AutoSizeRows(); } // Rigid groups { wxGridCellAttr* cellAttrName = new wxGridCellAttr; cellAttrName->SetRenderer(new wxGridCellStringRenderer); cellAttrName->SetEditor(new wxGridCellTextEditor); mpRigidGroupWin = new WXMolScrolledWindow(notebook,this,ID_WINDOW_RIGIDGROUP); notebook->AddPage(mpRigidGroupWin, _T("Rigid Groups"), true); mpRigidGroupWin->CreateGrid(0,1); mpRigidGroupWin->SetColMinimalWidth(0,600); mpRigidGroupWin->SetColSize(0,600); mpRigidGroupWin->SetColAttr(0,cellAttrName); mpRigidGroupWin->SetColLabelValue(0,_T("Atoms in Rigid Group")); //mpRigidGroupWin->ForceRefresh(); //mpRigidGroupWin->AutoSizeRows(); } //non-flip atoms { wxGridCellAttr* cellAttrName = new wxGridCellAttr; cellAttrName->SetReadOnly(); cellAttrName->SetRenderer(new wxGridCellStringRenderer); cellAttrName->SetEditor(new wxGridCellTextEditor); mpNonFlipAtomWin = new WXMolScrolledWindow(notebook,this,ID_WINDOW_NONFLIPATOM); notebook->AddPage(mpNonFlipAtomWin, _T("Optically active atoms"), true); mpNonFlipAtomWin->CreateGrid(0,1); mpNonFlipAtomWin->SetColMinimalWidth(0,600); mpNonFlipAtomWin->SetColSize(0,600); mpNonFlipAtomWin->SetColAttr(0,cellAttrName); mpNonFlipAtomWin->SetColLabelValue(0,_T("Optically active atom")); } notebook->SetSelection(0); this->CrystUpdate(true); frame->Show(true); frame->Layout(); } void WXMolecule::OnMenuRigidfyWithDihedralAngles(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXMolecule::OnMenuRigidfyWithDihedralAngles()",6) WXCrystValidateAllUserInput(); wxString msg; msg.Printf( _T("This will add all possible dihedral angles,\n") _T("in practice making the Molecule rigid\n\n") _T("Are you sure you want to proceed ?") ); wxMessageDialog w(this,msg,_T("Warning !"),wxYES_NO|wxNO_DEFAULT|wxICON_EXCLAMATION); int result=w.ShowModal(); if(wxID_YES==result) mpMolecule->RigidifyWithDihedralAngles(); VFN_DEBUG_EXIT("WXMolecule::OnMenuRigidfyWithDihedralAngles()",6) } void WXMolecule::OnMenuSetDeltaSigma(wxCommandEvent &event) { VFN_DEBUG_ENTRY("WXMolecule::OnMenuSetDeltaSigma()",6) WXCrystValidateAllUserInput(); double sigma=0.01,delta=0.02; { wxString s; s.Printf(_T("%f"),delta); wxString title=_T("Choose 'delta' value"); wxString info; info.Printf(_T("The 'delta' value is the allowed range \n") _T("(without penalty) around the expected value.\n\n") _T("It is by default equal to 0.02, in Angstroems for bond lengths,\n") _T("and in radians for angles (0.02rad = 1.15deg)\n\n") _T("DO NOT TRY TO CHANGE THE DEFAULT VALUE\n") _T("UNLESS YOU REALLY KNOW WHAT YOU ARE DOING\n") _T("Fox has been optimized with the default values...") ); wxTextEntryDialog dialog(this,info,title,s,wxOK|wxCANCEL); dialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=dialog.ShowModal()) { VFN_DEBUG_EXIT("WXMolecule::OnMenuSetDeltaSigma():Canceled",6) return; } dialog.GetValue().ToDouble(&delta); } { wxString s; s.Printf(_T("%f"),sigma); wxString title=_T("Choose 'sigma' value"); wxString info; info.Printf(_T("The 'sigma' value is used to compute \n") _T("penalty)around the expected value\n\n") _T("It is by default equal to 0.01, in Angstroems for bond angles,\n") _T("and in radians for angles (0.01rad = 0.57deg)\n\n") _T("DO NOT TRY TO CHANGE THE DEFAULT VALUE\n") _T("UNLESS YOU REALLY KNOW WHAT YOU ARE DOING\n") _T("Fox has been optimized with the default values...") ); wxTextEntryDialog dialog(this,info,title.c_str(),s,wxOK|wxCANCEL); dialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=dialog.ShowModal()) { VFN_DEBUG_EXIT("WXMolecule::OnMenuSetDeltaSigma():Canceled",6) return; } dialog.GetValue().ToDouble(&sigma); } for(vector::iterator pos=mpMolecule->GetBondList().begin(); pos != mpMolecule->GetBondList().end();++pos) { (*pos)->SetLengthDelta(delta); (*pos)->SetLengthSigma(sigma); } for(vector::iterator pos=mpMolecule->GetBondAngleList().begin(); pos != mpMolecule->GetBondAngleList().end();++pos) { (*pos)->SetAngleDelta(delta*DEG2RAD); (*pos)->SetAngleSigma(sigma*DEG2RAD); } for(vector::iterator pos=mpMolecule->GetDihedralAngleList().begin(); pos != mpMolecule->GetDihedralAngleList().end();++pos) { //(*pos)->AngleDelta()=delta; //(*pos)->AngleSigma()=sigma; } mpMolecule->GetBondListClock().Click(); this->CrystUpdate(true); VFN_DEBUG_EXIT("WXMolecule::OnMenuSetDeltaSigma()",6) } void WXMolecule::OnChangeCenterAtom(wxCommandEvent &event) { WXCrystValidateAllUserInput(); int choice; MolAtom *const at=WXDialogChooseFromVector(mpMolecule->GetAtomList(), (wxWindow*)this,"Choose a new Atom",choice); if(0==at) return; mpMolecule->SetCenterAtom(*at); } void WXMolecule::NotifyDeleteListWin(WXMolScrolledWindow *win) { VFN_DEBUG_ENTRY("WXMolecule::NotifyDeleteListWin()",6) if(win==mpBondWin) { VFN_DEBUG_MESSAGE("WXMolecule::NotifyDeleteListWin(): Bond List window",5) mpBondWin=0; mvpBond.clear(); } if(win==mpAngleWin) { VFN_DEBUG_MESSAGE("WXMolecule::NotifyDeleteListWin(): Angle List window",5) mpAngleWin=0; mvpBondAngle.clear(); } if(win==mpDihedralAngleWin) { VFN_DEBUG_MESSAGE("WXMolecule::NotifyDeleteListWin(): Dihedral Angle List window",5) mpDihedralAngleWin=0; mvpDihedralAngle.clear(); } if(win==mpRigidGroupWin) { VFN_DEBUG_MESSAGE("WXMolecule::NotifyDeleteListWin(): Dihedral Angle List window",5) mpRigidGroupWin=0; mvpRigidGroup.clear(); } if(win==mpNonFlipAtomWin) { VFN_DEBUG_MESSAGE("WXMolecule::NotifyDeleteListWin(): non-flip atom list window",5) mpNonFlipAtomWin=0; } VFN_DEBUG_EXIT("WXMolecule::NotifyDeleteListWin()",6) } void WXMolecule::UpdateUI(const bool lock) { if(lock) mMutex.Lock(); VFN_DEBUG_ENTRY("WXMolecule::UpdateUI()",5) { unsigned long i=0; for(list::iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos) { if(pos->mNeedUpdateUI==true) { mIsSelfUpdating=true; mpAtomWin->SetCellValue(i, 0, wxString::FromAscii(pos->mName.c_str())); mpAtomWin->SetCellValue(i, 1, wxString::FromAscii(pos->mpScatteringPower->GetName().c_str())); wxString tmp; tmp.Printf(_T("%.3f"),pos->mX); mpAtomWin->SetCellValue(i, 2, tmp); tmp.Printf(_T("%.3f"),pos->mY); mpAtomWin->SetCellValue(i, 3, tmp); tmp.Printf(_T("%.3f"),pos->mZ); mpAtomWin->SetCellValue(i, 4, tmp); tmp.Printf(_T("%.3f"),pos->mOcc); mpAtomWin->SetCellValue(i, 5, tmp); mIsSelfUpdating=false; } ++i; } } if(0!=mpBondWin) { unsigned long i=0; for(list::iterator pos=mvpBond.begin();pos!=mvpBond.end();++pos) { if(pos->mNeedUpdateUI==true) { mIsSelfUpdating=true; mpBondWin->SetCellValue(i, 0, wxString::FromAscii(pos->mAtom1.c_str())); mpBondWin->SetCellValue(i, 1, wxString::FromAscii(pos->mAtom2.c_str())); wxString tmp; tmp.Printf(_T("%f"),pos->mLength); mpBondWin->SetCellValue(i, 2, tmp); tmp.Printf(_T("%f"),pos->mLength0); mpBondWin->SetCellValue(i, 3, tmp); tmp.Printf(_T("%f"),pos->mSigma); mpBondWin->SetCellValue(i, 4, tmp); tmp.Printf(_T("%f"),pos->mDelta); mpBondWin->SetCellValue(i, 5, tmp); mIsSelfUpdating=false; } ++i; } } if(0!=mpAngleWin) { unsigned long i=0; for(list::iterator pos=mvpBondAngle.begin();pos!=mvpBondAngle.end();++pos) { if(pos->mNeedUpdateUI==true) { mIsSelfUpdating=true; mpAngleWin->SetCellValue(i, 0, wxString::FromAscii(pos->mAtom1.c_str())); mpAngleWin->SetCellValue(i, 1, wxString::FromAscii(pos->mAtom2.c_str())); mpAngleWin->SetCellValue(i, 2, wxString::FromAscii(pos->mAtom3.c_str())); wxString tmp; tmp.Printf(_T("%f"),pos->mAngle*RAD2DEG); mpAngleWin->SetCellValue(i, 3, tmp); tmp.Printf(_T("%f"),pos->mAngle0*RAD2DEG); mpAngleWin->SetCellValue(i, 4, tmp); tmp.Printf(_T("%f"),pos->mSigma*RAD2DEG); mpAngleWin->SetCellValue(i, 5, tmp); tmp.Printf(_T("%f"),pos->mDelta*RAD2DEG); mpAngleWin->SetCellValue(i, 6, tmp); mIsSelfUpdating=false; } ++i; } } if(0!=mpDihedralAngleWin) { unsigned long i=0; for(list::iterator pos=mvpDihedralAngle.begin();pos!=mvpDihedralAngle.end();++pos) { if(pos->mNeedUpdateUI==true) { mIsSelfUpdating=true; mpDihedralAngleWin->SetCellValue(i, 0, wxString::FromAscii(pos->mAtom1.c_str())); mpDihedralAngleWin->SetCellValue(i, 1, wxString::FromAscii(pos->mAtom2.c_str())); mpDihedralAngleWin->SetCellValue(i, 2, wxString::FromAscii(pos->mAtom3.c_str())); mpDihedralAngleWin->SetCellValue(i, 3, wxString::FromAscii(pos->mAtom4.c_str())); wxString tmp; tmp.Printf(_T("%f"),pos->mAngle*RAD2DEG); mpDihedralAngleWin->SetCellValue(i, 4, tmp); tmp.Printf(_T("%f"),pos->mAngle0*RAD2DEG); mpDihedralAngleWin->SetCellValue(i, 5, tmp); tmp.Printf(_T("%f"),pos->mSigma*RAD2DEG); mpDihedralAngleWin->SetCellValue(i, 6, tmp); tmp.Printf(_T("%f"),pos->mDelta*RAD2DEG); mpDihedralAngleWin->SetCellValue(i, 7, tmp); mIsSelfUpdating=false; } ++i; } } if(0!=mpRigidGroupWin) { unsigned long i=0; for(list::iterator pos=mvpRigidGroup.begin();pos!=mvpRigidGroup.end();++pos) { if(pos->mNeedUpdateUI==true) { mIsSelfUpdating=true; mpRigidGroupWin->SetCellValue(i, 0, wxString::FromAscii(pos->mpGroup->GetName().c_str())); mIsSelfUpdating=false; } ++i; } } if(0!=mpNonFlipAtomWin) { //for(unsigned long i=0;i< // mpNonFlipAtomWin->SetCellValue(v[i]->GetName(), i, 1); } if(mpMolecule->GetCenterAtom()!=0) mpFieldCenterAtom->SetValue(mpMolecule->GetCenterAtom()->GetName()); else mpFieldCenterAtom->SetValue("No atom !"); //if(mpMolecule->GetOption(3).GetChoice()==0) mpFieldCenterAtom->Enable(false); //else mpFieldCenterAtom->Enable(true); if(lock) mMutex.Unlock(); this->WXRefinableObj::UpdateUI(lock); VFN_DEBUG_EXIT("WXMolecule::UpdateUI()",5) } bool WXMolecule::Enable(bool e) { if(0!=mpAtomWin) mpAtomWin ->Enable(e); if(0!=mpBondWin) mpBondWin ->Enable(e); if(0!=mpAngleWin) mpAngleWin ->Enable(e); if(0!=mpDihedralAngleWin)mpDihedralAngleWin->Enable(e); if(0!=mpRigidGroupWin) mpRigidGroupWin ->Enable(e); return this->::wxWindow::Enable(e); } } //namespace objcryst-2022.1/ObjCryst/wxCryst/wxMolecule.h000066400000000000000000000223061430515525000211610ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2007 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _VFN_WX_MOLECULE_H_ #define _VFN_WX_MOLECULE_H_ #include "wx/grid.h" #include "ObjCryst/wxCryst/wxScatterer.h" #include "ObjCryst/ObjCryst/Molecule.h" namespace ObjCryst { class WXMolecule; // Scrolled window for bonds, bond angles and dihedral angles class WXMolScrolledWindow:public wxGrid { public: WXMolScrolledWindow(wxWindow* parent, WXMolecule* pWXMol,long id=-1); virtual ~WXMolScrolledWindow(); private: /// The WXMolecule window which created this window, and who should be told /// if it is destroyed. WXMolecule* mpWXMolecule; }; /// wx class for MolAtom objects class WXMolAtom:public WXCrystObjBasic { public: WXMolAtom(wxWindow *parent, MolAtom*); virtual ~WXMolAtom(); virtual void CrystUpdate(const bool updateUI=false,const bool mutexlock=false); virtual void UpdateUI(const bool mutexlock=false); void OnChangeScattPow(wxCommandEvent &); private: MolAtom *mpMolAtom; wxBoxSizer *mpSizer; WXCrystObjBasicList mList; WXFieldString *mpFieldName; WXFieldChoice* mpFieldScattPower; DECLARE_EVENT_TABLE() }; /// wx class for MolBond objects class WXMolBond:public WXCrystObjBasic { public: WXMolBond(wxWindow *parent, MolBond*); virtual ~WXMolBond(); virtual void CrystUpdate(const bool updateUI=false,const bool mutexlock=false); virtual void UpdateUI(const bool mutexlock=false); void OnChangeAtom(wxCommandEvent &); /// Toggle the 'free' status of the bond. void OnToggleFree(wxCommandEvent & WXUNUSED(event)); private: MolBond *mpMolBond; wxBoxSizer *mpSizer; WXCrystObjBasicList mList; WXFieldChoice* mpFieldAtom1; WXFieldChoice* mpFieldAtom2; wxCheckBox *mpButtonFree; /// The current value REAL mValue; DECLARE_EVENT_TABLE() }; /// wx class for MolBondAngle objects class WXMolBondAngle:public WXCrystObjBasic { public: WXMolBondAngle(wxWindow *parent, MolBondAngle*); virtual ~WXMolBondAngle(); virtual void CrystUpdate(const bool updateUI=false,const bool mutexlock=false); virtual void UpdateUI(const bool mutexlock=false); void OnChangeAtom(wxCommandEvent &); private: MolBondAngle *mpMolBondAngle; wxBoxSizer *mpSizer; WXCrystObjBasicList mList; WXFieldChoice* mpFieldAtom1; WXFieldChoice* mpFieldAtom2; WXFieldChoice* mpFieldAtom3; /// The current value REAL mValue; DECLARE_EVENT_TABLE() }; /// wx class for MolDihedralAngle objects class WXMolDihedralAngle:public WXCrystObjBasic { public: WXMolDihedralAngle(wxWindow *parent, MolDihedralAngle*); virtual ~WXMolDihedralAngle(); virtual void CrystUpdate(const bool updateUI=false,const bool mutexlock=false); virtual void UpdateUI(const bool mutexlock=false); void OnChangeAtom(wxCommandEvent &); private: MolDihedralAngle *mpMolDihedralAngle; wxBoxSizer *mpSizer; WXCrystObjBasicList mList; WXFieldChoice* mpFieldAtom1; WXFieldChoice* mpFieldAtom2; WXFieldChoice* mpFieldAtom3; WXFieldChoice* mpFieldAtom4; /// The current value REAL mValue; DECLARE_EVENT_TABLE() }; /// wxCryst class for Molecule objects class WXMolecule: public WXScatterer { public: WXMolecule(wxWindow *parent, Molecule*); virtual ~WXMolecule(); void OnMenuOptimizeConformation(wxCommandEvent & WXUNUSED(event)); void OnMenuPrintRestraintStatus(wxCommandEvent & WXUNUSED(event)); void OnMenuExportRestraints(wxCommandEvent & WXUNUSED(event)); void OnMenuAddAtom(wxCommandEvent & WXUNUSED(event)); void OnMenuAddBond(wxCommandEvent & WXUNUSED(event)); void OnMenuAddAngle(wxCommandEvent & WXUNUSED(event)); void OnMenuAddDihedralAngle(wxCommandEvent & WXUNUSED(event)); void OnMenuAddRigidGroup(wxCommandEvent & WXUNUSED(event)); void OnMenuAddNonFlipAtom(wxCommandEvent & WXUNUSED(event)); void OnMenuRigidfyWithDihedralAngles(wxCommandEvent & WXUNUSED(event)); void OnMenuRemoveAtom(wxCommandEvent & WXUNUSED(event)); void OnMenuRemoveBond(wxCommandEvent & WXUNUSED(event)); void OnMenuRemoveAngle(wxCommandEvent & WXUNUSED(event)); void OnMenuRemoveDihedralAngle(wxCommandEvent & WXUNUSED(event)); void OnMenuRemoveNonFlipAtom(wxCommandEvent & WXUNUSED(event)); void OnMenuRemoveRigidGroup(wxCommandEvent & WXUNUSED(event)); void OnMenuSetLimits(wxCommandEvent &event); void OnMenuShowRestraintWindow(wxCommandEvent &event); void OnMenuSetDeltaSigma(wxCommandEvent &event); void OnChangeCenterAtom(wxCommandEvent &event); void OnEditGridAtom(wxGridEvent &e); void OnEditGridBondLength(wxGridEvent &e); void OnEditGridBondAngle(wxGridEvent &e); void OnEditGridDihedralAngle(wxGridEvent &e); void OnEditGridRigidGroup(wxGridEvent &e); void OnMenuExport2ZMatrix(wxCommandEvent &event); void OnMenuTest(wxCommandEvent &event); void OnMenuMDTest(wxCommandEvent &event); void OnMenuRotate(wxCommandEvent &event); /// Notify that either the bond, bond angle or dihedral angle list window has /// been destroyed void NotifyDeleteListWin(WXMolScrolledWindow *win); virtual void CrystUpdate(const bool updateUI=false,const bool mutexlock=false); virtual void UpdateUI(const bool mutexlock=false); virtual bool Enable(bool enable=true); private: Molecule* mpMolecule; WXMolScrolledWindow* mpAtomWin; WXMolScrolledWindow* mpBondWin; WXMolScrolledWindow* mpAngleWin; WXMolScrolledWindow* mpDihedralAngleWin; WXMolScrolledWindow* mpRigidGroupWin; WXMolScrolledWindow* mpNonFlipAtomWin; /// Structure to store the Atom parameters struct CellAtom { CellAtom(); MolAtom* mpAtom; std::string mName; const ScatteringPower* mpScatteringPower; REAL mX,mY,mZ,mOcc; /// True if we need to update the displayed values bool mNeedUpdateUI; }; /** Displayed list of atoms */ std::list mvpAtom; /// Structure to store the bond current values struct CellBond { CellBond(); MolBond* mpBond; std::string mAtom1; std::string mAtom2; REAL mLength; REAL mLength0; REAL mSigma; REAL mDelta; /// True if we need to update the displayed values bool mNeedUpdateUI; }; /** Displayed list of bonds, in the order they appear */ std::list mvpBond; /// Structure to store the bond angles current values struct CellBondAngle { CellBondAngle(); MolBondAngle* mpBondAngle; std::string mAtom1; std::string mAtom2; std::string mAtom3; REAL mAngle; REAL mAngle0; REAL mSigma; REAL mDelta; /// True if we need to update the displayed values bool mNeedUpdateUI; }; /** Displayed list of bond angle */ std::list mvpBondAngle; /// Structure to store the dihedral angles current values struct CellDihedralAngle { CellDihedralAngle(); MolDihedralAngle* mpDihedralAngle; std::string mAtom1; std::string mAtom2; std::string mAtom3; std::string mAtom4; REAL mAngle; REAL mAngle0; REAL mSigma; REAL mDelta; /// True if we need to update the displayed values bool mNeedUpdateUI; }; /** Displayed list of Dihedral angles */ std::list mvpDihedralAngle; struct CellRigidGroup { CellRigidGroup(); /// Rigid group in the Molecule RigidGroup *mpGroup; /// Copy of the set of atoms, as it was last displayed RigidGroup mGroupCopy; /// True if we need to update the displayed values bool mNeedUpdateUI; }; /** Displayed list of Dihedral angles */ std::list mvpRigidGroup; /// Flag to indicate whether we are updating values in the wxGrid data. /// (enabled in wxMolecule::UpdateUI()). bool mIsSelfUpdating; /// Center atom WXFieldChoice* mpFieldCenterAtom; DECLARE_EVENT_TABLE() }; } //namespace #endif //_VFN_WX_MOLECULE_H_ objcryst-2022.1/ObjCryst/wxCryst/wxMultiGraph.cpp000066400000000000000000000372701430515525000220310ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2005- Vincent Favre-Nicolin vincefn@users.sourceforge.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include // wx headers, with or without precompilation #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "wx/dcbuffer.h" #include "wx/gdicmn.h" #include "ObjCryst/ObjCryst/General.h" #include "ObjCryst/wxCryst/wxMultiGraph.h" #include "ObjCryst/wxCryst/wxCryst.h" using namespace std; namespace ObjCryst { static const char* swxColourNameList[]={ "BLACK", "BLUE", "RED", "GREEN", "BROWN", "CYAN", "ORANGE", "YELLOW", "MAGENTA", "MAROON", "GOLD", "GREY", "PINK", "SALMON", "PURPLE", "DARK GREY", "CORAL", "AQUAMARINE", "VIOLET", "BLUE VIOLET", "CADET BLUE", "CORNFLOWER BLUE", "DARK GREEN", "DARK OLIVE GREEN", "DARK ORCHID", "DARK SLATE BLUE", "DARK SLATE GREY DARK TURQUOISE", "DIM GREY", "FIREBRICK", "FOREST GREEN", "GOLDENROD", "GREEN YELLOW", "INDIAN RED", "KHAKI", "LIGHT BLUE", "LIGHT GREY", "LIGHT STEEL BLUE", "LIME GREEN", "MEDIUM AQUAMARINE", "MEDIUM BLUE", "MEDIUM FOREST GREEN", "MEDIUM GOLDENROD", "MEDIUM ORCHID", "MEDIUM SEA GREEN", "MEDIUM SLATE BLUE", "MEDIUM SPRING GREEN", "MEDIUM TURQUOISE", "MEDIUM VIOLET RED", "MIDNIGHT BLUE", "NAVY", "ORANGE RED", "ORCHID", "PALE GREEN", "PLUM", "SEA GREEN", "SIENNA", "SKY BLUE", "SLATE BLUE", "SPRING GREEN", "STEEL BLUE", "TAN", "THISTLE", "TURQUOISE", "VIOLET RED", "WHEAT", //"WHITE", "YELLOW GREEN."}; //////////////////////////////////////////////////////////////////////// // // WXMultiGraph // //////////////////////////////////////////////////////////////////////// static const long ID_UPDATEUI= WXCRYST_ID(); static const long ID_MENU_AUTOSCALE= WXCRYST_ID(); BEGIN_EVENT_TABLE(WXMultiGraph, wxWindow) EVT_PAINT( WXMultiGraph::OnPaint) EVT_MOUSE_EVENTS( WXMultiGraph::OnMouse) EVT_CHAR( WXMultiGraph::OnKeyDown) EVT_MOUSEWHEEL( WXMultiGraph::OnMouseWheel) EVT_UPDATE_UI(ID_UPDATEUI, WXMultiGraph::OnUpdateUI) EVT_SIZE( WXMultiGraph::OnSize) END_EVENT_TABLE() WXMultiGraph::WXMultiGraph(wxFrame *frame): wxWindow(frame,-1,wxPoint(-1,-1),wxSize(-1,-1)), mMinX(0.0),mMaxX(1.0),mMinY(0.0),mMaxY(1.0), mLeft(40),mRight(10),mTop(10),mBottom(25), mIsDragging(false),mpParentFrame(frame) { #ifdef VFN_CRYST_MUTEX cout <<"new CrystMutex("<<&mMutexData<<")for WXMultiGraph:"<Append(ID_MENU_AUTOSCALE, _T("&AutoScale")); //mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_TOGGLELABEL, "&Hide Labels"); } WXMultiGraph::~WXMultiGraph() { VFN_DEBUG_MESSAGE("WXMultiGraph::~WXMultiGraph():",4) delete mpPopUpMenu; #ifdef VFN_CRYST_MUTEX cout <<"Deleting CrystMutex("<<&mMutexData<<")for WXMultiGraph:"<=0;id--) if(mvData.end()==mvData.find(id)) break; mvData[id].name=name; mvData[id].xmin=0.0; mvData[id].xmax=-1.0; mvData[id].ymin=0.0; mvData[id].ymax=-1.0; return id; } void WXMultiGraph::SetGraphData (const unsigned long id,const std::valarray &vx, const std::valarray &vy) { bool rescale=false; mMutexData.Lock(); if(mvData[id].xmin>mvData[id].xmax)rescale=true;// A new graph has been added mvData[id].vx.resize(vx.size()); mvData[id].vy.resize(vx.size()); mvData[id].vx=vx; mvData[id].vy=vy; if(vx.size()!=0) { mvData[id].xmin=mvData[id].vx.min(); mvData[id].xmax=mvData[id].vx.max(); mvData[id].ymin=mvData[id].vy.min(); mvData[id].ymax=mvData[id].vy.max(); VFN_DEBUG_MESSAGE("WXMultiGraph::SetGraphData():"<AutoScale(-1); } else mMutexData.Unlock(); } void WXMultiGraph::DeleteGraph(const unsigned long id) { mvData.erase(id); } void WXMultiGraph::OnPaint(wxPaintEvent &event) { wxMutexLocker mlock(mMutexData); if(mvData.size()<1) return; VFN_DEBUG_ENTRY("WXMultiGraph::OnPaint()",4) wxBufferedPaintDC dc(this); this->PrepareDC(dc); mpParentFrame->PrepareDC(dc); dc.DestroyClippingRegion(); dc.SetBackground(wxBrush(_T("white"), wxSOLID)); dc.Clear(); wxString fontInfo; #ifdef __WIN32__ dc.SetFont(*wxNORMAL_FONT); #else dc.SetFont(*wxSMALL_FONT); #endif // Get Window Size wxCoord width,height; this->GetSize(&width, &height); // Draw Axis VFN_DEBUG_MESSAGE("WXMultiGraph::OnPaint():Axis",3) { dc.SetPen(*wxBLACK_PEN); dc.SetTextForeground(*wxBLACK); int nbTick=5;//approx. wxCoord tmpW,tmpH; float xs,ys; // X & Y margins. float yStep,xStep,dx,dy; dx=mMaxX-mMinX; dy=mMaxY-mMinY; if(dx<1e-6)dx=1e-6; if(dy<1e-6)dy=1e-6; yStep=pow((float)10,(float)floor(log10(dy/nbTick))); yStep *= floor((dy/yStep+0.1)/nbTick); xStep=pow((float)10,(float)floor(log10(dx/nbTick))); xStep *= floor((dx/xStep+0.1)/nbTick); mLeft=0; for(float y=yStep*ceil(mMinY/yStep);ymLeft) mLeft=tmpW+3; } fontInfo.Printf(_T("%g"),xStep); dc.GetTextExtent(fontInfo, &tmpW, &tmpH); mBottom=tmpH*3/2+3; //Y axis dc.DrawLine(mLeft,height-mBottom,mLeft,mTop); VFN_DEBUG_MESSAGE("WXMultiGraph::OnPaint():AxisStep="<Data2Screen(xs,ys); VFN_DEBUG_MESSAGE("WXMultiGraph::OnPaint():Axis:"<Data2Screen(xs,ys); dc.DrawLine(wxCoord(xs),wxCoord(ys-3),wxCoord(xs),wxCoord(ys+3)); fontInfo.Printf(_T("%g"),x); dc.GetTextExtent(fontInfo, &tmpW, &tmpH); dc.DrawText(fontInfo,wxCoord(xs-tmpW/2),wxCoord(ys+tmpH/2)); } // Axis labels; dc.GetTextExtent(mYLabel, &tmpW, &tmpH); dc.DrawText(mYLabel,wxCoord(0),wxCoord(0)); xs=xStep*ceil(mMinX/xStep)+(nbTick-1.5)*xStep; ys=mMinY; this->Data2Screen(xs,ys); dc.GetTextExtent(mXLabel, &tmpW, &tmpH); dc.DrawText(mXLabel,wxCoord(xs-tmpW/2),wxCoord(ys+tmpH/2+3)); } // Draw data map::const_iterator pos; long ix=-1,ixdrawn=-1; for(pos=mvData.begin();pos!=mvData.end();++pos) { ix++; VFN_DEBUG_MESSAGE("WXMultiGraph::OnPaint():Data#"<second.vx.size()<1)||(pos->second.vx.size()!=pos->second.vy.size())) continue; ixdrawn++; dc.SetPen(wxPen(wxTheColourDatabase->Find(wxString::FromAscii(swxColourNameList[ix])),1,wxSOLID)); float x1,y1,x2,y2; x2=pos->second.vx[0]; y2=pos->second.vy[0]; this->Data2Screen(x2,y2); for(unsigned long i=0;isecond.vx.size();i++) { x1=x2; y1=y2; x2=pos->second.vx[i]; y2=pos->second.vy[i]; this->Data2Screen(x2,y2); if( ((x1>=mLeft)&&(x1<=(width-mRight))&&(y1>=mBottom)&&(y1<=(height-mTop))) ||((x2>=mLeft)&&(x2<=(width-mRight))&&(y2>=mBottom)&&(y2<=(height-mTop)))) dc.DrawLine(wxCoord(x1),wxCoord(y1),wxCoord(x2),wxCoord(y2)); } // Print Name dc.SetTextForeground(wxPen(wxTheColourDatabase->Find(wxString::FromAscii(swxColourNameList[ix])),1,wxSOLID).GetColour()); wxCoord tmpW,tmpH; fontInfo.Printf(wxString::FromAscii(pos->second.name.c_str())); dc.GetTextExtent(fontInfo, &tmpW, &tmpH); dc.DrawText(fontInfo,wxCoord(width-tmpW-2),wxCoord(tmpH*(ixdrawn)+2)); } VFN_DEBUG_EXIT("WXMultiGraph::OnPaint()",4) } void WXMultiGraph::OnMouse(wxMouseEvent &event) { event.Skip();// Make sure the default handler gets the event too if(event.Leaving()) return;// ? wxCoord width,height; this->GetSize(&width, &height); // Write mouse pointer coordinates wxClientDC dc(this); PrepareDC(dc); mpParentFrame->PrepareDC(dc); wxPoint pos=event.GetPosition(); float x= float(dc.DeviceToLogicalX(pos.x)); float y= float(dc.DeviceToLogicalY(pos.y)); if((x>width)||(y>height)) { return; } this->Screen2Data(x,y); wxString str; str.Printf(_T("x=%f ,y=%f"),x,y); mpParentFrame->SetStatusText(str); if(event.RightIsDown()) { this->PopupMenu(mpPopUpMenu, event.GetX(), event.GetY() ); return; } if (event.Dragging() && event.LeftIsDown() && (!mIsDragging)) {//Begin zooming mIsDragging=true; mDragX0=x; mDragY0=y; return; } if(event.LeftUp() && mIsDragging) {//Finished zooming ! mMutexData.Lock(); mIsDragging=false; if(x>mDragX0) { mMinX=mDragX0; mMaxX=x; } else { mMinX=x; mMaxX=mDragX0; } if(y>mDragY0) { mMinY=mDragY0; mMaxY=y; } else { mMinY=y; mMaxY=mDragY0; } if(mMaxX<=mMinX) mMaxX=mMinX+1e-6; if(mMaxY<=mMinY) mMaxY=mMinY+1e-6; mMutexData.Unlock(); this->UpdateDisplay(); return; } if(false==event.Dragging()) mIsDragging=false; if(event.LeftDClick()) {//Reset axis range this->AutoScale(); this->UpdateDisplay(); return; } } void WXMultiGraph::OnMouseWheel(wxMouseEvent &event) { if(event.GetWheelRotation()>=event.GetWheelDelta()) { const REAL range=mMaxX-mMinX; mMaxX += range/8; mMinX += range/8; } if(event.GetWheelRotation()<=(-event.GetWheelDelta())) { const REAL range=mMaxX-mMinX; mMaxX -= range/8; mMinX -= range/8; } this->UpdateDisplay(); } void WXMultiGraph::AutoScale(const long id,const bool xmin,const bool xmax, const bool ymin,const bool ymax) { wxMutexLocker mlock(mMutexData); if(mvData.size()==0) return; std::map::const_iterator pos; if(id<0)pos=mvData.end(); else pos=mvData.find((unsigned long)id); if(pos==mvData.end()) { pos=mvData.begin(); if(xmax) mMaxX=pos->second.xmax; if(xmin) mMinX=pos->second.xmin; if(ymax) mMaxY=pos->second.ymax; if(ymin) mMinY=pos->second.ymin; ++pos; for(;pos!=mvData.end();++pos) { if(xmax) if(mMaxXsecond.xmax) mMaxX=pos->second.xmax; if(xmin) if(mMinX>pos->second.xmin) mMinX=pos->second.xmin; if(ymax) if(mMaxYsecond.ymax) mMaxY=pos->second.ymax; if(ymin) if(mMinY>pos->second.ymin) mMinY=pos->second.ymin; } } else { if(xmax) mMaxX=pos->second.xmax; if(xmin) mMinX=pos->second.xmin; if(ymax) mMaxY=pos->second.ymax; if(ymin) mMinY=pos->second.ymin; } if(mMaxX<=mMinX) mMaxX=mMinX+1e-6; if(mMaxY<=mMinY) mMaxY=mMinY+1e-6; //cout<<"Autoscale to:"<"<"<UpdateDisplay(); event.Skip();// Make sure the default handler gets the event too } void WXMultiGraph::OnUpdateUI(wxUpdateUIEvent &event) { VFN_DEBUG_MESSAGE("WXMultiGraph::OnUpdateUI()",4) this->Refresh(false); event.Skip(); } void WXMultiGraph::OnSize(wxSizeEvent &event) { this->Refresh(false); } void WXMultiGraph::SetXLabel(const wxString &xlabel) { mXLabel=xlabel; } void WXMultiGraph::SetYLabel(const wxString &ylabel) { mYLabel=ylabel; } void WXMultiGraph::UpdateDisplay() { VFN_DEBUG_ENTRY("WXMultiGraph::UpdateDisplay()",4) if(wxThread::IsMain()) this->Refresh(false); else { wxUpdateUIEvent event(ID_UPDATEUI); wxPostEvent(this,event); } VFN_DEBUG_EXIT("WXMultiGraph::UpdateDisplay()",4) } void WXMultiGraph::Screen2Data(float &x,float &y) { wxCoord width,height; this->GetSize(&width, &height); float range=float(width-(mLeft+mRight)); if(range<=0) range=1.0; x=(x-mLeft)/range; x=mMinX+x*(mMaxX-mMinX); range=float(height-(mTop+mBottom)); if(range<=0) range=1.0; y=(height-mBottom-y)/range; y=mMinY+y*(mMaxY-mMinY); } void WXMultiGraph::Data2Screen(float &x,float &y) { VFN_DEBUG_ENTRY("WXMultiGraph::Data2Screen()"<GetSize(&width, &height); float range=float(width-(mLeft+mRight)); x=(x-mMinX)/(mMaxX-mMinX); x=mLeft+x*range; range=float(height-(mTop+mBottom)); y=(y-mMinY)/(mMaxY-mMinY); y=height-mBottom-y*range; VFN_DEBUG_EXIT("WXMultiGraph::Data2Screen()->"< #include #include #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "ObjCryst/wxCryst/wxCryst.h" /* WX Select colour using wxColourDatabase (wxTheColourDatabase All display is normalized to max-min, i.e. each tracked value has its own scale. Zooming is therefore relative to [0.0-1.0] Choose displayed Y values using a wxChoice, for both Y axis The list of values to be displayed can be chosen from a wxListBox */ namespace ObjCryst { class WXMultiGraph:public wxWindow { public: WXMultiGraph(wxFrame *frame); virtual ~WXMultiGraph(); void OnPaint(wxPaintEvent &event); void OnMouse(wxMouseEvent &event); void OnMouseWheel(wxMouseEvent &event); void OnKeyDown(wxKeyEvent &event); /** Add a graph. This returns an ID identifying the graph * */ unsigned long AddGraph(const std::string &name); /** Set data for a given graph. * * The two arrays \b must have the same number of elements */ void SetGraphData(const unsigned long id,const std::valarray &vx, const std::valarray &vy); /** Remove graph. * */ virtual void DeleteGraph(const unsigned long id); /** Auto-scale graph, i.e. bring min& max along both axes to * the min&max of a given graph. However * */ void AutoScale(const long id=-1,const bool xmin=true,const bool xmax=true, const bool ymin=true,const bool ymax=true); void OnUpdateUI(wxUpdateUIEvent &event); void OnSize(wxSizeEvent &event); void SetXLabel(const wxString &xlabel); void SetYLabel(const wxString &ylabel); virtual void UpdateDisplay(); private: /// Convert data to screen (pixel) coordinates void Data2Screen(float &x,float &y); /// Convert screen (pixel) to data coordinates void Screen2Data(float &x,float &y); struct GraphData { std::string name; std::valarray vx; std::valarray vy; float xmin,xmax,ymin,ymax; }; std::map mvData; /// The \e current min & max values along x and y. float mMinX,mMaxX,mMinY,mMaxY; /// The margins in pixels around the graph long mLeft,mRight,mTop,mBottom; /// Pop-up menu wxMenu* mpPopUpMenu; /// Are we within a dragging event ? bool mIsDragging; /// dragging origin (in reduced coordinates) float mDragX0,mDragY0; /// Mutex for the data CrystMutex mMutexData; /// parent frame wxFrame *mpParentFrame; /// X label wxString mXLabel; /// Y label wxString mYLabel; DECLARE_EVENT_TABLE() }; }//namespace #endif objcryst-2022.1/ObjCryst/wxCryst/wxPowderPattern.cpp000066400000000000000000007512631430515525000225600ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include //for stringstream #include #include #include "cctbx/sgtbx/space_group.h" #include // wx headers, with or without precompilation #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "wx/dcbuffer.h" #include "wx/config.h" #include "wx/notebook.h" #include "wx/progdlg.h" #include "wx/filename.h" #include "ObjCryst/wxCryst/wxPowderPattern.h" #include "ObjCryst/wxCryst/wxRadiation.h" #include "ObjCryst/RefinableObj/Simplex.h" #include "ObjCryst/RefinableObj/LSQNumObj.h" #include "ObjCryst/ObjCryst/PowderPatternBackgroundBayesianMinimiser.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" #include "ObjCryst/Quirks/Chronometer.h" //Fixes for Cygwin; where do those stupid macros come from ? Somewhere in wxMSW headers #ifdef max #undef max #endif #ifdef min #undef min #endif #ifdef DrawText #undef DrawText #endif //#define USE_BACKGROUND_MAXLIKE_ERROR namespace ObjCryst { //////////////////////////////////////////////////////////////////////// // // WXRadiation // //////////////////////////////////////////////////////////////////////// BEGIN_EVENT_TABLE(WXRadiation, wxWindow) EVT_UPDATE_UI(ID_CRYST_UPDATEUI, WXRadiation::OnUpdateUI) END_EVENT_TABLE() WXRadiation::WXRadiation(wxWindow *parent, Radiation* rad): WXCrystObjBasic(parent),mpRadiation(rad) { VFN_DEBUG_ENTRY("WXRadiation::WXRadiation()",6) // :TODO: Add a choice for the wavlength type, with 'monochromatic', and a list // of X-Ray tubes. mpSizer=new wxBoxSizer(wxVERTICAL); wxSizer *pSizer1=new wxBoxSizer(wxHORIZONTAL); wxSizer *pSizer2=new wxBoxSizer(wxHORIZONTAL); mpFieldRadType= new WXFieldOption(this,-1,&(mpRadiation->mRadiationType)); pSizer1->Add(mpFieldRadType,0); mList.Add(mpFieldRadType); mpFieldWavelengthType= new WXFieldOption(this,-1,&(mpRadiation->mWavelengthType)); pSizer1->Add(mpFieldWavelengthType,0); mList.Add(mpFieldWavelengthType); WXCrystObjBasic* pFieldWavelength =mpRadiation->GetPar(mpRadiation->mWavelength.data()).WXCreate(this); pSizer1->Add(pFieldWavelength,0); mList.Add(pFieldWavelength); WXFieldPar *polarRate=new WXFieldPar(this,"Linear Polar Rate:",-1, &(mpRadiation->mLinearPolarRate)); pSizer2->Add(polarRate,0,wxALIGN_LEFT); mList.Add(polarRate); WXCrystObjBasic* pFieldXRayTubeDlambda=mpRadiation->GetPar("XRayTubeDeltaLambda").WXCreate(this); pSizer2->Add(pFieldXRayTubeDlambda,0,wxALIGN_LEFT|wxRESERVE_SPACE_EVEN_IF_HIDDEN); mList.Add(pFieldXRayTubeDlambda); WXCrystObjBasic* pFieldXRayTubeAlpha2Alpha1=mpRadiation->GetPar("XRayTubeAlpha2Alpha1Ratio").WXCreate(this); pSizer2->Add(pFieldXRayTubeAlpha2Alpha1,0,wxALIGN_LEFT|wxRESERVE_SPACE_EVEN_IF_HIDDEN); mList.Add(pFieldXRayTubeAlpha2Alpha1); mpSizer->Add(pSizer1,0); mpSizer->Add(pSizer2,0); this->CrystUpdate(true); this->SetSizer(mpSizer); mpSizer->SetSizeHints(this); this->Layout(); VFN_DEBUG_EXIT("WXRadiation::WXRadiation()",6) } WXRadiation::~WXRadiation() { mpRadiation->WXNotifyDelete(); } void WXRadiation::CrystUpdate(const bool uui,const bool lock) { if(lock) mMutex.Lock(); mList.CrystUpdate(false,false); if(lock) mMutex.Unlock(); if(uui) { if(true==wxThread::IsMain()) this->UpdateUI(lock); else { wxUpdateUIEvent event(ID_CRYST_UPDATEUI); wxPostEvent(this,event); } } } void WXRadiation::UpdateUI(const bool lock) { mList.UpdateUI(lock); } void WXRadiation::OnUpdateUI(wxUpdateUIEvent& event) { this->UpdateUI(true); event.Skip(); } //////////////////////////////////////// WXProfileFitting ///////////////////// class WXProfileFitting:public wxWindow { public: WXProfileFitting(wxWindow *parent,PowderPattern *pPattern,PowderPatternDiffraction *pDiff=0); ~WXProfileFitting(); /// Start Fitting void OnFit(wxCommandEvent &event); void OnExploreSpacegroups(wxCommandEvent &event); private: PowderPattern *mpPattern; PowderPatternDiffraction *mpDiff; wxCheckListBox *mpFitCheckList; wxTextCtrl *mpLog; wxListBox *mpList; LSQNumObj mLSQ; DECLARE_EVENT_TABLE() }; //////////////////////////////////////////////////////////////////////// // // WXPowderPattern // //////////////////////////////////////////////////////////////////////// static const long ID_POWDER_MENU_COMP_ADDBACKGD_BAYESIAN=WXCRYST_ID(); static const long ID_POWDER_MENU_COMP_ADDBACKGD= WXCRYST_ID(); static const long ID_POWDER_MENU_COMP_ADDCRYST= WXCRYST_ID(); static const long ID_POWDER_MENU_GRAPH= WXCRYST_ID(); static const long ID_POWDER_MENU_SAVETEXT= WXCRYST_ID(); static const long ID_POWDER_MENU_SIMULATE= WXCRYST_ID(); static const long ID_POWDER_MENU_EXPORT= WXCRYST_ID(); static const long ID_POWDER_MENU_EXPORT_FULLPROF= WXCRYST_ID(); static const long ID_POWDER_MENU_IMPORT_FULLPROF= WXCRYST_ID(); static const long ID_POWDER_MENU_IMPORT_PSI_DMC= WXCRYST_ID(); static const long ID_POWDER_MENU_IMPORT_ILL_D1A5= WXCRYST_ID(); static const long ID_POWDER_MENU_IMPORT_XDD= WXCRYST_ID(); static const long ID_POWDER_MENU_IMPORT_CPI= WXCRYST_ID(); static const long ID_POWDER_MENU_IMPORT_FULLPROF4= WXCRYST_ID(); static const long ID_POWDER_MENU_IMPORT_MULTIDETECTORLLBG42=WXCRYST_ID(); static const long ID_POWDER_MENU_IMPORT_2THETAOBSSIGMA= WXCRYST_ID(); static const long ID_POWDER_MENU_IMPORT_2THETAOBS= WXCRYST_ID(); static const long ID_POWDER_MENU_IMPORT_TOFISISXYSIGMA= WXCRYST_ID(); static const long ID_POWDER_MENU_IMPORT_GSAS= WXCRYST_ID(); static const long ID_POWDER_MENU_IMPORT_CIF= WXCRYST_ID(); static const long ID_POWDER_MENU_FITSCALE_R= WXCRYST_ID(); static const long ID_POWDER_MENU_FITSCALE_RW= WXCRYST_ID(); static const long ID_POWDER_MENU_WAVELENGTH= WXCRYST_ID(); static const long ID_POWDER_MENU_WAVELENGTH_XRAY= WXCRYST_ID(); static const long ID_POWDER_MENU_WAVELENGTH_NEUTRON= WXCRYST_ID(); static const long ID_POWDER_MENU_WAVELENGTH_NEUTRON_TOF= WXCRYST_ID(); static const long ID_POWDER_MENU_WAVELENGTH_SET= WXCRYST_ID(); static const long ID_POWDER_MENU_WAVELENGTH_SET_AG= WXCRYST_ID(); static const long ID_POWDER_MENU_WAVELENGTH_SET_MO= WXCRYST_ID(); static const long ID_POWDER_MENU_WAVELENGTH_SET_CU= WXCRYST_ID(); static const long ID_POWDER_MENU_WAVELENGTH_SET_FE= WXCRYST_ID(); static const long ID_POWDER_MENU_WAVELENGTH_SET_CO= WXCRYST_ID(); static const long ID_POWDER_MENU_WAVELENGTH_SET_CR= WXCRYST_ID(); static const long ID_POWDER_MENU_WAVELENGTH_SET_AGA1= WXCRYST_ID(); static const long ID_POWDER_MENU_WAVELENGTH_SET_MOA1= WXCRYST_ID(); static const long ID_POWDER_MENU_WAVELENGTH_SET_CUA1= WXCRYST_ID(); static const long ID_POWDER_MENU_WAVELENGTH_SET_FEA1= WXCRYST_ID(); static const long ID_POWDER_MENU_WAVELENGTH_SET_COA1= WXCRYST_ID(); static const long ID_POWDER_MENU_WAVELENGTH_SET_CRA1= WXCRYST_ID(); static const long ID_POWDER_MENU_ADD_2THETA_EXCLUDE= WXCRYST_ID(); static const long ID_POWDER_MENU_LEBAIL= WXCRYST_ID(); static const long ID_POWDERBACKGROUND_IMPORT= WXCRYST_ID(); static const long ID_POWDERBACKGROUND_OPTIMIZEBAYESIAN= WXCRYST_ID(); static const long ID_POWDERDIFF_CRYSTAL= WXCRYST_ID(); static const long ID_POWDERDIFF_SAVEHKLFCALC= WXCRYST_ID(); static const long ID_POWDER_GRAPH_NEW_PATTERN= WXCRYST_ID(); static const long ID_POWDERTEXTURE_MENU_ADDPHASE= WXCRYST_ID(); static const long ID_POWDERTEXTURE_MENU_DELETEPHASE= WXCRYST_ID(); static const long ID_POWDERPATTERN_MENU_COMPONENTS= WXCRYST_ID(); static const long ID_POWDERPATTERN_MENU_PATTERN= WXCRYST_ID(); static const long ID_POWDERDIFF_PROFILE_DEPV= WXCRYST_ID(); static const long ID_POWDER_GRAPH_WIN= WXCRYST_ID(); BEGIN_EVENT_TABLE(WXPowderPattern, wxWindow) EVT_BUTTON(ID_WXOBJ_COLLAPSE, WXCrystObj::OnToggleCollapse) EVT_MENU(ID_POWDER_MENU_EXPORT_FULLPROF, WXPowderPattern::OnMenuExport) EVT_MENU(ID_REFOBJ_MENU_OBJ_SAVE, WXRefinableObj::OnMenuSave) EVT_MENU(ID_REFOBJ_MENU_OBJ_LOAD, WXRefinableObj::OnMenuLoad) EVT_MENU(ID_REFOBJ_MENU_PAR_FIXALL, WXRefinableObj::OnMenuFixAllPar) EVT_MENU(ID_REFOBJ_MENU_PAR_UNFIXALL, WXRefinableObj::OnMenuUnFixAllPar) EVT_MENU(ID_POWDER_MENU_COMP_ADDBACKGD, WXPowderPattern::OnMenuAddCompBackgd) EVT_MENU(ID_POWDER_MENU_COMP_ADDBACKGD_BAYESIAN, WXPowderPattern::OnMenuAddCompBackgdBayesian) EVT_MENU(ID_POWDER_MENU_COMP_ADDCRYST, WXPowderPattern::OnMenuAddCompCryst) EVT_MENU(ID_POWDER_MENU_SAVETEXT, WXPowderPattern::OnMenuSaveText) EVT_MENU(ID_POWDER_MENU_SIMULATE, WXPowderPattern::OnMenuSimulate) EVT_MENU(ID_POWDER_MENU_IMPORT_FULLPROF, WXPowderPattern::OnMenuImportPattern) EVT_MENU(ID_POWDER_MENU_IMPORT_PSI_DMC, WXPowderPattern::OnMenuImportPattern) EVT_MENU(ID_POWDER_MENU_IMPORT_ILL_D1A5, WXPowderPattern::OnMenuImportPattern) EVT_MENU(ID_POWDER_MENU_IMPORT_XDD, WXPowderPattern::OnMenuImportPattern) EVT_MENU(ID_POWDER_MENU_IMPORT_CPI, WXPowderPattern::OnMenuImportPattern) EVT_MENU(ID_POWDER_MENU_IMPORT_FULLPROF4, WXPowderPattern::OnMenuImportPattern) EVT_MENU(ID_POWDER_MENU_IMPORT_MULTIDETECTORLLBG42,WXPowderPattern::OnMenuImportPattern) EVT_MENU(ID_POWDER_MENU_IMPORT_2THETAOBSSIGMA, WXPowderPattern::OnMenuImportPattern) EVT_MENU(ID_POWDER_MENU_IMPORT_2THETAOBS, WXPowderPattern::OnMenuImportPattern) EVT_MENU(ID_POWDER_MENU_IMPORT_TOFISISXYSIGMA, WXPowderPattern::OnMenuImportPattern) EVT_MENU(ID_POWDER_MENU_IMPORT_GSAS, WXPowderPattern::OnMenuImportPattern) EVT_MENU(ID_POWDER_MENU_IMPORT_CIF, WXPowderPattern::OnMenuImportPattern) EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET, WXPowderPattern::OnMenuSetWavelength) EVT_MENU(ID_POWDER_MENU_WAVELENGTH_XRAY, WXPowderPattern::OnMenuSetWavelength) EVT_MENU(ID_POWDER_MENU_WAVELENGTH_NEUTRON, WXPowderPattern::OnMenuSetWavelength) EVT_MENU(ID_POWDER_MENU_WAVELENGTH_NEUTRON_TOF, WXPowderPattern::OnMenuSetWavelength) EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET_AG, WXPowderPattern::OnMenuSetWavelength) EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET_MO, WXPowderPattern::OnMenuSetWavelength) EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET_CU, WXPowderPattern::OnMenuSetWavelength) EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET_FE, WXPowderPattern::OnMenuSetWavelength) EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET_CO, WXPowderPattern::OnMenuSetWavelength) EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET_CR, WXPowderPattern::OnMenuSetWavelength) EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET_AGA1, WXPowderPattern::OnMenuSetWavelength) EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET_MOA1, WXPowderPattern::OnMenuSetWavelength) EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET_CUA1, WXPowderPattern::OnMenuSetWavelength) EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET_FEA1, WXPowderPattern::OnMenuSetWavelength) EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET_COA1, WXPowderPattern::OnMenuSetWavelength) EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET_CRA1, WXPowderPattern::OnMenuSetWavelength) EVT_MENU(ID_POWDER_MENU_GRAPH, WXPowderPattern::OnMenuShowGraph) EVT_MENU(ID_POWDER_MENU_FITSCALE_R, WXPowderPattern::OnMenuFitScaleForR) EVT_MENU(ID_POWDER_MENU_FITSCALE_RW, WXPowderPattern::OnMenuFitScaleForRw) EVT_MENU(ID_POWDER_MENU_ADD_2THETA_EXCLUDE, WXPowderPattern::OnMenuAddExclude) EVT_MENU(ID_POWDER_MENU_LEBAIL, WXPowderPattern::OnMenuLeBail) EVT_UPDATE_UI(ID_CRYST_UPDATEUI, WXRefinableObj::OnUpdateUI) END_EVENT_TABLE() WXPowderPattern::WXPowderPattern(wxWindow *parent, PowderPattern* pow): WXRefinableObj(parent,pow),mpPowderPattern(pow),mpGraph(0), mChi2(0.0),mGoF(0.0),mRwp(0.0),mRp(0.0) { VFN_DEBUG_MESSAGE("WXPowderPattern::WXPowderPattern()",6) mpWXTitle->SetForegroundColour(wxColour(255,0,0)); mpWXTitle->SetSize(400,-1); // Menu mpMenuBar->AddMenu("Data",ID_REFOBJ_MENU_OBJ); //:TODO: reactivate & test those menus //mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_REFOBJ_MENU_OBJ_SAVE,"Save"); //mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_REFOBJ_MENU_OBJ_LOAD,"Load"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_SAVETEXT, "Save pattern (text)"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_SIMULATE, "Simulation mode (no obs. pattern)"); mpMenuBar->GetMenu(ID_REFOBJ_MENU_OBJ).AppendSeparator(); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_IMPORT_CIF, "Import CIF Powder Data"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_IMPORT_GSAS, "Import GSAS Data(CONS-ESD,CONS6STD,RALF-ALT)"); mpMenuBar->GetMenu(ID_REFOBJ_MENU_OBJ).AppendSeparator(); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_IMPORT_2THETAOBSSIGMA, "Import 2Theta-Obs-Sigma Pattern"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_IMPORT_2THETAOBS, "Import 2Theta-Obs Pattern"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_IMPORT_FULLPROF, "Import Fullprof Pattern"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_IMPORT_FULLPROF4, "Import FullProf format #4"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_IMPORT_XDD, "Import Xdd Pattern"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_IMPORT_CPI, "Import Sietronics CPI Pattern"); mpMenuBar->GetMenu(ID_REFOBJ_MENU_OBJ).AppendSeparator(); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_IMPORT_ILL_D1A5, "Import Neutron ILL(D1A-D1B) Pattern (D1A5)"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_IMPORT_PSI_DMC, "Import PSI(DMC) Pattern"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_IMPORT_MULTIDETECTORLLBG42, "Import Neutron Multi-Detector Format (LLB G42)"); mpMenuBar->GetMenu(ID_REFOBJ_MENU_OBJ).AppendSeparator(); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_IMPORT_TOFISISXYSIGMA, "Import Neutron TOF ISIS X Y Sigma"); mpMenuBar->AddMenu("Export",ID_POWDER_MENU_EXPORT); mpMenuBar->AddMenuItem(ID_POWDER_MENU_EXPORT,ID_POWDER_MENU_EXPORT_FULLPROF, "Export to Fullprof"); mpMenuBar->AddMenu("Parameters",ID_REFOBJ_MENU_PAR); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_FIXALL,"Fix all"); //mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_UNFIXALL,"Unfix all"); mpMenuBar->AddMenu("Phases",ID_POWDERPATTERN_MENU_COMPONENTS); mpMenuBar->AddMenuItem(ID_POWDERPATTERN_MENU_COMPONENTS, ID_POWDER_MENU_COMP_ADDBACKGD_BAYESIAN, "Add Background (Bayesian, automatic)"); mpMenuBar->AddMenuItem(ID_POWDERPATTERN_MENU_COMPONENTS, ID_POWDER_MENU_COMP_ADDBACKGD, "Add user-supplied Background "); mpMenuBar->AddMenuItem(ID_POWDERPATTERN_MENU_COMPONENTS,ID_POWDER_MENU_COMP_ADDCRYST, "Add Crystalline Phase"); mpMenuBar->AddMenu("Radiation",ID_POWDER_MENU_WAVELENGTH); mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH, ID_POWDER_MENU_WAVELENGTH_NEUTRON, "Neutron"); mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH, ID_POWDER_MENU_WAVELENGTH_NEUTRON_TOF, "Neutron Time Of Flight"); mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH, ID_POWDER_MENU_WAVELENGTH_XRAY, "X-Rays"); mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH, ID_POWDER_MENU_WAVELENGTH_SET, "Monochromatic Wavelength"); mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH, ID_POWDER_MENU_WAVELENGTH_SET_AG, "X-Ray Tube Ag Ka12"); mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH, ID_POWDER_MENU_WAVELENGTH_SET_AGA1, "X-Ray Tube Ag Ka1"); mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH, ID_POWDER_MENU_WAVELENGTH_SET_MO, "X-Ray Tube Mo Ka12"); mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH, ID_POWDER_MENU_WAVELENGTH_SET_MOA1, "X-Ray Tube Mo Ka1"); mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH, ID_POWDER_MENU_WAVELENGTH_SET_CU, "X-Ray Tube Cu Ka12"); mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH, ID_POWDER_MENU_WAVELENGTH_SET_CUA1, "X-Ray Tube Cu Ka1"); mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH, ID_POWDER_MENU_WAVELENGTH_SET_FE, "X-Ray Tube Fe Ka12"); mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH, ID_POWDER_MENU_WAVELENGTH_SET_FEA1, "X-Ray Tube Fe Ka1"); mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH, ID_POWDER_MENU_WAVELENGTH_SET_CO, "X-Ray Tube Co Ka12"); mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH, ID_POWDER_MENU_WAVELENGTH_SET_COA1, "X-Ray Tube Co Ka1"); mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH, ID_POWDER_MENU_WAVELENGTH_SET_CR, "X-Ray Tube Cr Ka12"); mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH, ID_POWDER_MENU_WAVELENGTH_SET_CRA1, "X-Ray Tube Cr Ka1"); mpMenuBar->AddMenu("Pattern",ID_POWDERPATTERN_MENU_PATTERN); mpMenuBar->AddMenuItem(ID_POWDERPATTERN_MENU_PATTERN,ID_POWDER_MENU_GRAPH, "Show Graph"); mpMenuBar->AddMenuItem(ID_POWDERPATTERN_MENU_PATTERN,ID_POWDER_MENU_FITSCALE_R, "Fit Scale for R"); mpMenuBar->AddMenuItem(ID_POWDERPATTERN_MENU_PATTERN,ID_POWDER_MENU_FITSCALE_RW, "Fit Scale for Rw"); mpMenuBar->AddMenuItem(ID_POWDERPATTERN_MENU_PATTERN, ID_POWDER_MENU_ADD_2THETA_EXCLUDE, "Add excluded region"); mpMenuBar->GetMenu(ID_POWDERPATTERN_MENU_PATTERN).AppendSeparator(); mpMenuBar->AddMenuItem(ID_POWDERPATTERN_MENU_PATTERN, ID_POWDER_MENU_LEBAIL, "Fit profile + Le Bail extract"); //mpSizer->SetItemMinSize(mpMenuBar, // mpMenuBar->GetSize().GetWidth(), // mpMenuBar->GetSize().GetHeight()); //Radiation mpSizer->Add(mpPowderPattern->mRadiation.WXCreate(this),0); mList.Add(mpPowderPattern->mRadiation.WXGet()); // Correction to 2Theta wxBoxSizer* thetaCorrSizer=new wxBoxSizer(wxHORIZONTAL); WXCrystObjBasic* fieldZero =mpPowderPattern->GetPar(&(mpPowderPattern->mXZero)).WXCreate(this); fieldZero->SetToolTip(_T("Zero shift of peaks\n") _T("2Theta = 2Theta_Bragg + Zero\n")); WXCrystObjBasic* fieldThetaDispl =mpPowderPattern->GetPar(&(mpPowderPattern->m2ThetaDisplacement)).WXCreate(this); fieldThetaDispl->SetToolTip(_T("Peak shift due to sample displacement:\n") _T("2Theta = 2Theta_Bragg + Displacement/cos(Theta)")); WXCrystObjBasic* fieldThetaTransp =mpPowderPattern->GetPar(&(mpPowderPattern->m2ThetaTransparency)).WXCreate(this); fieldThetaTransp->SetToolTip(_T("Zero shift of the peak 2theta positions\n") _T("2Theta = 2Theta_Bragg + Transparency*sin(Theta)")); thetaCorrSizer->Add(fieldZero,0); thetaCorrSizer->Add(fieldThetaDispl,0); thetaCorrSizer->Add(fieldThetaTransp,0); mList.Add(fieldZero); mList.Add(fieldThetaDispl); mList.Add(fieldThetaTransp); mpSizer->Add(thetaCorrSizer); // Time of Flight parameters wxBoxSizer* tofSizer=new wxBoxSizer(wxHORIZONTAL); WXCrystObjBasic* fieldDIFC=mpPowderPattern->GetPar(&(mpPowderPattern->mDIFC)).WXCreate(this); WXCrystObjBasic* fieldDIFA=mpPowderPattern->GetPar(&(mpPowderPattern->mDIFA)).WXCreate(this); fieldDIFA->SetToolTip(_T("Peak position (time, in microseconds):\n") _T("t = DIFA * d_hkl + DIFC * d_hkl^2 + ZERO")); fieldDIFC->SetToolTip(_T("Peak position (time, in microseconds):\n") _T("t = DIFA * d_hkl + DIFC * d_hkl^2 + ZERO")); tofSizer->Add(fieldDIFC,0); tofSizer->Add(fieldDIFA,0); mList.Add(fieldDIFC); mList.Add(fieldDIFA); mpSizer->Add(tofSizer); // Cylindrical absorption correction WXCrystObjBasic* fieldMuR=mpPowderPattern->GetPar(&(mpPowderPattern->mMuR)).WXCreate(this); fieldMuR->SetToolTip(_T("Cylindrical absorption correction parameter (muR)")); mList.Add(fieldMuR); mpSizer->Add(fieldMuR); // Max Sin(theta/Lambda) WXFieldPar *maxSiThOvLa= new WXFieldPar(this,"Max Sin(theta)/lambda:",-1, &(mpPowderPattern->mMaxSinThetaOvLambda)); mpSizer->Add(maxSiThOvLa,0,wxALIGN_LEFT); mList.Add(maxSiThOvLa); maxSiThOvLa->SetToolTip(_T("Maximum sin(theta)/lambda=1/2d\n") _T("For global optimization, the default value of ") _T("0.25 (2A resolution) should be sufficient.\n") _T("Use larger values if necessary (0.4(1.25A), 0.5(1A))") _T("but keep in mind that the number of reflections (and") _T("therefore the computing time) varies as [sin(theta/lambda)]^3...")); // Statistics wxBoxSizer* pStats=new wxBoxSizer(wxHORIZONTAL); WXFieldPar *pWXFieldChi2=new WXFieldPar(this,"Chi^2",-1,&mChi2,140); pStats->Add(pWXFieldChi2 ,0,wxALIGN_CENTER); mList.Add(pWXFieldChi2); pWXFieldChi2->SetToolTip(_T("Chi^2=SUM[(Obs_i-Calc_i)^2/Sigma_i^2]")); dynamic_cast(pWXFieldChi2)->SetFormat(_T("%10.2f")); WXFieldPar *pWXFieldGof=new WXFieldPar(this,"GoF",-1,&mGoF,90); pStats->Add(pWXFieldGof ,0,wxALIGN_CENTER); mList.Add(pWXFieldGof); pWXFieldGof->SetToolTip(_T("GoF=Chi^2/NbPoints")); dynamic_cast(pWXFieldGof)->SetFormat(_T("%8.3f")); WXFieldPar *pWXFieldRwp=new WXFieldPar(this,"Rwp",-1,&mRwp,70); pStats->Add(pWXFieldRwp ,0,wxALIGN_CENTER); mList.Add(pWXFieldRwp); pWXFieldRwp->SetToolTip(_T("Full profile R-factor (weighted)\n") _T("Will use integrated profiles if option is set.")); dynamic_cast(pWXFieldRwp)->SetFormat(_T("%8.4f")); WXFieldPar *pWXFieldRp=new WXFieldPar(this,"Rp",-1,&mRp,70); pStats->Add(pWXFieldRp ,0,wxALIGN_CENTER); mList.Add(pWXFieldRp); pWXFieldRp->SetToolTip(_T("Full profile R-factor (unweighted)\n") _T("Will use integrated profiles if option is set.")); dynamic_cast(pWXFieldRp)->SetFormat(_T("%8.4f")); //pStats->SetSizeHints(this); //pStats->Layout(); mpSizer->Add(pStats); // Components mpWXComponent=mpPowderPattern ->mPowderPatternComponentRegistry.WXCreate(this); mpSizer->Add(mpWXComponent,0,wxALIGN_LEFT); mList.Add(mpWXComponent); VFN_DEBUG_MESSAGE("WXPowderPattern::WXPowderPattern():1",6) this->CrystUpdate(true); { mPowderPatternWasPreviouslyEmpty = true; if(!wxConfigBase::Get()->HasEntry(_T("PowderPattern/BOOL/Automatically open powder pattern graph"))) wxConfigBase::Get()->Write(_T("PowderPattern/BOOL/Automatically open powder pattern graph"), false); else { bool val; wxConfigBase::Get()->Read(_T("PowderPattern/BOOL/Automatically open powder pattern graph"), &val); if(val) { wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,ID_POWDER_MENU_GRAPH); wxPostEvent(this,event); } else { mPowderPatternWasPreviouslyEmpty=false; } } } VFN_DEBUG_MESSAGE("WXPowderPattern::WXPowderPattern():End",6) } void WXPowderPattern::CrystUpdate(const bool uui,const bool lock) { VFN_DEBUG_ENTRY("WXPowderPattern::CrystUpdate()",7) wxWakeUpIdle(); WXCrystValidateAllUserInput(); if(lock) mMutex.Lock(); if(mpPowderPattern->GetNbPoint()<=0) { if(lock) mMutex.Unlock(); this->WXRefinableObj::CrystUpdate(uui,lock); return;// nothing to display yet } else { bool val=false; if(mPowderPatternWasPreviouslyEmpty) { wxConfigBase::Get()->Read(_T("PowderPattern/BOOL/Automatically open powder pattern graph"), &val); } if(mPowderPatternWasPreviouslyEmpty && val) { // We are supposed to automatically open powder pattern graph, but this could not be done // when initializing this window because there were no points. // WXPowderPattern::CrystUpdate() will be called again from WXPowderPattern::OnMenuShowGraph() mPowderPatternWasPreviouslyEmpty = false; wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,ID_POWDER_MENU_GRAPH); wxPostEvent(this,event); if(lock) mMutex.Unlock(); } else { // Will force re-generating reflection list if the wavelength, // or lattice par, or the spacegroup has changed. VFN_DEBUG_MESSAGE("WXPowderPattern::CrystUpdate()",7) mpPowderPattern->Prepare(); VFN_DEBUG_MESSAGE("WXPowderPattern::CrystUpdate()",7) mChi2=mpPowderPattern->GetChi2_Option(); if(mpPowderPattern->mNbPointUsed>0) mGoF=mpPowderPattern->GetChi2()/mpPowderPattern->mNbPointUsed; else mGoF=0; //cout<<"WXPowderPattern::CrystUpdate():"<GetChi2()<<"/"<mNbPointUsed<<"="<GetRw(); mRp=mpPowderPattern->GetR(); if(mpGraph!=0) { CrystVector_REAL tmp; mpPowderPattern->CalcPowderPattern(); tmp=mpPowderPattern->GetPowderPatternVariance(); for(long i=0;iSetPattern( mpPowderPattern->GetPowderPatternX(), mpPowderPattern->GetPowderPatternObs(), mpPowderPattern->GetPowderPatternCalc(), tmp, mpPowderPattern->GetChi2Cumul(1)); } if(lock) mMutex.Unlock(); this->WXRefinableObj::CrystUpdate(uui,lock); } } VFN_DEBUG_EXIT("WXPowderPattern::CrystUpdate()",7) } void WXPowderPattern::OnMenuAddCompBackgd(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_MESSAGE("WXPowderPattern::OnMenuAddCompBackgd()",6) WXCrystValidateAllUserInput(); const unsigned int nb=mpPowderPattern->GetNbPowderPatternComponent(); bool hasBack=false; for(unsigned int i=0;iGetPowderPatternComponent(i).GetClassName()=="PowderPatternBackground") { hasBack=true; break; } if(hasBack) { wxMessageDialog dialog(this,_T("You already have one background !\n") _T(" Are you sure you want to add one ?"), _T("Warning : Duplicate Background !"), wxYES_NO|wxICON_HAND|wxNO_DEFAULT); if(wxID_YES!=dialog.ShowModal()) return; } PowderPatternBackground *backgdData= new PowderPatternBackground; mpPowderPattern->AddPowderPatternComponent(*backgdData); if(mpGraph!=0) mpPowderPattern->Prepare();//else this will be done when opening the graph wxTheApp->GetTopWindow()->Layout(); wxTheApp->GetTopWindow()->SendSizeEvent(); } void WXPowderPattern::OnMenuAddCompBackgdBayesian(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXPowderPattern::OnMenuAddCompBackgdBayesian()",6) WXCrystValidateAllUserInput(); const unsigned int nb=mpPowderPattern->GetNbPowderPatternComponent(); bool hasBack=false; for(unsigned int i=0;iGetPowderPatternComponent(i).GetClassName()=="PowderPatternBackground") { hasBack=true; break; } if(hasBack) { wxMessageDialog dialog(this,_T("You already have one background !\n") _T(" Are you sure you want to add one ?"), _T("Warning : Duplicate Background !"), wxYES_NO|wxICON_HAND|wxNO_DEFAULT); if(wxID_YES!=dialog.ShowModal()) return; } long nbPointSpline=20; wxString mes=_T("Number of Interpolation Points"); wxString s; s.Printf(_T("%ld"),nbPointSpline); wxTextEntryDialog dialog(this,mes,_T("Automatic Bayesian (David-Sivia) Background"), s,wxOK | wxCANCEL); dialog.SetTextValidator(wxTextValidator(wxFILTER_DIGITS)); if(wxID_OK!=dialog.ShowModal()) { VFN_DEBUG_EXIT("WXPowderPattern::OnMenuAddCompBackgdBayesian():Canceled",6) return; } dialog.GetValue().ToLong(&nbPointSpline); if(nbPointSpline<=1)nbPointSpline=2; wxProgressDialog dlgProgress(_T("Automatic Bayesian Background"),_T("Automatic Background: Initializing..."), 4,this,wxPD_AUTO_HIDE|wxPD_ELAPSED_TIME|wxPD_CAN_ABORT|wxPD_APP_MODAL); PowderPatternBackground *pBckgd= new PowderPatternBackground; VFN_DEBUG_MESSAGE("WXPowderPattern::OnMenuAddCompBackgdBayesian()",6) mpPowderPattern->AddPowderPatternComponent(*pBckgd); VFN_DEBUG_MESSAGE("WXPowderPattern::OnMenuAddCompBackgdBayesian()",6) { CrystVector_REAL x(nbPointSpline),backgd(nbPointSpline); const CrystVector_REAL *pObs=&(pBckgd->GetParentPowderPattern().GetPowderPatternObs()); const unsigned long nbPoint=pBckgd->GetParentPowderPattern().GetNbPoint(); const float xmin=pBckgd->GetParentPowderPattern().GetPowderPatternX()(0), xmax=pBckgd->GetParentPowderPattern().GetPowderPatternX()(nbPoint-1); for(int i=0;i xmin, but in the right order (TOF) x(i)=xmin+(xmax-xmin)/(REAL)(nbPointSpline-1)*REAL(i); REAL x1=xmin+(xmax-xmin)/(REAL)(nbPointSpline-1)*REAL(i-.2); REAL x2=xmin+(xmax-xmin)/(REAL)(nbPointSpline-1)*REAL(i+.2); long n1=(long)(pBckgd->GetParentPowderPattern().X2Pixel(x1)); long n2=(long)(pBckgd->GetParentPowderPattern().X2Pixel(x2)); if(n1<0) n1=0; if(n2>(long)nbPoint)n2=nbPoint; backgd(i)=(*pObs)(n1); for(long j=n1;jSetInterpPoints(x,backgd); } if(mpGraph!=0) mpPowderPattern->Prepare();//else this will be done when opening the graph pBckgd->UnFixAllPar(); pBckgd->GetOption(0).SetChoice(0);//linear if(dlgProgress.Update(1,_T("Automatic Background: Optimizing Linear Model..."))==false) return; pBckgd->OptimizeBayesianBackground(); pBckgd->GetOption(0).SetChoice(1);//spline if(dlgProgress.Update(2,_T("Automatic Background: Optimizing Spline Model..."))==false) return; pBckgd->OptimizeBayesianBackground(); pBckgd->FixAllPar(); wxTheApp->GetTopWindow()->Layout(); wxTheApp->GetTopWindow()->SendSizeEvent(); VFN_DEBUG_EXIT("WXPowderPattern::OnMenuAddCompBackgdBayesian()",6) } void WXPowderPattern::OnMenuAddCompCryst(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXPowderPattern::OnMenuAddCompCryst()",10) WXCrystValidateAllUserInput(); PowderPatternDiffraction * diffData=new PowderPatternDiffraction; int choice; Crystal *cryst=dynamic_cast ( WXDialogChooseFromRegistry(gCrystalRegistry,(wxWindow*)this, "Choose a Crystal Structure:",choice)); if(0==cryst) {delete diffData;return;} VFN_DEBUG_MESSAGE("WXPowderPattern::OnMenuAddCompCryst()",10) diffData->SetCrystal(*cryst); VFN_DEBUG_MESSAGE("WXPowderPattern::OnMenuAddCompCryst()",10) mpPowderPattern->AddPowderPatternComponent(*diffData); VFN_DEBUG_MESSAGE("WXPowderPattern::OnMenuAddCompCryst()",10) if(diffData->GetRadiation().GetWavelengthType()==WAVELENGTH_TOF) { VFN_DEBUG_MESSAGE("WXPowderPattern::OnMenuAddCompCryst()",10) //wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,ID_POWDERDIFF_PROFILE_DEPV); //wxPostEvent(diffData->WXGet(),event); ReflectionProfileDoubleExponentialPseudoVoigt *p= new ReflectionProfileDoubleExponentialPseudoVoigt (diffData->GetCrystal()); diffData->SetProfile(p); } VFN_DEBUG_MESSAGE("WXPowderPattern::OnMenuAddCompCryst()",10) if(mpGraph!=0) mpPowderPattern->Prepare();//else this will be done when opening the graph wxTheApp->GetTopWindow()->Layout(); wxTheApp->GetTopWindow()->SendSizeEvent(); this->CrystUpdate(); VFN_DEBUG_EXIT("WXPowderPattern::OnMenuAddCompCryst()",10) } class WXPowderPatternGraphFrame :public wxFrame { public: WXPowderPatternGraphFrame(wxWindow *parent, wxWindowID id, const wxString& title, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_FRAME_STYLE, const wxString& name = wxFrameNameStr) : wxFrame(parent, id, title, pos, size, style, name) {} ~WXPowderPatternGraphFrame() { gvWindowPosition[ID_POWDER_GRAPH_WIN] = make_pair(this->GetScreenPosition(), this->GetSize()); } }; void WXPowderPattern::OnMenuShowGraph(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_MESSAGE("WXPowderPattern::OnMenuShowGraph()"<GetNbPoint()<=0) return; WXCrystValidateAllUserInput(); mpPowderPattern->Prepare(); wxFrame* frame; if(gvWindowPosition.count(ID_POWDER_GRAPH_WIN)) frame = new WXPowderPatternGraphFrame(this, ID_POWDER_GRAPH_WIN, wxString::FromAscii(mpPowderPattern->GetName().c_str()), gvWindowPosition[ID_POWDER_GRAPH_WIN].first, gvWindowPosition[ID_POWDER_GRAPH_WIN].second, wxCLOSE_BOX | wxRESIZE_BORDER | wxCAPTION | wxMINIMIZE_BOX | wxMAXIMIZE_BOX);//wxFRAME_FLOAT_ON_PARENT else frame = new WXPowderPatternGraphFrame(this, ID_POWDER_GRAPH_WIN, wxString::FromAscii(mpPowderPattern->GetName().c_str()), wxDefaultPosition, wxSize(500, 300), wxCLOSE_BOX | wxRESIZE_BORDER | wxCAPTION | wxMINIMIZE_BOX | wxMAXIMIZE_BOX);//wxFRAME_FLOAT_ON_PARENT mpGraph = new WXPowderPatternGraph(frame,this); wxSizer *ps=new wxBoxSizer(wxHORIZONTAL); ps->Add(mpGraph,1,wxEXPAND); frame->SetSizer(ps); frame->SetAutoLayout(true); frame->CreateStatusBar(2); frame->Show(true); frame->Raise(); this->CrystUpdate(true); //frame->SetStatusText(""); } void WXPowderPattern::OnMenuSaveText(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_MESSAGE("WXPowderPattern::OnMenuSaveText()",6) WXCrystValidateAllUserInput(); wxFileDialog save(this,_T("Choose a file"),_T(""),_T(""),_T("*.txt"),wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if(save.ShowModal() != wxID_OK) return; ofstream out(save.GetPath().ToAscii()); if(!out) return;//:TODO: mpPowderPattern->PrintObsCalcData(out); out.close(); } void WXPowderPattern::OnMenuSimulate(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXPowderPattern::OnMenuSimulate()",6) WXCrystValidateAllUserInput(); double min=0.,max=120.; long nbPoints=6000; { wxTextEntryDialog dialog(this,_T("2Theta Min"), _T("Enter minimum 2Theta (degrees)"),_T("5"),wxOK | wxCANCEL); dialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=dialog.ShowModal()) { VFN_DEBUG_EXIT("WXPowderPattern::OnMenuSimulate():Cancelled",6) return; } dialog.GetValue().ToDouble(&min); if(min<1) min=1.0; } { wxTextEntryDialog dialog(this,_T("2Theta Max"), _T("Enter maximum 2Theta (degrees)"),_T("100"),wxOK | wxCANCEL); dialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=dialog.ShowModal()) { VFN_DEBUG_EXIT("WXPowderPattern::OnMenuSimulate():Cancelled",6) return; } dialog.GetValue().ToDouble(&max); } { wxTextEntryDialog dialog(this,_T("Number of points"), _T("Enter the number of points"),_T("1000"),wxOK | wxCANCEL); dialog.SetTextValidator(wxTextValidator(wxFILTER_DIGITS)); if(wxID_OK!=dialog.ShowModal()) { VFN_DEBUG_EXIT("WXPowderPattern::OnMenuSimulate():Cancelled",6) return; } dialog.GetValue().ToLong(&nbPoints); } CrystVector_REAL newObs(nbPoints); mpPowderPattern->SetPowderPatternPar(min*DEG2RAD,(max-min)/(nbPoints-1)*DEG2RAD,nbPoints); newObs=1;//we must not have 0 in case a scale factor is fitted... newObs(0)=0.01;//Avoid having the same value for ALL points for scaling the graph. if(mpPowderPattern->GetNbPowderPatternComponent()>0) { // Use the calculated pattern, for indexing simulation newObs=mpPowderPattern->GetPowderPatternCalc(); // Add some noise ! for(long i=0;iSetPowderPatternObs(newObs); VFN_DEBUG_EXIT("WXPowderPattern::OnMenuSimulate()",6) } void WXPowderPattern::OnMenuImportPattern(wxCommandEvent &event) { VFN_DEBUG_MESSAGE("WXPowderPattern::OnMenuImportPattern()",6) wxFileDialog open(this,_T("Choose a file"),_T(""),_T(""),_T("*.*"),wxFD_OPEN | wxFD_FILE_MUST_EXIST); if(open.ShowModal() != wxID_OK) return; if(event.GetId()==(long)ID_POWDER_MENU_IMPORT_FULLPROF) mpPowderPattern->ImportPowderPatternFullprof(string(open.GetPath().ToAscii())); if(event.GetId()==(long)ID_POWDER_MENU_IMPORT_PSI_DMC) mpPowderPattern->ImportPowderPatternPSI_DMC(string(open.GetPath().ToAscii())); if(event.GetId()==(long)ID_POWDER_MENU_IMPORT_ILL_D1A5) mpPowderPattern->ImportPowderPatternILL_D1A5(string(open.GetPath().ToAscii())); if(event.GetId()==(long)ID_POWDER_MENU_IMPORT_XDD) mpPowderPattern->ImportPowderPatternXdd(string(open.GetPath().ToAscii())); if(event.GetId()==(long)ID_POWDER_MENU_IMPORT_CPI) mpPowderPattern->ImportPowderPatternSietronicsCPI(string(open.GetPath().ToAscii())); if(event.GetId()==(long)ID_POWDER_MENU_IMPORT_FULLPROF4) mpPowderPattern->ImportPowderPatternFullprof4(string(open.GetPath().ToAscii())); if(event.GetId()==(long)ID_POWDER_MENU_IMPORT_MULTIDETECTORLLBG42) mpPowderPattern->ImportPowderPatternMultiDetectorLLBG42(string(open.GetPath().ToAscii())); if(event.GetId()==(long)ID_POWDER_MENU_IMPORT_2THETAOBSSIGMA) mpPowderPattern->ImportPowderPattern2ThetaObsSigma(string(open.GetPath().ToAscii())); if(event.GetId()==(long)ID_POWDER_MENU_IMPORT_2THETAOBS) mpPowderPattern->ImportPowderPattern2ThetaObs(string(open.GetPath().ToAscii())); if(event.GetId()==(long)ID_POWDER_MENU_IMPORT_TOFISISXYSIGMA) mpPowderPattern->ImportPowderPatternTOF_ISIS_XYSigma(string(open.GetPath().ToAscii())); if(event.GetId()==(long)ID_POWDER_MENU_IMPORT_GSAS) mpPowderPattern->ImportPowderPatternGSAS(string(open.GetPath().ToAscii())); if(event.GetId()==(long)ID_POWDER_MENU_IMPORT_CIF) { ifstream fin (open.GetPath().ToAscii()); if(!fin) { throw ObjCrystException("WXPowderPattern::OnMenuImportPattern(): Error opening file for input:"+string(open.GetPath().ToAscii())); } ObjCryst::CIF cif(fin,true,true); mpPowderPattern->ImportPowderPatternCIF(cif); } bool val; wxConfigBase::Get()->Read(_T("PowderPattern/BOOL/Automatically open powder pattern graph"), &val); if(val) { wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,ID_POWDER_MENU_GRAPH); wxPostEvent(this,event); } } void WXPowderPattern::OnMenuFitScaleForR(wxCommandEvent & WXUNUSED(event)) { if(0==mpGraph) return; WXCrystValidateAllUserInput(); mpPowderPattern->FitScaleFactorForR();//FitScaleFactorForIntegratedR this->CrystUpdate(true); } void WXPowderPattern::OnMenuFitScaleForRw(wxCommandEvent & WXUNUSED(event)) { if(0==mpGraph) return; WXCrystValidateAllUserInput(); mpPowderPattern->FitScaleFactorForRw();//FitScaleFactorForIntegratedRw this->CrystUpdate(true); } void WXPowderPattern::OnMenuSetWavelength(wxCommandEvent & event) { WXCrystValidateAllUserInput(); // this looks stupid. In fact, if a user changed the wavelength in the // corresponding field, this is (unfortunately) not applied to the // components automagically. So we need this function to do the job... if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_XRAY) mpPowderPattern->SetRadiationType(RAD_XRAY); if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_NEUTRON) mpPowderPattern->SetRadiationType(RAD_NEUTRON); if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_NEUTRON_TOF) { mpPowderPattern->SetRadiationType(RAD_NEUTRON); mpPowderPattern->GetRadiation().SetWavelengthType(WAVELENGTH_TOF); } if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET) { double lambda; wxTextEntryDialog dialog(this,_T("new Wavelength)"), _T("Enter new Wavelength (Angstroems)"),_T("1"),wxOK | wxCANCEL); dialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=dialog.ShowModal()) { VFN_DEBUG_EXIT("WXPowderPattern))OnMenuSetWavelength())Monochromatic)Cancelled",6) return; } dialog.GetValue().ToDouble(&lambda); mpPowderPattern->SetWavelength(lambda); } if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET_AG) mpPowderPattern->SetWavelength("Ag"); if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET_MO) mpPowderPattern->SetWavelength("Mo"); if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET_CU) mpPowderPattern->SetWavelength("Cu"); if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET_FE) mpPowderPattern->SetWavelength("Fe"); if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET_CO) mpPowderPattern->SetWavelength("Co"); if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET_CR) mpPowderPattern->SetWavelength("Cr"); if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET_AGA1) mpPowderPattern->SetWavelength("AgA1"); if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET_MOA1) mpPowderPattern->SetWavelength("MoA1"); if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET_CUA1) mpPowderPattern->SetWavelength("CuA1"); if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET_FEA1) mpPowderPattern->SetWavelength("FeA1"); if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET_COA1) mpPowderPattern->SetWavelength("CoA1"); if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET_CRA1) mpPowderPattern->SetWavelength("CrA1"); this->CrystUpdate(true); } void WXPowderPattern::OnMenuAddExclude(wxCommandEvent & WXUNUSED(event)) { WXCrystValidateAllUserInput(); double min,max; //min { wxString txt=_T("Enter Min 2theta to exclude (degrees):"); if(mpPowderPattern->GetRadiation().GetWavelengthType()==WAVELENGTH_TOF) txt=_T("Enter Min 2theta to exclude (microseconds):"); wxTextEntryDialog dialog(this,_T("Min"),txt,_T("0"),wxOK | wxCANCEL); dialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=dialog.ShowModal()) { VFN_DEBUG_EXIT("WXPowderPattern::OnMenuAddExclude():Cancelled",6) return; } dialog.GetValue().ToDouble(&min); } //max { wxString txt=_T("Enter Max 2theta to exclude (degrees):"); if(mpPowderPattern->GetRadiation().GetWavelengthType()==WAVELENGTH_TOF) txt=_T("Enter Max 2theta to exclude (microseconds):"); wxTextEntryDialog dialog(this,_T("Max"),txt,_T("5"),wxOK | wxCANCEL); dialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=dialog.ShowModal()) { VFN_DEBUG_EXIT("WXPowderPattern::OnMenuAddExclude():Cancelled",6) return; } dialog.GetValue().ToDouble(&max); } if(maxGetRadiation().GetWavelengthType()==WAVELENGTH_TOF) mpPowderPattern->AddExcludedRegion(min,max); else mpPowderPattern->AddExcludedRegion(min*DEG2RAD,max*DEG2RAD); } void WXPowderPattern::OnMenuLeBail(wxCommandEvent& event) { #if 0 wxFrame *pFrame=new wxFrame(this,-1,_T("Profile Fitting")); WXProfileFitting *pFit; pFit=new WXProfileFitting(pFrame,&(this->GetPowderPattern())); pFrame->Show(true); #else cout<<"Beginning refinement"<GetPowderPattern(),0,true,true); lsq.PrepareRefParList(true); lsq.SetParIsFixed(gpRefParTypeObjCryst,true); lsq.SetParIsFixed(gpRefParTypeScatt,false); lsq.SetParIsFixed(gpRefParTypeScattDataScale,false); //lsq.SetParIsUsed(gpRefParTypeScattDataProfile,true); //lsq.SetParIsUsed(gpRefParTypeScattDataCorrPos,true); //lsq.SetParIsUsed(gpRefParTypeScattDataBackground,true); //lsq.SetParIsUsed(gpRefParTypeUnitCell,true); try {lsq.Refine(10,true,false);} catch(const ObjCrystException &except){}; cout<<"Finishing refinement"<GetPowderPattern().UpdateDisplay(); #endif } void WXPowderPattern::OnMenuExport(wxCommandEvent &event) { WXCrystValidateAllUserInput(); wxFileDialog save(this,_T("Choose a .pcr file"),_T(""),_T(""),_T("*.pcr"),wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if(save.ShowModal() != wxID_OK) return; wxString path,name,ext; wxFileName::SplitPath(save.GetPath(), &path, &name, &ext, wxPATH_NATIVE); wxString mes; wxString pcr=path+wxFileName::GetPathSeparator()+name+_T(".pcr"); wxString dat=path+wxFileName::GetPathSeparator()+name+_T(".dat"); mes.Printf(_T("This will create the files:\n %s\n %s"),pcr.c_str(),dat.c_str()); wxMessageDialog mesd(this,mes,_T("Files"),wxOK|wxCANCEL|wxICON_INFORMATION); if(mesd.ShowModal()==wxID_OK) mpPowderPattern->ExportFullprof(string((path+wxFileName::GetPathSeparator()+name).ToAscii())); } void WXPowderPattern::NotifyDeleteGraph() {mpGraph=0;} const PowderPattern& WXPowderPattern::GetPowderPattern()const { return *mpPowderPattern;} PowderPattern& WXPowderPattern::GetPowderPattern() { return *mpPowderPattern;} void WXPowderPattern::UpdateUI(const bool lock) { if(lock)mMutex.Lock(); if(mpGraph!=0) { mpGraph->GetParent()->SetLabel(wxString::FromAscii(mpPowderPattern->GetName().c_str())); } this->WXRefinableObj::UpdateUI(false); if(lock)mMutex.Unlock(); } //////////////////////////////////////////////////////////////////////// // // WXPowderPatternGraph // //////////////////////////////////////////////////////////////////////// static const long ID_POWDERGRAPH_MENU_UPDATE= WXCRYST_ID(); static const long ID_POWDERGRAPH_MENU_TOGGLELABEL= WXCRYST_ID(); static const long ID_POWDERGRAPH_MENU_TOGGPEAK= WXCRYST_ID(); static const long ID_POWDERGRAPH_MENU_FINDPEAKS= WXCRYST_ID(); static const long ID_POWDERGRAPH_MENU_LOADPEAKS= WXCRYST_ID(); static const long ID_POWDERGRAPH_MENU_SAVEPEAKS= WXCRYST_ID(); static const long ID_POWDERGRAPH_MENU_ADDPEAK= WXCRYST_ID(); static const long ID_POWDERGRAPH_MENU_REMOVEPEAK= WXCRYST_ID(); static const long ID_POWDERGRAPH_MENU_INDEX= WXCRYST_ID(); static const long ID_POWDERGRAPH_MENU_XSCALE_DATA= WXCRYST_ID(); static const long ID_POWDERGRAPH_MENU_XSCALE_D= WXCRYST_ID(); static const long ID_POWDERGRAPH_MENU_XSCALE_2PID= WXCRYST_ID(); static const long ID_POWDERGRAPH_MENU_YSCALE_LINEAR= WXCRYST_ID(); static const long ID_POWDERGRAPH_MENU_YSCALE_SQRT= WXCRYST_ID(); static const long ID_POWDERGRAPH_MENU_YSCALE_LOG10= WXCRYST_ID(); static const long ID_POWDERGRAPH_MENU_LEBAIL= WXCRYST_ID(); BEGIN_EVENT_TABLE(WXPowderPatternGraph, wxWindow) EVT_PAINT( WXPowderPatternGraph::OnPaint) EVT_MOUSE_EVENTS( WXPowderPatternGraph::OnMouse) EVT_MENU(ID_POWDERGRAPH_MENU_UPDATE, WXPowderPatternGraph::OnUpdate) EVT_MENU(ID_POWDERGRAPH_MENU_TOGGLELABEL, WXPowderPatternGraph::OnToggleLabel) EVT_MENU(ID_POWDERGRAPH_MENU_TOGGPEAK, WXPowderPatternGraph::OnToggleLabel) EVT_MENU(ID_POWDERGRAPH_MENU_FINDPEAKS, WXPowderPatternGraph::OnFindPeaks) EVT_MENU(ID_POWDERGRAPH_MENU_LOADPEAKS, WXPowderPatternGraph::OnLoadPeaks) EVT_MENU(ID_POWDERGRAPH_MENU_SAVEPEAKS, WXPowderPatternGraph::OnSavePeaks) EVT_MENU(ID_POWDERGRAPH_MENU_ADDPEAK, WXPowderPatternGraph::OnChangePeak) EVT_MENU(ID_POWDERGRAPH_MENU_REMOVEPEAK, WXPowderPatternGraph::OnChangePeak) EVT_MENU(ID_POWDERGRAPH_MENU_INDEX, WXPowderPatternGraph::OnIndex) EVT_MENU(ID_POWDERGRAPH_MENU_XSCALE_DATA, WXPowderPatternGraph::OnChangeScale) EVT_MENU(ID_POWDERGRAPH_MENU_XSCALE_D, WXPowderPatternGraph::OnChangeScale) EVT_MENU(ID_POWDERGRAPH_MENU_XSCALE_2PID, WXPowderPatternGraph::OnChangeScale) EVT_MENU(ID_POWDERGRAPH_MENU_YSCALE_LINEAR, WXPowderPatternGraph::OnChangeScale) EVT_MENU(ID_POWDERGRAPH_MENU_YSCALE_SQRT, WXPowderPatternGraph::OnChangeScale) EVT_MENU(ID_POWDERGRAPH_MENU_YSCALE_LOG10, WXPowderPatternGraph::OnChangeScale) EVT_MENU(ID_POWDERGRAPH_MENU_LEBAIL, WXPowderPatternGraph::OnLeBail) EVT_UPDATE_UI(ID_POWDER_GRAPH_NEW_PATTERN, WXPowderPatternGraph::OnRedrawNewPattern) EVT_CHAR( WXPowderPatternGraph::OnKeyDown) EVT_MOUSEWHEEL( WXPowderPatternGraph::OnMouseWheel) EVT_SIZE( WXPowderPatternGraph::OnSize) END_EVENT_TABLE() WXPowderPatternGraph::WXPowderPatternGraph(wxFrame *frame, WXPowderPattern* parent): wxWindow(frame,-1,wxPoint(-1,-1),wxSize(-1,-1)), mpPattern(parent),mMargin(20),mDiffPercentShift(.20), mMaxIntensity(-1),mMinIntensity(-1),mMinX(-1),mMaxX(-1), mDefaultIntensityScale(true), mpParentFrame(frame), mIsDragging(false),mDisplayLabel(true),mDisplayPeak(true) { mpPopUpMenu=new wxMenu(_T("Powder Pattern")); mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_UPDATE, _T("&Update")); mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_TOGGLELABEL, _T("&Hide labels")); #if 1 mpPopUpMenu->AppendSeparator(); mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_FINDPEAKS, _T("&Find peaks")); mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_LOADPEAKS, _T("&Load peaks")); mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_SAVEPEAKS, _T("&Save peaks")); mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_INDEX, _T("&Index !")); mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_TOGGPEAK, _T("&Hide peaks")); mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_ADDPEAK, _T("&Add peak")); mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_REMOVEPEAK, _T("&Remove peak")); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_SAVEPEAKS, FALSE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_TOGGPEAK, FALSE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_ADDPEAK, TRUE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_REMOVEPEAK, FALSE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_INDEX, FALSE); #endif mpPopUpMenu->AppendSeparator(); mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_LEBAIL, _T("Fit &Profile + Le Bail extraction")); mpPopUpMenu->AppendSeparator(); mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_XSCALE_DATA, _T("&X scale: 2theta/TOF")); mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_XSCALE_D, _T("&X scale: Q=1/d")); mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_XSCALE_2PID, _T("&X scale: Q=2pi/d")); mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_YSCALE_LINEAR, _T("&Y scale: I")); mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_YSCALE_SQRT, _T("&Y scale: sqrt(I)")); mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_YSCALE_LOG10, _T("&Y scale: log10(I)")); if(!wxConfigBase::Get()->HasEntry(_T("PowderPattern/BOOL/Default-display reflection indices"))) wxConfigBase::Get()->Write(_T("PowderPattern/BOOL/Default-display reflection indices"), mDisplayLabel); else { wxConfigBase::Get()->Read(_T("PowderPattern/BOOL/Default-display reflection indices"), &mDisplayLabel); if(mDisplayLabel) mpPopUpMenu->SetLabel(ID_POWDERGRAPH_MENU_TOGGLELABEL, _T("Hide labels")); else mpPopUpMenu->SetLabel(ID_POWDERGRAPH_MENU_TOGGLELABEL, _T("Show labels")); } // Scale used to display graph x coordinates : 0 - experimental ; 1 - 1/d ; 2 - 2pi/d if(!wxConfigBase::Get()->HasEntry(_T("PowderPattern/LONG/graph x scale"))) wxConfigBase::Get()->Write(_T("PowderPattern/LONG/graph x scale"), 0); // Scale used to display graph y coordinates : 0 - linear ; 1 - square root ; 2 - log10 if(!wxConfigBase::Get()->HasEntry(_T("PowderPattern/LONG/graph y scale"))) wxConfigBase::Get()->Write(_T("PowderPattern/LONG/graph y scale"), 0); wxConfigBase::Get()->Read(_T("PowderPattern/LONG/graph x scale"), &mXScale); wxConfigBase::Get()->Read(_T("PowderPattern/LONG/graph y scale"), &mYScale); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_XSCALE_DATA, TRUE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_XSCALE_D, TRUE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_XSCALE_2PID, TRUE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_YSCALE_LINEAR, TRUE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_YSCALE_SQRT, TRUE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_YSCALE_LOG10, TRUE); if(mXScale==0) mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_XSCALE_DATA, FALSE); if(mXScale==1) mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_XSCALE_D, FALSE); if(mXScale==2) mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_XSCALE_2PID, FALSE); if(mYScale==0)mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_YSCALE_LINEAR, FALSE); if(mYScale==1) mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_YSCALE_SQRT, FALSE); if(mYScale==2) mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_YSCALE_LOG10, FALSE); mpPattern->CrystUpdate(true); } WXPowderPatternGraph::~WXPowderPatternGraph() { mpPattern->NotifyDeleteGraph(); } void WXPowderPatternGraph::OnPaint(wxPaintEvent& WXUNUSED(event)) { if((mObs.numElements()<=0)||(mCalc.numElements()<=0)) return; VFN_DEBUG_MESSAGE("WXPowderPatternGraph:OnPaint()",5) unsigned int ct=0; while(wxMUTEX_NO_ERROR!=mMutex.TryLock()) { if(++ct>10) return; wxMilliSleep(50); } wxBufferedPaintDC dc(this); PrepareDC(dc); mpParentFrame->PrepareDC(dc); dc.DestroyClippingRegion(); dc.SetBackground(wxBrush(_T("white"), wxSOLID)); dc.Clear(); wxColour blue=wxColour(0,0,255); wxPen bluePen=wxPen(blue); wxString fontInfo; #ifdef __WIN32__ dc.SetFont(*wxNORMAL_FONT); #else dc.SetFont(*wxSMALL_FONT); #endif long nbPoint=mX.numElements(); // Get Window Size wxCoord width,height; this->GetSize(&width, &height); //const int margin=mMargin; //width -= margin; //height -= margin; VFN_DEBUG_MESSAGE("WXPowderPatternGraph:OnPaint():1",5) //Check pattern is not being updated VFN_DEBUG_MESSAGE("WXPowderPatternGraph:OnPaint():2:"<GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) { mind=2*mpPattern->GetPowderPattern().X2STOL(minx*DEG2RAD); maxd=2*mpPattern->GetPowderPattern().X2STOL(maxx*DEG2RAD); } else { mind=2*mpPattern->GetPowderPattern().X2STOL(minx); maxd=2*mpPattern->GetPowderPattern().X2STOL(maxx); } if(mXScale==1) {minx=mind; maxx=maxd;} if(mXScale==2) {minx=2*M_PI*mind;maxx=2*M_PI*maxd;} REAL xStep=pow((float)10,(float)floor(log10((maxx-minx)/nbTick))); xStep *= floor((maxx-minx)/xStep/nbTick); for(REAL xs=xStep*ceil(minx/xStep);xsGetPowderPattern().STOL2X(xs/2);} if(mXScale==2) {x=mpPattern->GetPowderPattern().STOL2X(xs/(4*M_PI));} if(mXScale==0) xc=this->Data2ScreenX(x); else { if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) xc=this->Data2ScreenX(RAD2DEG*x); else xc=this->Data2ScreenX(x); } dc.DrawLine(xc,yc-3,xc,yc+3); fontInfo.Printf(_T("%g"),xs); dc.GetTextExtent(fontInfo, &tmpW, &tmpH); dc.DrawText(fontInfo,xc-tmpW/2,yc+6); } } } // Draw cumulated Chi^2, scaled { dc.SetPen(* wxGREY_PEN); wxCoord x1,y1,x2,y2; x2=this->Point2ScreenX(0); const REAL s=(mMaxIntensity-mMinIntensity)/mChi2Cumul(mpPattern->GetPowderPattern().GetNbPointUsed()-1); y2=this->Data2ScreenY(mMinIntensity+mChi2Cumul(0)*s); for(unsigned long i=0;iGetPowderPattern().GetNbPointUsed();i++) { if((mX(i)>mMinX)&&(mX(i)Point2ScreenX(i); y2=this->Data2ScreenY(mMinIntensity+mChi2Cumul(i)*s); dc.DrawLine(x1,y1,x2,y2); } } } // Draw observed pattern VFN_DEBUG_MESSAGE("WXPowderPatternGraph:OnPaint():4:",5) { dc.SetPen(bluePen); wxCoord x1,y1,x2,y2; x2=this->Point2ScreenX(0); y2=this->Data2ScreenY(mObs(0)); for(long i=0;imMinX)&&(mX(i)Point2ScreenX(i); y2=this->Data2ScreenY(mObs(i)); dc.DrawLine(x1,y1,x2,y2); } } } // Draw calculated pattern VFN_DEBUG_MESSAGE("WXPowderPatternGraph:OnPaint():5:",5) { dc.SetPen(* wxRED_PEN); wxCoord x1,y1,x2,y2; x2=this->Point2ScreenX(0); y2=this->Data2ScreenY(mCalc(0)); for(long i=0;imMinX)&&(mX(i)Point2ScreenX(i); y2=this->Data2ScreenY(mCalc(i)); dc.DrawLine(x1,y1,x2,y2); } } } // Display labels ? list > > vLabel; if(true==mDisplayLabel) // "vLabel=mvLabelList;" does not work (gcc 4.1.1) for(list > >::const_iterator comp=mvLabelList.begin();comp!=mvLabelList.end();++comp) vLabel.push_back(*comp); // Show peaks ? if((true==mDisplayPeak)&&(mPeakList.GetPeakList().size()>0)) { list > peakLabels; char buf[50]; unsigned int ix=0; for(vector::const_iterator pos=mPeakList.GetPeakList().begin();pos!=mPeakList.GetPeakList().end();++pos) { const float x=mpPattern->GetPowderPattern().STOL2X(pos->dobs/2); if(pos->isSpurious) { if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) sprintf(buf,"#%2u,x=%6.3f d=%6.3fA SPURIOUS?",ix,x*RAD2DEG,1/pos->dobs); else sprintf(buf,"#%2u,x=%6.3f d=%6.3fA SPURIOUS?",ix,x ,1/pos->dobs); } else { if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) sprintf(buf,"#%2u,x=%6.2f d=%6.3fA",ix,x*RAD2DEG,1/pos->dobs); else sprintf(buf,"#%2u,x=%6.2f d=%6.3fA",ix,x ,1/pos->dobs); } ++ix; peakLabels.push_back(make_pair(x,buf)); } vLabel.push_back(peakLabels); // Do we have a list of predicted HKL positions as well ? if(mPeakList.mvPredictedHKL.size()>0) { peakLabels.clear(); for(list::const_iterator pos=mPeakList.mvPredictedHKL.begin();pos!=mPeakList.mvPredictedHKL.end();++pos) { const float dobs=sqrt(pos->d2calc); const float x=mpPattern->GetPowderPattern().STOL2X(dobs/2); sprintf(buf,"?(%2d %2d %2d)?",pos->h,pos->k,pos->l); peakLabels.push_back(make_pair(x,buf)); } vLabel.push_back(peakLabels); } } // Draw labels VFN_DEBUG_MESSAGE("WXPowderPatternGraph:OnPaint():5:",5) if(vLabel.size()>0) { wxCoord x,y; wxCoord tmpW,tmpH; int loop=1; REAL yr; unsigned int pen=0; unsigned int icomp=0; // First, Crystalline phases, background (empty), then list of peaks and predicted hkl list for(list > >::const_iterator comp=vLabel.begin();comp!=vLabel.end();comp++) { if(comp->size()==0) {// Only background components should be empty icomp++; continue; } switch(pen) { case 0 : dc.SetPen(wxPen(wxColour( 0, 0, 0),2));dc.SetTextForeground(wxColour( 0, 0, 0));break; case 1 : dc.SetPen(wxPen(wxColour( 0, 0,255),2));dc.SetTextForeground(wxColour( 0, 0,255));break; case 2 : dc.SetPen(wxPen(wxColour( 0,255, 0),2));dc.SetTextForeground(wxColour( 0,255, 0));break; case 3 : dc.SetPen(wxPen(wxColour(255, 0, 0),2));dc.SetTextForeground(wxColour(255, 0, 0));break; case 4 : dc.SetPen(wxPen(wxColour( 0,255,255),2));dc.SetTextForeground(wxColour( 0,255,255));break; case 5 : dc.SetPen(wxPen(wxColour(255, 0,255),2));dc.SetTextForeground(wxColour(255, 0,255));break; case 6 : dc.SetPen(wxPen(wxColour(255,160, 0),2));dc.SetTextForeground(wxColour(255,160, 0));break; case 7 : dc.SetPen(wxPen(wxColour(128,128,255),2));dc.SetTextForeground(wxColour(128,128,255));break; case 8 : dc.SetPen(wxPen(wxColour(128,255,128),2));dc.SetTextForeground(wxColour(128,255,128));break; case 9 : dc.SetPen(wxPen(wxColour(255,128,128),2));dc.SetTextForeground(wxColour(255,128,128));break; case 10: dc.SetPen(wxPen(wxColour( 0, 0,128),2));dc.SetTextForeground(wxColour( 0, 0,128));break; case 11: dc.SetPen(wxPen(wxColour( 0, 80, 0),2));dc.SetTextForeground(wxColour( 0, 80, 0));break; case 12: dc.SetPen(wxPen(wxColour(128, 0, 0),2));dc.SetTextForeground(wxColour(128, 0, 0));break; default: dc.SetPen(wxPen(wxColour(128,128,128),2));dc.SetTextForeground(wxColour(128,128,128));break; } unsigned long ct=0; for(list >::const_iterator pos=comp->begin();pos!=comp->end();++pos) { REAL point=pos->first; if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) point *= RAD2DEG; if((point>=mMinX)&&(point<=mMaxX)) { if(++ct>200) { cout <<"Too many labels (>100): displaying only first 100 and ticking 100 more..."<Data2ScreenX(point); const REAL pixel=mpPattern->GetPowderPattern().X2Pixel(pos->first); if(mCalc((long)pixel)>mObs((long)pixel)) yr=mCalc((long)pixel); else yr=mObs((long)pixel); y=this->Data2ScreenY(yr); dc.DrawLine(x,y-5,x,y-10); if(ct<100) { fontInfo.Printf(wxString::FromAscii(pos->second.c_str())); dc.GetTextExtent(fontInfo, &tmpW, &tmpH); dc.DrawText(fontInfo,x-tmpW/2,y-tmpH*(loop++)-10); } if(loop==5) loop=1; } } // Draw legend (crystal names, Le Bail mode,...) wxString legend; if(icompGetPowderPattern().GetNbPowderPatternComponent()) { PowderPatternDiffraction *pDiff=0; if(mpPattern->GetPowderPattern().GetPowderPatternComponent(icomp).GetClassName()=="PowderPatternDiffraction") { pDiff=dynamic_cast (&(mpPattern->GetPowderPattern().GetPowderPatternComponent(icomp))); if(pDiff->GetExtractionMode()) legend=wxString::FromAscii((pDiff->GetCrystal().GetName()+" (LE BAIL MODE)").c_str()); else legend=wxString::FromAscii(pDiff->GetCrystal().GetName().c_str()); } } else { if((icomp-mpPattern->GetPowderPattern().GetNbPowderPatternComponent())==0) legend="Found Peaks"; else legend="Indexed HKL"; } fontInfo.Printf(legend); wxCoord tmpW,tmpH; dc.GetTextExtent(fontInfo, &tmpW, &tmpH); dc.DrawText(fontInfo,(wxCoord)mMargin*3+5,(wxCoord)(mMargin+tmpH*(pen))); ++pen;++icomp; } } mMutex.Unlock(); VFN_DEBUG_MESSAGE("WXPowderPatternGraph:OnPaint():End",5) } void WXPowderPatternGraph::OnMouse(wxMouseEvent &event) { if(0 == mpPattern->GetPowderPattern().GetNbPoint()) return; if(event.Leaving()) return;// wxMSW2.4 bug ? if(wxMUTEX_NO_ERROR!=mMutex.TryLock()) { mIsDragging=false; return; } VFN_DEBUG_MESSAGE("WXPowderPatternGraph:OnMouse()" <PrepareDC(dc); wxPoint pos=event.GetPosition(); const long x= dc.DeviceToLogicalX(pos.x); const long y= dc.DeviceToLogicalY(pos.y); wxCoord width,height; this->GetSize(&width, &height); if((x>width)||(y>height)) { mMutex.Unlock(); return; } //cout <Screen2DataX(x); const REAL intensity=this->Screen2DataY(y); if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()==WAVELENGTH_TOF) { wxString str; const long pixel= (long)(mpPattern->GetPowderPattern().X2PixelCorr(x0)); str.Printf(_T("tof=%6.2f ,I=%12.2f. pixel=#%ld"),x0,intensity,pixel); mMutex.Unlock(); mpParentFrame->SetStatusText(str); mMutex.Lock(); str.Printf(_T("d=%6.3fA"),0.5/mpPattern->GetPowderPattern().X2STOL(x0)); mMutex.Unlock(); mpParentFrame->SetStatusText(str,1); mMutex.Lock(); } else { const REAL intensity=this->Screen2DataY(y); wxString str; const long pixel= (long)(mpPattern->GetPowderPattern().X2PixelCorr(x0*DEG2RAD)); str.Printf(_T("2theta=%6.2f ,I=%12.2f. pixel=#%ld"),x0,intensity,pixel); // SetStatusText() triggers an OnPaint event ? Avoid deadlock by releasing the data mutex.. mMutex.Unlock(); mpParentFrame->SetStatusText(str); mMutex.Lock(); str.Printf(_T("d=%6.3fA"),0.5/mpPattern->GetPowderPattern().X2STOL(x0*DEG2RAD)); mMutex.Unlock(); mpParentFrame->SetStatusText(str,1); mMutex.Lock(); } if (event.Dragging() && event.LeftIsDown() && (!mIsDragging)) {//Begin zooming mIsDragging=true; mDraggingX0=x0; mDraggingIntensity0=intensity; mMutex.Unlock(); return; } if(event.LeftUp() && mIsDragging) {//Finished zooming ! VFN_DEBUG_MESSAGE("WXPowderPatternGraph::OnMouse():Finished zooming...",5) mIsDragging=false; if( (fabs(x0-mDraggingX0)<.1) || (fabs(mDraggingIntensity0-intensity)< fabs(mMaxIntensity*.02)) ) { mMutex.Unlock(); return; } if(mDraggingIntensity0>intensity) { if(mDraggingIntensity0<0.) { mMutex.Unlock(); return; } mMinIntensity=intensity; mMaxIntensity=mDraggingIntensity0; } else { if(intensity<0.) { mMutex.Unlock(); return; } mMinIntensity=mDraggingIntensity0; mMaxIntensity=intensity; } if(mDraggingX0>x0) { mMinX=x0; mMaxX=mDraggingX0; } else { mMinX=mDraggingX0; mMaxX=x0; } mDefaultIntensityScale=false; mClockAxisLimits.Click(); mMutex.Unlock(); wxUpdateUIEvent event(ID_POWDER_GRAPH_NEW_PATTERN); wxPostEvent(this,event); return; } if(false==event.Dragging()) mIsDragging=false; if(event.LeftDClick()) {//Reset axis range mMutex.Unlock(); this->ResetAxisLimits(); wxUpdateUIEvent event(ID_POWDER_GRAPH_NEW_PATTERN); wxPostEvent(this,event); event.Skip(); return; } if(event.RightIsDown()) {//popup menu mMutex.Unlock(); if(mpPattern->GetPowderPattern().IsBeingRefined()) mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_UPDATE, false); else mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_UPDATE, true); // Store x coordinate to allow adding/removing peaks manually mDraggingX0=x; this->PopupMenu(mpPopUpMenu, event.GetX(), event.GetY() ); return; } if (event.GetWheelDelta()>0) {// Wheel or double-touch event on OSX + trackpad if(event.ControlDown()) { VFN_DEBUG_MESSAGE("WXPowderPatternGraph::OnMouse(): Mouse Wheel / double touch + control (OSX: command)",2) } else { VFN_DEBUG_MESSAGE("WXPowderPatternGraph::OnMouse(): Mouse Wheel / double touch",2) const int delta=event.GetWheelDelta(); int dx=0,dy=0; if(event.GetWheelAxis()==1) dx=event.GetWheelRotation(); else dy=event.GetWheelRotation(); if(dx>16) dx=16; if(dx<-16)dx=-16; if(dy>16) dy=16; if(dy<-16)dy=-16; const long nbPoint=mX.numElements(); if(dx>0) { const REAL range=mMaxX-mMinX; mMaxX += range/128.*abs(dx); if(mX(nbPoint-1)>mX(0)) { if(mMaxX>=mX(nbPoint-1)) mMaxX=mX(nbPoint-1); } else { if(mMaxX>=mX(0)) mMaxX=mX(0); } mMinX=mMaxX-range; } else if(dx<0) { const REAL range=mMaxX-mMinX; mMinX -= range/128.*abs(dx); if(mX(nbPoint-1)>mX(0)) { if(mMinX1) { const REAL halfrange=(mMaxX-mMinX)/2; const REAL middle=(mMaxX+mMinX)/2; //d1,d2 are used to zoom from the mouse position rather than the middle const REAL d1=(x0-mMinX)/halfrange; const REAL d2=(mMaxX-x0)/halfrange; mMinX= middle-halfrange*(64-abs(dy)*d1)/64.; mMaxX= middle+halfrange*(64-abs(dy)*d2)/64.; } } else if(dy>0) { const REAL halfrange=(mMaxX-mMinX)/2; const REAL middle=(mMaxX+mMinX)/2; const REAL d1=(x0-mMinX)/halfrange; const REAL d2=(mMaxX-x0)/halfrange; mMinX= middle-halfrange*(64+abs(dy)*d1)/64.; mMaxX= middle+halfrange*(64+abs(dy)*d2)/64.; } if(mX(nbPoint-1)>mX(0)) { if(mMinXmX(nbPoint-1)) mMaxX=mX(nbPoint-1); } else { if(mMinXmX(0)) mMaxX=mX(0); } if(mDefaultIntensityScale) {// Adapt max intensity as well float x0=mMinX,x1=mMaxX; if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) { x0 *= DEG2RAD; x1 *= DEG2RAD; } long ix0=long(this->mpPattern->GetPowderPattern().X2Pixel(x0)); long ix1=long(this->mpPattern->GetPowderPattern().X2Pixel(x1)); //cout<<"Switch default intensity 1: "<<"["<=mX.numElements()) ix0=mX.numElements()-1; if(ix1<0) ix1=0; if(ix1>=mX.numElements()) ix1=mX.numElements()-1; if(ix0>ix1) { const long ixtmp=ix0; ix0=ix1; ix1=ixtmp; } const long imin=mObs.imin(ix0,ix1); const long imax=mObs.imax(ix0,ix1); const long iminc=mCalc.imin(ix0,ix1); const long imaxc=mCalc.imax(ix0,ix1); //cout<<"Switch default intensity 3: "<mCalc(imaxc)) mMaxIntensity=mObs(imax); else mMaxIntensity=mCalc(imaxc); mMaxIntensity=mMaxIntensity+(mMaxIntensity-mMinIntensity)*0.1; } mMutex.Unlock(); mClockAxisLimits.Click(); wxUpdateUIEvent event(ID_POWDER_GRAPH_NEW_PATTERN); wxPostEvent(this,event); event.Skip(); return; } } mMutex.Unlock(); event.Skip(); } void WXPowderPatternGraph::OnMouseWheel(wxMouseEvent &event) { if(0 == mpPattern->GetPowderPattern().GetNbPoint()) return; VFN_DEBUG_ENTRY("WXPowderPatternGraph::OnMouseWheel()",6) wxMutexLocker mlock(mMutex); const long nbPoint=mX.numElements(); if(event.GetWheelRotation()>=event.GetWheelDelta()) { const REAL range=mMaxX-mMinX; mMaxX += range/8; if(mX(nbPoint-1)>mX(0)) { if(mMaxX>=mX(nbPoint-1)) mMaxX=mX(nbPoint-1); } else { if(mMaxX>=mX(0)) mMaxX=mX(0); } mMinX=mMaxX-range; } if(event.GetWheelRotation()<=(-event.GetWheelDelta())) { const REAL range=mMaxX-mMinX; mMinX -= range/8; if(mX(nbPoint-1)>mX(0)) { if(mMinXCrystUpdate(true,true); } void WXPowderPatternGraph::OnToggleLabel(wxCommandEvent &event) { VFN_DEBUG_MESSAGE("WXPowderPatternGraph::OnToggleLabel()",6) if(event.GetId()==ID_POWDERGRAPH_MENU_TOGGPEAK) { mDisplayPeak = !mDisplayPeak; if(mDisplayPeak) mpPopUpMenu->SetLabel(ID_POWDERGRAPH_MENU_TOGGPEAK, _T("Hide peaks")); else mpPopUpMenu->SetLabel(ID_POWDERGRAPH_MENU_TOGGPEAK, _T("Show peaks")); } if(event.GetId()==ID_POWDERGRAPH_MENU_TOGGLELABEL) { mDisplayLabel = !mDisplayLabel; if(mDisplayLabel) mpPopUpMenu->SetLabel(ID_POWDERGRAPH_MENU_TOGGLELABEL, _T("Hide labels")); else mpPopUpMenu->SetLabel(ID_POWDERGRAPH_MENU_TOGGLELABEL, _T("Show labels")); } this->Refresh(false); } void WXPowderPatternGraph::OnFindPeaks(wxCommandEvent& WXUNUSED(event)) { WXCrystValidateAllUserInput(); Chronometer chrono; chrono.start(); (*fpObjCrystInformUser)("Powder pattern: searching for peaks"); float dmin=1.5; while(true) { mPeakList=mpPattern->GetPowderPattern().FindPeaks(dmin,-1,1000); dmin*=0.75; if((mPeakList.GetPeakList().size()>30)||(dmin<0.3)) break; } const unsigned int nb=mPeakList.GetPeakList().size(); (*fpObjCrystInformUser)((boost::format("Powder pattern: found %u peaks (dt=%6.3fs)") % nb % chrono.seconds()).str()); //if(nb<5) return; mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_SAVEPEAKS, TRUE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_TOGGPEAK, TRUE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_INDEX, TRUE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_ADDPEAK, TRUE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_REMOVEPEAK, TRUE); // Keep lowest peaks if(mPeakList.GetPeakList().size()>40) mPeakList.GetPeakList().resize(40); //mpPattern->CrystUpdate(true,true); if(true) {// display 2nd derivative as 'calc' (will remain until an update to the pattern is made) CrystVector_REAL obsd2; obsd2=SavitzkyGolay(mObs,4,2); const float norm=-obsd2.min(); obsd2 /= -norm; mCalc=obsd2; mCalc*=mObs.max(); } this->Refresh(false); } void WXPowderPatternGraph::OnLoadPeaks(wxCommandEvent& WXUNUSED(event)) { wxFileDialog fn(this,_T("Choose a file"),_T(""),_T(""),_T("*"),wxFD_OPEN); if(fn.ShowModal() != wxID_OK) return; ifstream f(fn.GetPath().ToAscii()); if(!f) return;//:TODO: mPeakList.GetPeakList().clear(); f.imbue(std::locale::classic()); mPeakList.ImportDhklDSigmaIntensity(f); f.close(); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_SAVEPEAKS, TRUE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_TOGGPEAK, TRUE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_INDEX, TRUE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_ADDPEAK, TRUE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_REMOVEPEAK, TRUE); this->Refresh(false); } void WXPowderPatternGraph::OnSavePeaks(wxCommandEvent& WXUNUSED(event)) { wxFileDialog save(this,_T("Choose a file"),_T(""),_T(""),_T("*.txt"),wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if(save.ShowModal() != wxID_OK) return; ofstream out(save.GetPath().ToAscii()); if(!out) return;//:TODO: out.imbue(std::locale::classic()); mPeakList.ExportDhklDSigmaIntensity(out); out.close(); } void WXPowderPatternGraph::OnChangePeak(wxCommandEvent& event) { if(event.GetId()==ID_POWDERGRAPH_MENU_REMOVEPEAK) { unsigned int idx=0; const float d=2*mpPattern->GetPowderPattern().X2STOL(this->Screen2DataX((long)mDraggingX0)*DEG2RAD); float dist=100.0; for(unsigned int i=0;iGetPowderPattern().STOL2X(mPeakList.GetPeakList()[i].dobs/2); if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) x *= RAD2DEG; x=this->Data2ScreenX(x); if(abs(x-mDraggingX0)Enable(ID_POWDERGRAPH_MENU_INDEX, FALSE); if(mPeakList.GetPeakList().size()==0) { mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_TOGGPEAK, FALSE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_SAVEPEAKS, FALSE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_REMOVEPEAK, FALSE); } wxString buf; buf.Printf(_T("Removing peak at d=%6.3f"),1/mPeakList.GetPeakList()[idx].dobs); mpParentFrame->SetStatusText(buf,1); mPeakList.RemovePeak(idx); this->Refresh(false); } } if(event.GetId()==ID_POWDERGRAPH_MENU_ADDPEAK) { float d,sig; if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) { d = 2*mpPattern->GetPowderPattern().X2STOL(this->Screen2DataX((long)mDraggingX0 )*DEG2RAD); // Use 2*local step as sigma long x1=(long)(mpPattern->GetPowderPattern().STOL2Pixel(d/2)); if(x1<1) x1+=1; sig=2*abs( mpPattern->GetPowderPattern().X2STOL(mpPattern->GetPowderPattern().GetPowderPatternX()(x1 )) -mpPattern->GetPowderPattern().X2STOL(mpPattern->GetPowderPattern().GetPowderPatternX()(x1-1))); } else { d = 2*mpPattern->GetPowderPattern().X2STOL(this->Screen2DataX((long)mDraggingX0 )); long x1=(long)(mpPattern->GetPowderPattern().STOL2Pixel(d/2)); cout<<__FILE__<<":"<<__LINE__<<":"<GetPowderPattern().X2STOL(mpPattern->GetPowderPattern().GetPowderPatternX()(x1 )) -mpPattern->GetPowderPattern().X2STOL(mpPattern->GetPowderPattern().GetPowderPatternX()(x1-1))); cout<<__FILE__<<":"<<__LINE__<<":"<Enable(ID_POWDERGRAPH_MENU_SAVEPEAKS, TRUE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_TOGGPEAK, TRUE); if(mPeakList.GetPeakList().size()>=5) mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_INDEX, TRUE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_REMOVEPEAK, TRUE); wxString buf; buf.Printf(_T("Added peak at d=%6.3f"),1/d); mPeakList.AddPeak(d,1.0,sig); mpParentFrame->SetStatusText(buf,1); this->Refresh(false); mPeakList.Print(cout); } } //////////////////////////////////////// WXCellExplorer ///////////////////// class WXCellExplorer:public wxWindow { public: WXCellExplorer(wxWindow *parent,PeakList &peaklist,WXPowderPatternGraph *graph=NULL); ~WXCellExplorer(); /// Start indexing void OnIndex(wxCommandEvent &event); /// Select cell void OnSelectCell(wxCommandEvent &event); /// Apply cell void OnApplyCell(wxCommandEvent &event); /// Choose crystal to apply cell to void OnChooseCrystal(wxCommandEvent &event); /// User chose to automatically run Le Bail & profile fitting, ///make sure there is a background and a crystal structure selected void OnAutoLeBail(wxCommandEvent &event); /// Export indexing results to a csv file void OnExportIndexingResults(wxCommandEvent &event); private: WXPowderPatternGraph *mpGraph; PeakList *mpPeakList; CellExplorer *mpCellExplorer; wxRadioBox *mpAlgorithm; wxRadioBox *mpBravais; wxListBox *mpCell; wxTextCtrl *mpLog; wxTextCtrl *mpLengthMin,*mpLengthMax; wxTextCtrl *mpAngleMin,*mpAngleMax; wxTextCtrl *mpVolumeMin,*mpVolumeMax; wxTextCtrl *mpNbSpurious; wxTextCtrl *mpNbPeak; wxTextCtrl *mpErrorD; WXFieldChoice *mpFieldCrystal; wxTextCtrl *mpStopOnScore,*mpStopOnDepth; wxTextCtrl *mpReportOnScore,*mpReportOnDepth; Crystal *mpCrystal; PowderPatternDiffraction *mpDiff; wxCheckBox *mpWeakDiffraction; wxCheckBox *mpContinueOnSolution; wxCheckBox *mpTryCenteredLattice; wxCheckBox *mpTrySpurious; wxCheckBox *mpAutomaticLeBail; DECLARE_EVENT_TABLE() }; static const long ID_CELLEXPLORER_INDEX= WXCRYST_ID(); static const long ID_CELLEXPLORER_INDEX_QUICK= WXCRYST_ID(); static const long ID_CELLEXPLORER_WEAK= WXCRYST_ID(); static const long ID_CELLEXPLORER_SELECTCELL= WXCRYST_ID(); static const long ID_CELLEXPLORER_APPLYCELL= WXCRYST_ID(); static const long ID_CELLEXPLORER_CHOOSECRYSTAL= WXCRYST_ID(); static const long ID_CELLEXPLORER_LEBAIL= WXCRYST_ID(); static const long ID_CELLEXPLORER_CENTERED= WXCRYST_ID(); static const long ID_CELLEXPLORER_SPURIOUS= WXCRYST_ID(); static const long ID_CELLEXPLORER_EXPORT= WXCRYST_ID(); BEGIN_EVENT_TABLE(WXCellExplorer, wxWindow) EVT_BUTTON(ID_CELLEXPLORER_INDEX, WXCellExplorer::OnIndex) EVT_BUTTON(ID_CELLEXPLORER_INDEX_QUICK, WXCellExplorer::OnIndex) EVT_LISTBOX(ID_CELLEXPLORER_SELECTCELL, WXCellExplorer::OnSelectCell) EVT_LISTBOX_DCLICK(ID_CELLEXPLORER_SELECTCELL,WXCellExplorer::OnApplyCell) EVT_BUTTON(ID_CELLEXPLORER_APPLYCELL, WXCellExplorer::OnApplyCell) EVT_BUTTON(ID_CELLEXPLORER_CHOOSECRYSTAL, WXCellExplorer::OnChooseCrystal) EVT_CHECKBOX(ID_CELLEXPLORER_LEBAIL, WXCellExplorer::OnAutoLeBail) EVT_BUTTON(ID_CELLEXPLORER_EXPORT, WXCellExplorer::OnExportIndexingResults) END_EVENT_TABLE() //:TODO: allow sorting solutions by number of spurious lines or score //:TODO: make systematic Le Bail + profile fitting of all solutions, and allow to sort by GoF WXCellExplorer::WXCellExplorer(wxWindow *parent, PeakList &peaklist, WXPowderPatternGraph *graph): wxWindow(parent,-1),mpGraph(graph),mpPeakList(&peaklist),mpCellExplorer(0),mpCrystal(0),mpDiff(0) { wxBoxSizer *pSizer1=new wxBoxSizer(wxHORIZONTAL); this->SetSizer(pSizer1); wxNotebook *pNotebook = new wxNotebook(this, -1); pSizer1->Add(pNotebook,0,wxALIGN_TOP); // Quick interface wxWindow *pQuick=new wxWindow(pNotebook,-1); pNotebook->AddPage(pQuick,_T("Quick")); wxStaticBoxSizer *pSizerQuick=new wxStaticBoxSizer(wxVERTICAL,pQuick); wxButton *pQuickButtonIndex=new wxButton(pQuick,ID_CELLEXPLORER_INDEX_QUICK,_T("Find cell!")); pSizerQuick->Add(pQuickButtonIndex,0,wxALIGN_CENTER); wxButton *pQuickButtonExport=new wxButton(pQuick,ID_CELLEXPLORER_EXPORT,_T("Export Indexing Results")); pSizerQuick->Add(pQuickButtonExport,0,wxALIGN_CENTER); mpWeakDiffraction=new wxCheckBox(pQuick,ID_CELLEXPLORER_WEAK,_T("Weak Diffraction (scan larger volume)")); pSizerQuick->Add(mpWeakDiffraction,0,wxALIGN_CENTER); mpContinueOnSolution=new wxCheckBox(pQuick,ID_CELLEXPLORER_WEAK,_T("Continue exploring after solution")); pSizerQuick->Add(mpContinueOnSolution,0,wxALIGN_CENTER); mpTryCenteredLattice=new wxCheckBox(pQuick,ID_CELLEXPLORER_CENTERED,_T("Try Centered Lattices")); pSizerQuick->Add(mpTryCenteredLattice,0,wxALIGN_CENTER); mpTryCenteredLattice->SetValue(true); mpTrySpurious=new wxCheckBox(pQuick,ID_CELLEXPLORER_SPURIOUS,_T("Try with 1 and 2 spurious lines")); pSizerQuick->Add(mpTrySpurious,0,wxALIGN_CENTER); pQuick->SetSizer(pSizerQuick); pSizerQuick->Fit(pQuick); //pSizerQuick->RecalcSizes(); pQuick->Layout(); // Advanced interface wxWindow *pAdvanced=new wxWindow(pNotebook,-1); wxStaticBoxSizer *pSizerAdvanced=new wxStaticBoxSizer(wxVERTICAL,pAdvanced); wxButton *pButton1=new wxButton(pAdvanced,ID_CELLEXPLORER_INDEX,_T("Find cell!")); pSizerAdvanced->Add(pButton1,0,wxALIGN_CENTER); wxButton *pQuickButtonExport2=new wxButton(pAdvanced,ID_CELLEXPLORER_EXPORT,_T("Export Indexing Results")); pSizerAdvanced->Add(pQuickButtonExport2,0,wxALIGN_CENTER); wxBoxSizer *pLengthSizer=new wxBoxSizer(wxHORIZONTAL); wxStaticText *pLengthText=new wxStaticText(pAdvanced,-1,_T("Length min, max (A):")); pLengthSizer->Add(pLengthText,0,wxALIGN_CENTER); mpLengthMin=new wxTextCtrl(pAdvanced,-1,_T("3"),wxDefaultPosition,wxSize(30,-1),0, wxTextValidator(wxFILTER_NUMERIC)); pLengthSizer->Add(mpLengthMin,0,wxALIGN_CENTER); mpLengthMax=new wxTextCtrl(pAdvanced,-1,_T("25"),wxDefaultPosition,wxSize(30,-1),0, wxTextValidator(wxFILTER_NUMERIC)); pLengthSizer->Add(mpLengthMax,0,wxALIGN_CENTER); pSizerAdvanced->Add(pLengthSizer,0,wxALIGN_CENTER); wxBoxSizer *pAngleSizer=new wxBoxSizer(wxHORIZONTAL); wxStaticText *pAngleText=new wxStaticText(pAdvanced,-1,_T("Angle max(90< <179):")); pAngleSizer->Add(pAngleText,0,wxALIGN_CENTER); //mpAngleMin=new wxTextCtrl(this,-1,"90",wxDefaultPosition,wxSize(40,-1),0, // wxTextValidator(wxFILTER_NUMERIC)); //pAngleSizer->Add(mpAngleMin,0,wxALIGN_CENTER); mpAngleMax=new wxTextCtrl(pAdvanced,-1,_T("130"),wxDefaultPosition,wxSize(40,-1),0, wxTextValidator(wxFILTER_NUMERIC)); pAngleSizer->Add(mpAngleMax,0,wxALIGN_CENTER); pSizerAdvanced->Add(pAngleSizer,0,wxALIGN_CENTER); wxBoxSizer *pVolumeSizer=new wxBoxSizer(wxHORIZONTAL); wxStaticText *pVolumeText=new wxStaticText(pAdvanced,-1,_T("Volume min, max (A3):")); pVolumeSizer->Add(pVolumeText,0,wxALIGN_CENTER); mpVolumeMin=new wxTextCtrl(pAdvanced,-1,_T("10"),wxDefaultPosition,wxSize(50,-1),0, wxTextValidator(wxFILTER_NUMERIC)); pVolumeSizer->Add(mpVolumeMin,0,wxALIGN_CENTER); mpVolumeMax=new wxTextCtrl(pAdvanced,-1,_T("2500"),wxDefaultPosition,wxSize(50,-1),0, wxTextValidator(wxFILTER_NUMERIC)); pVolumeSizer->Add(mpVolumeMax,0,wxALIGN_CENTER); pSizerAdvanced->Add(pVolumeSizer,0,wxALIGN_CENTER); wxBoxSizer *pSpuriousSizer=new wxBoxSizer(wxHORIZONTAL); wxStaticText *pSpuriousText=new wxStaticText(pAdvanced,-1,_T("Nb spurious lines:")); pSpuriousSizer->Add(pSpuriousText,0,wxALIGN_CENTER); mpNbSpurious=new wxTextCtrl(pAdvanced,-1,_T("0"),wxDefaultPosition,wxSize(40,-1),0, wxTextValidator(wxFILTER_NUMERIC)); pSpuriousSizer->Add(mpNbSpurious,0,wxALIGN_CENTER); pSizerAdvanced->Add(pSpuriousSizer,0,wxALIGN_CENTER); wxBoxSizer *pNbPeakSizer=new wxBoxSizer(wxHORIZONTAL); wxStaticText *pNbPeakText=new wxStaticText(pAdvanced,-1,_T("Use Nb Peaks:")); pNbPeakSizer->Add(pNbPeakText,0,wxALIGN_CENTER); mpNbPeak=new wxTextCtrl(pAdvanced,-1,_T("20"),wxDefaultPosition,wxSize(40,-1),0, wxTextValidator(wxFILTER_NUMERIC)); pNbPeakSizer->Add(mpNbPeak,0,wxALIGN_CENTER); pSizerAdvanced->Add(pNbPeakSizer,0,wxALIGN_CENTER); wxBoxSizer *pStopSizer=new wxBoxSizer(wxHORIZONTAL); wxStaticText* pStopOnScoreText=new wxStaticText(pAdvanced,-1,_T("Stop on Score>")); pStopSizer->Add(pStopOnScoreText,0,wxALIGN_CENTER); mpStopOnScore=new wxTextCtrl(pAdvanced,-1,_T("50"),wxDefaultPosition,wxSize(50,-1),0, wxTextValidator(wxFILTER_NUMERIC)); pStopSizer->Add(mpStopOnScore,0,wxALIGN_CENTER); wxStaticText* pStopOnDepthText=new wxStaticText(pAdvanced,-1,_T("and depth>=")); pStopSizer->Add(pStopOnDepthText,0,wxALIGN_CENTER); mpStopOnDepth=new wxTextCtrl(pAdvanced,-1,_T("6"),wxDefaultPosition,wxSize(30,-1),0, wxTextValidator(wxFILTER_NUMERIC)); pStopSizer->Add(mpStopOnDepth,0,wxALIGN_CENTER); pSizerAdvanced->Add(pStopSizer,0,wxALIGN_CENTER); wxBoxSizer *pReportSizer=new wxBoxSizer(wxHORIZONTAL); wxStaticText* pReportOnScoreText=new wxStaticText(pAdvanced,-1,_T("Report score>")); pReportSizer->Add(pReportOnScoreText,0,wxALIGN_CENTER); mpReportOnScore=new wxTextCtrl(pAdvanced,-1,_T("10"),wxDefaultPosition,wxSize(50,-1),0, wxTextValidator(wxFILTER_NUMERIC)); pReportSizer->Add(mpReportOnScore,0,wxALIGN_CENTER); wxStaticText* pReportOnDepthText=new wxStaticText(pAdvanced,-1,_T("or depth>=")); pReportSizer->Add(pReportOnDepthText,0,wxALIGN_CENTER); mpReportOnDepth=new wxTextCtrl(pAdvanced,-1,_T("4"),wxDefaultPosition,wxSize(50,-1),0, wxTextValidator(wxFILTER_NUMERIC)); pReportSizer->Add(mpReportOnDepth,0,wxALIGN_CENTER); pSizerAdvanced->Add(pReportSizer,0,wxALIGN_CENTER); wxBoxSizer *pErrorSizer=new wxBoxSizer(wxHORIZONTAL); wxStaticText* pErrorText=new wxStaticText(pAdvanced,-1,_T("delta(d)/d^2 error:")); pErrorSizer->Add(pErrorText,0,wxALIGN_CENTER); mpErrorD=new wxTextCtrl(pAdvanced,-1,_T("0"),wxDefaultPosition,wxSize(50,-1),0, wxTextValidator(wxFILTER_NUMERIC)); pErrorSizer->Add(mpErrorD,0,wxALIGN_CENTER); pSizerAdvanced->Add(pErrorSizer,0,wxALIGN_CENTER); wxArrayString bravaisChoices; bravaisChoices.Add(_T("Triclinic")); bravaisChoices.Add(_T("Monoclinic")); bravaisChoices.Add(_T("Orthorombic")); bravaisChoices.Add(_T("Hexagonal")); bravaisChoices.Add(_T("Rhomboedral")); bravaisChoices.Add(_T("Tetragonal")); bravaisChoices.Add(_T("Cubic")); mpBravais=new wxRadioBox((wxWindow*)pAdvanced,-1,_T("Crystal System"),wxDefaultPosition,wxDefaultSize,bravaisChoices,0,wxRA_SPECIFY_ROWS); mpBravais->SetSelection(2); //mpBravais->Enable(0,false); pSizerAdvanced->Add(mpBravais,0,wxALIGN_CENTER); wxArrayString algoChoices; algoChoices.Add(_T("DICVOL")); //algoChoices.Add(_T("Differential Evolution")); // :TODO: re-enable after testing #if 0 mpAlgorithm=new wxRadioBox(pAdvanced,-1,_T("Algorithm"),wxDefaultPosition,wxDefaultSize,algoChoices,0,wxRA_SPECIFY_ROWS); mpAlgorithm->Enable(1,false); pSizerAdvanced->Add(mpAlgorithm,0,wxALIGN_CENTER); #endif pAdvanced->SetSizer(pSizerAdvanced); pSizerAdvanced->Fit(pAdvanced); //pSizerAdvanced->RecalcSizes(); pAdvanced->Layout(); pNotebook->AddPage(pAdvanced,_T("Advanced")); pNotebook->Layout(); // Solutions & log wxBoxSizer *pSizer2=new wxBoxSizer(wxVERTICAL); //wxButton *pButton2=new wxButton(this,ID_CELLEXPLORER_APPLYCELL,"Apply selected cell"); //pSizer2->Add(pButton2,0,wxALIGN_CENTER); mpFieldCrystal=new WXFieldChoice(this,ID_CELLEXPLORER_CHOOSECRYSTAL,"Choose crystal to apply selected cell to:",200); pSizer2->Add(mpFieldCrystal,0,wxALIGN_CENTER); mpAutomaticLeBail=new wxCheckBox(this,ID_CELLEXPLORER_LEBAIL,_T("Automatic Profile Fitting (Le Bail)")); pSizer2->Add(mpAutomaticLeBail,0,wxALIGN_CENTER); wxArrayString cells; mpCell=new wxListBox(this,ID_CELLEXPLORER_SELECTCELL,wxDefaultPosition,wxSize(750,400),cells,wxLB_SINGLE); mpCell->SetFont(wxFont(9,wxTELETYPE,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL)); pSizer2->Add(mpCell,0,wxALIGN_CENTER); mpLog =new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(750,250),wxTE_MULTILINE|wxTE_READONLY|wxTE_DONTWRAP); mpLog->SetFont(wxFont(9,wxTELETYPE,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL)); pSizer2->Add(mpLog,0,wxALIGN_CENTER); pSizer1->Add(pSizer2,0,wxALIGN_TOP); this->Layout(); pSizer1->Fit(this->GetParent()); pSizer1->SetSizeHints(this); // Estimate volume from number of peaks at a given dmin // See J. Appl. Cryst. 20 (1987), 161 unsigned int nb=mpPeakList->GetPeakList().size(); if(nb>20) nb=20;// Just use 20 - beyond that we probably have a lot of weak peaks missed const float dmin=mpPeakList->GetPeakList()[nb-1].dobs; const float dmax=mpPeakList->GetPeakList()[0].dobs/10;// /10: assume no peaks at lower resolution mpLog->AppendText(wxString::Format(_T("Predicted unit vell volume from %2u observed peaks between: dmax=%6.3f A-> dmin=%6.3fA\n"),nb,1/dmax,1/dmin)); mpLog->AppendText(wxString::Format(_T("(Assuming observed lines represent 120%% down to 30%% of existing reflections)\n"))); mpLog->AppendText(wxString::Format(_T(" Cubic P v=%6.0f -> %6.0f A\n"),EstimateCellVolume(dmin,dmax,nb,CUBIC ,LATTICE_P,1.2),EstimateCellVolume(dmin,dmax,nb,CUBIC ,LATTICE_P,0.3))); mpLog->AppendText(wxString::Format(_T(" Cubic I v=%6.0f -> %6.0f A\n"),EstimateCellVolume(dmin,dmax,nb,CUBIC ,LATTICE_I,1.2),EstimateCellVolume(dmin,dmax,nb,CUBIC ,LATTICE_I,0.3))); mpLog->AppendText(wxString::Format(_T(" Cubic F v=%6.0f -> %6.0f A\n"),EstimateCellVolume(dmin,dmax,nb,CUBIC ,LATTICE_F,1.2),EstimateCellVolume(dmin,dmax,nb,CUBIC ,LATTICE_F,0.3))); mpLog->AppendText(wxString::Format(_T(" Tetragonal P v=%6.0f -> %6.0f A\n"),EstimateCellVolume(dmin,dmax,nb,TETRAGONAL ,LATTICE_P,1.2),EstimateCellVolume(dmin,dmax,nb,TETRAGONAL ,LATTICE_P,0.3))); mpLog->AppendText(wxString::Format(_T(" Tetragonal I v=%6.0f -> %6.0f A\n"),EstimateCellVolume(dmin,dmax,nb,TETRAGONAL ,LATTICE_I,1.2),EstimateCellVolume(dmin,dmax,nb,TETRAGONAL ,LATTICE_I,0.3))); mpLog->AppendText(wxString::Format(_T(" Orthorombic P v=%6.0f -> %6.0f A\n"),EstimateCellVolume(dmin,dmax,nb,ORTHOROMBIC,LATTICE_P,1.2),EstimateCellVolume(dmin,dmax,nb,ORTHOROMBIC,LATTICE_P,0.3))); mpLog->AppendText(wxString::Format(_T(" Orthorombic I,C v=%6.0f -> %6.0f A\n"),EstimateCellVolume(dmin,dmax,nb,ORTHOROMBIC,LATTICE_I,1.2),EstimateCellVolume(dmin,dmax,nb,ORTHOROMBIC,LATTICE_I,0.3))); mpLog->AppendText(wxString::Format(_T(" Orthorombic F v=%6.0f -> %6.0f A\n"),EstimateCellVolume(dmin,dmax,nb,ORTHOROMBIC,LATTICE_F,1.2),EstimateCellVolume(dmin,dmax,nb,ORTHOROMBIC,LATTICE_F,0.3))); mpLog->AppendText(wxString::Format(_T(" Hexagonal v=%6.0f -> %6.0f A\n"),EstimateCellVolume(dmin,dmax,nb,HEXAGONAL ,LATTICE_P,1.2),EstimateCellVolume(dmin,dmax,nb,HEXAGONAL ,LATTICE_P,0.3))); mpLog->AppendText(wxString::Format(_T(" Monoclinic P v=%6.0f -> %6.0f A\n"),EstimateCellVolume(dmin,dmax,nb,MONOCLINIC ,LATTICE_P,1.2),EstimateCellVolume(dmin,dmax,nb,MONOCLINIC ,LATTICE_P,0.3))); mpLog->AppendText(wxString::Format(_T(" Monoclinic C v=%6.0f -> %6.0f A\n"),EstimateCellVolume(dmin,dmax,nb,MONOCLINIC ,LATTICE_C,1.2),EstimateCellVolume(dmin,dmax,nb,MONOCLINIC ,LATTICE_C,0.3))); mpLog->AppendText(wxString::Format(_T(" Triclinic v=%6.0f -> %6.0f A\n"),EstimateCellVolume(dmin,dmax,nb,TRICLINIC ,LATTICE_P,1.2),EstimateCellVolume(dmin,dmax,nb,TRICLINIC ,LATTICE_P,0.3))); } WXCellExplorer::~WXCellExplorer() { if(mpDiff!=0) { mpDiff->SetExtractionMode(false,false); mpDiff->UpdateDisplay(); } } void WXCellExplorer::OnIndex(wxCommandEvent &event) { Chronometer chrono; if(event.GetId()==ID_CELLEXPLORER_INDEX_QUICK) { // Erase spurious record for(vector::iterator pos=mpPeakList->mvHKL.begin();pos!=mpPeakList->mvHKL.end();++pos) pos->isSpurious=false; // Use at most 30 reflections for indexing PeakList peaklist=*mpPeakList; if(peaklist.GetPeakList().size()>20) peaklist.GetPeakList().resize(20); // Estimate volume from number of peaks at a given dmin // See J. Appl. Cryst. 20 (1987), 161 unsigned int nb=mpPeakList->GetPeakList().size(); if(nb>20) nb=20;// Just use 20 - beyond that we probably have a lot of weak peaks float dmin=mpPeakList->GetPeakList()[nb-1].dobs; const float dmax=mpPeakList->GetPeakList()[0].dobs/10;//assume there are no peaks at lower resolution mpLog->AppendText(wxString::Format(_T("Predicting volumes from %2u peaks between d=%6.3f and d=%6.3f\n"),nb,1/dmax,1/dmin)); mpLog->AppendText(wxString::Format(_T("Starting indexing using %2u peaks\n"),nb)); mpCellExplorer = new CellExplorer(peaklist,CUBIC,0); mpCellExplorer->SetLengthMinMax(3,25); mpCellExplorer->SetAngleMinMax(90*DEG2RAD,140*DEG2RAD); mpCellExplorer->SetD2Error(0); float weak_f=1.0; if(mpWeakDiffraction->GetValue()) weak_f=0.5; const bool continueOnSolution=mpContinueOnSolution->GetValue(); const bool noCentered=!(mpTryCenteredLattice->GetValue()); const float stopOnScore=50, reportOnScore=10; const unsigned int stopOnDepth=6+int(continueOnSolution), reportOnDepth=4; unsigned int nbSpurious=0; wxProgressDialog dlgProgress(_T("Indexing..."),_T("Starting Indexing in Quick Mode"), 7,this,wxPD_AUTO_HIDE|wxPD_ELAPSED_TIME|wxPD_CAN_ABORT|wxPD_APP_MODAL); unsigned int maxNbSpurious=0; if(mpTrySpurious->GetValue()) maxNbSpurious=2; while(nbSpurious<=maxNbSpurious) { float t0,minv,maxv,lengthmax; mpCellExplorer->SetNbSpurious(nbSpurious); CrystalCentering cent; char centc; for(int lat=0;lat<=2;++lat) { switch(lat) {//LATTICE_P,LATTICE_I,LATTICE_A,LATTICE_B,LATTICE_C,LATTICE_F case 0:cent=LATTICE_P;centc='P';break; case 1:cent=LATTICE_I;centc='I';break; case 2:cent=LATTICE_F;centc='F';break; } minv=EstimateCellVolume(dmin,dmax,nb,CUBIC ,cent,1.5); maxv=EstimateCellVolume(dmin,dmax,nb,CUBIC ,cent,0.4*weak_f); mpCellExplorer->SetVolumeMinMax(minv,maxv); lengthmax=pow(maxv,(float)(1/3.0))*3; if(lengthmax<25)lengthmax=25; mpCellExplorer->SetLengthMinMax(3,lengthmax); mpCellExplorer->SetCrystalSystem(CUBIC); mpCellExplorer->SetCrystalCentering(cent); mpLog->AppendText(wxString::Format(_T("CUBIC %c : V= %6.0f -> %6.0f A^3, max length=%6.2fA"),centc,minv,maxv,lengthmax)); t0=chrono.seconds(); if(dlgProgress.Update(0,wxString::Format(_T("CUBIC %c (%u spurious), V=%6.0f-%6.0f, l<%6.2fA\n") _T("Best Score=%6.1f"),centc, nbSpurious,minv,maxv,lengthmax,mpCellExplorer->GetBestScore()))==false) break; mpCellExplorer->DicVol(reportOnScore,reportOnDepth,stopOnScore,stopOnDepth); mpLog->AppendText(wxString::Format(_T(" -> %3u sols in %6.2fs, best score=%6.1f\n"), (unsigned int)(mpCellExplorer->GetSolutions().size()),chrono.seconds()-t0,mpCellExplorer->GetBestScore())); mpLog->Update(); if(noCentered) break; } for(int lat=0;lat<=1;++lat) if((mpCellExplorer->GetBestScore()<=stopOnScore)||continueOnSolution) { switch(lat) {//LATTICE_P,LATTICE_I,LATTICE_A,LATTICE_B,LATTICE_C,LATTICE_F case 0:cent=LATTICE_P;centc='P';break; case 1:cent=LATTICE_I;centc='I';break; } minv=EstimateCellVolume(dmin,dmax,nb,TETRAGONAL,cent,1.5); maxv=EstimateCellVolume(dmin,dmax,nb,TETRAGONAL,cent,0.4*weak_f); mpCellExplorer->SetVolumeMinMax(minv,maxv); float lengthmax=pow(maxv,(float)(1/3.0))*3; if(lengthmax<25)lengthmax=25; mpCellExplorer->SetLengthMinMax(3,lengthmax); mpCellExplorer->SetCrystalSystem(TETRAGONAL); mpCellExplorer->SetCrystalCentering(cent); mpLog->AppendText(wxString::Format(_T("TETRAGONAL %c : V= %6.0f -> %6.0f A^3, max length=%6.2fA"),centc,minv,maxv,lengthmax)); t0=chrono.seconds(); if(dlgProgress.Update(1,wxString::Format(_T("TETRAGONAL %c (%u spurious), V=%6.0f-%6.0f, l<%6.2fA\n") _T("Best Score=%6.1f"),centc, nbSpurious,minv,maxv,lengthmax,mpCellExplorer->GetBestScore()))==false) break; mpCellExplorer->DicVol(reportOnScore,reportOnDepth,stopOnScore,stopOnDepth); mpLog->AppendText(wxString::Format(_T(" -> %3u sols in %6.2fs, best score=%6.1f\n"), (unsigned int)(mpCellExplorer->GetSolutions().size()),chrono.seconds()-t0,mpCellExplorer->GetBestScore())); mpLog->Update(); if(noCentered) break; } if((mpCellExplorer->GetBestScore()<=stopOnScore)||continueOnSolution) { minv=EstimateCellVolume(dmin,dmax,nb,RHOMBOEDRAL,LATTICE_P,1.5); maxv=EstimateCellVolume(dmin,dmax,nb,RHOMBOEDRAL,LATTICE_P,0.4*weak_f); mpCellExplorer->SetVolumeMinMax(minv,maxv); lengthmax=pow(maxv,(float)(1/3.0))*3; if(lengthmax<25)lengthmax=25; mpCellExplorer->SetLengthMinMax(3,lengthmax); mpCellExplorer->SetCrystalSystem(RHOMBOEDRAL); mpCellExplorer->SetCrystalCentering(LATTICE_P); mpLog->AppendText(wxString::Format(_T("RHOMBOEDRAL : V= %6.0f -> %6.0f A^3, max length=%6.2fA"),minv,maxv,lengthmax)); t0=chrono.seconds(); if(dlgProgress.Update(2,wxString::Format(_T("RHOMBOEDRAL (%u spurious), V=%6.0f-%6.0f, l<%6.2fA\n") _T("Best Score=%6.1f"), nbSpurious,minv,maxv,lengthmax,mpCellExplorer->GetBestScore()))==false) break; mpCellExplorer->DicVol(reportOnScore,reportOnDepth,stopOnScore,stopOnDepth); mpLog->AppendText(wxString::Format(_T(" -> %3u sols in %6.2fs, best score=%6.1f\n"), (unsigned int)(mpCellExplorer->GetSolutions().size()),chrono.seconds()-t0,mpCellExplorer->GetBestScore())); mpLog->Update(); } if((mpCellExplorer->GetBestScore()<=stopOnScore)||continueOnSolution) { minv=EstimateCellVolume(dmin,dmax,nb,HEXAGONAL,LATTICE_P,1.5); maxv=EstimateCellVolume(dmin,dmax,nb,HEXAGONAL,LATTICE_P,0.4*weak_f); mpCellExplorer->SetVolumeMinMax(minv,maxv); lengthmax=pow(maxv,(float)(1/3.0))*3; if(lengthmax<25)lengthmax=25; mpCellExplorer->SetLengthMinMax(3,lengthmax); mpCellExplorer->SetCrystalSystem(HEXAGONAL); mpCellExplorer->SetCrystalCentering(LATTICE_P); mpLog->AppendText(wxString::Format(_T("HEXAGONAL : V= %6.0f -> %6.0f A^3, max length=%6.2fA"),minv,maxv,lengthmax)); t0=chrono.seconds(); if(dlgProgress.Update(3,wxString::Format(_T("HEXAGONAL (%u spurious), V=%6.0f-%6.0f, l<%6.2fA\n") _T("Best Score=%6.1f"), nbSpurious,minv,maxv,lengthmax,mpCellExplorer->GetBestScore()))==false) break; mpCellExplorer->DicVol(reportOnScore,reportOnDepth,stopOnScore,stopOnDepth); mpLog->AppendText(wxString::Format(_T(" -> %3u sols in %6.2fs, best score=%6.1f\n"), (unsigned int)(mpCellExplorer->GetSolutions().size()),chrono.seconds()-t0,mpCellExplorer->GetBestScore())); mpLog->Update(); } for(int lat=0;lat<=5;++lat) if((mpCellExplorer->GetBestScore()<=stopOnScore)||continueOnSolution) { switch(lat) {//LATTICE_P,LATTICE_I,LATTICE_A,LATTICE_B,LATTICE_C,LATTICE_F case 0:cent=LATTICE_P;centc='P';break; case 1:cent=LATTICE_I;centc='I';break; case 2:cent=LATTICE_A;centc='A';break; case 3:cent=LATTICE_B;centc='B';break; case 4:cent=LATTICE_C;centc='C';break; case 5:cent=LATTICE_F;centc='F';break; } minv=EstimateCellVolume(dmin,dmax,nb,ORTHOROMBIC,cent,1.5); maxv=EstimateCellVolume(dmin,dmax,nb,ORTHOROMBIC,cent,0.4*weak_f); mpCellExplorer->SetVolumeMinMax(minv,maxv); lengthmax=pow(maxv,(float)(1/3.0))*3; if(lengthmax<25)lengthmax=25; mpCellExplorer->SetLengthMinMax(3,lengthmax); mpCellExplorer->SetCrystalSystem(ORTHOROMBIC); mpCellExplorer->SetCrystalCentering(cent); mpLog->AppendText(wxString::Format(_T("ORTHOROMBIC %c: V= %6.0f -> %6.0f A^3, max length=%6.2fA"),centc,minv,maxv,lengthmax)); t0=chrono.seconds(); if(dlgProgress.Update(4,wxString::Format(_T("ORTHOROMBIC %c (%u spurious), V=%6.0f-%6.0f, l<%6.2fA\n") _T("Best Score=%6.1f"),centc, nbSpurious,minv,maxv,lengthmax,mpCellExplorer->GetBestScore()))==false) break; mpCellExplorer->DicVol(reportOnScore,reportOnDepth,stopOnScore,stopOnDepth); mpLog->AppendText(wxString::Format(_T(" -> %3u sols in %6.2fs, best score=%6.1f\n"), (unsigned int)(mpCellExplorer->GetSolutions().size()),chrono.seconds()-t0,mpCellExplorer->GetBestScore())); mpLog->Update(); if(noCentered) break; } for(int lat=0;lat<=3;++lat) if((mpCellExplorer->GetBestScore()<=stopOnScore)||continueOnSolution) { switch(lat) {//LATTICE_P,LATTICE_I,LATTICE_A,LATTICE_B,LATTICE_C,LATTICE_F case 0:cent=LATTICE_P;centc='P';break; case 1:cent=LATTICE_C;centc='C';break; case 2:cent=LATTICE_I;centc='I';break; case 3:cent=LATTICE_A;centc='A';break; } minv=EstimateCellVolume(dmin,dmax,nb,MONOCLINIC,cent,1.5); maxv=EstimateCellVolume(dmin,dmax,nb,MONOCLINIC,cent,0.4*weak_f); mpCellExplorer->SetVolumeMinMax(minv,maxv); lengthmax=pow(maxv,(float)(1/3.0))*3; if(lengthmax<25)lengthmax=25; mpCellExplorer->SetLengthMinMax(3,lengthmax); mpCellExplorer->SetCrystalSystem(MONOCLINIC); mpCellExplorer->SetCrystalCentering(cent); mpLog->AppendText(wxString::Format(_T("MONOCLINIC %c : V= %6.0f -> %6.0f A^3, max length=%6.2fA"),centc,minv,maxv,lengthmax)); t0=chrono.seconds(); if(dlgProgress.Update(5,wxString::Format(_T("MONOCLINIC %c (%u spurious), V=%6.0f-%6.0f, l<%6.2fA\n") _T("Best Score=%6.1f"),centc, nbSpurious,minv,maxv,lengthmax,mpCellExplorer->GetBestScore()))==false) break; mpCellExplorer->DicVol(reportOnScore,reportOnDepth,stopOnScore,stopOnDepth); mpLog->AppendText(wxString::Format(_T(" -> %3u sols in %6.2fs, best score=%6.1f\n"), (unsigned int)(mpCellExplorer->GetSolutions().size()),chrono.seconds()-t0,mpCellExplorer->GetBestScore())); mpLog->Update(); if(noCentered) break; } nbSpurious+=1; if((mpCellExplorer->GetBestScore()>=stopOnScore)||(nbSpurious>3)) break; mpLog->AppendText(wxString::Format(_T("\n Trying now with %2u spurious peaks\n"),nbSpurious)); mpLog->Update(); } } else { // Erase spurious record for(vector::iterator pos=mpPeakList->mvHKL.begin();pos!=mpPeakList->mvHKL.end();++pos) pos->isSpurious=false; wxString s; double lmin,lmax,amin=90,amax,vmin,vmax,error,stopOnScore,reportOnScore; long nbspurious,nbPeak,stopOnDepth,reportOnDepth; s=mpLengthMin->GetValue();s.ToDouble(&lmin); s=mpLengthMax->GetValue();s.ToDouble(&lmax); //s=mpAngleMin->GetValue();s.ToDouble(&amin); s=mpAngleMax->GetValue();s.ToDouble(&amax); s=mpVolumeMin->GetValue();s.ToDouble(&vmin); s=mpVolumeMax->GetValue();s.ToDouble(&vmax); s=mpNbSpurious->GetValue();s.ToLong( urious); s=mpNbPeak->GetValue();s.ToLong(&nbPeak); s=mpErrorD->GetValue();s.ToDouble(&error); s=mpStopOnScore->GetValue();s.ToDouble(&stopOnScore); s=mpStopOnDepth->GetValue();s.ToLong(&stopOnDepth); s=mpReportOnScore->GetValue();s.ToDouble(&reportOnScore); s=mpReportOnDepth->GetValue();s.ToLong(&reportOnDepth); // Use at most 30 reflections for indexing if(mpPeakList->GetPeakList().size()>nbPeak) mpPeakList->GetPeakList().resize(nbPeak); mpCellExplorer = new CellExplorer(*mpPeakList,(CrystalSystem)(mpBravais->GetSelection()),0); mpCellExplorer->SetLengthMinMax((float)lmin,(float)lmax); mpCellExplorer->SetAngleMinMax((float)amin*DEG2RAD,(float)amax*DEG2RAD); mpCellExplorer->SetVolumeMinMax((float)vmin,(float)vmax); mpCellExplorer->SetNbSpurious((unsigned int)nbspurious); mpCellExplorer->SetD2Error((float)(error*error)); mpCellExplorer->SetCrystalCentering(LATTICE_P); cout<DicVol(reportOnScore,reportOnDepth,stopOnScore,stopOnDepth); #else if(mpAlgorithm->GetSelection()==0) mpCellExplorer->DicVol(reportOnScore,reportOnDepth,stopOnScore,stopOnDepth); else { for(unsigned int i=0;i<20;++i) { mpCellExplorer->Evolution(5000,true,0.7,0.5,50); if(mpCellExplorer->GetBestScore()>stopOnScore) break; } } #endif } mpLog->AppendText(wxString::Format(_T("Finished indexing, bestscore=%6.1f, elapsed time=%6.2fs\n"), mpCellExplorer->GetBestScore(),chrono.seconds())); // Merge similar solutions - useful here for solutions from different runs/different systems mpCellExplorer->ReduceSolutions(); if(mpCellExplorer->GetSolutions().size()>0) { char buf[200]; wxArrayString sols; float bestvol=0; for(list >::const_iterator pos=mpCellExplorer->GetSolutions().begin(); pos!=mpCellExplorer->GetSolutions().end();++pos) { vector uc=pos->first.DirectUnitCell(); if(pos==mpCellExplorer->GetSolutions().begin()) bestvol=uc[6]*.99999; const float relvol=uc[6]/bestvol; string sys; switch(pos->first.mlattice) { case TRICLINIC:sys="TRICLINIC"; break; case MONOCLINIC:sys="MONOCLINIC"; break; case ORTHOROMBIC:sys="ORTHOROMBIC"; break; case HEXAGONAL:sys="HEXAGONAL"; break; case RHOMBOEDRAL:sys="RHOMBOEDRAL"; break; case TETRAGONAL:sys="TETRAGONAL"; break; case CUBIC:sys="CUBIC"; break; } char centc; switch(pos->first.mCentering) { case LATTICE_P:centc='P'; break; case LATTICE_I:centc='I'; break; case LATTICE_A:centc='A'; break; case LATTICE_B:centc='B'; break; case LATTICE_C:centc='C'; break; case LATTICE_F:centc='F'; break; } stringstream spurious; if(pos->first.mNbSpurious>0) spurious<<"(nbspurious = "<first.mNbSpurious<<")"; sprintf(buf,"Score=%6.1f V=%6.1f(%3.1fV) %6.3f %6.3f %6.3f %6.2f %6.2f %6.2f %s %c %s",pos->second, uc[6],relvol,uc[0],uc[1],uc[2],uc[3]*RAD2DEG,uc[4]*RAD2DEG,uc[5]*RAD2DEG,sys.c_str(),centc,spurious.str().c_str()); //cout<Set(sols); } if(mpGraph!=0) mpGraph->Refresh(FALSE); } void WXCellExplorer::OnSelectCell(wxCommandEvent &event) { VFN_DEBUG_ENTRY("WXCellExplorer::OnSelectCell()",7) const int choice=mpCell->GetSelection(); if(choice!=wxNOT_FOUND) { wxString s; long nbspurious; s=mpNbSpurious->GetValue();s.ToLong( urious); list >::const_iterator pos=mpCellExplorer->GetSolutions().begin(); for(int i=0;ifirst,nbspurious,true,true,true); if(mpCrystal!=NULL) { // Apply crystal structure list >::const_iterator pos=mpCellExplorer->GetSolutions().begin(); for(int i=0;i uc=pos->first.DirectUnitCell(); mpCrystal->GetPar("a").SetValue(uc[0]); mpCrystal->GetPar("b").SetValue(uc[1]); mpCrystal->GetPar("c").SetValue(uc[2]); mpCrystal->GetPar("alpha").SetValue(uc[3]); mpCrystal->GetPar("beta").SetValue(uc[4]); mpCrystal->GetPar("gamma").SetValue(uc[5]); // Choose the spcegroup with the highest possible symmetry given the centering used. // We only try P, I, F, but also handle others, just in case switch(pos->first.mCentering) { case LATTICE_P: { switch(pos->first.mlattice) { case TRICLINIC:mpCrystal->GetSpaceGroup().ChangeSpaceGroup("P-1");break; case MONOCLINIC:mpCrystal->GetSpaceGroup().ChangeSpaceGroup("P2/m");break; case ORTHOROMBIC:mpCrystal->GetSpaceGroup().ChangeSpaceGroup("Pmmm");break; case HEXAGONAL:mpCrystal->GetSpaceGroup().ChangeSpaceGroup("P6/mmm");break; case RHOMBOEDRAL:mpCrystal->GetSpaceGroup().ChangeSpaceGroup("R-3m");break; case TETRAGONAL:mpCrystal->GetSpaceGroup().ChangeSpaceGroup("P4/mmm");break; case CUBIC:mpCrystal->GetSpaceGroup().ChangeSpaceGroup("Pm-3m");break; } break; } case LATTICE_I: { switch(pos->first.mlattice) { case MONOCLINIC:mpCrystal->GetSpaceGroup().ChangeSpaceGroup("I2/m");break; case ORTHOROMBIC:mpCrystal->GetSpaceGroup().ChangeSpaceGroup("I222");break; case TETRAGONAL:mpCrystal->GetSpaceGroup().ChangeSpaceGroup("I4/mmm");break; case CUBIC:mpCrystal->GetSpaceGroup().ChangeSpaceGroup("Im-3m");break; } break; } case LATTICE_A: { switch(pos->first.mlattice) { case MONOCLINIC:mpCrystal->GetSpaceGroup().ChangeSpaceGroup("A2/m");break; case ORTHOROMBIC:mpCrystal->GetSpaceGroup().ChangeSpaceGroup("Amm2");break; } break; } case LATTICE_C: { switch(pos->first.mlattice) { case MONOCLINIC:mpCrystal->GetSpaceGroup().ChangeSpaceGroup("C2/m");break; case ORTHOROMBIC:mpCrystal->GetSpaceGroup().ChangeSpaceGroup("Cmmm");break; } break; } case LATTICE_F://,LATTICE_A,LATTICE_B,LATTICE_C}; { switch(pos->first.mlattice) { case ORTHOROMBIC:mpCrystal->GetSpaceGroup().ChangeSpaceGroup("Fmmm");break; case CUBIC:mpCrystal->GetSpaceGroup().ChangeSpaceGroup("Fm-3m");break; } break; } } mpCrystal->UpdateDisplay(); } try{ if(mpAutomaticLeBail->GetValue()) { VFN_DEBUG_MESSAGE("WXCellExplorer::OnSelectCell():auto-Le Bail",7); // run Le Bail const bool fitzero=true, fitwidth0=true, fitwidth=true, fiteta=true, fitasym=true, fitdispltransp=false, fitbackgd=true, fitcell=true; wxProgressDialog dlgProgress(_T("Le Bail and Profile Fitting"),_T("Le Bail Fitting, cycle #0/20"), 25,this,wxPD_AUTO_HIDE|wxPD_ELAPSED_TIME|wxPD_CAN_ABORT|wxPD_APP_MODAL); mpDiff->SetExtractionMode(true,true); VFN_DEBUG_MESSAGE("WXCellExplorer::OnSelectCell():auto-Le Bail",7); LSQNumObj lsqobj("Profile Fitting object"); lsqobj.SetRefinedObj(mpDiff->GetParentPowderPattern(),0,true,true); lsqobj.PrepareRefParList(true); lsqobj.SetParIsUsed(gpRefParTypeObjCryst,false); lsqobj.SetParIsUsed(gpRefParTypeScattDataScale,true); lsqobj.SetParIsUsed(gpRefParTypeScattDataProfile,true); lsqobj.SetParIsUsed(gpRefParTypeScattDataCorrPos,true); lsqobj.SetParIsUsed(gpRefParTypeScattDataBackground,true); lsqobj.SetParIsUsed(gpRefParTypeUnitCell,true); lsqobj.SetParIsFixed(gpRefParTypeObjCryst,true); lsqobj.SetParIsFixed(gpRefParTypeScattDataScale,false); std::list vnewpar; std::list vnewpartype; // :TODO: take car of other profiles than pseudo-voigt (DE-PV) // Start from default values // :TODO: store values initially set by user, if any ? lsqobj.GetCompiledRefinedObj().GetPar("Zero").SetValue(0); lsqobj.GetCompiledRefinedObj().GetPar("W").SetValue(0.01*DEG2RAD*DEG2RAD); lsqobj.GetCompiledRefinedObj().GetPar("U").SetValue(0); lsqobj.GetCompiledRefinedObj().GetPar("V").SetValue(0); lsqobj.GetCompiledRefinedObj().GetPar("Eta0").SetValue(0.5); lsqobj.GetCompiledRefinedObj().GetPar("Eta1").SetValue(0); lsqobj.GetCompiledRefinedObj().GetPar("Asym0").SetValue(1); lsqobj.GetCompiledRefinedObj().GetPar("Asym1").SetValue(0); lsqobj.GetCompiledRefinedObj().GetPar("Asym2").SetValue(0); lsqobj.GetCompiledRefinedObj().GetPar("2ThetaDispl").SetValue(0); lsqobj.GetCompiledRefinedObj().GetPar("2ThetaTransp").SetValue(0); // Start from bayesian-optimised background const unsigned int nbcomp= mpGraph->GetWXPowderPattern().GetPowderPattern().GetNbPowderPatternComponent(); for(unsigned int i=0;iGetWXPowderPattern().GetPowderPattern().GetPowderPatternComponent(i).GetClassName()=="PowderPatternBackground") { mpLog->AppendText(wxString::Format(_T("Bayesian optimisation of background\n\n"))); if(dlgProgress.Update(0,_T("Bayesian optimisation of background"))==false) return; PowderPatternBackground *pback=dynamic_cast (&(mpGraph->GetWXPowderPattern().GetPowderPattern().GetPowderPatternComponent(i))); pback->UnFixAllPar(); pback->OptimizeBayesianBackground(); pback->FixAllPar(); } mpLog->AppendText(wxString::Format(_T("Starting 20 Le Bail cycles\n"))); for(int i=0;i<10;++i) { VFN_DEBUG_MESSAGE("WXCellExplorer::OnSelectCell():auto-Le Bail #"<ExtractLeBail(2); mpDiff->GetParentPowderPattern().FitScaleFactorForRw(); VFN_DEBUG_MESSAGE("WXCellExplorer::OnSelectCell():auto-Le Bail #"<GetParentPowderPattern().UpdateDisplay(); if(dlgProgress.Update(i,wxString::Format(_T("Le Bail Fitting, cycle #%d/20"),i*2))==false) return; } mpLog->AppendText(wxString::Format(_T(" => Rwp=%5.3f%%, GoF=%7.3f\n"), mpDiff->GetParentPowderPattern().GetRw()*100, mpDiff->GetParentPowderPattern().GetChi2() /mpDiff->GetParentPowderPattern().GetNbPointUsed())); if(fitzero) vnewpar.push_back(&lsqobj.GetCompiledRefinedObj().GetPar("Zero")); if(fitzero) { mpLog->AppendText(wxString::Format(_T("Fitting zero shift\n"))); if(dlgProgress.Update(11,_T("Fitting zero shift"))==false) return; const bool result = lsqobj.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false); if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n")); vnewpar.clear(); vnewpartype.clear(); mpDiff->GetParentPowderPattern().FitScaleFactorForRw(); mpDiff->GetParentPowderPattern().UpdateDisplay(); mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"), mpDiff->GetParentPowderPattern().GetRw()*100, mpDiff->GetParentPowderPattern().GetChi2() /mpDiff->GetParentPowderPattern().GetNbPointUsed())); } if(fitwidth0) vnewpar.push_back(&lsqobj.GetCompiledRefinedObj().GetPar("W")); if(fitwidth0) { mpLog->AppendText(wxString::Format(_T("Fitting zero constant width\n"))); if(dlgProgress.Update(11,_T("Fitting constant width"))==false) return; const bool result = lsqobj.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false); if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n")); vnewpar.clear(); vnewpartype.clear(); mpDiff->GetParentPowderPattern().FitScaleFactorForRw(); mpDiff->GetParentPowderPattern().UpdateDisplay(); mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"), mpDiff->GetParentPowderPattern().GetRw()*100, mpDiff->GetParentPowderPattern().GetChi2() /mpDiff->GetParentPowderPattern().GetNbPointUsed())); } if(fitwidth) vnewpar.push_back(&lsqobj.GetCompiledRefinedObj().GetPar("U")); if(fitwidth) vnewpar.push_back(&lsqobj.GetCompiledRefinedObj().GetPar("V")); if(fiteta) vnewpar.push_back(&lsqobj.GetCompiledRefinedObj().GetPar("Eta0")); if(fitwidth||fiteta) { mpLog->AppendText(wxString::Format(_T("Fitting width and gaussian/lorentzian fixed mix\n"))); if(dlgProgress.Update(12,_T("Fitting variable width and gaussian/lorentzian fixed mix"))==false) return; const bool result = lsqobj.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false); if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n")); vnewpar.clear(); vnewpartype.clear(); mpDiff->GetParentPowderPattern().FitScaleFactorForRw(); mpDiff->GetParentPowderPattern().UpdateDisplay(); mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"), mpDiff->GetParentPowderPattern().GetRw()*100, mpDiff->GetParentPowderPattern().GetChi2() /mpDiff->GetParentPowderPattern().GetNbPointUsed())); } if(fiteta) vnewpar.push_back(&lsqobj.GetCompiledRefinedObj().GetPar("Eta1")); if(fiteta) { mpLog->AppendText(wxString::Format(_T("Fitting variable width and gaussian/lorentzian mix\n"))); if(dlgProgress.Update(13,_T("Fitting variable width and gaussian/lorentzian mix"))==false) return; const bool result = lsqobj.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false); if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n")); vnewpar.clear(); vnewpartype.clear(); mpDiff->GetParentPowderPattern().FitScaleFactorForRw(); mpDiff->GetParentPowderPattern().UpdateDisplay(); mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"), mpDiff->GetParentPowderPattern().GetRw()*100, mpDiff->GetParentPowderPattern().GetChi2() /mpDiff->GetParentPowderPattern().GetNbPointUsed())); } if(fitasym) vnewpar.push_back(&lsqobj.GetCompiledRefinedObj().GetPar("Asym0")); if(fitasym) vnewpar.push_back(&lsqobj.GetCompiledRefinedObj().GetPar("Asym1")); if(fitasym) vnewpar.push_back(&lsqobj.GetCompiledRefinedObj().GetPar("Asym2")); if(fitdispltransp) vnewpar.push_back(&lsqobj.GetCompiledRefinedObj().GetPar("2ThetaDispl")); if(fitdispltransp) vnewpar.push_back(&lsqobj.GetCompiledRefinedObj().GetPar("2ThetaTransp")); if(fitdispltransp||fitasym) { mpLog->AppendText(wxString::Format(_T("Fitting assymetry and sample displacement/transparency\n"))); if(dlgProgress.Update(14,_T("Fitting assymetry and sample displacement/transparency"))==false) return; const bool result = lsqobj.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false); if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n")); vnewpar.clear(); vnewpartype.clear(); mpDiff->GetParentPowderPattern().FitScaleFactorForRw(); mpDiff->GetParentPowderPattern().UpdateDisplay(); mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"), mpDiff->GetParentPowderPattern().GetRw()*100, mpDiff->GetParentPowderPattern().GetChi2() /mpDiff->GetParentPowderPattern().GetNbPointUsed())); } if(fitbackgd) { lsqobj.SetParIsFixed(gpRefParTypeScattDataBackground,false); // Make sure points beyond max resolution are not optimized const unsigned int nbcomp= mpGraph->GetWXPowderPattern().GetPowderPattern().GetNbPowderPatternComponent(); for(unsigned int i=0;iGetWXPowderPattern().GetPowderPattern().GetPowderPatternComponent(i).GetClassName()=="PowderPatternBackground") { PowderPatternBackground *pback=dynamic_cast (&(mpGraph->GetWXPowderPattern().GetPowderPattern().GetPowderPatternComponent(i))); pback->FixParametersBeyondMaxresolution(lsqobj.GetCompiledRefinedObj()); } for(unsigned int i=0; iAppendText(wxString::Format(_T("Fitting background\n"))); if(dlgProgress.Update(15,_T("Fitting background"))==false) return; const bool result = lsqobj.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false); if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n")); vnewpar.clear(); vnewpartype.clear(); mpDiff->GetParentPowderPattern().FitScaleFactorForRw(); mpDiff->GetParentPowderPattern().UpdateDisplay(); mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"), mpDiff->GetParentPowderPattern().GetRw()*100, mpDiff->GetParentPowderPattern().GetChi2() /mpDiff->GetParentPowderPattern().GetNbPointUsed())); } if(fitcell) vnewpartype.push_back(gpRefParTypeUnitCell); if(fitcell) { mpLog->AppendText(wxString::Format(_T("Fitting unit cell\n"))); if(dlgProgress.Update(16,_T("Fitting unit cell"))==false) return; const bool result = lsqobj.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false); if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n")); vnewpar.clear(); vnewpartype.clear(); mpDiff->GetParentPowderPattern().FitScaleFactorForRw(); mpDiff->GetParentPowderPattern().UpdateDisplay(); mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"), mpDiff->GetParentPowderPattern().GetRw()*100, mpDiff->GetParentPowderPattern().GetChi2() /mpDiff->GetParentPowderPattern().GetNbPointUsed())); } // Run Le Bail again from scratch const REAL lastchi2=mpDiff->GetParentPowderPattern().GetChi2(); CrystVector_REAL lastFhklObsSq; lastFhklObsSq = mpDiff->GetFhklObsSq(); mpDiff->SetExtractionMode(true,true); mpLog->AppendText(wxString::Format(_T("Starting 10 Le Bail cycles\n"))); for(int i=17;i<22;++i) { if(dlgProgress.Update(i,wxString::Format(_T("Le Bail Fitting, cycle #%d/10"),(i-17)*2))==false) return; mpDiff->ExtractLeBail(2); mpDiff->GetParentPowderPattern().FitScaleFactorForRw(); mpDiff->GetParentPowderPattern().UpdateDisplay(); } cout<<"Before/after last Le Bail: "<GetParentPowderPattern().GetChi2()<GetParentPowderPattern().GetChi2() > lastchi2) { mpLog->AppendText(_T("Fit did not improve during last LeBail => reverting to previous intensities\n")); mpDiff->SetFhklObsSq(lastFhklObsSq); mpDiff->GetParentPowderPattern().FitScaleFactorForRw(); } mpLog->AppendText(wxString::Format(_T(" => Rwp=%5.3f%%, GoF=%7.3f\n"), mpDiff->GetParentPowderPattern().GetRw()*100, mpDiff->GetParentPowderPattern().GetChi2() /mpDiff->GetParentPowderPattern().GetNbPointUsed())); // Last fit mpLog->AppendText(wxString::Format(_T("Last fit...\n"))); if(dlgProgress.Update(23,_T("Last fit..."))==false) return; lsqobj.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false); mpDiff->GetParentPowderPattern().FitScaleFactorForRw(); mpLog->AppendText(wxString::Format(_T(" => Rwp=%5.3f%%, GoF=%7.3f\n"), mpDiff->GetParentPowderPattern().GetRw()*100, mpDiff->GetParentPowderPattern().GetChi2() /mpDiff->GetParentPowderPattern().GetNbPointUsed())); mpDiff->GetParentPowderPattern().UpdateDisplay(); mpCrystal->UpdateDisplay(); } } catch(const ObjCrystException &except) { mpLog->AppendText(wxString::Format(_T(" OOPS : refinement diverged ! Aborting."))); } if(mpGraph!=0) mpGraph->Refresh(FALSE); //:TODO: store refined cell parameters, display GoF in cell list } VFN_DEBUG_EXIT("WXCellExplorer::OnSelectCell",7) } void WXCellExplorer::OnApplyCell(wxCommandEvent &event) { const int choice=mpCell->GetSelection(); if((mpCrystal!=0)&&(choice!=wxNOT_FOUND)) { list >::const_iterator pos=mpCellExplorer->GetSolutions().begin(); for(int i=0;i uc=pos->first.DirectUnitCell(); mpCrystal->GetPar("a").SetValue(uc[0]); mpCrystal->GetPar("b").SetValue(uc[1]); mpCrystal->GetPar("c").SetValue(uc[2]); mpCrystal->GetPar("alpha").SetValue(uc[3]); mpCrystal->GetPar("beta").SetValue(uc[4]); mpCrystal->GetPar("gamma").SetValue(uc[5]); mpCrystal->UpdateDisplay(); if(mpGraph!=0) { wxCommandEvent ev(ID_POWDERGRAPH_MENU_UPDATE); mpGraph->OnUpdate(ev); } } } void WXCellExplorer::OnChooseCrystal(wxCommandEvent &event) { VFN_DEBUG_MESSAGE("WXCellExplorer::OnChooseCrystal()",6) WXCrystValidateAllUserInput(); int choice; mpCrystal=WXDialogChooseFromRegistry(gCrystalRegistry,(wxWindow*)this, "Choose a Crystal Structure:",choice); if(0==mpCrystal) { mpFieldCrystal->SetValue("No Crystal chosen"); mpAutomaticLeBail->SetValue(false); } else mpFieldCrystal->SetValue(mpCrystal->GetName()); } void WXCellExplorer::OnAutoLeBail(wxCommandEvent &event) { if(mpGraph==NULL) { mpAutomaticLeBail->SetValue(false); return; } VFN_DEBUG_ENTRY("WXCellExplorer::OnAutoLeBail()",7) // Check if powder pattern has a background phase const unsigned int nbcomp= mpGraph->GetWXPowderPattern().GetPowderPattern().GetNbPowderPatternComponent(); bool needBackground=true; for(unsigned int i=0;iGetWXPowderPattern().GetPowderPattern().GetPowderPatternComponent(i).GetClassName()=="PowderPatternBackground") { needBackground=false; break; }; if(needBackground) { int answer =wxMessageBox(_T("To automatically run profile-fitting\n") _T("and Le Bail extraction, you must have\n") _T("defined a background phase for the pattern\n") _T("and you will need to choose a crystal phase\n\n") _T("Do you want to do that now ?"), _T("Add Background ?"),wxYES_NO|wxICON_QUESTION); if(answer==wxNO) { mpAutomaticLeBail->SetValue(false); return; } wxCommandEvent ev; mpGraph->GetWXPowderPattern().OnMenuAddCompBackgdBayesian(ev); } // Check if a crystal structure has been selected to apply the calculated cell if(mpCrystal==NULL) { if(gCrystalRegistry.GetNb()==0) { mpCrystal=new Crystal(4,5,6,"P1"); mpCrystal->SetName("Indexing Result"); wxTheApp->GetTopWindow()->Layout(); wxTheApp->GetTopWindow()->SendSizeEvent(); } else { int answer =wxMessageBox(_T("To automatically run profile-fitting\n") _T("and Le Bail extraction, you must have\n") _T("defined a Crystal phase to apply the cell to\n\n") _T("Do you want to use an EXISTING crystal structure ?\n") _T("(otherwise a new one will be created for you)"), _T("Select Crystal ?"),wxYES_NO|wxICON_QUESTION); if(answer==wxNO) { mpCrystal=new Crystal(4,5,6,"P1"); mpCrystal->SetName("Indexing Result"); wxTheApp->GetTopWindow()->Layout(); wxTheApp->GetTopWindow()->SendSizeEvent(); } else { wxCommandEvent ev; this->OnChooseCrystal(ev); if(0==mpCrystal) return; } } } // Now make sure this Crystal structure is used by the powder pattern object bool needPowderPatternDiffraction=true; unsigned int nbPowderPatternDiffraction=0; for(unsigned int i=0;iGetWXPowderPattern().GetPowderPattern().GetPowderPatternComponent(i).GetClassName()=="PowderPatternDiffraction") { nbPowderPatternDiffraction++; mpDiff=dynamic_cast (&(mpGraph->GetWXPowderPattern().GetPowderPattern().GetPowderPatternComponent(i))); if(&(mpDiff->GetCrystal())==mpCrystal) { needPowderPatternDiffraction=false; break; } }; VFN_DEBUG_MESSAGE("WXCellExplorer::OnAutoLeBail():needPowderPatternDiffraction=="<0) { int answer =wxMessageBox(_T("To automatically run profile-fitting\n") _T("and Le Bail extraction, you must assign\n") _T("the Crystal to a Diffraction Component\n\n") _T("Do you want to use an already existing one ?"), _T("Use Crystal Phase ?"),wxYES_NO|wxICON_QUESTION); if(answer==wxYES) { //if(nbPowderPatternDiffraction==1) :TODO: handle multiple phases { for(unsigned int i=0;iGetWXPowderPattern().GetPowderPattern().GetPowderPatternComponent(i).GetClassName()=="PowderPatternDiffraction") { mpDiff=dynamic_cast (&(mpGraph->GetWXPowderPattern().GetPowderPattern().GetPowderPatternComponent(i))); mpDiff->SetCrystal(*mpCrystal); return; } } } } else {// Create one crystalline phase VFN_DEBUG_MESSAGE("WXCellExplorer::OnAutoLeBail():Create PowderPatternDiffraction",7) mpDiff=new PowderPatternDiffraction; mpDiff->SetCrystal(*mpCrystal); mpGraph->GetWXPowderPattern().GetPowderPattern().AddPowderPatternComponent(*mpDiff); if(mpGraph->GetWXPowderPattern().GetPowderPattern().GetRadiation().GetWavelengthType()==WAVELENGTH_TOF) { wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,ID_POWDERDIFF_PROFILE_DEPV); wxPostEvent(mpDiff->WXGet(),event); } mpGraph->GetWXPowderPattern().GetPowderPattern().Prepare(); mpGraph->GetWXPowderPattern().CrystUpdate(); wxTheApp->GetTopWindow()->Layout(); wxTheApp->GetTopWindow()->SendSizeEvent(); } } // Limit resolution (:TODO: Take into account density of peask to limit to ~100 reflections) unsigned int nbpeak = mpPeakList->GetPeakList().size(); if(nbpeak>40) nbpeak = 40; REAL max_stol = mpPeakList->GetPeakList()[nbpeak-1].dobs/2; if(max_stol>0.5) max_stol=0.5; mpDiff->GetParentPowderPattern().SetMaxSinThetaOvLambda(max_stol); mpLog->AppendText(wxString::Format(_T("\n\nNOTE: automatically set max(sin(theta)/lambda)=%5.3f (d=%5.2fA) for automatic Le Bail & profile fitting\n\n"), max_stol,1/(2*max_stol))); mpDiff->GetParentPowderPattern().UpdateDisplay(); // If one cell is already selected, do optimization immediately if(mpCell->GetSelection()>=0) { VFN_DEBUG_MESSAGE("WXCellExplorer::OnAutoLeBail()->OnSelectCell()",7) cout<GetSelection()<OnSelectCell(ev); } VFN_DEBUG_EXIT("WXCellExplorer::OnAutoLeBail()",7) } void WXCellExplorer::OnExportIndexingResults(wxCommandEvent &event) { bool ok=true; if(mpCellExplorer==0) ok = false; else { if(mpCellExplorer->GetSolutions().size()==0) ok = false; } if(!ok) { wxMessageDialog dumbUser(this,_T("There are no solutions. Index first !"), _T("Whooops"),wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); return; } wxFileDialog save(this,_T("Choose a file"),_T(""),_T(""),_T("*.csv"),wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if(save.ShowModal() != wxID_OK) return; ofstream out(save.GetPath().ToAscii()); if(!out) return;//:TODO: wxArrayString sols; float bestvol=0; out <<"Score, Volume, Volume/V_best, a, b, c, alpha, beta, gamma, Lattice, Centering, NbSpurious"< >::const_iterator pos=mpCellExplorer->GetSolutions().begin(); pos!=mpCellExplorer->GetSolutions().end();++pos) { vector uc=pos->first.DirectUnitCell(); if(pos==mpCellExplorer->GetSolutions().begin()) bestvol=uc[6]*.99999; const float relvol=uc[6]/bestvol; string sys; switch(pos->first.mlattice) { case TRICLINIC:sys="TRICLINIC"; break; case MONOCLINIC:sys="MONOCLINIC"; break; case ORTHOROMBIC:sys="ORTHOROMBIC"; break; case HEXAGONAL:sys="HEXAGONAL"; break; case RHOMBOEDRAL:sys="RHOMBOEDRAL"; break; case TETRAGONAL:sys="TETRAGONAL"; break; case CUBIC:sys="CUBIC"; break; } char centc; switch(pos->first.mCentering) { case LATTICE_P:centc='P'; break; case LATTICE_I:centc='I'; break; case LATTICE_A:centc='A'; break; case LATTICE_B:centc='B'; break; case LATTICE_C:centc='C'; break; case LATTICE_F:centc='F'; break; } stringstream spurious; if(pos->first.mNbSpurious>0) spurious<<"(nbspurious = "<first.mNbSpurious<<")"; out<second<<","<first.mNbSpurious<Show(TRUE); } void WXPowderPatternGraph::OnChangeScale(wxCommandEvent& event) { VFN_DEBUG_MESSAGE("WXPowderPatternGraph::OnChangeScale()",10) if(event.GetId()==ID_POWDERGRAPH_MENU_XSCALE_DATA) mXScale=0; if(event.GetId()==ID_POWDERGRAPH_MENU_XSCALE_D) mXScale=1; if(event.GetId()==ID_POWDERGRAPH_MENU_XSCALE_2PID) mXScale=2; if(event.GetId()==ID_POWDERGRAPH_MENU_YSCALE_LINEAR)mYScale=0; if(event.GetId()==ID_POWDERGRAPH_MENU_YSCALE_SQRT) mYScale=1; if(event.GetId()==ID_POWDERGRAPH_MENU_YSCALE_LOG10) mYScale=2; mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_XSCALE_DATA, TRUE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_XSCALE_D, TRUE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_XSCALE_2PID, TRUE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_YSCALE_LINEAR, TRUE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_YSCALE_SQRT, TRUE); mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_YSCALE_LOG10, TRUE); if(mXScale==0) mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_XSCALE_DATA, FALSE); if(mXScale==1) mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_XSCALE_D, FALSE); if(mXScale==2) mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_XSCALE_2PID, FALSE); if(mYScale==0)mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_YSCALE_LINEAR, FALSE); if(mYScale==1) mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_YSCALE_SQRT, FALSE); if(mYScale==2) mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_YSCALE_LOG10, FALSE); this->Refresh(false); } void WXPowderPatternGraph::OnLeBail(wxCommandEvent& event) { wxFrame *pFrame=new wxFrame(this,-1,_T("Profile Fitting")); WXProfileFitting *pFit; pFit=new WXProfileFitting(pFrame,&(this->GetWXPowderPattern().GetPowderPattern())); pFrame->Show(true); } void WXPowderPatternGraph::OnKeyDown(wxKeyEvent& event) { wxMutexLocker mlock(mMutex); const long nbPoint=mX.numElements(); switch(event.GetKeyCode()) { case(WXK_LEFT): { const REAL range=mMaxX-mMinX; mMinX -= range/8; if(mX(nbPoint-1)>mX(0)) { if(mMinXmX(0)) { if(mMaxX>=mX(nbPoint-1)) mMaxX=mX(nbPoint-1); } else { if(mMaxX>=mX(0)) mMaxX=mX(0); } mMinX=mMaxX-range; break; } case(WXK_UP): { REAL max=mObs.max(),min=mObs.min(); if(min<1e-6*max)min=1e-6*max; if(mYScale==2) { const REAL range=log10(max)-log10(min); mMinIntensity*=pow(10,range/8); mMaxIntensity*=pow(10,range/8); break; } const REAL range=mMaxIntensity-mMinIntensity; mMinIntensity+=range/8; mMaxIntensity+=range/8; break; } case(WXK_DOWN): { REAL max=mObs.max(),min=mObs.min(); if(min<1e-6*max)min=1e-6*max; if(mYScale==2) { const REAL range=log10(max)-log10(min); mMinIntensity*=pow(10,-range/8); mMaxIntensity*=pow(10,-range/8); break; } const REAL range=mMaxIntensity-mMinIntensity; mMinIntensity-=range/8; if(mMinIntensity<1e-6*max) mMinIntensity=1e-6*max; mMaxIntensity=mMinIntensity+range; break; } case(43):// WXK_ADD ? { if(abs(mMaxX-mMinX)>1) { const REAL halfrange=(mMaxX-mMinX)/2; const REAL middle=(mMaxX+mMinX)/2; mMinX= (long)(middle-halfrange*4./5.); mMaxX = (long)(middle+halfrange*4./5.); } break; } case(45):// WXK_SUBTRACT ? { const REAL halfrange=(mMaxX-mMinX)/2; const REAL middle=(mMaxX+mMinX)/2; mMinX= (long)(middle-halfrange*5./4.); mMaxX = (long)(middle+halfrange*5./4.); if(mX(nbPoint-1)>mX(0)) { if(mMinXmX(nbPoint-1)) mMaxX=mX(nbPoint-1); } else { if(mMinXmX(0)) mMaxX=mX(0); } break; } case(42):// WXK_MULTIPLY { const REAL range=mMaxIntensity-mMinIntensity; mMaxIntensity=mMinIntensity+range*4./5.; break; } case(47):// WXK_DIVIDE { const REAL range=mMaxIntensity-mMinIntensity; mMaxIntensity=mMinIntensity+range*5./4.; break; } default: { VFN_DEBUG_MESSAGE("WXPowderPatternGraph::OnKeyDown(): no command for key #"<Refresh(false); } WXPowderPattern& WXPowderPatternGraph::GetWXPowderPattern(){return *mpPattern;} const WXPowderPattern& WXPowderPatternGraph::GetWXPowderPattern()const{return *mpPattern;} void WXPowderPatternGraph::SetPattern(const CrystVector_REAL &x, const CrystVector_REAL &obs, const CrystVector_REAL &calc, const CrystVector_REAL &sigma, const CrystVector_REAL &chi2Cumul) { VFN_DEBUG_ENTRY("WXPowderPatternGraph::SetPattern(x,obs,calc,sigma)",4) mMutex.Lock(); mX=x; if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) mX*=RAD2DEG; mCalc=calc; //mCalc=SavitzkyGolay(obs,4,2); //mCalc *= -obs.max()/mCalc.max(); mObs=obs; mSigma=sigma; mChi2Cumul=chi2Cumul; // Reset the zoom parameters, only for the first display or if the limits of the // full pattern have changed if( (mMaxX<0) ||(mpPattern->GetPowderPattern().GetClockPowderPatternPar()>mClockAxisLimits)) { mMutex.Unlock(); this->ResetAxisLimits(); mMutex.Lock(); } mvLabelList.clear(); for(unsigned int i=0;iGetPowderPattern().GetNbPowderPatternComponent();++i) mvLabelList.push_back(mpPattern->GetPowderPattern() .GetPowderPatternComponent(i).GetPatternLabelList()); mMutex.Unlock(); // If we only send an OnPaint event, only the parts which have been erased are redrawn // (under windows). SO we must force the complete Refresh of the window... in the // main thread of course... if(true==wxThread::IsMain()) { this->Refresh(false); } else { wxUpdateUIEvent event(ID_POWDER_GRAPH_NEW_PATTERN); wxPostEvent(this,event); } //cout<(x,obs,calc,sigma)<Refresh(false); } void WXPowderPatternGraph::ResetAxisLimits() { wxMutexLocker mlock(mMutex); mMaxIntensity=mObs.max(); mMinIntensity=mObs.min(); const float max=mObs.max(); const float min=mObs.min(); if(max>mMaxIntensity) mMaxIntensity=max; if(minGetSize(&width, &height); REAL xs=x,minx=mMinX,maxx=mMaxX; if(xsmaxx)xs=maxx; float d,mind,maxd; if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) { d=2*mpPattern->GetPowderPattern().X2STOL(xs*DEG2RAD); mind=2*mpPattern->GetPowderPattern().X2STOL(minx*DEG2RAD); maxd=2*mpPattern->GetPowderPattern().X2STOL(maxx*DEG2RAD); } else { d=2*mpPattern->GetPowderPattern().X2STOL(xs); mind=2*mpPattern->GetPowderPattern().X2STOL(minx); maxd=2*mpPattern->GetPowderPattern().X2STOL(maxx); } if(mXScale==1) {xs=d;minx=mind;maxx=maxd;} if(mXScale==2) {xs=2*M_PI*d;minx=2*M_PI*mind;maxx=2*M_PI*maxd;} return (long)(mMargin*3+(xs-minx)*(width-3*mMargin)/(maxx-minx)); } long WXPowderPatternGraph::Point2ScreenX(const long x)const { return this->Data2ScreenX(mX(x)); } long WXPowderPatternGraph::Data2ScreenY(const REAL y)const { wxCoord width,height; this->GetSize(&width, &height); REAL ys=y,miny=mMinIntensity,maxy=mMaxIntensity; if(ysmaxy)ys=maxy; if(mYScale==1) {ys=sqrt(ys) ;miny=sqrt(miny) ;maxy=sqrt(maxy);} if(mYScale==2) {ys=log10(ys);miny=log10(miny);maxy=log10(maxy);} return (long)(height-mMargin-(ys-miny)*(height-2*mMargin)/(maxy-miny)); } REAL WXPowderPatternGraph::Screen2DataX(const long x)const { wxCoord width,height; this->GetSize(&width, &height); REAL minx=mMinX,maxx=mMaxX; float mind,maxd; if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) { mind=2*mpPattern->GetPowderPattern().X2STOL(minx*DEG2RAD); maxd=2*mpPattern->GetPowderPattern().X2STOL(maxx*DEG2RAD); } else { mind=2*mpPattern->GetPowderPattern().X2STOL(minx); maxd=2*mpPattern->GetPowderPattern().X2STOL(maxx); } if(mXScale==1) { minx=mind; maxx=maxd; REAL stol=(minx+(x-mMargin*3)*(maxx-minx)/(REAL)(width-3*mMargin))/2; if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) return mpPattern->GetPowderPattern().STOL2X(stol)*RAD2DEG; else return mpPattern->GetPowderPattern().STOL2X(stol); } if(mXScale==2) { minx=2*M_PI*mind; maxx=2*M_PI*maxd; REAL stol=(minx+(x-mMargin*3)*(maxx-minx)/(REAL)(width-3*mMargin))/(4*M_PI); if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) return mpPattern->GetPowderPattern().STOL2X(stol)*RAD2DEG; else return mpPattern->GetPowderPattern().STOL2X(stol); } return mMinX+(x-mMargin*3)*(mMaxX-mMinX)/(REAL)(width-3*mMargin); } REAL WXPowderPatternGraph::Screen2DataY(const long y)const { wxCoord width,height; this->GetSize(&width, &height); REAL miny=mMinIntensity,maxy=mMaxIntensity; if(mYScale==1) {miny=sqrt(miny) ;maxy=sqrt(maxy);} if(mYScale==2) {miny=log10(miny);maxy=log10(maxy);} REAL ys=miny+(height-mMargin-y)*(maxy-miny)/(REAL)(height-2*mMargin); if(mYScale==1) ys=ys*ys; if(mYScale==2) ys=pow((float)10,(float)ys); return ys; } //////////////////////////////////////////////////////////////////////// // // WXPowderPatternBackgound // //////////////////////////////////////////////////////////////////////// static const long ID_POWDERBACKGROUND_GRID= WXCRYST_ID(); static const long ID_POWDERBACKGROUND_NEWBAYESIAN= WXCRYST_ID(); BEGIN_EVENT_TABLE(WXPowderPatternBackground, wxWindow) EVT_MENU(ID_POWDERBACKGROUND_IMPORT, WXPowderPatternBackground::OnMenuImportUserBackground) EVT_MENU(ID_POWDERBACKGROUND_OPTIMIZEBAYESIAN, WXPowderPatternBackground::OnMenuOptimizeBayesianBackground) EVT_GRID_CMD_CELL_CHANGED(ID_POWDERBACKGROUND_GRID, WXPowderPatternBackground::OnEditGridBackgroundPoint) EVT_MENU(ID_POWDERBACKGROUND_NEWBAYESIAN, WXPowderPatternBackground::OnMenuAutomaticBayesianBackground) END_EVENT_TABLE() WXPowderPatternBackground::WXPowderPatternBackground(wxWindow *parent, PowderPatternBackground *b): WXRefinableObj(parent,b),mpPowderPatternBackground(b),mNeedUpdateUI(false),mIsSelfUpdating(false) { mpWXTitle->SetForegroundColour(wxColour(0,255,0)); //Menu mpMenuBar->AddMenu("Object",ID_REFOBJ_MENU_OBJ); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDERBACKGROUND_IMPORT,"Import"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDERBACKGROUND_OPTIMIZEBAYESIAN, "Bayesian Optimization"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDERBACKGROUND_NEWBAYESIAN, "New Automatic Background (Change Number of Points)"); VFN_DEBUG_MESSAGE(mpMenuBar->GetSize().GetWidth()<<","<GetSize().GetHeight(),10); //mpSizer->SetItemMinSize(mpMenuBar, // mpMenuBar->GetSize().GetWidth(), // mpMenuBar->GetSize().GetHeight()); #ifdef USE_BACKGROUND_MAXLIKE_ERROR WXCrystObjBasic* pFieldModelSigma=mpPowderPatternBackground ->GetPar("ML Model Error").wxCreate(this); mpSizer->Add(pFieldModelSigma,0,wxALIGN_LEFT); mList.Add(pFieldModelSigma); #endif // List of background points wxGridCellAttr* cellAttrFloat = new wxGridCellAttr; cellAttrFloat->SetRenderer(new wxGridCellFloatRenderer(10,3)); cellAttrFloat->SetEditor(new wxGridCellFloatEditor(10,3)); mpGridBackgroundPoint= new wxGrid(this,ID_POWDERBACKGROUND_GRID); mpGridBackgroundPoint->SetSize(400,300); mpGridBackgroundPoint->EnableScrolling(true,true); mpGridBackgroundPoint->SetSizeHints(-1,300,-1,300); mpGridBackgroundPoint->SetDefaultColSize(150); mpGridBackgroundPoint->CreateGrid(0,2); mpGridBackgroundPoint->SetColAttr(0,cellAttrFloat); mpGridBackgroundPoint->SetColAttr(1,cellAttrFloat->Clone()); mpGridBackgroundPoint->SetColLabelValue(0,_T("Position")); mpGridBackgroundPoint->SetColLabelValue(1,_T("Intensity")); mpGridBackgroundPoint->AutoSizeRows(); mpSizer->Add(mpGridBackgroundPoint,0,wxALIGN_LEFT); mpTopSizer->SetSizeHints(this); this->Layout(); this->CrystUpdate(true); } void WXPowderPatternBackground::OnMenuImportUserBackground(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_MESSAGE("WXPowderPatternBackground::OnMenuImportUserBackground()",6) WXCrystValidateAllUserInput(); wxFileDialog *open= new wxFileDialog(this,_T("Choose background file with 2Theta Ibackgd"), _T(""),_T(""),_T("*.*"),wxFD_OPEN | wxFD_FILE_MUST_EXIST); if(open->ShowModal() != wxID_OK) return; mpPowderPatternBackground->ImportUserBackground(string(open->GetPath().ToAscii())); open->Destroy(); } void WXPowderPatternBackground::OnMenuOptimizeBayesianBackground(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXPowderPatternBackground::OnMenuOptimizeBayesianBackground()",6) WXCrystValidateAllUserInput(); mpPowderPatternBackground->UnFixAllPar(); mpPowderPatternBackground->OptimizeBayesianBackground(); mpPowderPatternBackground->FixAllPar(); this->CrystUpdate(); VFN_DEBUG_EXIT("WXPowderPatternBackground::OnMenuOptimizeBayesianBackground()",6) } void WXPowderPatternBackground::OnMenuAutomaticBayesianBackground(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXPowderPatternBackground::OnMenuAutomaticBayesianBackground()",6) WXCrystValidateAllUserInput(); long nbPointSpline=20; wxString mes(_T("Number of Interpolation Points")); wxString s; s.Printf(_T("%ld"),nbPointSpline); wxTextEntryDialog dialog(this,mes,_T("Automatic Bayesian (David-Sivia) Background"), s,wxOK | wxCANCEL); dialog.SetTextValidator(wxTextValidator(wxFILTER_DIGITS)); if(wxID_OK!=dialog.ShowModal()) { VFN_DEBUG_EXIT("WXPowderPatternBackground::OnMenuAutomaticBayesianBackground():Canceled",6) return; } dialog.GetValue().ToLong(&nbPointSpline); wxProgressDialog dlgProgress(_T("Automatic Bayesian Background"),_T("Automatic Background, Initializing..."), 4,this,wxPD_AUTO_HIDE|wxPD_ELAPSED_TIME|wxPD_CAN_ABORT|wxPD_APP_MODAL); if(nbPointSpline<2) nbPointSpline=2; { CrystVector_REAL x(nbPointSpline),backgd(nbPointSpline); const CrystVector_REAL *pObs=&(mpPowderPatternBackground->GetParentPowderPattern().GetPowderPatternObs()); const unsigned long nbPoint=mpPowderPatternBackground->GetParentPowderPattern().GetNbPoint(); const float xmin=mpPowderPatternBackground->GetParentPowderPattern() .GetPowderPatternX()(0), xmax=mpPowderPatternBackground->GetParentPowderPattern() .GetPowderPatternX()(nbPoint-1); for(int i=0;i xmin, but in the right order (TOF) x(i)=xmin+(xmax-xmin)/(REAL)(nbPointSpline-1)*REAL(i); REAL x1=xmin+(xmax-xmin)/(REAL)(nbPointSpline-1)*REAL(i-.2); REAL x2=xmin+(xmax-xmin)/(REAL)(nbPointSpline-1)*REAL(i+.2); long n1=(long)(mpPowderPatternBackground->GetParentPowderPattern().X2Pixel(x1)); long n2=(long)(mpPowderPatternBackground->GetParentPowderPattern().X2Pixel(x2)); if(n1<0) n1=0; if(n2>(long)nbPoint)n2=nbPoint; backgd(i)=(*pObs)(n1); for(long j=n1;jSetInterpPoints(x,backgd); } //mpPowderPatternBackground->GetParentPowderPattern().Prepare(); mpPowderPatternBackground->UnFixAllPar(); mpPowderPatternBackground->GetOption(0).SetChoice(0);//linear if(dlgProgress.Update(1,_T("Automatic Background: Optimizing Linear Model..."))==false) return; mpPowderPatternBackground->OptimizeBayesianBackground(); mpPowderPatternBackground->GetOption(0).SetChoice(1);//spline if(dlgProgress.Update(2,_T("Automatic Background: Optimizing Spline Model..."))==false) return; mpPowderPatternBackground->OptimizeBayesianBackground(); mpPowderPatternBackground->FixAllPar(); this->CrystUpdate(); VFN_DEBUG_EXIT("WXPowderPatternBackground::OnMenuAutomaticBayesianBackground()",6) } void WXPowderPatternBackground::OnEditGridBackgroundPoint(wxGridEvent &e) { if(mIsSelfUpdating) return; WXCrystValidateAllUserInput(); VFN_DEBUG_ENTRY("WXPowderPatternBackground::OnEditGridBackgroundPoint():"<GetCellValue(r,c); if(s!=_T("")) { REAL f=1.0; if(mpPowderPatternBackground->GetParentPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF)f=DEG2RAD; double d; s.ToDouble(&d); if(c==0) { if(d!=mBackgroundInterpPointX(r)) mBackgroundInterpPointX(r)=d*f; } else { if(d!=mBackgroundInterpPointX(r)) mBackgroundInterpPointIntensity(r)=d; } mpPowderPatternBackground->SetInterpPoints(mBackgroundInterpPointX, mBackgroundInterpPointIntensity); // The order of the points might have changed mBackgroundInterpPointX =*(mpPowderPatternBackground->GetInterpPoints().first); mBackgroundInterpPointIntensity=*(mpPowderPatternBackground->GetInterpPoints().second); } mNeedUpdateUI=true, this->UpdateUI(); mpPowderPatternBackground->GetParentPowderPattern().UpdateDisplay(); VFN_DEBUG_EXIT("WXPowderPatternBackground::OnEditGridBackgroundPoint():"<WXRefinableObj::CrystUpdate(uui,false); if(false==mpPowderPatternBackground->IsBeingRefined()) { const long diff=mpPowderPatternBackground->GetInterpPoints().first->numElements() -mpGridBackgroundPoint->GetNumberRows(); if(diff>0) { mNeedUpdateUI=true; mpGridBackgroundPoint->AppendRows(diff); } if(diff<0) { mNeedUpdateUI=true; mpGridBackgroundPoint->DeleteRows(0,-diff); } if(diff==0) if( (MaxDifference(mBackgroundInterpPointX , *(mpPowderPatternBackground->GetInterpPoints().first ))) ||(MaxDifference(mBackgroundInterpPointIntensity, *(mpPowderPatternBackground->GetInterpPoints().second)))) mNeedUpdateUI=true; if(mNeedUpdateUI) { mBackgroundInterpPointX =*(mpPowderPatternBackground->GetInterpPoints().first); mBackgroundInterpPointIntensity=*(mpPowderPatternBackground->GetInterpPoints().second); } } if(lock) mMutex.Unlock(); } void WXPowderPatternBackground::UpdateUI(const bool lock) { if(lock) mMutex.Lock(); if(mNeedUpdateUI) { REAL f=1.0; if(mpPowderPatternBackground->GetParentPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF)f=RAD2DEG; const long nb=mBackgroundInterpPointX.numElements(); mIsSelfUpdating=true; for(long i=0;iSetCellValue(i,0,tmp); tmp.Printf(_T("%f"),mBackgroundInterpPointIntensity(i)); mpGridBackgroundPoint->SetCellValue(i,1,tmp); } mIsSelfUpdating=false; } mNeedUpdateUI=false; this->WXRefinableObj::UpdateUI(false); if(lock) mMutex.Unlock(); } bool WXPowderPatternBackground::Enable(bool e) { if(0!=mpGridBackgroundPoint) mpGridBackgroundPoint->Enable(e); return this->::wxWindow::Enable(e); } //////////////////////////////////////////////////////////////////////// // // WXTexturePhaseMarchDollase // //////////////////////////////////////////////////////////////////////// WXTexturePhaseMarchDollase::WXTexturePhaseMarchDollase(wxWindow *parent, TexturePhaseMarchDollase *pObj, TextureMarchDollase* pTex): WXCrystObjBasic(parent),mpTexturePhaseMarchDollase(pObj) { VFN_DEBUG_ENTRY("WXTexturePhaseMarchDollase::WXTexturePhaseMarchDollase()",5) mpSizer=new wxBoxSizer(wxHORIZONTAL); this->SetSizer(mpSizer); pTex->Print(); WXCrystObjBasic* pFieldFraction=pTex->GetPar(&(pObj->mFraction)).WXCreate(this); mpSizer->Add(pFieldFraction,0,wxALIGN_LEFT); mList.Add(pFieldFraction); WXCrystObjBasic* pFieldMarch=pTex->GetPar(&(pObj->mMarchCoeff)).WXCreate(this); mpSizer->Add(pFieldMarch,0,wxALIGN_LEFT); mList.Add(pFieldMarch); WXCrystObjBasic* pFieldH=pTex->GetPar(&(pObj->mH)).WXCreate(this); mpSizer->Add(pFieldH,0,wxALIGN_LEFT); mList.Add(pFieldH); WXCrystObjBasic* pFieldK=pTex->GetPar(&(pObj->mK)).WXCreate(this); mpSizer->Add(pFieldK,0,wxALIGN_LEFT); mList.Add(pFieldK); WXCrystObjBasic* pFieldL=pTex->GetPar(&(pObj->mL)).WXCreate(this); mpSizer->Add(pFieldL,0,wxALIGN_LEFT); mList.Add(pFieldL); this->CrystUpdate(true); VFN_DEBUG_EXIT("WXTexturePhaseMarchDollase::WXTexturePhaseMarchDollase()",5) } WXTexturePhaseMarchDollase::~WXTexturePhaseMarchDollase() { mpTexturePhaseMarchDollase->WXNotifyDelete(); } void WXTexturePhaseMarchDollase::CrystUpdate(const bool uui,const bool lock) { if(lock) mMutex.Lock(); mList.CrystUpdate(uui,false); if(lock) mMutex.Unlock(); } void WXTexturePhaseMarchDollase::UpdateUI(const bool lock) { if(lock) mMutex.Lock(); mList.UpdateUI(false); if(lock) mMutex.Unlock(); } //////////////////////////////////////////////////////////////////////// // // WXTextureMarchDollase // //////////////////////////////////////////////////////////////////////// BEGIN_EVENT_TABLE(WXTextureMarchDollase, wxWindow) EVT_MENU(ID_POWDERTEXTURE_MENU_ADDPHASE, WXTextureMarchDollase::OnAddTexturePhase) EVT_MENU(ID_POWDERTEXTURE_MENU_DELETEPHASE,WXTextureMarchDollase::OnDeleteTexturePhase) EVT_UPDATE_UI(ID_CRYST_UPDATEUI, WXRefinableObj::OnUpdateUI) END_EVENT_TABLE() WXTextureMarchDollase::WXTextureMarchDollase(wxWindow *parent, TextureMarchDollase*obj): WXRefinableObj(parent,(RefinableObj*)obj),mpTextureMarchDollase(obj) { VFN_DEBUG_ENTRY("WXTextureMarchDollase::WXTextureMarchDollase()",5) // Menu mpMenuBar->AddMenu("Phases",ID_REFOBJ_MENU_OBJ); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDERTEXTURE_MENU_ADDPHASE, "Add Phase"); //existing phases WXRegistry *pWXPhaseRegistry =mpTextureMarchDollase->mPhaseRegistry.WXCreate(this); mpSizer->Add(pWXPhaseRegistry,0,wxALIGN_LEFT); mList.Add(pWXPhaseRegistry); this->CrystUpdate(true); this->SetToolTip(_T("Texture for this crystalline phase.\n") _T("You can describe the preferred orientation using ") _T("the March-Dollase model (use the menu).\n\n") _T("Although possible, it is not recommended to enable ") _T("the global optimization of texture parameters, ") _T("as it is *extremely* slow")); VFN_DEBUG_EXIT("WXTextureMarchDollase::WXTextureMarchDollase()",5) } void WXTextureMarchDollase::OnAddTexturePhase(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXTextureMarchDollase::OnAddTexturePhase()",5) mpTextureMarchDollase->AddPhase(0.,1.,1,0,0); VFN_DEBUG_EXIT("WXTextureMarchDollase::OnAddTexturePhase()",5) } void WXTextureMarchDollase::OnDeleteTexturePhase(wxCommandEvent & WXUNUSED(event)) { } //////////////////////////////////////////////////////////////////////// // // WXTextureEllipsoid // //////////////////////////////////////////////////////////////////////// WXTextureEllipsoid::WXTextureEllipsoid(wxWindow *parent, TextureEllipsoid *pObj): WXCrystObj(parent),mpTextureEllipsoid(pObj) { VFN_DEBUG_ENTRY("WXTextureEllipsoid::WXTextureEllipsoid()",6) mpWXTitle->SetLabel("Texture ellipsoid"); mpWXTitle->SetForegroundColour(wxColour(0,0,255)); // First line wxBoxSizer* sizer1=new wxBoxSizer(wxHORIZONTAL); WXCrystObjBasic* pFieldEPR1=mpTextureEllipsoid->GetPar((long)0).WXCreate(this); WXCrystObjBasic* pFieldEPR2=mpTextureEllipsoid->GetPar(1).WXCreate(this); WXCrystObjBasic* pFieldEPR3=mpTextureEllipsoid->GetPar(2).WXCreate(this); sizer1->Add(pFieldEPR1,0); sizer1->Add(pFieldEPR2,0); sizer1->Add(pFieldEPR3,0); mList.Add(pFieldEPR1); mList.Add(pFieldEPR2); mList.Add(pFieldEPR3); mpSizer->Add(sizer1); pFieldEPR1->SetToolTip(_T("Texture Ellipsoidal function parameters:\n") _T("Icorr = Iobs[ 1 + (EPR1*h^2 + EPR2*k^2 + EPR3*l^2 + EPR4*2hk + EPR5*2hl + EPR6*2kl) * 0.001d^2 ]^-1.5")); pFieldEPR2->SetToolTip(_T("Texture Ellipsoidal function parameters:\n") _T("Icorr = Iobs[ 1 + (EPR1*h^2 + EPR2*k^2 + EPR3*l^2 + EPR4*2hk + EPR5*2hl + EPR6*2kl) * 0.001d^2 ]^-1.5")); pFieldEPR3->SetToolTip(_T("Texture Ellipsoidal function parameters:\n") _T("Icorr = Iobs[ 1 + (EPR1*h^2 + EPR2*k^2 + EPR3*l^2 + EPR4*2hk + EPR5*2hl + EPR6*2kl) * 0.001d^2 ]^-1.5")); // Second line wxBoxSizer* sizer2=new wxBoxSizer(wxHORIZONTAL); WXCrystObjBasic* pFieldEPR4=mpTextureEllipsoid->GetPar(3).WXCreate(this); WXCrystObjBasic* pFieldEPR5=mpTextureEllipsoid->GetPar(4).WXCreate(this); WXCrystObjBasic* pFieldEPR6=mpTextureEllipsoid->GetPar(5).WXCreate(this); sizer2->Add(pFieldEPR4,0); sizer2->Add(pFieldEPR5,0); sizer2->Add(pFieldEPR6,0); mList.Add(pFieldEPR4); mList.Add(pFieldEPR5); mList.Add(pFieldEPR6); mpSizer->Add(sizer2); pFieldEPR4->SetToolTip(_T("Texture Ellipsoidal function parameters:\n") _T("Icorr = Iobs[ 1 + (EPR1*h^2 + EPR2*k^2 + EPR3*l^2 + EPR4*2hk + EPR5*2hl + EPR6*2kl) * 0.001d^2 ]^-1.5")); pFieldEPR5->SetToolTip(_T("Texture Ellipsoidal function parameters:\n") _T("Icorr = Iobs[ 1 + (EPR1*h^2 + EPR2*k^2 + EPR3*l^2 + EPR4*2hk + EPR5*2hl + EPR6*2kl) * 0.001d^2 ]^-1.5")); pFieldEPR6->SetToolTip(_T("Texture Ellipsoidal function parameters:\n") _T("Icorr = Iobs[ 1 + (EPR1*h^2 + EPR2*k^2 + EPR3*l^2 + EPR4*2hk + EPR5*2hl + EPR6*2kl) * 0.001d^2 ]^-1.5")); this->CrystUpdate(true); VFN_DEBUG_EXIT("WXTextureEllipsoid::WXTextureEllipsoid()",6) } WXTextureEllipsoid::~WXTextureEllipsoid() { mpTextureEllipsoid->WXNotifyDelete(); } bool WXTextureEllipsoid::OnChangeName(const int id) { return false; } //////////////////////////////////////////////////////////////////////// // // WXPowderPatternDiffraction // //////////////////////////////////////////////////////////////////////// static const long ID_POWDERDIFF_PROFILE= WXCRYST_ID(); static const long ID_POWDERDIFF_PROFILE_PV= WXCRYST_ID(); static const long ID_POWDERDIFF_PROFILE_PV_ANISO= WXCRYST_ID(); static const long ID_POWDERDIFF_LEBAIL= WXCRYST_ID(); static const long ID_POWDERDIFF_PROFILEFITTINGMODE= WXCRYST_ID(); static const long ID_POWDERDIFF_USELOCALLATTICEPAR= WXCRYST_ID(); BEGIN_EVENT_TABLE(WXPowderPatternDiffraction, wxWindow) EVT_BUTTON(ID_POWDERDIFF_CRYSTAL,WXPowderPatternDiffraction::OnChangeCrystal) EVT_MENU(ID_POWDERDIFF_SAVEHKLFCALC, WXPowderPatternDiffraction::OnMenuSaveHKLFcalc) EVT_MENU(ID_POWDERDIFF_PROFILE_PV, WXPowderPatternDiffraction::OnChangeProfile) EVT_MENU(ID_POWDERDIFF_PROFILE_PV_ANISO, WXPowderPatternDiffraction::OnChangeProfile) EVT_MENU(ID_POWDERDIFF_PROFILE_DEPV, WXPowderPatternDiffraction::OnChangeProfile) EVT_MENU(ID_POWDERDIFF_LEBAIL, WXPowderPatternDiffraction::OnLeBail) EVT_CHECKBOX(ID_POWDERDIFF_PROFILEFITTINGMODE,WXPowderPatternDiffraction::OnLeBail) EVT_CHECKBOX(ID_POWDERDIFF_USELOCALLATTICEPAR,WXPowderPatternDiffraction::OnFreezeLatticePar) EVT_UPDATE_UI(ID_CRYST_UPDATEUI, WXRefinableObj::OnUpdateUI) END_EVENT_TABLE() WXPowderPatternDiffraction::WXPowderPatternDiffraction(wxWindow *parent, PowderPatternDiffraction *p): WXRefinableObj(parent,p),mpPowderPatternDiffraction(p), mFreezeLatticePar(false),mFrozenLatticePar(6),mNeedLayout(false) { VFN_DEBUG_ENTRY("WXPowderPatternDiffraction::WXPowderPatternDiffraction()",6) mpWXTitle->SetForegroundColour(wxColour(0,255,0)); //Menu mpMenuBar->AddMenu("File",ID_REFOBJ_MENU_OBJ); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDERDIFF_SAVEHKLFCALC, "Save HKL Fcalc"); mpMenuBar->AddMenu("Profile",ID_POWDERDIFF_PROFILE); mpMenuBar->AddMenuItem(ID_POWDERDIFF_PROFILE,ID_POWDERDIFF_PROFILE_PV, "Pseudo-Voigt (X-Ray & monochromatic neutron)"); mpMenuBar->AddMenuItem(ID_POWDERDIFF_PROFILE,ID_POWDERDIFF_PROFILE_PV_ANISO, "Anisotropic Pseudo-Voigt (X-Ray & monochromatic neutron)"); mpMenuBar->AddMenuItem(ID_POWDERDIFF_PROFILE,ID_POWDERDIFF_PROFILE_DEPV, "Double-Exponential Pseudo-Voigt (neutron TOF)"); mpMenuBar->GetMenu(ID_POWDERDIFF_PROFILE).AppendSeparator(); mpMenuBar->AddMenuItem(ID_POWDERDIFF_PROFILE,ID_POWDERDIFF_LEBAIL, "Profile Fitting + Le Bail Extraction"); //mpSizer->SetItemMinSize(mpMenuBar, // mpMenuBar->GetSize().GetWidth(), // mpMenuBar->GetSize().GetHeight()); // Profile Fitting Mode mpProfileFittingMode= new wxCheckBox(this,ID_POWDERDIFF_PROFILEFITTINGMODE, _T("Profile Fitting (Le Bail) Mode")); mpSizer->Add(mpProfileFittingMode,0,wxALIGN_LEFT); // Crystal Choice mpFieldCrystal=new WXFieldChoice(this,ID_POWDERDIFF_CRYSTAL,"Crystal:",300); mpSizer->Add(mpFieldCrystal,0,wxALIGN_LEFT); mList.Add(mpFieldCrystal); mpFieldCrystal->SetToolTip(_T("Crystal structure for this diffraction phase\n") _T("Click on the button to select another structure")); // Freeze lattice par ? wxSizer *pSizerFreezePar=new wxBoxSizer(wxHORIZONTAL); mpFreezeLatticePar= new wxCheckBox(this,ID_POWDERDIFF_USELOCALLATTICEPAR, _T("Freeze lattice par.")); pSizerFreezePar->Add(mpFreezeLatticePar); mpGridFrozenLatticePar=new wxGrid(this,-1,wxDefaultPosition,wxDefaultSize); mpGridFrozenLatticePar->SetColLabelSize(0); mpGridFrozenLatticePar->SetRowLabelSize(0); mpGridFrozenLatticePar->DisableDragRowSize(); pSizerFreezePar->Add(mpGridFrozenLatticePar); mpGridFrozenLatticePar->SetDefaultEditor(new wxGridCellFloatEditor(7,4)); mpGridFrozenLatticePar->SetDefaultRenderer(new wxGridCellFloatRenderer(7,4)); mpGridFrozenLatticePar->EnableScrolling(false,false); mpGridFrozenLatticePar->ShowScrollbars(wxSHOW_SB_NEVER ,wxSHOW_SB_NEVER ); mpGridFrozenLatticePar->CreateGrid(1,6); mpGridFrozenLatticePar->SetDefaultColSize(60); mpGridFrozenLatticePar->EnableEditing(false); mpSizer->AddSpacer(1); mpSizer->Add(pSizerFreezePar); mpSizer->AddSpacer(1); //Global Biso factor WXCrystObjBasic* fieldGlobalBiso =mpPowderPatternDiffraction->GetPar(&(mpPowderPatternDiffraction->mGlobalBiso)) .WXCreate(this); mList.Add(fieldGlobalBiso); mpSizer->Add(fieldGlobalBiso); // Texture (March Dollase WXTextureMarchDollase* pTexMD =new WXTextureMarchDollase(this,&(mpPowderPatternDiffraction->mCorrTextureMarchDollase)); mList.Add(pTexMD); mpSizer->Add(pTexMD); // Texture Ellipsoid WXTextureEllipsoid* pTexEllips =new WXTextureEllipsoid(this,&(mpPowderPatternDiffraction->mCorrTextureEllipsoid)); mList.Add(pTexEllips); mpSizer->Add(pTexEllips); // Profile if(mpPowderPatternDiffraction->mpReflectionProfile!=0) { VFN_DEBUG_ENTRY("WXPowderPatternDiffraction::WXPowderPatternDiffraction()",6) WXCrystObjBasic* pWXProf=mpPowderPatternDiffraction ->mpReflectionProfile->WXCreate(this); mpSizer->Add(pWXProf); mList.Add(pWXProf); VFN_DEBUG_EXIT("WXPowderPatternDiffraction::WXPowderPatternDiffraction()",6) } this->CrystUpdate(true); VFN_DEBUG_EXIT("WXPowderPatternDiffraction::WXPowderPatternDiffraction()",6) } void WXPowderPatternDiffraction::OnChangeCrystal(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_MESSAGE("WXPowderPatternDiffraction::OnChangeCrystal()",6) WXCrystValidateAllUserInput(); int choice; Crystal *cryst=dynamic_cast ( WXDialogChooseFromRegistry(gCrystalRegistry,(wxWindow*)this, "Choose a Crystal Structure:",choice)); if(0==cryst) return; mpPowderPatternDiffraction->SetCrystal(*cryst); this->CrystUpdate(true); } void WXPowderPatternDiffraction::OnMenuSaveHKLFcalc(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_MESSAGE("WXPowderPatternDiffraction::OnMenuSaveHKLFcalc()",6) WXCrystValidateAllUserInput(); wxFileDialog save(this,_T("Choose a file to save to"),_T(""),_T(""),_T("*.txt"),wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if(save.ShowModal() != wxID_OK) return; ofstream out(save.GetPath().ToAscii()); if(!out) return;//:TODO: mpPowderPatternDiffraction->PrintFhklCalc(out); out.close(); } void WXPowderPatternDiffraction::CrystUpdate(const bool uui,const bool lock) { VFN_DEBUG_MESSAGE("WXPowderPatternDiffraction::CrystUpdate()",10) if(lock) mMutex.Lock(); for(unsigned int i=0;i<6;i++) mFrozenLatticePar(i)=mpPowderPatternDiffraction->GetFrozenLatticePar(i); if(mFreezeLatticePar!=mpPowderPatternDiffraction->FreezeLatticePar()) { mFreezeLatticePar=mpPowderPatternDiffraction->FreezeLatticePar(); mNeedLayout=true; } this->WXRefinableObj::CrystUpdate(uui,false); if(lock) mMutex.Unlock(); } void WXPowderPatternDiffraction::UpdateUI(const bool lock) { VFN_DEBUG_MESSAGE("WXPowderPatternDiffraction::UpdateUI()",10) if(lock) mMutex.Lock(); mpFieldCrystal->SetValue(mpPowderPatternDiffraction->GetCrystal().GetName()); mpProfileFittingMode->SetValue(mpPowderPatternDiffraction->GetExtractionMode()); mpPowderPatternDiffraction->mCorrTextureEllipsoid.UpdateEllipsoidPar(); mpGridFrozenLatticePar->Show(mFreezeLatticePar); if(mFreezeLatticePar) { for(unsigned int i=0;i<3;++i) mpGridFrozenLatticePar->SetCellValue(0, i, wxString::Format("%.4f",mFrozenLatticePar(i))); for(unsigned int i=3;i<6;++i) mpGridFrozenLatticePar->SetCellValue(0, i, wxString::Format("%.3f",mFrozenLatticePar(i)*180/M_PI)); } mpFreezeLatticePar->SetValue(mFreezeLatticePar); if(mNeedLayout) { VFN_DEBUG_MESSAGE("WXPowderPatternDiffraction::UpdateUI():Layout !", 10) this->Layout(); mNeedLayout=false; } if(lock) mMutex.Unlock(); this->WXRefinableObj::UpdateUI(lock); } bool WXPowderPatternDiffraction::Enable(bool e) { if(0!=mpGridFrozenLatticePar) mpGridFrozenLatticePar->Enable(e); return this->::wxWindow::Enable(e); } void WXPowderPatternDiffraction::OnChangeProfile(wxCommandEvent & event) { VFN_DEBUG_ENTRY("WXPowderPatternDiffraction::OnChangeProfile()",6) WXCrystValidateAllUserInput(); bool add=false; if(event.GetId()==ID_POWDERDIFF_PROFILE_PV) { if(mpPowderPatternDiffraction->mpReflectionProfile==0) { ReflectionProfilePseudoVoigt *p= new ReflectionProfilePseudoVoigt; mpPowderPatternDiffraction->SetProfile(p); add=true; } else if(mpPowderPatternDiffraction->mpReflectionProfile->GetClassName() !="ReflectionProfilePseudoVoigt") { ReflectionProfilePseudoVoigt *p= new ReflectionProfilePseudoVoigt; if(mpPowderPatternDiffraction->mpReflectionProfile->GetClassName()=="ReflectionProfilePseudoVoigtAnisotropic") { p->GetPar("U").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("U").GetValue()); p->GetPar("V").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("V").GetValue()); p->GetPar("W").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("W").GetValue()); p->GetPar("Eta0").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("Eta0").GetValue()); p->GetPar("Eta1").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("Eta1").GetValue()); p->GetPar("Asym0").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("Asym0").GetValue()); p->GetPar("Asym1").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("Asym1").GetValue()); p->GetPar("Asym2").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("Asym2").GetValue()); } mpPowderPatternDiffraction->SetProfile(p); add=true; } } if(event.GetId()==ID_POWDERDIFF_PROFILE_PV_ANISO) { if(mpPowderPatternDiffraction->mpReflectionProfile==0) { ReflectionProfilePseudoVoigtAnisotropic *p= new ReflectionProfilePseudoVoigtAnisotropic; mpPowderPatternDiffraction->SetProfile(p); add=true; } else if(mpPowderPatternDiffraction->mpReflectionProfile->GetClassName() !="ReflectionProfilePseudoVoigtAnisotropic") { ReflectionProfilePseudoVoigtAnisotropic *p= new ReflectionProfilePseudoVoigtAnisotropic; if(mpPowderPatternDiffraction->mpReflectionProfile->GetClassName()=="ReflectionProfilePseudoVoigt") { p->GetPar("U").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("U").GetValue()); p->GetPar("V").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("V").GetValue()); p->GetPar("W").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("W").GetValue()); p->GetPar("Eta0").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("Eta0").GetValue()); p->GetPar("Eta1").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("Eta1").GetValue()); p->GetPar("Asym0").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("Asym0").GetValue()); p->GetPar("Asym1").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("Asym1").GetValue()); p->GetPar("Asym2").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("Asym2").GetValue()); p->GetPar("X").SetValue(sqrt(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("W").GetValue())); } mpPowderPatternDiffraction->SetProfile(p); add=true; } } if(event.GetId()==ID_POWDERDIFF_PROFILE_DEPV) { if(mpPowderPatternDiffraction->mpReflectionProfile==0) { ReflectionProfileDoubleExponentialPseudoVoigt *p= new ReflectionProfileDoubleExponentialPseudoVoigt (mpPowderPatternDiffraction->GetCrystal()); mpPowderPatternDiffraction->SetProfile(p); add=true; } else if(mpPowderPatternDiffraction->mpReflectionProfile->GetClassName() !="ReflectionProfileDoubleExponentialPseudoVoigt") { ReflectionProfileDoubleExponentialPseudoVoigt *p= new ReflectionProfileDoubleExponentialPseudoVoigt (mpPowderPatternDiffraction->GetCrystal()); mpPowderPatternDiffraction->SetProfile(p); add=true; } } if(add) { mpPowderPatternDiffraction->mpReflectionProfile->WXCreate(this); mList.Add(mpPowderPatternDiffraction->mpReflectionProfile->WXGet()); mpSizer->Add(mpPowderPatternDiffraction->mpReflectionProfile->WXGet()); wxTheApp->GetTopWindow()->Layout(); wxTheApp->GetTopWindow()->SendSizeEvent(); mpPowderPatternDiffraction->GetParentPowderPattern().UpdateDisplay(); } VFN_DEBUG_EXIT("WXPowderPatternDiffraction::OnChangeProfile()",6) } //////////////////////////////////////// WXProfileFitting ///////////////////// static const long ID_PROFILEFITTING_RUN= WXCRYST_ID(); static const long ID_PROFILEFITTING_RUN_MANUAL= WXCRYST_ID(); static const long ID_PROFILEFITTING_EXPLORE_SPG= WXCRYST_ID(); static const long ID_PROFILEFITTING_EXPLORE_SPG_QUICK= WXCRYST_ID(); BEGIN_EVENT_TABLE(WXProfileFitting, wxWindow) EVT_BUTTON(ID_PROFILEFITTING_RUN, WXProfileFitting::OnFit) EVT_BUTTON(ID_PROFILEFITTING_RUN_MANUAL, WXProfileFitting::OnFit) EVT_BUTTON(ID_PROFILEFITTING_EXPLORE_SPG, WXProfileFitting::OnExploreSpacegroups) EVT_BUTTON(ID_PROFILEFITTING_EXPLORE_SPG_QUICK, WXProfileFitting::OnExploreSpacegroups) END_EVENT_TABLE() WXProfileFitting::WXProfileFitting(wxWindow *parent,PowderPattern *pPattern,PowderPatternDiffraction *pDiff): wxWindow(parent,-1),mpPattern(pPattern),mpDiff(pDiff),mLSQ("Profile Fitting object"),mpList(0) { wxBoxSizer *pSizer0=new wxBoxSizer(wxVERTICAL); this->SetSizer(pSizer0); wxNotebook *pNotebook = new wxNotebook(this, -1,wxDefaultPosition,wxSize(600,400)); pSizer0->Add(pNotebook,0,wxALIGN_CENTER); // Quick interface wxWindow *pQuick=new wxWindow(pNotebook,-1); pNotebook->AddPage(pQuick,_T("Quick Fit"),true); wxBoxSizer *pSizer=new wxBoxSizer(wxVERTICAL); wxButton *pButton1=new wxButton(pQuick,ID_PROFILEFITTING_RUN,_T("Le Bail + Fit Profile !")); pSizer->Add(pButton1,0,wxALIGN_CENTER); if(mpDiff==0) { // List crystal phases wxArrayString choices; { unsigned int nb=mpPattern->GetNbPowderPatternComponent(); for(unsigned int i=0;iGetPowderPatternComponent(i).GetClassName()==string("PowderPatternDiffraction")) { pDiff=dynamic_cast(&(mpPattern->GetPowderPatternComponent(i))); if(pDiff!=0) { cout<<"WXProfileFitting::WXProfileFitting():"<GetPowderPatternComponent(i).GetName() <<","<GetCrystal().GetName()<GetCrystal().GetName().c_str()) +wxString::Format(_T(", a=%6.3f b=%6.3f c=%6.3f"), pDiff->GetCrystal().GetLatticePar(0), pDiff->GetCrystal().GetLatticePar(1), pDiff->GetCrystal().GetLatticePar(2))); //cout<<"WXProfileFitting::WXProfileFitting():"<GetParent()->Destroy(); return; } if(choices.GetCount()==1) { cout<<"WXProfileFitting::WXProfileFitting():"<Add(pLabel,0,wxALIGN_CENTER); mpList=new wxListBox(pQuick,-1,wxDefaultPosition,wxSize(-1,80),choices,wxLB_SINGLE); mpList->SetSelection(0); pSizer->Add(mpList,0,wxALIGN_CENTER); } } if(mpList!=0) { wxArrayInt selections; mpList->GetSelections(selections); const int choice=selections[0]; int ct=0; unsigned int nb=mpPattern->GetNbPowderPatternComponent(); for(unsigned int i=0;iGetPowderPatternComponent(i).GetClassName()==string("PowderPatternDiffraction")) { pDiff=dynamic_cast(&(mpPattern->GetPowderPatternComponent(i))); cout<<"WXProfileFitting::WXProfileFitting():"<GetPowderPatternComponent(i).GetName()<GetPowderPatternComponent(i).GetName()<GetPowderPatternComponent(i).GetName()<GetProfile().GetClassName()=="ReflectionProfileDoubleExponentialPseudoVoigt") { fitChoices.Add(_T("Fit Zero shift")); fitChoices.Add(_T("Fit Instrumental Width (alpha1,beta0,beta1)")); fitChoices.Add(_T("Fit Size/Strain Broadening (sigma1,gamma2)")); fitChoices.Add(_T("Fit Background")); fitChoices.Add(_T("Fit Unit Cell")); } else { fitChoices.Add(_T("Fit Zero shift")); fitChoices.Add(_T("Fit Constant Width")); fitChoices.Add(_T("Fit Variable Width")); fitChoices.Add(_T("Fit Gaussian-Lorentzian Mixing")); fitChoices.Add(_T("Fit Asymmetric parameters")); fitChoices.Add(_T("Fit Displacement+Transparency")); fitChoices.Add(_T("Fit Background")); fitChoices.Add(_T("Fit Unit Cell")); } mpFitCheckList=new wxCheckListBox(pQuick,-1,wxDefaultPosition,wxDefaultSize,fitChoices); if(mpDiff->GetProfile().GetClassName()=="ReflectionProfileDoubleExponentialPseudoVoigt") { mpFitCheckList->Check(0,false); mpFitCheckList->Check(1,false); mpFitCheckList->Check(2,true); mpFitCheckList->Check(3,true); mpFitCheckList->Check(4,true); } else { mpFitCheckList->Check(0,true); mpFitCheckList->Check(1,true); mpFitCheckList->Check(2,true); mpFitCheckList->Check(3,true); mpFitCheckList->Check(4,true); mpFitCheckList->Check(5,true); mpFitCheckList->Check(6,true); mpFitCheckList->Check(7,true); } pSizer->Add(mpFitCheckList,1,wxEXPAND); pQuick->SetSizer(pSizer); pSizer->SetSizeHints(pQuick); pQuick->Layout(); // Manual interface // prepare LSQ object mLSQ.SetRefinedObj(pDiff->GetParentPowderPattern(),0,true,true); mLSQ.PrepareRefParList(true); //mLSQ.SetParIsUsed(gpRefParTypeObjCryst,false); //mLSQ.SetParIsUsed(gpRefParTypeScattDataScale,true); //mLSQ.SetParIsUsed(gpRefParTypeScattDataProfile,true); //mLSQ.SetParIsUsed(gpRefParTypeScattDataCorrPos,true); //mLSQ.SetParIsUsed(gpRefParTypeScattDataBackground,true); //mLSQ.SetParIsUsed(gpRefParTypeUnitCell,true); mLSQ.SetParIsUsed(gpRefParTypeScatt,false); mLSQ.SetParIsUsed(gpRefParTypeScattPow,false); //mLSQ.SetParIsFixed(gpRefParTypeObjCryst,true); //mLSQ.SetParIsFixed(gpRefParTypeScattDataScale,false); // wxLSQ object wxScrolledWindow *pManual=new wxScrolledWindow(pNotebook,-1,wxDefaultPosition, wxSize(400,250),wxHSCROLL | wxVSCROLL); wxBoxSizer *pSizerManual=new wxBoxSizer(wxVERTICAL); wxButton *pButton2=new wxButton(pManual,ID_PROFILEFITTING_RUN_MANUAL,_T("Le Bail + Fit Profile !")); pSizerManual->Add(pButton2,0,wxALIGN_CENTER); //pManual->SetSize(pQuick->GetSize()); pSizerManual->Add(mLSQ.WXCreate(pManual),1,wxALIGN_CENTER); mLSQ.WXGet()->CrystUpdate(true,true); pManual->SetScrollRate(10,10); pManual->SetSizer(pSizerManual); pManual->Layout(); pSizerManual->FitInside(pManual); pNotebook->AddPage(pManual,_T("Manual Fit"),true); // Spacegroup exploration wxScrolledWindow *pSpgExplor=new wxScrolledWindow(pNotebook,-1,wxDefaultPosition, wxSize(600,250),wxHSCROLL | wxVSCROLL); wxBoxSizer *pSizerSpgExplor=new wxBoxSizer(wxVERTICAL); wxButton *pButton3=new wxButton(pSpgExplor,ID_PROFILEFITTING_EXPLORE_SPG,_T("Try all possible spacegroups - Le Bail + Least Squares (SLOW)")); pSizerSpgExplor->Add(pButton3,0,wxALIGN_CENTER); wxButton *pButton4=new wxButton(pSpgExplor,ID_PROFILEFITTING_EXPLORE_SPG_QUICK,_T("Try all possible spacegroups - Le Bail only")); pSizerSpgExplor->Add(pButton4,0,wxALIGN_CENTER); pSpgExplor->SetSizer(pSizerSpgExplor); pSpgExplor->Layout(); pSizerSpgExplor->FitInside(pSpgExplor); pNotebook->AddPage(pSpgExplor,_T("Spacegroup Explorer"),true); pNotebook->ChangeSelection(0); mpLog =new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(600,300),wxTE_MULTILINE|wxTE_READONLY|wxTE_DONTWRAP); mpLog->SetFont(wxFont(10,wxTELETYPE,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL)); pSizer0->Add(mpLog,1,wxEXPAND); mpLog->AppendText(wxString::Format(_T("Profile fitting & Space Group exploration:\n"))); mpLog->AppendText(wxString::Format(_T("\nTo perform a QUICK fit:\n"))); mpLog->AppendText(wxString::Format(_T(" - if you are not too far to a reasonable fit, just use 'Le Bail + Fit profile',\n"))); mpLog->AppendText(wxString::Format(_T(" the parameters will be progressively relaxed to avoid divergence\n"))); mpLog->AppendText(wxString::Format(_T(" - you can also choose to only refine some groups of parameters for more safety\n"))); mpLog->AppendText(wxString::Format(_T("\nYou can also perform a MANUAL fit (nececessary for advanced fit, or anisotropic profiles):\n"))); mpLog->AppendText(wxString::Format(_T(" - select the Manual Fit tab\n"))); mpLog->AppendText(wxString::Format(_T(" - select the individual parameters to refine (check the 'R')\n"))); mpLog->AppendText(wxString::Format(_T(" - you can also set some limits by right-clicking on 'L'\n"))); mpLog->AppendText(wxString::Format(_T("\n Spacegroup exploration:\n"))); mpLog->AppendText(wxString::Format(_T(" - use this after a good profile fitting has been obtained.\n"))); mpLog->AppendText(wxString::Format(_T(" - Fox will try a le Bail Fit on all possible spacegroup settings.\n"))); mpLog->AppendText(wxString::Format(_T(" which are compatible with the current unit cell.\n"))); mpLog->AppendText(wxString::Format(_T(" - try the 'Le Bail only' option first (much faster, no profile fitting for each spacegroup)\n"))); mpLog->AppendText(wxString::Format(_T("---------------------------------------------------------------------------------------------\n\n"))); //pSizer0->Layout(); pSizer0->SetSizeHints(this); //pSizer0->Fit(this); pSizer0->Fit(this->GetParent()); this->Layout(); } WXProfileFitting::~WXProfileFitting() { if(mpDiff!=0) mpDiff->SetExtractionMode(false); else { unsigned int nb=mpPattern->GetNbPowderPatternComponent(); for(unsigned int i=0;iGetPowderPatternComponent(i).GetClassName()==string("PowderPatternDiffraction")) { PowderPatternDiffraction *pDiff=dynamic_cast(&(mpPattern->GetPowderPatternComponent(i))); if(pDiff!=0) pDiff->SetExtractionMode(false); } } mpPattern->UpdateDisplay(); } void WXProfileFitting::OnFit(wxCommandEvent &event) { WXCrystValidateAllUserInput(); // Map of crystalline phases to be fitted (or not) map vpDiff; // Multiple phases can be fitted - which one was chosen ? if(mpList!=0) { wxArrayInt selections; mpList->GetSelections(selections); const int choice=selections[0]; int ct=0; unsigned int nb=mpPattern->GetNbPowderPatternComponent(); for(unsigned int i=0;iGetPowderPatternComponent(i).GetClassName()==string("PowderPatternDiffraction")) { PowderPatternDiffraction *pDiff=dynamic_cast(&(mpPattern->GetPowderPatternComponent(i))); cout<<"WXProfileFitting::WXProfileFitting():"<GetPowderPatternComponent(i).GetName()<GetNbPowderPatternComponent(); for(unsigned int i=0;iGetPowderPatternComponent(i).GetClassName()==string("PowderPatternDiffraction")) { PowderPatternDiffraction *pDiff=dynamic_cast(&(mpPattern->GetPowderPatternComponent(i))); cout<<"WXProfileFitting::WXProfileFitting():"<GetPowderPatternComponent(i).GetName()<GetNbPowderPatternComponent(); unsigned int n=0; const unsigned int n0=mpList->GetSelection(); for(unsigned int i=0;iGetPowderPatternComponent(i).GetClassName()==string("PowderPatternDiffraction")) { pDiff=dynamic_cast(&(mpPattern->GetPowderPatternComponent(i))); if(pDiff!=0) { if(n++==n0) break; } } } } #endif cout<<"Selected PowderPatternDiffraction:"<GetName()<<","<GetCrystal().GetName()<::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) if(pos->second) pos->first->SetExtractionMode(true,true); mpLog->AppendText(wxString::Format(_T("Starting 20 Le Bail cycles\n"))); wxProgressDialog dlgProgress(_T("Le Bail and Profile Fitting"),_T("Le Bail Fitting, cycle #0/20"), 18,this,wxPD_AUTO_HIDE|wxPD_ELAPSED_TIME|wxPD_CAN_ABORT|wxPD_APP_MODAL); for(int i=0;i<10;++i) { for(map::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) if(pos->second) {// Only one should be in LeBail mode, but this code is general pos->first->ExtractLeBail(2); pos->first->GetParentPowderPattern().FitScaleFactorForRw(); pos->first->GetParentPowderPattern().UpdateDisplay(); } if(dlgProgress.Update(i,wxString::Format(_T("Le Bail Fitting, cycle #%d/20"),i*2))==false) return; } mpLog->AppendText(wxString::Format(_T(" => Rwp=%5.3f%%, GoF=%7.3f\n"), mpDiff->GetParentPowderPattern().GetRw()*100, mpDiff->GetParentPowderPattern().GetChi2() /mpDiff->GetParentPowderPattern().GetNbPointUsed())); if(event.GetId()==ID_PROFILEFITTING_RUN) { bool fitzero=false,fitwidth0=false,fitwidth=false,fiteta=false, fitasym=false,fitdispltransp=false,fitbackgd=false,fitcell=false, fitanisotropic=false, fitTOFInstWidth=false,fitTOFBroadening=false; if(mpDiff->GetProfile().GetClassName()=="ReflectionProfileDoubleExponentialPseudoVoigt") { mpDiff->GetProfile().Print(); fitzero=mpFitCheckList->IsChecked(0); fitTOFInstWidth=mpFitCheckList->IsChecked(1); fitTOFBroadening=mpFitCheckList->IsChecked(2); fitbackgd=mpFitCheckList->IsChecked(3); fitcell=mpFitCheckList->IsChecked(4); } else { fitzero=mpFitCheckList->IsChecked(0); fitwidth0=mpFitCheckList->IsChecked(1); fitwidth=mpFitCheckList->IsChecked(2); fiteta=mpFitCheckList->IsChecked(3); fitasym=mpFitCheckList->IsChecked(4); fitdispltransp=mpFitCheckList->IsChecked(5); fitbackgd=mpFitCheckList->IsChecked(6); fitcell=mpFitCheckList->IsChecked(7); } try{ mLSQ.SetParIsFixed(gpRefParTypeScattDataScale,false); std::list vnewpar; std::list vnewpartype; mLSQ.SafeRefine(vnewpar,vnewpartype,2,true,false); if(fitzero) vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("Zero")); if(fitwidth0) for(map::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) if(pos->second) vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("W")); if(fitwidth0) for(map::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) if((pos->second) && (pos->first->GetProfile().GetClassName()=="ReflectionProfilePseudoVoigtAnisotropic")) vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("X")); if(fitzero||fitwidth0) { mpLog->AppendText(wxString::Format(_T("Fitting zero shift && constant width\n"))); if(dlgProgress.Update(11,_T("Fitting zero shift && constant width"))==false) return; const bool result = mLSQ.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false); if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n")); vnewpar.clear(); vnewpartype.clear(); mpDiff->ExtractLeBail(2); mpDiff->GetParentPowderPattern().UpdateDisplay(); mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"), mpDiff->GetParentPowderPattern().GetRw()*100, mpDiff->GetParentPowderPattern().GetChi2() /mpDiff->GetParentPowderPattern().GetNbPointUsed())); } if(fitwidth) for(map::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) if(pos->second) vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("U")); if(fitwidth) for(map::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) if(pos->second) vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("V")); if(fitwidth) for(map::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) if((pos->second) && (pos->first->GetProfile().GetClassName()=="ReflectionProfilePseudoVoigtAnisotropic")) vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("Y")); if(fitwidth) for(map::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) if((pos->second) && (pos->first->GetProfile().GetClassName()=="ReflectionProfilePseudoVoigtAnisotropic")) vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("P")); if(fiteta) for(map::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) if(pos->second) vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("Eta0")); if(fitwidth||fiteta) { mpLog->AppendText(wxString::Format(_T("Fitting width and gaussian/lorentzian fixed mix\n"))); if(dlgProgress.Update(12,_T("Fitting variable width and gaussian/lorentzian fixed mix"))==false) return; const bool result = mLSQ.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false); if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n")); vnewpar.clear(); vnewpartype.clear(); mpDiff->ExtractLeBail(2); mpDiff->GetParentPowderPattern().UpdateDisplay(); mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"), mpDiff->GetParentPowderPattern().GetRw()*100, mpDiff->GetParentPowderPattern().GetChi2() /mpDiff->GetParentPowderPattern().GetNbPointUsed())); } if(fitTOFInstWidth) {// TOF mpDiff->GetProfile().Print(); for(map::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) if(pos->second) { vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("Alpha1")); vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("Beta0")); vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("Beta1")); } mpLog->AppendText(wxString::Format(_T("Fitting TOF instrumental width (alpha1,beta0,beta1)\n"))); if(dlgProgress.Update(12,_T("Fitting TOF instrumental width (alpha1,beta0,beta1)"))==false) return; const bool result = mLSQ.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false); if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n")); vnewpar.clear(); vnewpartype.clear(); mpDiff->ExtractLeBail(2); mpDiff->GetParentPowderPattern().UpdateDisplay(); mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"), mpDiff->GetParentPowderPattern().GetRw()*100, mpDiff->GetParentPowderPattern().GetChi2() /mpDiff->GetParentPowderPattern().GetNbPointUsed())); } if(fitTOFBroadening) {// TOF mpDiff->GetProfile().Print(); for(map::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) if(pos->second) { vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("GaussianSigma1")); //vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("LorentzianGamma2")); //vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("GaussianSigma1")); //vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("LorentzianGamma2")); } mpLog->AppendText(wxString::Format(_T("Fitting size/strain broadening parameters (sigma1,gamma2)\n"))); if(dlgProgress.Update(12,_T("Fitting size/strain broadening parameters (sigma1,gamma2)"))==false) return; const bool result = mLSQ.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false); if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n")); vnewpar.clear(); vnewpartype.clear(); mpDiff->ExtractLeBail(2); mpDiff->GetParentPowderPattern().UpdateDisplay(); mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"), mpDiff->GetParentPowderPattern().GetRw()*100, mpDiff->GetParentPowderPattern().GetChi2() /mpDiff->GetParentPowderPattern().GetNbPointUsed())); for(map::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) if(pos->second) vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("GaussianSigma1")); } if(fiteta) mLSQ.SetParIsFixed(mpDiff->GetProfile().GetPar("Eta1"),false); if(fiteta) { mpLog->AppendText(wxString::Format(_T("Fitting gaussian/lorentzian mix\n"))); if(dlgProgress.Update(13,_T("Fitting variable width and gaussian/lorentzian mix"))==false) return; const bool result = mLSQ.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false); if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n")); vnewpar.clear(); vnewpartype.clear(); mpDiff->ExtractLeBail(2); mpDiff->GetParentPowderPattern().UpdateDisplay(); mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"), mpDiff->GetParentPowderPattern().GetRw()*100, mpDiff->GetParentPowderPattern().GetChi2() /mpDiff->GetParentPowderPattern().GetNbPointUsed())); } if(fitasym) for(map::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) if(pos->second) vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("Asym0")); if(fitasym) for(map::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) if(pos->second) vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("Asym1")); if(fitasym) for(map::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) if(pos->second) vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("Asym2")); if(fitdispltransp) for(map::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) if(pos->second) vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("2ThetaDispl")); if(fitdispltransp) for(map::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) if(pos->second) vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("2ThetaTransp")); if(fitdispltransp||fitasym) { mpLog->AppendText(wxString::Format(_T("Fitting assymetry and sample displacement/transparency\n"))); if(dlgProgress.Update(14,_T("Fitting assymetry and sample displacement/transparency"))==false) return; const bool result = mLSQ.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false); if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n")); vnewpar.clear(); vnewpartype.clear(); mpDiff->ExtractLeBail(2); mpDiff->GetParentPowderPattern().UpdateDisplay(); mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"), mpDiff->GetParentPowderPattern().GetRw()*100, mpDiff->GetParentPowderPattern().GetChi2() /mpDiff->GetParentPowderPattern().GetNbPointUsed())); } if(fitbackgd) { mLSQ.SetParIsFixed(gpRefParTypeScattDataBackground,false); // Make sure points beyond max resolution are not optimized const unsigned int nbcomp= mpDiff->GetParentPowderPattern().GetNbPowderPatternComponent(); for(unsigned int i=0;iGetParentPowderPattern().GetPowderPatternComponent(i).GetClassName()=="PowderPatternBackground") { PowderPatternBackground *pback=dynamic_cast (&(mpDiff->GetParentPowderPattern().GetPowderPatternComponent(i))); pback->FixParametersBeyondMaxresolution(mLSQ.GetCompiledRefinedObj()); } for(unsigned int i=0; iAppendText(wxString::Format(_T("Fitting background\n"))); if(dlgProgress.Update(15,_T("Fitting background"))==false) return; const bool result = mLSQ.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false); if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n")); vnewpar.clear(); vnewpartype.clear(); mpDiff->ExtractLeBail(2); mpDiff->GetParentPowderPattern().UpdateDisplay(); mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"), mpDiff->GetParentPowderPattern().GetRw()*100, mpDiff->GetParentPowderPattern().GetChi2() /mpDiff->GetParentPowderPattern().GetNbPointUsed())); } if(fitcell) { vnewpartype.push_back(gpRefParTypeUnitCell); // Fix uc parameters of unrefined phases for(map::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos) if(!(pos->second)) mLSQ.SetParIsFixed(pos->first->GetCrystal(),true); mpLog->AppendText(wxString::Format(_T("Fitting unit cell\n"))); if(dlgProgress.Update(16,_T("Fitting unit cell"))==false) return; const bool result = mLSQ.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false); if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n")); vnewpar.clear(); vnewpartype.clear(); mpDiff->ExtractLeBail(2); mpDiff->GetParentPowderPattern().UpdateDisplay(); mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"), mpDiff->GetParentPowderPattern().GetRw()*100, mpDiff->GetParentPowderPattern().GetChi2() /mpDiff->GetParentPowderPattern().GetNbPointUsed())); } } catch(const ObjCrystException &except) { mpLog->AppendText(wxString::Format(_T(" OOPS : refinement diverged ! Aborting. Try with fewer parameters ?\n"))); mLSQ.EndOptimization(); } } else {// Manual fit try { std::list vnewpar; std::list vnewpartype; mpLog->AppendText(wxString::Format(_T("Profile fitting (manual):\n"))); mpLog->AppendText(wxString::Format(_T(" Initial values: Rwp=%6.3f%%, GoF=%7.3f\n"), mpDiff->GetParentPowderPattern().GetRw()*100, mpDiff->GetParentPowderPattern().GetChi2() /mpDiff->GetParentPowderPattern().GetNbPointUsed())); mpLog->AppendText(wxString::Format(_T("3 LSQ cycles...\n"))); if(false==mLSQ.SafeRefine(vnewpar, vnewpartype, 1.05, 5,true,false)) mpLog->AppendText(_T(" OUPS: Fit did not improve fit => reverting\n")); mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"), mpDiff->GetParentPowderPattern().GetRw()*100, mpDiff->GetParentPowderPattern().GetChi2() /mpDiff->GetParentPowderPattern().GetNbPointUsed())); mpLog->AppendText(wxString::Format(_T("2 Le Bail cycles...\n"))); if(dlgProgress.Update(9,_T("Manual Le Bail + Profile fitting"))==false) return; mpDiff->ExtractLeBail(2); mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"), mpDiff->GetParentPowderPattern().GetRw()*100, mpDiff->GetParentPowderPattern().GetChi2() /mpDiff->GetParentPowderPattern().GetNbPointUsed())); mpLog->AppendText(wxString::Format(_T("3 LSQ cycles...\n"))); if(dlgProgress.Update(13,_T("Manual Le Bail + Profile fitting"))==false) return; if(false==mLSQ.SafeRefine(vnewpar, vnewpartype, 1.05, 5,true,false)) mpLog->AppendText(_T(" OUPS: Fit did not improve fit => reverting\n")); if(dlgProgress.Update(17,_T("Manual Le Bail + Profile fitting"))==false) return; mpDiff->GetParentPowderPattern().UpdateDisplay(); mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"), mpDiff->GetParentPowderPattern().GetRw()*100, mpDiff->GetParentPowderPattern().GetChi2() /mpDiff->GetParentPowderPattern().GetNbPointUsed())); } catch(const ObjCrystException &except) { mpLog->AppendText(wxString::Format(_T(" OOPS : refinement diverged ! Aborting.\n"))); if(mLSQ.GetCompiledRefinedObj().GetNbParNotFixed() <= 1) mpLog->AppendText(wxString::Format(_T(" You had selected only %ld parameters to refine !!\n"), mLSQ.GetCompiledRefinedObj().GetNbParNotFixed())); else mpLog->AppendText(wxString::Format(_T(" Change selection of parameters to refine ?\n"))); mLSQ.EndOptimization(); } } mLSQ.WXGet()->CrystUpdate(true,true); mpDiff->GetCrystal().UpdateDisplay(); } void WXProfileFitting::OnExploreSpacegroups(wxCommandEvent &event) { WXCrystValidateAllUserInput(); TAU_PROFILE("WXProfileFitting::OnExploreSpacegroups()","void (wxCommandEvent &)",TAU_DEFAULT); PowderPatternDiffraction *pDiff=0; if(mpDiff!=0) pDiff=mpDiff; else { unsigned int nb=mpPattern->GetNbPowderPatternComponent(); unsigned int n=0; const unsigned int n0=mpList->GetSelection(); for(unsigned int i=0;iGetPowderPatternComponent(i).GetClassName()==string("PowderPatternDiffraction")) { pDiff=dynamic_cast(&(mpPattern->GetPowderPatternComponent(i))); if(pDiff!=0) { if(n++==n0) break; } } } } cout<<"Selected PowderPatternDiffraction:"<GetName()<<","<GetCrystal().GetName()<SetExtractionMode(true,true); Crystal *pCrystal=&(pDiff->GetCrystal()); // Keep initial lattice parameters & spg const REAL a=pCrystal->GetLatticePar(0), b=pCrystal->GetLatticePar(1), c=pCrystal->GetLatticePar(2), d=pCrystal->GetLatticePar(3), e=pCrystal->GetLatticePar(4), f=pCrystal->GetLatticePar(5); const string spgname=pCrystal->GetSpaceGroup().GetName(); const string name=pCrystal->GetName(); const cctbx::uctbx::unit_cell uc(scitbx::af::double6(a,b,c,d*RAD2DEG,e*RAD2DEG,f*RAD2DEG)); cctbx::sgtbx::space_group_symbol_iterator it=cctbx::sgtbx::space_group_symbol_iterator(); // First, count compatible spacegroups unsigned int nbspg=0; //unsigned int hmlen=0; for(;;) { cctbx::sgtbx::space_group_symbols s=it.next(); if(s.number()==0) break; cctbx::sgtbx::space_group spg(s); if(spg.is_compatible_unit_cell(uc,0.01,0.1)) nbspg++; //if(s.universal_hermann_mauguin().size()>hmlen) hmlen=s.universal_hermann_mauguin().size(); } mpLog->AppendText(wxString::Format(_T("Beginning spacegroup exploration... %u to go...\n"),nbspg)); //cout<<"Max HM symbol length:"< vSPG; SpaceGroupExplorer ex(pDiff); // we don't have the extinction symbols, so do it the stupid way // create a fingerprint of systematically extinct reflections // for 0,SPGScore> vSPGExtinctionFingerprint; // Nb refl below max sin(theta/lambda) for p1, to compute nGoF unsigned int nb_refl_p1=1; // Try & optimize every spacegroup it=cctbx::sgtbx::space_group_symbol_iterator(); Chronometer chrono; chrono.start(); bool user_stop=false; for(int i=0;;) { cctbx::sgtbx::space_group_symbols s=it.next(); if(s.number()==0) break; cctbx::sgtbx::space_group spg(s); bool compat=spg.is_compatible_unit_cell(uc,0.01,0.1); if(compat) { i++; const string hm=s.universal_hermann_mauguin(); cout<AppendText(wxString::Format(_T(" (#%3d) %-14s:"),s.number(),wxString::FromAscii(hm.c_str()).c_str())); pCrystal->Init(a,b,c,d,e,f,hm,name); std::vector fgp=spgExtinctionFingerprint(*pCrystal,spg); std::map,SPGScore>::iterator posfgp=vSPGExtinctionFingerprint.find(fgp); if(posfgp!=vSPGExtinctionFingerprint.end()) { mpDiff->SetExtractionMode(true,true); //:TODO: why is this needed to actually get the updated GetNbReflBelowMaxSinThetaOvLambda ? unsigned int nbrefl = pDiff->GetNbReflBelowMaxSinThetaOvLambda(); REAL ngof = (posfgp->second.ngof * nbrefl) / posfgp->second.nbreflused; SPGScore score = SPGScore(hm.c_str(),posfgp->second.rw,posfgp->second.gof, posfgp->second.nbextinct446, ngof, nbrefl); vSPG.push_back(score); cout<<"Spacegroup:"<second.hm<AppendText(_T(" same as:")+wxString::FromAscii(posfgp->second.hm.c_str())+_T("\n")); mpLog->AppendText(wxString::Format(_T(" same refl as %13s nGoF=%9.5f (%3u reflections, %3u extinct)\n"), wxString::FromAscii(posfgp->second.hm.c_str()), score.ngof, score.nbreflused, score.nbextinct446)); } else { SPGScore score = ex.Run(spg, event.GetId()==ID_PROFILEFITTING_EXPLORE_SPG, false, false); pDiff->GetParentPowderPattern().UpdateDisplay(); if(s.number() == 1) nb_refl_p1 = score.nbreflused; score.ngof *= mpDiff->GetNbReflBelowMaxSinThetaOvLambda() / (float)nb_refl_p1; if(dlgProgress.Update(i*nbcycle,wxString::FromAscii(hm.c_str())+wxString::Format(_T(" (%u cycles)\n Rwp=%5.2f%%\n GoF=%9.2f"), nbcycle,score.rw,score.gof))==false) user_stop=true; if(user_stop) break; vSPG.push_back(score); mpLog->AppendText(wxString::Format(_T(" Rwp= %5.2f%% GoF=%8.3f nGoF=%9.5f (%3u reflections, %3u extinct)\n"),score.rw,score.gof,score.ngof, score.nbreflused,score.nbextinct446)); vSPGExtinctionFingerprint.insert(make_pair(fgp,score)); } } if(user_stop) break; } // sort results by GoF vSPG.sort(compareSPGScore); mpLog->AppendText(wxString::Format(_T("\n\nBEST Solutions, from min_nGoF to 4*min_nGof:\n"))); mpLog->AppendText(wxString::Format(_T("\nThe number of reflections use for the fit is given, and\n" " \'extinct\' gives the number of extinct reflections\n"))); mpLog->AppendText(wxString::Format(_T(" for 0<=H<=4 0<=K<=4 0<=L<=6 \n\n"))); mpLog->AppendText(wxString::Format(_T("GoF = Chi^2 / nb observed points\n\n"))); mpLog->AppendText(wxString::Format(_T("nGof = iGoF_P1 * (nb_refl) / (nb_refl_P1) \n" " where iGoF_P1 is the integrated Goodness-of-Fit \n" " using P1 integration intervals.\n" " This takes into account the number of used reflections\n" " and is the best indicator\n\n"))); for(list::const_iterator pos=vSPG.begin();pos!=vSPG.end();++pos) { if( (pos->ngof>(4*vSPG.begin()->ngof))) break; mpLog->AppendText(wxString::Format(_T(" Rwp=%5.2f%% GoF=%8.2f nGoF=%9.5f: (%3u reflections, %3u extinct) "),pos->rw,pos->gof,pos->ngof, pos->nbreflused,pos->nbextinct446)+wxString::FromAscii(pos->hm.c_str())+_T(" \n")); } mpLog->AppendText(wxString::Format(_T("\n\nYou can copy the chosen spacegroup symbol in the Crystal window\n"))); mpLog->AppendText(wxString::Format(_T("\n\nThe spacegroup with the best nGoF has been applied\n"))); // Set best solution pCrystal->GetSpaceGroup().ChangeSpaceGroup(vSPG.front().hm); pDiff->GetParentPowderPattern().UpdateDisplay(); pDiff->SetExtractionMode(true,true); pDiff->ExtractLeBail(5); pDiff->GetParentPowderPattern().UpdateDisplay(); ex.RunAll(event.GetId()==ID_PROFILEFITTING_EXPLORE_SPG, true); } void WXPowderPatternDiffraction::OnLeBail(wxCommandEvent &event) { WXCrystValidateAllUserInput(); if((event.GetId()==ID_POWDERDIFF_PROFILEFITTINGMODE)&&(mpProfileFittingMode->GetValue()==false)) { mpPowderPatternDiffraction->SetExtractionMode(false); mpPowderPatternDiffraction->GetParentPowderPattern().UpdateDisplay(); return; } mpPowderPatternDiffraction->SetExtractionMode(true,false); wxFrame *pFrame=new wxFrame(this,-1,_T("Profile Fitting")); WXProfileFitting *pFit; pFit=new WXProfileFitting(pFrame,&(mpPowderPatternDiffraction->GetParentPowderPattern()),mpPowderPatternDiffraction); pFrame->Show(true); } void WXPowderPatternDiffraction::OnFreezeLatticePar(wxCommandEvent &event) { mpPowderPatternDiffraction->FreezeLatticePar(mpFreezeLatticePar->GetValue()); } //////////////////////////////////////////////////////////////////////// // // WXProfilePseudoVoigt // //////////////////////////////////////////////////////////////////////// WXProfilePseudoVoigt::WXProfilePseudoVoigt(wxWindow *parent, ReflectionProfilePseudoVoigt *prof): WXCrystObj(parent),mpProfile(prof) { VFN_DEBUG_ENTRY("WXProfilePseudoVoigt::WXProfilePseudoVoigt()",6) mpWXTitle->SetLabel("Pseudo-Voigt profile"); mpWXTitle->SetForegroundColour(wxColour(0,0,255)); // Width wxBoxSizer* sizer1=new wxBoxSizer(wxHORIZONTAL); WXCrystObjBasic* pFieldCagliotiU=mpProfile->GetPar("U").WXCreate(this); WXCrystObjBasic* pFieldCagliotiV=mpProfile->GetPar("V").WXCreate(this); WXCrystObjBasic* pFieldCagliotiW=mpProfile->GetPar("W").WXCreate(this);; sizer1->Add(pFieldCagliotiU,0); sizer1->Add(pFieldCagliotiV,0); sizer1->Add(pFieldCagliotiW,0); mList.Add(pFieldCagliotiU); mList.Add(pFieldCagliotiV); mList.Add(pFieldCagliotiW); mpSizer->Add(sizer1); pFieldCagliotiU->SetToolTip(_T("Width Parameters (Caglioti's law):\n") _T("fwhm=[W+V*tan(theta)+U*tan^2(theta)]^1/2")); pFieldCagliotiV->SetToolTip(_T("Width Parameters (Caglioti's law):\n") _T("fwhm=[W+V*tan(theta)+U*tan^2(theta)]^1/2")); pFieldCagliotiW->SetToolTip(_T("Width Parameters (Caglioti's law):\n") _T("fwhm=[W+V*tan(theta)+U*tan^2(theta)]^1/2")); // Mixing parameter wxBoxSizer* sizer2=new wxBoxSizer(wxHORIZONTAL); WXCrystObjBasic* pFieldEta0=mpProfile->GetPar("Eta0").WXCreate(this); WXCrystObjBasic* pFieldEta1=mpProfile->GetPar("Eta1").WXCreate(this); sizer2->Add(pFieldEta0,0); sizer2->Add(pFieldEta1,0); mList.Add(pFieldEta0); mList.Add(pFieldEta1); mpSizer->Add(sizer2); pFieldEta0->SetToolTip(_T("Gaussian/Lorentzian mixing parameters:\n") _T(" PV(x) = eta*L(x) + (1-eta)*G(x)\n\n") _T("eta=Eta0+Eta11*2theta")); pFieldEta1->SetToolTip(_T("Gaussian/Lorentzian mixing parameters:\n") _T(" PV(x) = eta*L(x) + (1-eta)*G(x)\n\n") _T("eta=Eta0+Eta11*2theta")); // Asymmetry parameter wxBoxSizer* sizer3=new wxBoxSizer(wxHORIZONTAL); //WXCrystObjBasic* pFieldAsymA0=mpProfile->GetPar("AsymA0").WXCreate(this); //WXCrystObjBasic* pFieldAsymA1=mpProfile->GetPar("AsymA1").WXCreate(this); //WXCrystObjBasic* pFieldAsymB0=mpProfile->GetPar("AsymB0").WXCreate(this); //WXCrystObjBasic* pFieldAsymB1=mpProfile->GetPar("AsymB1").WXCreate(this); //sizer3->Add(pFieldAsymA0,0); //sizer3->Add(pFieldAsymA1,0); //sizer3->Add(pFieldAsymB0,0); //sizer3->Add(pFieldAsymB1,0); //mList.Add(pFieldAsymA0); //mList.Add(pFieldAsymA1); //mList.Add(pFieldAsymB0); //mList.Add(pFieldAsymB1); WXCrystObjBasic* pFieldAsym0=mpProfile->GetPar("Asym0").WXCreate(this); WXCrystObjBasic* pFieldAsym1=mpProfile->GetPar("Asym1").WXCreate(this); WXCrystObjBasic* pFieldAsym2=mpProfile->GetPar("Asym2").WXCreate(this); sizer3->Add(pFieldAsym0,0); sizer3->Add(pFieldAsym1,0); sizer3->Add(pFieldAsym2,0); mList.Add(pFieldAsym0); mList.Add(pFieldAsym1); mList.Add(pFieldAsym2); mpSizer->Add(sizer3); pFieldAsym0->SetToolTip(_T("Asymmetry parameters:\n\n") _T("A=A0+A1/sin(2theta)+A2/sin^2(2theta) ")); pFieldAsym1->SetToolTip(_T("Asymmetry parameters:\n\n") _T("A=A0+A1/sin(2theta)+A2/sin^2(2theta) ")); pFieldAsym2->SetToolTip(_T("Asymmetry parameters:\n\n") _T("A=A0+A1/sin(2theta)+A2/sin^2(2theta) ")); this->CrystUpdate(true); VFN_DEBUG_EXIT("WXProfilePseudoVoigt::WXProfilePseudoVoigt()",6) } WXProfilePseudoVoigt::~WXProfilePseudoVoigt() { mpProfile->WXNotifyDelete(); } bool WXProfilePseudoVoigt::OnChangeName(const int id) { return false; } //////////////////////////////////////////////////////////////////////// // // WXProfilePseudoVoigtAnisotropic // //////////////////////////////////////////////////////////////////////// WXProfilePseudoVoigtAnisotropic::WXProfilePseudoVoigtAnisotropic(wxWindow *parent, ReflectionProfilePseudoVoigtAnisotropic *prof): WXCrystObj(parent),mpProfile(prof) { VFN_DEBUG_ENTRY("WXProfilePseudoVoigtAnisotropic::WXProfilePseudoVoigtAnisotropic()",6) mpWXTitle->SetLabel("Pseudo-Voigt Anisotropic profile"); mpWXTitle->SetForegroundColour(wxColour(0,0,255)); // Gaussian Width wxBoxSizer* sizer1=new wxBoxSizer(wxHORIZONTAL); WXCrystObjBasic* pFieldCagliotiU=mpProfile->GetPar("U").WXCreate(this); WXCrystObjBasic* pFieldCagliotiV=mpProfile->GetPar("V").WXCreate(this); WXCrystObjBasic* pFieldCagliotiW=mpProfile->GetPar("W").WXCreate(this);; WXCrystObjBasic* pFieldScherrerP=mpProfile->GetPar("P").WXCreate(this);; sizer1->Add(pFieldCagliotiU,0); sizer1->Add(pFieldCagliotiV,0); sizer1->Add(pFieldCagliotiW,0); sizer1->Add(pFieldScherrerP,0); mList.Add(pFieldCagliotiU); mList.Add(pFieldCagliotiV); mList.Add(pFieldCagliotiW); mList.Add(pFieldScherrerP); mpSizer->Add(sizer1); pFieldCagliotiU->SetToolTip(_T("Gaussian Width Parameters:\n") _T("fwhm=[W+V*tan(theta)+U*tan^2(theta)+P/cos^2(theta)]^1/2")); pFieldCagliotiV->SetToolTip(_T("Gaussian Width Parameters:\n") _T("fwhm=[W+V*tan(theta)+U*tan^2(theta)+P/cos^2(theta)]^1/2")); pFieldCagliotiW->SetToolTip(_T("Gaussian Width Parameters:\n") _T("fwhm=[W+V*tan(theta)+U*tan^2(theta)+P/cos^2(theta)]^1/2")); pFieldScherrerP->SetToolTip(_T("Gaussian Width Parameters:\n") _T("fwhm=[W+V*tan(theta)+U*tan^2(theta)+P/cos^2(theta)]^1/2")); // Lorentzian & Mixing parameter wxBoxSizer* sizer2=new wxBoxSizer(wxHORIZONTAL); WXCrystObjBasic* pFieldEta0=mpProfile->GetPar("Eta0").WXCreate(this); WXCrystObjBasic* pFieldEta1=mpProfile->GetPar("Eta1").WXCreate(this); WXCrystObjBasic* pFieldX=mpProfile->GetPar("X").WXCreate(this); WXCrystObjBasic* pFieldY=mpProfile->GetPar("Y").WXCreate(this); sizer2->Add(pFieldEta0,0); sizer2->Add(pFieldEta1,0); sizer2->Add(pFieldX,0); sizer2->Add(pFieldY,0); mList.Add(pFieldX); mList.Add(pFieldY); mList.Add(pFieldEta0); mList.Add(pFieldEta1); mpSizer->Add(sizer2); pFieldEta0->SetToolTip(_T("Gaussian/Lorentzian mixing parameters:\n") _T(" PV(x) = eta*L(x) + (1-eta)*G(x)\n\n") _T("eta=Eta0+Eta11*2theta")); pFieldEta1->SetToolTip(_T("Gaussian/Lorentzian mixing parameters:\n") _T(" PV(x) = eta*L(x) + (1-eta)*G(x)\n\n") _T("eta=Eta0+Eta1*2theta")); pFieldX->SetToolTip(_T("Lorentzian width:\n") _T(" FWHM(x) = X/cos(theta) + (Y + gam_L/sin^2(theta))*tan(theta)\n\n") _T("gam_L=gam_hh*H^2 + gam_kk*K^2 + gam_ll*L^2\n") _T(" +gam_hk*HK + gam_hl*HL + gam_kl*HL")); pFieldY->SetToolTip(_T("Lorentzian width:\n") _T(" FWHM(x) = X/cos(theta) + (Y + gam_L/sin^2(theta))*tan(theta)\n\n") _T("gam_L=gam_hh*H^2 + gam_kk*K^2 + gam_ll*L^2\n") _T(" +gam_hk*HK + gam_hl*HL + gam_kl*HL")); // Anisotropic coefficients wxBoxSizer* sizerA=new wxBoxSizer(wxHORIZONTAL); WXCrystObjBasic* pFieldGHH=mpProfile->GetPar("G_HH").WXCreate(this); WXCrystObjBasic* pFieldGKK=mpProfile->GetPar("G_KK").WXCreate(this); WXCrystObjBasic* pFieldGLL=mpProfile->GetPar("G_LL").WXCreate(this); WXCrystObjBasic* pFieldGHK=mpProfile->GetPar("G_HK").WXCreate(this); WXCrystObjBasic* pFieldGHL=mpProfile->GetPar("G_HL").WXCreate(this); WXCrystObjBasic* pFieldGKL=mpProfile->GetPar("G_KL").WXCreate(this); sizerA->Add(pFieldGHH,0); sizerA->Add(pFieldGKK,0); sizerA->Add(pFieldGLL,0); sizerA->Add(pFieldGHK,0); sizerA->Add(pFieldGHL,0); sizerA->Add(pFieldGKL,0); mList.Add(pFieldGHH); mList.Add(pFieldGKK); mList.Add(pFieldGLL); mList.Add(pFieldGHK); mList.Add(pFieldGHL); mList.Add(pFieldGKL); mpSizer->Add(sizerA); pFieldGHH->SetToolTip(_T("Lorentzian width:\n") _T(" FWHM(x) = X/cos(theta) + (Y + gam_L/sin^2(theta))*tan(theta)\n\n") _T("gam_L=gam_hh*H^2 + gam_kk*K^2 + gam_ll*L^2\n") _T(" +gam_hk*HK + gam_hl*HL + gam_kl*HL")); pFieldGKK->SetToolTip(_T("Lorentzian width:\n") _T(" FWHM(x) = X/cos(theta) + (Y + gam_L/sin^2(theta))*tan(theta)\n\n") _T("gam_L=gam_hh*H^2 + gam_kk*K^2 + gam_ll*L^2\n") _T(" +gam_hk*HK + gam_hl*HL + gam_kl*HL")); pFieldGLL->SetToolTip(_T("Lorentzian width:\n") _T(" FWHM(x) = X/cos(theta) + (Y + gam_L/sin^2(theta))*tan(theta)\n\n") _T("gam_L=gam_hh*H^2 + gam_kk*K^2 + gam_ll*L^2\n") _T(" +gam_hk*HK + gam_hl*HL + gam_kl*HL")); pFieldGHK->SetToolTip(_T("Lorentzian width:\n") _T(" FWHM(x) = X/cos(theta) + (Y + gam_L/sin^2(theta))*tan(theta)\n\n") _T("gam_L=gam_hh*H^2 + gam_kk*K^2 + gam_ll*L^2\n") _T(" +gam_hk*HK + gam_hl*HL + gam_kl*HL")); pFieldGHL->SetToolTip(_T("Lorentzian width:\n") _T(" FWHM(x) = X/cos(theta) + (Y + gam_L/sin^2(theta))*tan(theta)\n\n") _T("gam_L=gam_hh*H^2 + gam_kk*K^2 + gam_ll*L^2\n") _T(" +gam_hk*HK + gam_hl*HL + gam_kl*HL")); pFieldGKL->SetToolTip(_T("Lorentzian width:\n") _T(" FWHM(x) = X/cos(theta) + (Y + gam_L/sin^2(theta))*tan(theta)\n\n") _T("gam_L=gam_hh*H^2 + gam_kk*K^2 + gam_ll*L^2\n") _T(" +gam_hk*HK + gam_hl*HL + gam_kl*HL")); // Asymmetry parameters wxBoxSizer* sizer3=new wxBoxSizer(wxHORIZONTAL); WXCrystObjBasic* pFieldAsym0=mpProfile->GetPar("Asym0").WXCreate(this); WXCrystObjBasic* pFieldAsym1=mpProfile->GetPar("Asym1").WXCreate(this); WXCrystObjBasic* pFieldAsym2=mpProfile->GetPar("Asym2").WXCreate(this); sizer3->Add(pFieldAsym0,0); sizer3->Add(pFieldAsym1,0); sizer3->Add(pFieldAsym2,0); mList.Add(pFieldAsym0); mList.Add(pFieldAsym1); mList.Add(pFieldAsym2); mpSizer->Add(sizer3); pFieldAsym0->SetToolTip(_T("Asymmetry parameters:\n\n") _T("A=A0+A1/sin(2theta)+A2/sin^2(2theta) ")); pFieldAsym1->SetToolTip(_T("Asymmetry parameters:\n\n") _T("A=A0+A1/sin(2theta)+A2/sin^2(2theta) ")); pFieldAsym2->SetToolTip(_T("Asymmetry parameters:\n\n") _T("A=A0+A1/sin(2theta)+A2/sin^2(2theta) ")); this->CrystUpdate(true); VFN_DEBUG_EXIT("WXProfilePseudoVoigtAnisotropic::WXProfilePseudoVoigtAnisotropic()",6) } WXProfilePseudoVoigtAnisotropic::~WXProfilePseudoVoigtAnisotropic() { mpProfile->WXNotifyDelete(); } bool WXProfilePseudoVoigtAnisotropic::OnChangeName(const int id) { return false; } //////////////////////////////////////////////////////////////////////// // // WXProfileDoubleExponentialPseudoVoigt // //////////////////////////////////////////////////////////////////////// WXProfileDoubleExponentialPseudoVoigt::WXProfileDoubleExponentialPseudoVoigt (wxWindow *parent, ReflectionProfileDoubleExponentialPseudoVoigt *prof): WXCrystObj(parent),mpProfile(prof) { VFN_DEBUG_ENTRY("WXProfileDoubleExponentialPseudoVoigt::WXProfileDoubleExponentialPseudoVoigt()",6) mpWXTitle->SetLabel("Double-Exponential Pseudo-Voigt profile (for neutron TOF)"); mpWXTitle->SetForegroundColour(wxColour(0,0,255)); // Instrumental wxBoxSizer* sizer1=new wxBoxSizer(wxHORIZONTAL); WXCrystObjBasic* pFieldCagliotiA0=mpProfile->GetPar("Alpha0").WXCreate(this); WXCrystObjBasic* pFieldCagliotiA =mpProfile->GetPar("Alpha1").WXCreate(this); WXCrystObjBasic* pFieldCagliotiB0=mpProfile->GetPar("Beta0").WXCreate(this); WXCrystObjBasic* pFieldCagliotiB1=mpProfile->GetPar("Beta1").WXCreate(this); sizer1->Add(pFieldCagliotiA0,0); sizer1->Add(pFieldCagliotiA,0); sizer1->Add(pFieldCagliotiB0,0); sizer1->Add(pFieldCagliotiB1,0); mList.Add(pFieldCagliotiA0); mList.Add(pFieldCagliotiA); mList.Add(pFieldCagliotiB0); mList.Add(pFieldCagliotiB1); mpSizer->Add(sizer1); // Instrumental wxBoxSizer* sizer2=new wxBoxSizer(wxHORIZONTAL); WXCrystObjBasic* pFieldSigma0=mpProfile->GetPar("GaussianSigma0").WXCreate(this); WXCrystObjBasic* pFieldSigma1=mpProfile->GetPar("GaussianSigma1").WXCreate(this); WXCrystObjBasic* pFieldSigma2=mpProfile->GetPar("GaussianSigma2").WXCreate(this); sizer2->Add(pFieldSigma0,0); sizer2->Add(pFieldSigma1,0); sizer2->Add(pFieldSigma2,0); mList.Add(pFieldSigma0); mList.Add(pFieldSigma1); mList.Add(pFieldSigma2); mpSizer->Add(sizer2); // Instrumental wxBoxSizer* sizer3=new wxBoxSizer(wxHORIZONTAL); WXCrystObjBasic* pFieldGamma0=mpProfile->GetPar("LorentzianGamma0").WXCreate(this); WXCrystObjBasic* pFieldGamma1=mpProfile->GetPar("LorentzianGamma1").WXCreate(this); WXCrystObjBasic* pFieldGamma2=mpProfile->GetPar("LorentzianGamma2").WXCreate(this); sizer3->Add(pFieldGamma0,0); sizer3->Add(pFieldGamma1,0); sizer3->Add(pFieldGamma2,0); mList.Add(pFieldGamma0); mList.Add(pFieldGamma1); mList.Add(pFieldGamma2); mpSizer->Add(sizer3); this->CrystUpdate(true); VFN_DEBUG_EXIT("WXProfileDoubleExponentialPseudoVoigt::WXProfileDoubleExponentialPseudoVoigt()",6) } WXProfileDoubleExponentialPseudoVoigt::~WXProfileDoubleExponentialPseudoVoigt() { mpProfile->WXNotifyDelete(); } bool WXProfileDoubleExponentialPseudoVoigt::OnChangeName(const int id) { return false; } }// namespace objcryst-2022.1/ObjCryst/wxCryst/wxPowderPattern.h000066400000000000000000000316011430515525000222100ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _VFN_WX_POWDERPATTERN_H_ #define _VFN_WX_POWDERPATTERN_H_ #include "wx/grid.h" #include "ObjCryst/wxCryst/wxRefinableObj.h" #include "ObjCryst/ObjCryst/ScatteringCorr.h" #include "ObjCryst/ObjCryst/PowderPattern.h" #include "ObjCryst/ObjCryst/Indexing.h" namespace ObjCryst { class WXPowderPatternGraph; /// WX Class for PowderPattern objects class WXPowderPattern: public WXRefinableObj { public: WXPowderPattern(wxWindow *parent, PowderPattern*); virtual void CrystUpdate(const bool updateUI=false,const bool mutexlock=false); void OnMenuAddCompBackgd(wxCommandEvent & WXUNUSED(event)); void OnMenuAddCompBackgdBayesian(wxCommandEvent & WXUNUSED(event)); void OnMenuAddCompCryst(wxCommandEvent & WXUNUSED(event)); void OnMenuShowGraph(wxCommandEvent & WXUNUSED(event)); void OnMenuSaveText(wxCommandEvent & WXUNUSED(event)); void OnMenuSimulate(wxCommandEvent & WXUNUSED(event)); void OnMenuImportPattern(wxCommandEvent & WXUNUSED(event)); void OnMenuFitScaleForR(wxCommandEvent & WXUNUSED(event)); void OnMenuFitScaleForRw(wxCommandEvent & WXUNUSED(event)); void OnMenuSavePattern(wxCommandEvent & WXUNUSED(event)); void OnMenuSetWavelength(wxCommandEvent &event); void OnMenuAddExclude(wxCommandEvent & WXUNUSED(event)); /// Profile fitting & Le Bail intensity extraction void OnMenuLeBail(wxCommandEvent &event); void OnMenuExport(wxCommandEvent &event); void NotifyDeleteGraph(); const PowderPattern& GetPowderPattern()const; PowderPattern& GetPowderPattern(); void UpdateUI(const bool mutexlock=false); private: PowderPattern *mpPowderPattern; WXRegistry *mpWXComponent; WXPowderPatternGraph *mpGraph; // Store statistics for display REAL mChi2; REAL mGoF; REAL mRwp; REAL mRp; /// This flag is used to automatically open the powder pattern graph once data has been loaded. bool mPowderPatternWasPreviouslyEmpty; DECLARE_EVENT_TABLE() }; /** Class to display a Powder Pattern (calc,obs) in a graphic window. * * So far only displays calc and obs patterns. * \todo display the difference pattern. Allow to zoom. Display * reflection positions for crystalline phases. */ class WXPowderPatternGraph: public wxWindow { public: /// Constructor. The top frame should have a Status bar with two fields (at least) WXPowderPatternGraph(wxFrame *frame, WXPowderPattern* parent); ~WXPowderPatternGraph(); /// Redraw the spectrum void OnPaint(wxPaintEvent& WXUNUSED(event)); /// Display the Theta and intensity values at the mouse position, in the status bar void OnMouse(wxMouseEvent &event); /// Wheel wan be used to scroll the pattern void OnMouseWheel(wxMouseEvent &event); /// Update the powder spectrum, at the user's request. This calls /// the WXPowderPattern::CrystUpdate(). void OnUpdate(wxCommandEvent & WXUNUSED(event)); /** Update the pattern. This is called by the WXPowderPattern parent. * * \deprecated Rather, use the new WXPowderPatternGraph::SetPattern() which * takes a full vector of x coordinates rather than min & step */ void SetPattern(const CrystVector_REAL &obs, const CrystVector_REAL &calc, const REAL tthetaMin,const REAL tthetaStep, const CrystVector_REAL &sigma, const CrystVector_REAL &chi2Cumul); /** Update the pattern. This is called by the WXPowderPattern parent. * */ void SetPattern(const CrystVector_REAL &x, const CrystVector_REAL &obs, const CrystVector_REAL &calc, const CrystVector_REAL &sigma, const CrystVector_REAL &chi2Cumul); /// Redraw the pattern (special function to ensure complete redrawing under windows...) void OnRedrawNewPattern(wxUpdateUIEvent& WXUNUSED(event)); void OnToggleLabel(wxCommandEvent& WXUNUSED(event)); void OnFindPeaks(wxCommandEvent& WXUNUSED(event)); void OnLoadPeaks(wxCommandEvent& WXUNUSED(event)); void OnSavePeaks(wxCommandEvent& WXUNUSED(event)); /// Add or remove peak void OnChangePeak(wxCommandEvent& WXUNUSED(event)); void OnIndex(wxCommandEvent& WXUNUSED(event)); void OnChangeScale(wxCommandEvent &event); /// Profile fitting & Le Bail intensity extraction void OnLeBail(wxCommandEvent &event); void OnKeyDown(wxKeyEvent& event); void OnSize(wxSizeEvent& event); WXPowderPattern& GetWXPowderPattern(); const WXPowderPattern& GetWXPowderPattern()const; private: /// Reset the limits of the axis to full range. void ResetAxisLimits(); /// Convert X data (2theta) coordinate to screen coordinate (pixel) long Data2ScreenX(const REAL x)const; /// Convert X data (as data point index) to screen coordinate (pixel) long Point2ScreenX(const long x)const; /// Convert Y data (intensity) coordinate to screen coordinate (pixel) long Data2ScreenY(const REAL y)const; /// Convert X screen coordinate (pixel) to data (2theta) coordinate REAL Screen2DataX(const long x)const; /// Convert Y screen coordinate (pixel) to data (intensity) coordinate REAL Screen2DataY(const long y)const; WXPowderPattern *mpPattern; /// Data vectors (Note that when x coordinates are 2theta, they are stored in degrees here) CrystVector_REAL mX,mObs,mCalc,m2theta,mSigma,mChi2Cumul; const long mMargin; const REAL mDiffPercentShift; REAL mMaxIntensity,mMinIntensity,mMinX,mMaxX; /// True if no vertical zoom has been used bool mDefaultIntensityScale; wxFrame *mpParentFrame; /// Mutex to lock the pattern and associated data CrystMutex mMutex; /// Pop-up menu wxMenu* mpPopUpMenu; /// Are we within a dragging event ? bool mIsDragging; /// Remember coordinates at the beginning of the dragging REAL mDraggingX0,mDraggingIntensity0; /// Clock corresponding to when the graph limits where last changed. This /// is compared to PowderPattern::GetClockPowderPatternPar() to know if /// these parameter need to be reset. RefinableObjClock mClockAxisLimits; /// Display labels ? bool mDisplayLabel; /// Display peaks ? bool mDisplayPeak; /// The lists of labels for all components of the powder pattern. list > > mvLabelList; /// List of observed peak positions PeakList mPeakList; /// Scaling options for x and y axis /// x: 0 data (2theta, tof) ; 1: 1/d ; 2: 2pi/d /// y: 0 linear ; 1: sqrt(I) ; 2: log10(I) long mXScale,mYScale; DECLARE_EVENT_TABLE() }; /** Class to display a Powder Pattern Background * * Still very limited ! Only allows to import a list of background * points... * \todo Display the list of background points with the refinable * intensity. Add th possibility to change the points. */ class WXPowderPatternBackground: public WXRefinableObj { public: WXPowderPatternBackground(wxWindow *parent, PowderPatternBackground*); void OnMenuImportUserBackground(wxCommandEvent & WXUNUSED(event)); void OnMenuOptimizeBayesianBackground(wxCommandEvent & WXUNUSED(event)); void OnMenuAutomaticBayesianBackground(wxCommandEvent & WXUNUSED(event)); void OnEditGridBackgroundPoint(wxGridEvent &e); virtual void CrystUpdate(const bool updateUI=false,const bool mutexlock=false); virtual void UpdateUI(const bool mutexlock=false); virtual bool Enable(bool enable=true); private: PowderPatternBackground *mpPowderPatternBackground; wxGrid *mpGridBackgroundPoint; /// Copy of the list of points and intensity mutable CrystVector_REAL mBackgroundInterpPointX,mBackgroundInterpPointIntensity; /// True if the list of points has changed since last displayed bool mNeedUpdateUI; bool mIsSelfUpdating; DECLARE_EVENT_TABLE() }; /** Class to display one Preferred Orientation phase using * the March-Dollase parametrization * */ class WXTexturePhaseMarchDollase: public WXCrystObjBasic { public: WXTexturePhaseMarchDollase(wxWindow *parent, TexturePhaseMarchDollase*,TextureMarchDollase*); ~WXTexturePhaseMarchDollase(); virtual void CrystUpdate(const bool updateUI=false,const bool mutexlock=false); virtual void UpdateUI(const bool mutexlock=false); private: wxBoxSizer *mpSizer; WXCrystObjBasicList mList; TexturePhaseMarchDollase* mpTexturePhaseMarchDollase; }; /** Class to display the Preferred Orientation Correction using * the March-Dollase parametrization * * Allows to add phases, and change the parameters. */ class WXTextureMarchDollase: public WXRefinableObj { public: WXTextureMarchDollase(wxWindow *parent, TextureMarchDollase*); void OnAddTexturePhase(wxCommandEvent & WXUNUSED(event)); void OnDeleteTexturePhase(wxCommandEvent & WXUNUSED(event)); private: TextureMarchDollase* mpTextureMarchDollase; DECLARE_EVENT_TABLE() }; /** Class to display one Preferred Orientation phase using * the Ellipsoid model * */ class WXTextureEllipsoid: public WXCrystObj { public: WXTextureEllipsoid(wxWindow *parent, TextureEllipsoid *prof); virtual ~WXTextureEllipsoid(); virtual bool OnChangeName(const int id); private: TextureEllipsoid* mpTextureEllipsoid; }; /** Class to display a Powder Pattern for a crystalline phase * * Allows to choose the Crystal, as well as the profile * associated to this crystalline phase. */ class WXPowderPatternDiffraction: public WXRefinableObj { public: WXPowderPatternDiffraction(wxWindow *parent, PowderPatternDiffraction*); void OnChangeCrystal(wxCommandEvent & WXUNUSED(event)); void OnMenuSaveHKLFcalc(wxCommandEvent & WXUNUSED(event)); void OnChangeProfile(wxCommandEvent & event); virtual void CrystUpdate(const bool updateUI=false,const bool mutexlock=false); virtual void UpdateUI(const bool mutexlock=false); virtual bool Enable(bool enable=true); /// Perform Le Bail extraction void OnLeBail(wxCommandEvent &event); /// Freeze lattice parameter, which will not follow anymore the Crystal Unitcell values void OnFreezeLatticePar(wxCommandEvent &event); private: PowderPatternDiffraction *mpPowderPatternDiffraction; WXFieldChoice* mpFieldCrystal; wxCheckBox *mpProfileFittingMode; wxCheckBox *mpFreezeLatticePar; wxGrid *mpGridFrozenLatticePar; bool mFreezeLatticePar; CrystVector_REAL mFrozenLatticePar; //Need Layout if we show/hide frozen lattice parameters bool mNeedLayout; DECLARE_EVENT_TABLE() }; /** Class to display a Powder Pattern Pseudo-Voigt Profile * */ class WXProfilePseudoVoigt: public WXCrystObj { public: WXProfilePseudoVoigt(wxWindow *parent, ReflectionProfilePseudoVoigt *prof); virtual ~WXProfilePseudoVoigt(); virtual bool OnChangeName(const int id); private: ReflectionProfilePseudoVoigt *mpProfile; }; /** Class to display a Powder Pattern Pseudo-Voigt Profile with Anisotropic broadening * */ class WXProfilePseudoVoigtAnisotropic: public WXCrystObj { public: WXProfilePseudoVoigtAnisotropic(wxWindow *parent, ReflectionProfilePseudoVoigtAnisotropic *prof); virtual ~WXProfilePseudoVoigtAnisotropic(); virtual bool OnChangeName(const int id); private: ReflectionProfilePseudoVoigtAnisotropic *mpProfile; }; /** Class to display a Powder Pattern Pseudo-Voigt Profile * */ class WXProfileDoubleExponentialPseudoVoigt: public WXCrystObj { public: WXProfileDoubleExponentialPseudoVoigt (wxWindow *parent, ReflectionProfileDoubleExponentialPseudoVoigt *prof); virtual ~WXProfileDoubleExponentialPseudoVoigt(); virtual bool OnChangeName(const int id); private: ReflectionProfileDoubleExponentialPseudoVoigt *mpProfile; }; } //namespace #endif //_VFN_WX_POWDERPATTERN_H_ objcryst-2022.1/ObjCryst/wxCryst/wxRadiation.h000066400000000000000000000032171430515525000213260ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _VFN_WX_RADIATION_H_ #define _VFN_WX_RADIATION_H_ #include "ObjCryst/wxCryst/wxRefinableObj.h" #include "ObjCryst/ObjCryst/ScatteringData.h" namespace ObjCryst { /// WX Class for Radiation class WXRadiation: public WXCrystObjBasic { public: WXRadiation(wxWindow *parent, Radiation*); virtual ~WXRadiation(); virtual void CrystUpdate(const bool updateUI=false,const bool mutexlock=false); virtual void UpdateUI(const bool mutexlock=false); virtual void OnUpdateUI(wxUpdateUIEvent & WXUNUSED(event)); private: Radiation *mpRadiation; WXFieldOption *mpFieldRadType; WXFieldOption *mpFieldWavelengthType; wxBoxSizer *mpSizer; WXCrystObjBasicList mList; DECLARE_EVENT_TABLE() }; }//namespace #endif objcryst-2022.1/ObjCryst/wxCryst/wxRefinableObj.cpp000066400000000000000000000614011430515525000222700ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ //#include //for stringstream #include // wx headers, with or without precompilation #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "ObjCryst/wxCryst/wxRefinableObj.h" #include "ObjCryst/wxCryst/wxRefinableObj.h" #include "ObjCryst/Quirks/VFNStreamFormat.h" #include "ObjCryst/RefinableObj/GlobalOptimObj.h" //These are only for explicit instantiation #include "ObjCryst/ObjCryst/Atom.h" #include "ObjCryst/ObjCryst/Crystal.h" #include "ObjCryst/ObjCryst/DiffractionDataSingleCrystal.h" #include "ObjCryst/ObjCryst/PowderPattern.h" #include "ObjCryst/ObjCryst/ScatteringPower.h" #include "ObjCryst/ObjCryst/ZScatterer.h" #include "ObjCryst/ObjCryst/ScatteringCorr.h" #include "ObjCryst/ObjCryst/ReflectionProfile.h" #include "ObjCryst/Quirks/Chronometer.h" //Fixes for Cygwin; where do those stupid macros come from ? Somewhere in wxMSW headers #ifdef max #undef max #endif #ifdef min #undef min #endif #ifdef DrawText #undef DrawText #endif namespace ObjCryst { /// This pointer records the last wxField in which something was enetered, /// so that it can be validated when inpu is finished (either when another /// input has begun in another field, or when an action requires to purge /// all input extern WXField *spLastWXFieldInputNotValidated; //////////////////////////////////////////////////////////////////////// // // WXFieldRefPar // //////////////////////////////////////////////////////////////////////// static const long ID_WXFIELD_REFPAR =WXCRYST_ID(); static const long ID_WXFIELD_REFPAR_FIXBUTTON =WXCRYST_ID(); static const long ID_WXFIELD_REFPAR_LIMITEDBUTTON=WXCRYST_ID(); static const long ID_REFPAR_POPUP_SET_LIMITS =WXCRYST_ID(); BEGIN_EVENT_TABLE(WXFieldRefPar,wxWindow) EVT_TEXT_ENTER(ID_WXFIELD, WXFieldRefPar::OnEnter) EVT_TEXT(ID_WXFIELD, WXFieldRefPar::OnText) EVT_CHECKBOX(ID_WXFIELD_REFPAR_FIXBUTTON, WXFieldRefPar::OnToggleFix) EVT_CHECKBOX(ID_WXFIELD_REFPAR_LIMITEDBUTTON,WXFieldRefPar::OnToggleLimited) EVT_RIGHT_DOWN( WXFieldRefPar::OnPopupMenu) EVT_MENU(ID_REFPAR_POPUP_SET_LIMITS, WXFieldRefPar::OnPopupMenuChoice) END_EVENT_TABLE() WXFieldRefPar::WXFieldRefPar(wxWindow *parent,const string& label, RefinablePar *par, const int hsize, const bool enableFixButton, const bool enableLimitedButton): WXField(parent,label,ID_WXFIELD_REFPAR),mValue(0.),mpRefPar(par),mIsSelfUpdating(false),mFormat(_T("%8f")) { VFN_DEBUG_MESSAGE("WXFieldRefPar::WXFieldName():End", 6) mpLabel->Bind(wxEVT_RIGHT_DOWN, &WXFieldRefPar::OnPopupMenu, this); if (enableFixButton) { this->SetLabel(label+":R"); mpButtonFix=new wxCheckBox(this,ID_WXFIELD_REFPAR_FIXBUTTON,_T("L"),wxDefaultPosition, wxDefaultSize); //mpButtonFix->Fit(); mpButtonFix->SetToolTip(_T("Check this box to enable optimizing this parameter.\n") _T("(some parameters may be automatically fixed for global optimization)")); mpSizer->Add(mpButtonFix,0,wxALIGN_CENTER); mpButtonFix->Bind(wxEVT_RIGHT_DOWN, &WXFieldRefPar::OnPopupMenu, this); } else mpButtonFix = 0; if(enableLimitedButton) { mpButtonLimited=new wxCheckBox(this,ID_WXFIELD_REFPAR_LIMITEDBUTTON,_T(""), wxDefaultPosition, wxSize(16,20)); mpButtonLimited->SetToolTip(_T("Check this box to use limits for this parameter")); mpSizer->Add(mpButtonLimited,0,wxALIGN_CENTER); mpButtonLimited->Bind(wxEVT_RIGHT_DOWN, &WXFieldRefPar::OnPopupMenu, this); } else mpButtonLimited = 0; mpField=new wxTextCtrl(this,ID_WXFIELD,_T(""), wxDefaultPosition,wxSize(hsize,-1),wxTE_PROCESS_ENTER, wxTextValidator(wxFILTER_NUMERIC)); mpSizer->Add(mpField,0,wxALIGN_CENTER); mpField->Bind(wxEVT_RIGHT_DOWN, &WXFieldRefPar::OnPopupMenu, this); } WXFieldRefPar::~WXFieldRefPar() { mpRefPar->WXNotifyDelete(); } void WXFieldRefPar::OnEnter(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_MESSAGE("WXFieldRefPar::OnEnter()",6) WXCrystValidateAllUserInput(); } void WXFieldRefPar::OnText(wxCommandEvent & WXUNUSED(event)) { if(true==mIsSelfUpdating) return; VFN_DEBUG_MESSAGE("WXFieldRefPar::OnEnter()",6) if(spLastWXFieldInputNotValidated!=this) { WXCrystValidateAllUserInput(); spLastWXFieldInputNotValidated=this; } } void WXFieldRefPar::OnToggleFix(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_MESSAGE("WXFieldRefPar::OnToggleFix()",6) if(0!=mpButtonFix) mpRefPar->SetIsFixed(!(mpButtonFix->GetValue())); mpRefPar->Print(); } void WXFieldRefPar::OnToggleLimited(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_MESSAGE("WXFieldRefPar::OnToggleLimited()",6) if(0!=mpButtonLimited) mpRefPar->SetIsLimited(mpButtonLimited->GetValue()); mpRefPar->Print(); } void WXFieldRefPar::OnPopupMenu(wxMouseEvent & WXUNUSED(event)) { static wxMenu sWXFieldRefParPopupMenu;//("Refinable Parameter"); static bool needInitMenu=true; if(needInitMenu) { needInitMenu=false; sWXFieldRefParPopupMenu.Append(ID_REFPAR_POPUP_SET_LIMITS, _T("Change Limits")); } this->PopupMenu(&sWXFieldRefParPopupMenu,0,0); } void WXFieldRefPar::OnPopupMenuChoice(wxCommandEvent& event) { VFN_DEBUG_MESSAGE("WXFieldRefPar::OnPopupMenuChoice()",7) if(event.GetId()== ID_REFPAR_POPUP_SET_LIMITS) { double min,max; { wxString str; str << mpRefPar->GetHumanMin(); wxTextEntryDialog limitDialog(this,_T("Enter the minimum value"), _T("Minimum"),str,wxOK | wxCANCEL); limitDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=limitDialog.ShowModal()) { VFN_DEBUG_EXIT("WXFieldRefPar::OnPopupMenuChoice():Cancelled",6) return; } limitDialog.GetValue().ToDouble(&min); } { wxString str; str << mpRefPar->GetHumanMax(); wxTextEntryDialog limitDialog(this,_T("Enter the maximum value"), _T("Maximum"),str,wxOK | wxCANCEL); limitDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=limitDialog.ShowModal()) { VFN_DEBUG_EXIT("WXFieldRefPar::OnPopupMenuChoice():Cancelled",6) return; } limitDialog.GetValue().ToDouble(&max); } if(max<=min) { wxMessageDialog dumbUser(this,_T("max <= min !!!"), _T("Whooops"),wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); return; } mpRefPar->SetHumanMin(min); mpRefPar->SetHumanMax(max); mpRefPar->SetIsLimited(true); mpRefPar->Print(); } } void WXFieldRefPar::CrystUpdate(const bool uui,const bool lock) { VFN_DEBUG_MESSAGE("WXFieldRefPar::CrystUpdate()",6) if(lock) mMutex.Lock(); bool needUpdate=false; if(wxThread::IsMain()) { if(mpRefPar->IsUsed()!=this->IsShown()) needUpdate=true; if(0!=mpButtonFix) if(mpButtonFix->GetValue()==mpRefPar->IsFixed()) needUpdate=true; if(0!=mpButtonLimited) if(mpButtonLimited->GetValue()==mpRefPar->IsLimited()) needUpdate=true; } if(mValue!=mpRefPar->GetHumanValue()) needUpdate=true; if(!needUpdate) { if(lock) mMutex.Unlock(); return; } mValueOld=mValue; mValue=mpRefPar->GetHumanValue(); mNeedUpdateUI=true; if(lock) mMutex.Unlock(); if(mNeedUpdateUI && wxThread::IsMain()) this->UpdateUI(lock); } void WXFieldRefPar::UpdateUI(const bool lock) { VFN_DEBUG_MESSAGE("WXFieldRefPar::UpdateUI("<IsUsed()) this->Show(false); else this->Show(true); if(mpField==0) { if(lock) mMutex.Unlock(); return; } //mpField->SetValue(wxString::Printf("%f",mValue)); wxString tmp; //if((abs(mValue)<100)&&(abs(mValue)>0.01)) tmp.Printf(_T("%6.4f"),mValue); tmp.Printf(mFormat,mValue); mIsSelfUpdating=true; mpField->SetValue(tmp); mIsSelfUpdating=false; if(0!=mpButtonFix) mpButtonFix->SetValue(!(mpRefPar->IsFixed())); if(0!=mpButtonLimited) mpButtonLimited->SetValue(mpRefPar->IsLimited()); mNeedUpdateUI=false; if(lock) mMutex.Unlock(); } void WXFieldRefPar::Revert() { VFN_DEBUG_MESSAGE("WXFieldRefPar::Revert()",6) wxMutexLocker mlock(mMutex); mValue=mValueOld; mNeedUpdateUI=true; } void WXFieldRefPar::ValidateUserInput() { VFN_DEBUG_MESSAGE("WXFieldRefPar::ValidateUserInput()",6) wxMutexLocker mlock(mMutex); mValueOld=mValue; wxString s=mpField->GetValue(); double tmp; s.ToDouble(&tmp); mValue=tmp; mpRefPar->SetHumanValue(mValue); } void WXFieldRefPar::SetToolTip(const wxString& tip){mpField->SetToolTip(tip);} void WXFieldRefPar::SetFormat(const wxString &format) { mFormat=format; } //////////////////////////////////////////////////////////////////////// // // WXFieldOption // //////////////////////////////////////////////////////////////////////// BEGIN_EVENT_TABLE(WXFieldOption,wxWindow) EVT_CHOICE(ID_WXFIELD,WXFieldOption::OnChoice) END_EVENT_TABLE() WXFieldOption::WXFieldOption(wxWindow *parent, const int field_id,RefObjOpt* option): WXField(parent,option->GetName(),field_id), mChoice(-1),mChoiceOld(-1),mpOption(option),mpList(0) { wxString choices[20];//:TODO: dynamically choose correct number for(int i=0;iGetNbChoice();i++) choices[i]=wxString::FromAscii(mpOption->GetChoiceName(i).c_str()); mpList= new wxChoice(this,ID_WXFIELD,wxDefaultPosition,wxDefaultSize, mpOption->GetNbChoice(),choices); mpSizer->Add(mpList,0,wxALIGN_CENTER); } WXFieldOption::~WXFieldOption() { mpOption->WXNotifyDelete(); } void WXFieldOption::OnChoice(wxCommandEvent & WXUNUSED(event)) { if(mChoice==mpList->GetSelection()) return; mChoiceOld=mChoice; mChoice=mpList->GetSelection(); mpOption->SetChoice(mChoice); } void WXFieldOption::CrystUpdate(const bool uui,const bool lock) { VFN_DEBUG_MESSAGE("WXFieldOption::CrystUpdate("<GetChoice()) { if(lock) mMutex.Unlock(); return; } mChoice=mpOption->GetChoice(); mNeedUpdateUI=true; if(lock) mMutex.Unlock(); } void WXFieldOption::UpdateUI(const bool lock) { VFN_DEBUG_MESSAGE("WXFieldOption::UpdateUI("<SetSelection(mChoice); mNeedUpdateUI=false; if(lock) mMutex.Unlock(); } void WXFieldOption::Revert() { wxMutexLocker mlock(mMutex); mChoice=mChoiceOld; mNeedUpdateUI=true; } void WXFieldOption::ValidateUserInput() { } void WXFieldOption::SetToolTip(const wxString& tip){mpList->SetToolTip(tip);} //////////////////////////////////////////////////////////////////////// // // WXRegistry // //////////////////////////////////////////////////////////////////////// template WXRegistry::WXRegistry(wxWindow *parent,ObjRegistry* reg): WXCrystObj(parent,wxHORIZONTAL,false),mpRegistry(reg) { VFN_DEBUG_ENTRY("WXCrystRegistry::WXCrystRegistry(wxWindow*)",6) #ifdef VFN_CRYST_MUTEX cout <<"new CrystMutex("<<&mMutex<<")for WXCrystRegistry:"<GetName()<GetName().c_str())); mpSizer->Add(mpLabel,0,wxALIGN_LEFT); mpLabel->SetForegroundColour(wxColour(0,0,255)); VFN_DEBUG_EXIT("WXCrystRegistry::WXCrystRegistry(wxWindow*):End",6) } template WXRegistry::~WXRegistry() { mpRegistry->WXNotifyDelete(); #ifdef VFN_CRYST_MUTEX cout <<"Deleting CrystMutex("<<&mMutex<<")for WXCrystRegistry:"<GetName()< void WXRegistry::Add(WXCrystObjBasic *obj) { VFN_DEBUG_ENTRY("WXCrystRegistry::AddWXCrystObj(WXCrystObj*)",6) mList.Add(obj); obj->Show(mIsExpanded); this->AddChild(obj); VFN_DEBUG_EXIT("WXCrystRegistry::AddWXCrystObj(WXCrystObj*)",6) } template void WXRegistry::Remove(WXCrystObjBasic *obj) { if(obj==0) return; VFN_DEBUG_ENTRY("WXCrystRegistry::RemoveWXCrystObj(WXCrystObj*)",6) mList.Remove(obj); //mpSizer->Detach((wxWindow*)obj); obj->Destroy(); this->BottomLayout(0); VFN_DEBUG_EXIT("WXCrystRegistry::RemoveWXCrystObj(WXCrystObj*):End",6) } template bool WXRegistry::OnChangeName(const int id) { VFN_DEBUG_MESSAGE("WXRegistry::OnChangeName()",6) if(id==ID_WXOBJ_NAME) { mpRegistry->SetName(mpWXTitle->GetValue()); return true; } return false; } //Explicit instantiation template class WXRegistry; template class WXRegistry; template class WXRegistry; template class WXRegistry; template class WXRegistry; template class WXRegistry; template class WXRegistry; template class WXRegistry; template class WXRegistry; template class WXRegistry; template class WXRegistry; //template class WXRegistry;//to be removed template class WXRegistry; template class WXRegistry; template class WXRegistry; template class WXRegistry; //////////////////////////////////////////////////////////////////////// // // WXDialogChooseFromRegistry // //////////////////////////////////////////////////////////////////////// template T* WXDialogChooseFromRegistry(ObjRegistry ®,wxWindow*parent, const string &message,int &choice) { wxString* choices=new wxString[reg.GetNb()]; for(int i=0;i &,wxWindow*,const string &,int &); template Crystal* WXDialogChooseFromRegistry(ObjRegistry &,wxWindow*,const string &,int &); template Scatterer* WXDialogChooseFromRegistry(ObjRegistry &,wxWindow*,const string &,int &); template ScatteringPower* WXDialogChooseFromRegistry(ObjRegistry &,wxWindow*,const string &,int &); template ScatteringPowerAtom* WXDialogChooseFromRegistry(ObjRegistry &,wxWindow*, const string &,int &); template ZAtom* WXDialogChooseFromRegistry(ObjRegistry &,wxWindow*,const string &,int &); template PowderPattern* WXDialogChooseFromRegistry(ObjRegistry &,wxWindow*,const string &,int &); template PowderPatternComponent* WXDialogChooseFromRegistry(ObjRegistry&,wxWindow*, const string&,int &); template DiffractionDataSingleCrystal* WXDialogChooseFromRegistry(ObjRegistry&,wxWindow*, const string &,int &); template OptimizationObj* WXDialogChooseFromRegistry(ObjRegistry &,wxWindow*,const string &,int &); template XMLCrystTag* WXDialogChooseFromRegistry(ObjRegistry &,wxWindow*,const string &,int &); template const T* WXDialogChooseFromRegistry(const ObjRegistry ®, wxWindow*parent,const string &message ,int &choice) { wxString* choices=new wxString[reg.GetNb()]; for(int i=0;i &,wxWindow*,const string &,int &); template const Crystal* WXDialogChooseFromRegistry(const ObjRegistry &,wxWindow*,const string &,int &); template const Scatterer* WXDialogChooseFromRegistry(const ObjRegistry &,wxWindow*,const string &,int &); template const ScatteringPower* WXDialogChooseFromRegistry(const ObjRegistry &,wxWindow*, const string &,int &); template const ScatteringPowerAtom* WXDialogChooseFromRegistry(const ObjRegistry &,wxWindow*, const string &,int &); template const ZAtom* WXDialogChooseFromRegistry(const ObjRegistry &,wxWindow*,const string &,int &); template const PowderPattern* WXDialogChooseFromRegistry(const ObjRegistry &,wxWindow*, const string &,int &); template const PowderPatternComponent* WXDialogChooseFromRegistry(const ObjRegistry&,wxWindow*, const string&,int &); template const DiffractionDataSingleCrystal* WXDialogChooseFromRegistry(const ObjRegistry&,wxWindow*, const string &,int &); template const OptimizationObj* WXDialogChooseFromRegistry(const ObjRegistry &,wxWindow*, const string &,int &); template const XMLCrystTag* WXDialogChooseFromRegistry(const ObjRegistry &,wxWindow*, const string &,int &); //////////////////////////////////////////////////////////////////////// // // WXRefinableObj // //////////////////////////////////////////////////////////////////////// BEGIN_EVENT_TABLE(WXRefinableObj,wxWindow) EVT_MENU(ID_REFOBJ_MENU_OBJ_SAVE, WXRefinableObj::OnMenuSave) EVT_MENU(ID_REFOBJ_MENU_OBJ_LOAD, WXRefinableObj::OnMenuLoad) EVT_MENU(ID_REFOBJ_MENU_PAR_FIXALL, WXRefinableObj::OnMenuFixAllPar) EVT_MENU(ID_REFOBJ_MENU_PAR_UNFIXALL, WXRefinableObj::OnMenuUnFixAllPar) EVT_MENU(ID_REFOBJ_MENU_PAR_RANDOMIZE, WXRefinableObj::OnMenuParRandomize) EVT_UPDATE_UI(ID_CRYST_UPDATEUI, WXRefinableObj::OnUpdateUI) END_EVENT_TABLE() WXRefinableObj::WXRefinableObj(wxWindow* parent, RefinableObj*obj): WXCrystObj(parent,wxHORIZONTAL),mpRefinableObj(obj) { VFN_DEBUG_ENTRY("WXRefinableObj::WXRefinableObj():"<GetName(),6) #ifdef VFN_CRYST_MUTEX cout <<"new CrystMutex("<<&mMutex<<")for :"<GetClassName()<<":"<GetName()<SetLabel(mpRefinableObj->GetClassName()); // Menu mpMenuBar=new WXCrystMenuBar(this,this); mpSizer->Add(mpMenuBar); mList.Add(mpMenuBar); //:TODO: Rather use a WXRegistry for the options ? for(unsigned int i=0;iGetNbOption();i++) { VFN_DEBUG_MESSAGE("WXRefinableObj::WXRefinableObj():Adding option "<GetOption(i).WXCreate(this); mpSizer->Add(opt,0,wxALIGN_LEFT); mList.Add(opt); } //this->BottomLayout(0); //this->CrystUpdate(true,true); VFN_DEBUG_EXIT("WXRefinableObj::WXRefinableObj()",6) } WXRefinableObj::~WXRefinableObj() { VFN_DEBUG_MESSAGE("WXRefinableObj::~WXRefinableObj():"<GetName(),6) mpRefinableObj->WXNotifyDelete(); #ifdef VFN_CRYST_MUTEX cout <<"Deleting CrystMutex("<<&mMutex<<")for :"<GetClassName() <<":"<GetName()<GetName(),6) //if(lock) mMutex.Lock(); this->WXCrystObj::CrystUpdate(false,lock); //if(lock) mMutex.Unlock(); if(uui) { if(true==wxThread::IsMain()) this->UpdateUI(lock); else { wxUpdateUIEvent event(ID_CRYST_UPDATEUI); wxPostEvent(this,event); } } VFN_DEBUG_EXIT("WXRefinableObj::CrystUpdate():"<GetName(),6) } bool WXRefinableObj::OnChangeName(const int id) { VFN_DEBUG_MESSAGE("WXRefinableObj::OnChangeName()",6) if(id==ID_WXOBJ_NAME) { VFN_DEBUG_MESSAGE("WXRefinableObj::OnChangeName():Changing RefinableObj Name",6) mpRefinableObj->SetName(mpWXTitle->GetValue()); return true; } return false; } void WXRefinableObj::OnMenuSave(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_MESSAGE("WXRefinableObj::OnButtonSave()",6) wxFileDialog save(this,_T("Choose a file"),_T(""),_T(""),_T("*.xml"),wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if(save.ShowModal() != wxID_OK) return; ofstream out(save.GetPath().ToAscii()); if(!out) return;//:TODO: { out.imbue(std::locale::classic()); mpRefinableObj->XMLOutput(out); } out.close(); } void WXRefinableObj::OnMenuLoad(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_MESSAGE("WXRefinableObj::OnButtonLoad()",6) wxFileDialog *open= new wxFileDialog(this,_T("Choose a file"),_T(""),_T(""),_T("*.xml"), wxFD_OPEN | wxFD_FILE_MUST_EXIST); if(open->ShowModal() != wxID_OK) return; ifstream fin(open->GetPath().ToAscii()); if(!fin) return;//:TODO: { XMLCrystTag tag(fin);//:TODO: load all tags and find the right ones for this class mpRefinableObj->XMLInput(fin,tag); } fin.close(); open->Destroy(); } void WXRefinableObj::OnMenuFixAllPar(wxCommandEvent & WXUNUSED(event)) { mpRefinableObj->FixAllPar(); this->CrystUpdate(true); } void WXRefinableObj::OnMenuUnFixAllPar(wxCommandEvent & WXUNUSED(event)) { mpRefinableObj->UnFixAllPar(); this->CrystUpdate(true); } void WXRefinableObj::OnMenuParRandomize(wxCommandEvent & WXUNUSED(event)) { (*fpObjCrystInformUser)("Randomizing object:"+mpRefinableObj->GetName()); Chronometer chrono; chrono.start(); mpRefinableObj->RandomizeConfiguration(); this->CrystUpdate(true); char buf [200]; sprintf(buf,"Finished randomizing object: %s, dt=%6.2fs",mpRefinableObj->GetName().c_str(),chrono.seconds()); (*fpObjCrystInformUser)(buf); } void WXRefinableObj::OnUpdateUI(wxUpdateUIEvent& event) { this->UpdateUI(true); event.Skip(); } void WXRefinableObj::UpdateUI(const bool lock) { VFN_DEBUG_ENTRY("WXRefinableObj::UpdateUI("<GetName(),6) if(!mpRefinableObj->IsBeingRefined()) { if(lock) mMutex.Lock(); mpWXTitle->SetValue(mpRefinableObj->GetName()); mpWXTitle->UpdateUI(false); //mpSizer->SetItemMinSize // (mpWXTitle, mpWXTitle->GetSize().GetWidth(),mpWXTitle->GetSize().GetHeight()); //mpWXTitle->Layout(); if(lock) mMutex.Unlock(); } this->WXCrystObj::UpdateUI(lock); VFN_DEBUG_EXIT("WXRefinableObj::UpdateUI()"<GetName(),6) } }// namespace objcryst-2022.1/ObjCryst/wxCryst/wxRefinableObj.h000066400000000000000000000152261430515525000217410ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * header file for the RefinablePar and RefinableObj classes * * This is still in early development stages !! Not secure ! * */ #ifndef _VFN_WX_REFINABLE_OBJ_H_ #define _VFN_WX_REFINABLE_OBJ_H_ namespace ObjCryst { template class WXRegistry; class WXFieldOption; class WXFieldRefPar; } //namespace #include "ObjCryst/wxCryst/wxCryst.h" // We should not have to put this here. !! :TODO: #include "ObjCryst/RefinableObj/RefinableObj.h" namespace ObjCryst { class RefinablePar; class RefinableObj; /// This function allows to pick up one object in a registry. Shows a modal /// dialog with a list of objects template T* WXDialogChooseFromRegistry(ObjRegistry ®,wxWindow*parent, const string &message,int &); /// This function allows to pick up one object in a registry. Shows a modal /// dialog with a list of objects. This is a const access. template const T* WXDialogChooseFromRegistry(const ObjRegistry ®, wxWindow*parent, const string &message, int &); /// A field for a RefinablePar. This shows the 'human' value of the parameter, and allows /// the modification of the parameter. A button allows to fix/unfix the parameter. /// \todo: allow acces to the parameters limits class WXFieldRefPar:public WXField { public: WXFieldRefPar(wxWindow *parent,const string& label, RefinablePar *refpar,const int hsize=65, const bool enableFixButton=true, const bool enableLimitedButton=true); /// When a new value is entered (must type it and then hit the 'enter' key). /// The Field reads the new value, /// and directly changes the RefinablePar value (contrary to what happens /// for WXFieldName)by using RefinablePar::SetHumanValue(). ~WXFieldRefPar(); void OnEnter(wxCommandEvent & WXUNUSED(event)); /// Records when text is entered (either from self-updating or user input) void OnText(wxCommandEvent & WXUNUSED(event)); /// Toggle the 'fixed' status of the parameter. void OnToggleFix(wxCommandEvent & WXUNUSED(event)); /// Toggle the 'limited' status of the parameter. void OnToggleLimited(wxCommandEvent & WXUNUSED(event)); /// Opens the popu menu, to allow changing limits void OnPopupMenu(wxMouseEvent & event); /// Opens the popu menu, to allow changing limits void OnPopupMenuChoice(wxCommandEvent& event); virtual void CrystUpdate(const bool updateUI=false,const bool mutexlock=false); virtual void UpdateUI(const bool mutexlock=false); /// Get the RefinablePar associated to this field RefinablePar& GetRefPar(); void Revert(); virtual void ValidateUserInput(); /// Set tooltip for this window. It will be activated when going over the entry field. virtual void SetToolTip(const wxString& tip); /// Set Format void SetFormat(const wxString &format); protected: REAL mValue; wxCheckBox *mpButtonFix; wxCheckBox *mpButtonLimited; wxTextCtrl *mpField; RefinablePar *mpRefPar; REAL mValueOld; bool mIsSelfUpdating; /// Format to be used, default = _T("%8f") wxString mFormat; DECLARE_EVENT_TABLE() }; class RefObjOpt;// Declared in RefinableObj.h /// WX representation of a RefObj option. This displays the names of the different choices. class WXFieldOption:public WXField { public: WXFieldOption(wxWindow *parent,const int field_id, RefObjOpt* option); virtual ~WXFieldOption(); void OnUpdateUI(wxUpdateUIEvent & WXUNUSED(event)); /// When a new value is entered. The Field reads the new value, then /// forwards the event to its owner, who will take care of anything /// that must be done. void OnChoice(wxCommandEvent & WXUNUSED(event)); virtual void CrystUpdate(const bool updateUI=false,const bool mutexlock=false); virtual void UpdateUI(const bool mutexlock=false); void Revert(); /// Does nothing. Any user input is directly validated (OnChoice). virtual void ValidateUserInput(); /// Set tooltip for this window. It will be activated when going over the choice field. virtual void SetToolTip(const wxString& tip); protected: int mChoice; int mChoiceOld; RefObjOpt* mpOption; wxChoice *mpList; DECLARE_EVENT_TABLE() }; /// This displays all components of a ObjCryst++ Registry. template class WXRegistry:public WXCrystObj { public: WXRegistry(wxWindow *parent,ObjRegistry* reg); ~WXRegistry(); void Add(WXCrystObjBasic *obj); void Remove(WXCrystObjBasic *obj); virtual bool OnChangeName(const int id); private: ObjRegistry *mpRegistry; }; /// The base wxCryst class for all RefinableObj objects. This shows the title, /// a menu for XMLInput/XMLOutput, and all RefObjOpt. class WXRefinableObj: public WXCrystObj { public: WXRefinableObj(wxWindow *parent, RefinableObj*); ~WXRefinableObj(); virtual void CrystUpdate(const bool updateUI=false,const bool mutexlock=false); virtual void UpdateUI(const bool mutexlock=false); virtual bool OnChangeName(const int id); void OnMenuSave(wxCommandEvent & WXUNUSED(event)); void OnMenuLoad(wxCommandEvent & WXUNUSED(event)); void OnMenuFixAllPar(wxCommandEvent & WXUNUSED(event)); void OnMenuUnFixAllPar(wxCommandEvent & WXUNUSED(event)); void OnMenuParRandomize(wxCommandEvent & WXUNUSED(event)); virtual void OnUpdateUI(wxUpdateUIEvent& event); protected: WXCrystMenuBar* mpMenuBar; private: RefinableObj* mpRefinableObj; DECLARE_EVENT_TABLE() }; } //namespace #endif //_VFN_WX_REFINABLE_OBJ_H_ objcryst-2022.1/ObjCryst/wxCryst/wxScatterer.cpp000066400000000000000000000055461430515525000217120ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ //#include //for stringstream #include // wx headers, with or without precompilation #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "ObjCryst/wxCryst/wxScatterer.h" //Fixes for Cygwin; where do those stupid macros come from ? Somewhere in wxMSW headers #ifdef max #undef max #endif #ifdef min #undef min #endif #ifdef DrawText #undef DrawText #endif namespace ObjCryst { //////////////////////////////////////////////////////////////////////// // // WXScatterer // //////////////////////////////////////////////////////////////////////// WXScatterer::WXScatterer(wxWindow* parent, Scatterer *obj): WXRefinableObj(parent,(RefinableObj*)obj),mpScatterer(obj) { VFN_DEBUG_MESSAGE("WXScatterer::WXScatterer()",6) mpWXTitle->SetForegroundColour(wxColour(0,100,0)); //Lattice wxBoxSizer* sizer=new wxBoxSizer(wxHORIZONTAL); WXCrystObjBasic* pFieldX =mpScatterer->GetPar(mpScatterer->mXYZ.data()+0).WXCreate(this); WXCrystObjBasic* pFieldY =mpScatterer->GetPar(mpScatterer->mXYZ.data()+1).WXCreate(this); WXCrystObjBasic* pFieldZ =mpScatterer->GetPar(mpScatterer->mXYZ.data()+2).WXCreate(this); WXCrystObjBasic* pFieldPopu =mpScatterer->GetPar(&(mpScatterer->mOccupancy)).WXCreate(this); dynamic_cast (pFieldX)->SetLabel("X: R"); dynamic_cast (pFieldY)->SetLabel("Y: R"); dynamic_cast (pFieldZ)->SetLabel("Z: R"); dynamic_cast (pFieldPopu)->SetLabel("Occup: R"); sizer->Add(pFieldX ,0,wxALIGN_CENTER); sizer->Add(pFieldY ,0,wxALIGN_CENTER); sizer->Add(pFieldZ ,0,wxALIGN_CENTER); sizer->Add(pFieldPopu ,0,wxALIGN_CENTER); mpSizer->Add(sizer,0,wxALIGN_LEFT); mList.Add(pFieldX); mList.Add(pFieldY); mList.Add(pFieldZ); mList.Add(pFieldPopu); //layout & update is done in derived objects } }// namespace objcryst-2022.1/ObjCryst/wxCryst/wxScatterer.h000066400000000000000000000026501430515525000213500ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * header file for the RefinablePar and RefinableObj classes * * This is still in early development stages !! Not secure ! * */ #ifndef _VFN_WX_SCATTERER_OBJ_H_ #define _VFN_WX_SCATTERER_OBJ_H_ #include "ObjCryst/wxCryst/wxRefinableObj.h" #include "ObjCryst/ObjCryst/Scatterer.h" namespace ObjCryst { /// base wxCryst class for Scatterers class WXScatterer: public WXRefinableObj { public: WXScatterer(wxWindow *parent, Scatterer*); protected: Scatterer* mpScatterer; }; } //namespace #endif //_VFN_WX_SCATTERER_OBJ_H_ objcryst-2022.1/ObjCryst/wxCryst/wxScatteringPower.cpp000066400000000000000000000120671430515525000230720ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ //#include //for stringstream #include // wx headers, with or without precompilation #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "ObjCryst/wxCryst/wxScatteringPower.h" //Fixes for Cygwin; where do those stupid macros come from ? Somewhere in wxMSW headers #ifdef max #undef max #endif #ifdef min #undef min #endif #ifdef DrawText #undef DrawText #endif namespace ObjCryst { //////////////////////////////////////////////////////////////////////// // // WXScatteringPowerAtom // //////////////////////////////////////////////////////////////////////// static const long ID_WXSCATTPOWATOM_SYMBOL =WXCRYST_ID(); static const long ID_SCATTPOWATOM_MENU_COLOUR =WXCRYST_ID(); static const long ID_SCATTPOWATOM_MENU_COLOUR_SETRGB=WXCRYST_ID(); BEGIN_EVENT_TABLE(WXScatteringPowerAtom, wxWindow) EVT_MENU(ID_SCATTPOWATOM_MENU_COLOUR_SETRGB, WXScatteringPowerAtom::OnChangeColour) EVT_UPDATE_UI(ID_CRYST_UPDATEUI, WXRefinableObj::OnUpdateUI) END_EVENT_TABLE() WXScatteringPowerAtom::WXScatteringPowerAtom(wxWindow* parent, ScatteringPowerAtom *obj): WXRefinableObj(parent,(RefinableObj*)obj),mpScatteringPowerAtom(obj) { VFN_DEBUG_MESSAGE("WXScatteringPowerAtom::WXScatteringPowerAtom()",6) mpWXTitle->SetForegroundColour(wxColour(0,200,0)); //Lattice mpFieldSymbol=new WXFieldName (this,"Symbol:",this,ID_WXSCATTPOWATOM_SYMBOL); mpTopSizer->Add(mpFieldSymbol ,0,wxALIGN_TOP); mList.Add(mpFieldSymbol); this->Layout(); this->BottomLayout(0); this->CrystUpdate(true); } bool WXScatteringPowerAtom::OnChangeName(const int id) { VFN_DEBUG_MESSAGE("WXScatteringPowerAtom::OnChangeName()",6) if(this->WXRefinableObj::OnChangeName(id)==true) return true; if(id==ID_WXSCATTPOWATOM_SYMBOL) { VFN_DEBUG_MESSAGE("WXScatteringPowerAtom::OnChangeName():Changing Symbol",6) mpScatteringPowerAtom->Init(mpScatteringPowerAtom->GetName(), mpFieldSymbol->GetValue(), mpScatteringPowerAtom->GetBiso()); return true; } return false; } void WXScatteringPowerAtom::OnChangeColour(wxCommandEvent & event) { VFN_DEBUG_ENTRY("WXScatteringPowerAtom::OnChangeColour()",6) const float* oldColour=mpScatteringPowerAtom->GetColourRGB(); double r,g,b; r=oldColour[0]; g=oldColour[1]; b=oldColour[2]; //red { wxString str; str<SetColour(r,g,b); VFN_DEBUG_EXIT("WXScatteringPowerAtom::OnChangeColour()",6) } void WXScatteringPowerAtom::UpdateUI(const bool lock) { VFN_DEBUG_ENTRY("WXScatteringPowerAtom::UpdateUI()",3) if(lock) mMutex.Lock(); mpFieldSymbol->SetValue(mpScatteringPowerAtom->GetSymbol()); this->WXRefinableObj::UpdateUI(false); if(lock) mMutex.Unlock(); VFN_DEBUG_EXIT("WXScatteringPowerAtom::UpdateUI()",3) } }// namespace objcryst-2022.1/ObjCryst/wxCryst/wxScatteringPower.h000066400000000000000000000031111430515525000225250ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _VFN_WX_SCATTERINGPOWER_OBJ_H_ #define _VFN_WX_SCATTERINGPOWER_OBJ_H_ #include "ObjCryst/wxCryst/wxRefinableObj.h" #include "ObjCryst/ObjCryst/ScatteringPower.h" namespace ObjCryst { /// wxCryst class for ScatteringPowerAtom class WXScatteringPowerAtom: public WXRefinableObj { public: WXScatteringPowerAtom(wxWindow *parent, ScatteringPowerAtom*); virtual bool OnChangeName(const int id); void OnChangeColour(wxCommandEvent & event); virtual void UpdateUI(const bool mutexlock=false); protected: ScatteringPowerAtom* mpScatteringPowerAtom; WXFieldName *mpFieldSymbol; DECLARE_EVENT_TABLE() }; } //namespace #endif //_VFN_WX_SCATTERINGPOWER_OBJ_H_ objcryst-2022.1/ObjCryst/wxCryst/wxScatteringPowerSphere.cpp000066400000000000000000000114041430515525000242330ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ //#include //for stringstream #include // wx headers, with or without precompilation #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "ObjCryst/wxCryst/wxScatteringPowerSphere.h" //Fixes for Cygwin; where do those stupid macros come from ? Somewhere in wxMSW headers #ifdef max #undef max #endif #ifdef min #undef min #endif #ifdef DrawText #undef DrawText #endif namespace ObjCryst { //////////////////////////////////////////////////////////////////////// // // WXScatteringPowerSphere // //////////////////////////////////////////////////////////////////////// static const long ID_SCATTPOWATOM_MENU_COLOUR=WXCRYST_ID(); static const long ID_SCATTPOWATOM_MENU_COLOUR_SETRGB=WXCRYST_ID(); BEGIN_EVENT_TABLE(WXScatteringPowerSphere, wxWindow) EVT_MENU(ID_SCATTPOWATOM_MENU_COLOUR_SETRGB, WXScatteringPowerSphere::OnChangeColour) EVT_UPDATE_UI(ID_CRYST_UPDATEUI, WXRefinableObj::OnUpdateUI) END_EVENT_TABLE() WXScatteringPowerSphere::WXScatteringPowerSphere(wxWindow* parent, ScatteringPowerSphere *obj): WXRefinableObj(parent,(RefinableObj*)obj),mpScatteringPower(obj) { VFN_DEBUG_MESSAGE("WXScatteringPowerSphere::ScatteringPowerSphere()",6) mpWXTitle->SetForegroundColour(wxColour(0,200,0)); //Lattice mpMenuBar->AddMenu("Colour",ID_SCATTPOWATOM_MENU_COLOUR); mpMenuBar->AddMenuItem(ID_SCATTPOWATOM_MENU_COLOUR, ID_SCATTPOWATOM_MENU_COLOUR_SETRGB,"Set RGB Colour"); WXCrystObjBasic* pFieldRadius= mpScatteringPower->GetPar(&(mpScatteringPower->mRadius)).WXCreate(this); WXCrystObjBasic* pFieldBiso= mpScatteringPower->GetPar(&(mpScatteringPower->mBiso )).WXCreate(this); mpSizer->Add(pFieldRadius,0,wxALIGN_LEFT); mList.Add(pFieldRadius); mpSizer->Add(pFieldBiso,0,wxALIGN_LEFT); mList.Add(pFieldBiso); this->CrystUpdate(true); this->Layout(); } bool WXScatteringPowerSphere::OnChangeName(const int id) { VFN_DEBUG_MESSAGE("WXScatteringPowerSphere::OnChangeName()",6) if(this->WXRefinableObj::OnChangeName(id)==true) return true; return false; } void WXScatteringPowerSphere::OnChangeColour(wxCommandEvent & event) { const float* oldColour=mpScatteringPower->GetColourRGB(); double r,g,b; r=oldColour[0]; g=oldColour[1]; b=oldColour[2]; //red { wxString str; str<SetColour(r,g,b); } void WXScatteringPowerSphere::UpdateUI(const bool lock) { this->WXRefinableObj::UpdateUI(lock); } }// namespace objcryst-2022.1/ObjCryst/wxCryst/wxScatteringPowerSphere.h000066400000000000000000000030771430515525000237070ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _VFN_WX_SCATTERINGPOWERSPHERE_OBJ_H_ #define _VFN_WX_SCATTERINGPOWERSPHERE_OBJ_H_ #include "ObjCryst/wxCryst/wxRefinableObj.h" #include "ObjCryst/ObjCryst/ScatteringPowerSphere.h" namespace ObjCryst { /// wxCryst class for ScatteringPowerSphere class WXScatteringPowerSphere: public WXRefinableObj { public: WXScatteringPowerSphere(wxWindow *parent, ScatteringPowerSphere*); virtual bool OnChangeName(const int id); void OnChangeColour(wxCommandEvent & event); virtual void UpdateUI(const bool mutexlock=false); protected: ScatteringPowerSphere* mpScatteringPower; DECLARE_EVENT_TABLE() }; } //namespace #endif //_VFN_WX_SCATTERINGPOWER_OBJ_H_ objcryst-2022.1/ObjCryst/wxCryst/wxTrackerGraph.cpp000066400000000000000000000066261430515525000223330ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2005- Vincent Favre-Nicolin vincefn@users.sourceforge.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ObjCryst/wxCryst/wxTrackerGraph.h" namespace ObjCryst { WXTrackerGraph::WXTrackerGraph(wxFrame *frame, MainTracker *tracker): WXMultiGraph(frame),mpMainTracker(tracker) { this->UpdateDisplay(); } WXTrackerGraph::~WXTrackerGraph() { if(mpMainTracker!=0) mpMainTracker->WXNotifyDelete(); } void WXTrackerGraph::UpdateDisplay() { VFN_DEBUG_ENTRY("WXTrackerGraph::UpdateDisplay()",4) const std::set *pList=&(mpMainTracker->GetTrackerList()); std::set::const_iterator pos; // Remove orphan graphs if(mClockGraphListGetClockTrackerList()) { std::map::iterator pos1; std::map id=mvId; for(pos1=id.begin();pos1!=id.end();pos1++) if(pList->find(pos1->first)==pList->end()) { this->DeleteGraph(pos1->second); mClockGraphList.Click(); } } unsigned long nbxMax=0; // Add new graphs and update data for all if( (mClockGraphList GetClockTrackerList()) ||(mClockGraphValuesGetClockValues())) { for(pos=pList->begin();pos!=pList->end();pos++) { if(mvId.find(*pos)==mvId.end()) { mvId[*pos]=this->AddGraph((*pos)->GetName()); mClockGraphList.Click(); } const unsigned long nb=(*pos)->GetValues().size(); std::map::const_iterator pos2; valarray vx(nb),vy(nb); unsigned long i=0; bool allnull=true; for(pos2=(*pos)->GetValues().begin();pos2!=(*pos)->GetValues().end();pos2++) { vx[i]=pos2->first; vy[i]=pos2->second; if(pos2->second!=0) allnull=false; i++; } if(!allnull) {// Only display graph if some values are non-null this->SetGraphData(mvId[*pos],vx,vy); mClockGraphValues.Click(); if(nbxMaxAutoScale(-1);// first drawing, so rescale everything else this->AutoScale(-1,false,true,false,false);//just rescale xmax } this->WXMultiGraph::UpdateDisplay(); VFN_DEBUG_EXIT("WXTrackerGraph::UpdateDisplay()",4) } void WXTrackerGraph::DeleteGraph(const unsigned long id) { // remove tracker. Maybe should keep a reverse map. std::map::iterator pos; for(pos=mvId.begin();pos!=mvId.end();pos++) { if((long)id==pos->second) { mvId.erase(pos); break; } } this->WXMultiGraph::DeleteGraph(id); } }//namespace objcryst-2022.1/ObjCryst/wxCryst/wxTrackerGraph.h000066400000000000000000000034251430515525000217720ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2005- Vincent Favre-Nicolin vincefn@users.sourceforge.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _WX_WXTRACKER_H_ #define _WX_WXTRACKER_H_ #include #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif namespace ObjCryst { class WXTrackerGraph; } //namespace #include "ObjCryst/wxCryst/wxMultiGraph.h" #include "ObjCryst/RefinableObj/Tracker.h" namespace ObjCryst { class WXTrackerGraph:public WXMultiGraph { public: WXTrackerGraph(wxFrame *frame, MainTracker *tracker); virtual ~WXTrackerGraph(); /// reads new values from the MainTracker, and asks for a repaint. virtual void UpdateDisplay(); virtual void DeleteGraph(const unsigned long id); private: MainTracker *mpMainTracker; std::map mvId; /// Last time a tracker was added to the graph RefinableObjClock mClockGraphList; /// Last time values were added to the graph RefinableObjClock mClockGraphValues; }; }//namespace #endif objcryst-2022.1/ObjCryst/wxCryst/wxZScatterer.cpp000066400000000000000000000462441430515525000220440ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include //for sprintf() #include // wx headers, with or without precompilation #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "ObjCryst/wxCryst/wxZScatterer.h" #include "ObjCryst/ObjCryst/Molecule.h" //Fixes for Cygwin; where do those stupid macros come from ? Somewhere in wxMSW headers #ifdef max #undef max #endif #ifdef min #undef min #endif #ifdef DrawText #undef DrawText #endif namespace ObjCryst { //////////////////////////////////////////////////////////////////////// // // WXZAtom // //////////////////////////////////////////////////////////////////////// static const long ID_ZATOM_NAME= WXCRYST_ID(); static const long ID_ZATOM_SCATTPOW=WXCRYST_ID(); static const long ID_ZATOM_BOND= WXCRYST_ID(); static const long ID_ZATOM_ANGLE= WXCRYST_ID(); static const long ID_ZATOM_DIHED= WXCRYST_ID(); BEGIN_EVENT_TABLE(WXZAtom,wxWindow) EVT_BUTTON(ID_ZATOM_SCATTPOW, WXZAtom::OnChangeScattPow) END_EVENT_TABLE() WXZAtom::WXZAtom(wxWindow* parent, ZAtom *obj): WXCrystObjBasic(parent),mpZAtom(obj) { VFN_DEBUG_ENTRY("WXZAtom::WXZAtom()",6) mpSizer=new wxBoxSizer(wxHORIZONTAL); mpFieldName=new WXFieldString(this, mpZAtom->mName,ID_ZATOM_NAME,80,true); mpSizer->Add(mpFieldName,0,wxALIGN_LEFT); mpFieldScattPower=new WXFieldChoice(this,ID_ZATOM_SCATTPOW,"Type:",60); mpSizer->Add(mpFieldScattPower,0,wxALIGN_LEFT); mList.Add(mpFieldScattPower); if(0GetZScatterer().GetZAtomRegistry().Find(*mpZAtom)) { RefinablePar *par=&(mpZAtom->GetZScatterer().GetPar(&(mpZAtom->mBondLength))); par->SetName("Bond(w/"+(mpZAtom->GetZScatterer().GetZAtomRegistry() .GetObj(mpZAtom->GetZBondAtom())).GetName()+")"); WXCrystObjBasic* pFieldBond=par->WXCreate(this); mpSizer->Add(pFieldBond,0,wxALIGN_LEFT); mList.Add(pFieldBond); } if(1GetZScatterer().GetZAtomRegistry().Find(*mpZAtom)) { RefinablePar *par=&(mpZAtom->GetZScatterer().GetPar(&(mpZAtom->mAngle))); par->SetName("Angle(w/"+(mpZAtom->GetZScatterer().GetZAtomRegistry() .GetObj(mpZAtom->GetZAngleAtom())).GetName()+")"); WXCrystObjBasic* pFieldAngle =par->WXCreate(this); mpSizer->Add(pFieldAngle,0,wxALIGN_LEFT); mList.Add(pFieldAngle); } if(2GetZScatterer().GetZAtomRegistry().Find(*mpZAtom)) { RefinablePar *par=&(mpZAtom->GetZScatterer().GetPar(&(mpZAtom->mDihed))); par->SetName("DihedralAngle(w/"+(mpZAtom->GetZScatterer().GetZAtomRegistry() .GetObj(mpZAtom->GetZDihedralAngleAtom())).GetName()+")"); WXCrystObjBasic* pFieldDihed=par->WXCreate(this); mpSizer->Add(pFieldDihed,0,wxALIGN_LEFT); mList.Add(pFieldDihed); } { RefinablePar *par=&(mpZAtom->GetZScatterer().GetPar(&(mpZAtom->mOccupancy))); par->SetName("Occup."); WXCrystObjBasic* pFieldOccup=par->WXCreate(this); mpSizer->Add(pFieldOccup,0,wxALIGN_LEFT); mList.Add(pFieldOccup); } this->SetSizer(mpSizer); this->BottomLayout(0); this->CrystUpdate(true); VFN_DEBUG_EXIT("WXZAtom::WXZAtom()",6) } void WXZAtom::CrystUpdate(const bool uui,const bool lock) { VFN_DEBUG_ENTRY("WXZAtom::CrystUpdate()",6) if(lock) mMutex.Lock(); mList.CrystUpdate(uui,false); if(lock) mMutex.Unlock(); VFN_DEBUG_EXIT("WXZAtom::CrystUpdate()",6) } void WXZAtom::UpdateUI(const bool lock) { VFN_DEBUG_ENTRY("WXZAtom::UpdateUI()",6) if(lock) mMutex.Lock(); mList.UpdateUI(false); mpFieldName->SetValue(mpZAtom->GetName().c_str()); if(0!=mpZAtom->GetScatteringPower()) mpFieldScattPower->SetValue(mpZAtom->GetScatteringPower()->GetName()); else mpFieldScattPower->SetValue("Dummy"); if(lock) mMutex.Unlock(); VFN_DEBUG_EXIT("WXZAtom::UpdateUI()",6) } void WXZAtom::OnChangeScattPow(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_MESSAGE("WXAtom::OnChangeScattPow()",6) WXCrystValidateAllUserInput(); int choice; const ScatteringPower *scatt=WXDialogChooseFromRegistry( mpZAtom->GetZScatterer().GetCrystal().GetScatteringPowerRegistry(), (wxWindow*)this,"Choose a new Scattering Power",choice); if(0==scatt) return; mpZAtom->SetScatteringPower(scatt); this->CrystUpdate(true); this->UpdateUI(true); } //////////////////////////////////////////////////////////////////////// // // WXZScatterer // //////////////////////////////////////////////////////////////////////// static const long ID_ZSCATTERER_MENU_ATOM= WXCRYST_ID(); static const long ID_ZSCATTERER_MENU_ATOM_ADD= WXCRYST_ID(); static const long ID_ZSCATTERER_MENU_ATOM_CHANGE_PIVOT= WXCRYST_ID(); static const long ID_ZSCATTERER_MENU_PAR_LIMITS_RELAT_BOND= WXCRYST_ID(); static const long ID_ZSCATTERER_MENU_PAR_LIMITS_RELAT_ANGLE=WXCRYST_ID(); static const long ID_ZSCATTERER_MENU_PAR_LIMITS_RELAT_DIHED=WXCRYST_ID(); static const long ID_ZSCATTERER_MENU_FILE= WXCRYST_ID(); static const long ID_ZSCATTERER_MENU_IMPORT_FHZ= WXCRYST_ID(); static const long ID_ZSCATTERER_MENU_EXPORT_FHZ= WXCRYST_ID(); static const long ID_ZSCATTERER_MENU_CONVERT2MOLECULE= WXCRYST_ID(); BEGIN_EVENT_TABLE(WXZScatterer,wxWindow) EVT_BUTTON(ID_WXOBJ_COLLAPSE, WXCrystObj::OnToggleCollapse) EVT_MENU(ID_REFOBJ_MENU_PAR_FIXALL, WXRefinableObj::OnMenuFixAllPar) EVT_MENU(ID_REFOBJ_MENU_PAR_UNFIXALL, WXRefinableObj::OnMenuUnFixAllPar) EVT_MENU(ID_REFOBJ_MENU_PAR_RANDOMIZE, WXRefinableObj::OnMenuParRandomize) EVT_MENU(ID_ZSCATTERER_MENU_PAR_LIMITS_RELAT_BOND, WXZScatterer::OnMenuSetLimits) EVT_MENU(ID_ZSCATTERER_MENU_PAR_LIMITS_RELAT_ANGLE, WXZScatterer::OnMenuSetLimits) EVT_MENU(ID_ZSCATTERER_MENU_PAR_LIMITS_RELAT_DIHED, WXZScatterer::OnMenuSetLimits) EVT_MENU(ID_ZSCATTERER_MENU_ATOM_ADD, WXZScatterer::OnMenuAddZAtom) EVT_MENU(ID_ZSCATTERER_MENU_ATOM_CHANGE_PIVOT, WXZScatterer::OnMenuChangePivotAtom) EVT_MENU(ID_ZSCATTERER_MENU_IMPORT_FHZ, WXZScatterer::OnMenuImportZMatrix) EVT_MENU(ID_ZSCATTERER_MENU_EXPORT_FHZ, WXZScatterer::OnMenuExportZMatrix) EVT_MENU(ID_ZSCATTERER_MENU_CONVERT2MOLECULE, WXZScatterer::OnMenuConvert2Molecule) END_EVENT_TABLE() WXZScatterer::WXZScatterer(wxWindow* parent, ZScatterer *obj): WXScatterer(parent,obj),mpZScatterer(obj) { VFN_DEBUG_MESSAGE("WXZScatterer::WXZScatterer()",6) //Menus mpMenuBar->AddMenu("Import/Export",ID_ZSCATTERER_MENU_FILE); mpMenuBar->AddMenuItem(ID_ZSCATTERER_MENU_FILE, ID_ZSCATTERER_MENU_IMPORT_FHZ, "Import Fenske-Hall Zmatrix"); mpMenuBar->AddMenuItem(ID_ZSCATTERER_MENU_FILE, ID_ZSCATTERER_MENU_EXPORT_FHZ, "Save as Fenske-Hall Zmatrix"); mpMenuBar->AddMenuItem(ID_ZSCATTERER_MENU_FILE, ID_ZSCATTERER_MENU_CONVERT2MOLECULE, "Convert to Molecule"); mpMenuBar->AddMenu("Parameters",ID_REFOBJ_MENU_PAR); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_FIXALL,"Fix all"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_UNFIXALL,"Unfix all"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_RANDOMIZE, "Randomize Configuration"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_ZSCATTERER_MENU_PAR_LIMITS_RELAT_BOND, "Set limits (relative) on all bondlengths"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_ZSCATTERER_MENU_PAR_LIMITS_RELAT_ANGLE, "Set limits (relative) on all bond angles"); mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_ZSCATTERER_MENU_PAR_LIMITS_RELAT_DIHED, "Set limits (relative) on all dihedral angles"); mpMenuBar->AddMenu("Atom",ID_ZSCATTERER_MENU_ATOM); mpMenuBar->AddMenuItem(ID_ZSCATTERER_MENU_ATOM,ID_ZSCATTERER_MENU_ATOM_ADD, "Add an Atom"); mpMenuBar->AddMenuItem(ID_ZSCATTERER_MENU_ATOM,ID_ZSCATTERER_MENU_ATOM_CHANGE_PIVOT, "Change Pivot Atom"); //mpSizer->SetItemMinSize(mpMenuBar, // mpMenuBar->GetSize().GetWidth(), // mpMenuBar->GetSize().GetHeight()); //Orientation wxBoxSizer* sizer=new wxBoxSizer(wxHORIZONTAL); WXCrystObjBasic* pFieldPhi =mpZScatterer->GetPar(&(mpZScatterer->mPhi)).WXCreate(this); WXCrystObjBasic* pFieldChi =mpZScatterer->GetPar(&(mpZScatterer->mChi)).WXCreate(this); WXCrystObjBasic* pFieldPsi =mpZScatterer->GetPar(&(mpZScatterer->mPsi)).WXCreate(this); sizer->Add(pFieldPhi ,0,wxALIGN_CENTER); sizer->Add(pFieldChi ,0,wxALIGN_CENTER); sizer->Add(pFieldPsi ,0,wxALIGN_CENTER); mpSizer->Add(sizer,0,wxALIGN_LEFT); mList.Add(pFieldPhi); mList.Add(pFieldChi); mList.Add(pFieldPsi); //Atoms mpWXZAtomRegistry=mpZScatterer->mZAtomRegistry.WXCreate(this); mpSizer->Add(mpWXZAtomRegistry,0,wxALIGN_LEFT); mList.Add(mpWXZAtomRegistry); this->BottomLayout(0); this->CrystUpdate(true); } void WXZScatterer::OnMenuAddZAtom(wxCommandEvent & WXUNUSED(event)) { VFN_DEBUG_ENTRY("WXZScatterer::OnMenuAddZAtom()",6) WXCrystValidateAllUserInput(); int choice; int bondAtomId=0; double bondLength; int angleAtomId=0;; double angle; int dihedAtomId=0;; double dihed; //Scattering power const ScatteringPower *scattPow=WXDialogChooseFromRegistry( mpZScatterer->GetCrystal().GetScatteringPowerRegistry(), this,"Choose an atom type (ScatteringPower):",choice); if(0==scattPow) { VFN_DEBUG_EXIT("WXZScatterer::OnMenuAddZAtom():Cancelled",6) return; } //Bond atom if(0GetZAtomRegistry().GetNb()) { const ZAtom *bondAtom=WXDialogChooseFromRegistry(mpZScatterer->GetZAtomRegistry(), this,"Choose the bonded atom",bondAtomId); if(0==bondAtom) { VFN_DEBUG_EXIT("WXZScatterer::OnMenuAddZAtom():Cancelled",6) return; } //Bond length wxTextEntryDialog bondLengthDialog(this,_T("Enter bond length (Angstroems)"), _T("Bond length"),_T("1.5"),wxOK | wxCANCEL); bondLengthDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=bondLengthDialog.ShowModal()) { VFN_DEBUG_EXIT("WXZScatterer::OnMenuAddZAtom():Cancelled",6) return; } bondLengthDialog.GetValue().ToDouble(&bondLength); } //angle atom if(1GetZAtomRegistry().GetNb()) { const ZAtom *angleAtom=WXDialogChooseFromRegistry(mpZScatterer->GetZAtomRegistry(), this,"Angle Atom",angleAtomId); if(0==angleAtom) { VFN_DEBUG_EXIT("WXZScatterer::OnMenuAddZAtom():Cancelled",6) return; } //angle wxTextEntryDialog angleDialog(this,_T("Enter bond angle (degrees)"), _T("Bond Angle"),_T("110"),wxOK | wxCANCEL); angleDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=angleDialog.ShowModal()) { VFN_DEBUG_EXIT("WXZScatterer::OnMenuAddZAtom():Cancelled",6) return; } angleDialog.GetValue().ToDouble(&angle); } //dihedral atom if(2GetZAtomRegistry().GetNb()) { const ZAtom *dihedAtom=WXDialogChooseFromRegistry(mpZScatterer->GetZAtomRegistry(), this,"Dihedral angle Atom",dihedAtomId); if(0==dihedAtom) { VFN_DEBUG_EXIT("WXZScatterer::OnMenuAddZAtom():Cancelled",6) return; } //dihedral angle wxTextEntryDialog dihedDialog(this,_T("Enter dihedral angle (degrees)"), _T("Dihedral Angle"),_T("0"),wxOK | wxCANCEL); dihedDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=dihedDialog.ShowModal()) { VFN_DEBUG_EXIT("WXZScatterer::OnMenuAddZAtom():Cancelled",6) return; } dihedDialog.GetValue().ToDouble(&dihed); } // Check all atoms are different if(1GetZAtomRegistry().GetNb()) if(bondAtomId==angleAtomId) { wxMessageDialog dumbUser(this,_T("Bond, angle an dihedral atoms *must* be different"), _T("Whooops"),wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); return; } if(2GetZAtomRegistry().GetNb()) if((bondAtomId==angleAtomId)||(bondAtomId==dihedAtomId)||(angleAtomId==dihedAtomId)) { wxMessageDialog dumbUser(this,_T("Bond, angle an dihedral atoms *must* be different"), _T("Whooops"),wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); return; } char buf [5]; sprintf(buf,"%d",mpZScatterer->GetNbComponent()+1); mpZScatterer->AddAtom (scattPow->GetName()+(string)buf, scattPow, bondAtomId,bondLength, angleAtomId,angle*DEG2RAD, dihedAtomId,dihed*DEG2RAD, 1.); this->CrystUpdate(true); VFN_DEBUG_EXIT("WXZScatterer::OnMenuAddZAtom()",6) } void WXZScatterer::OnMenuSetLimits(wxCommandEvent & event) {//:TODO: Need to VFN_DEBUG_ENTRY("WXZScatterer::OnMenuSetLimits()",6) WXCrystValidateAllUserInput(); if(event.GetId()==ID_ZSCATTERER_MENU_PAR_LIMITS_RELAT_BOND) { double limit=.1; wxTextEntryDialog limitDialog(this,_T("Enter maximum shift in Angstroems\n The limits are taken symmetrically around current position:\n X0-l < X < X0+l "), _T("Set limits (relative) for bondlengths"),_T(".1"),wxOK | wxCANCEL); limitDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=limitDialog.ShowModal()) { VFN_DEBUG_EXIT("WXZScatterer::OnMenuSetLimits():Cancelled",6) return; } limitDialog.GetValue().ToDouble(&limit); if(limit<=0) { wxMessageDialog dumbUser(this,_T("Limit must be > 0 !"), _T("Whooops"),wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); return; } mpZScatterer->SetLimitsRelative(gpRefParTypeScattConformBondLength,-limit,limit); } if(event.GetId()==ID_ZSCATTERER_MENU_PAR_LIMITS_RELAT_ANGLE) { double limit=5; wxTextEntryDialog limitDialog(this,_T("Enter maximum shift in Degrees\n The limits are taken symmetrically around current position:\n X0-l < X < X0+l "), _T("Set limits (relative) for bond angles"),_T(".1"),wxOK | wxCANCEL); limitDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=limitDialog.ShowModal()) { VFN_DEBUG_EXIT("WXZScatterer::OnMenuSetLimits():Cancelled",6) return; } limitDialog.GetValue().ToDouble(&limit); if(limit<=0) { wxMessageDialog dumbUser(this,_T("Limit must be > 0 !"), _T("Whooops"),wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); return; } limit *=DEG2RAD; mpZScatterer->SetLimitsRelative(gpRefParTypeScattConformBondAngle,-limit,limit); } if(event.GetId()==ID_ZSCATTERER_MENU_PAR_LIMITS_RELAT_DIHED) { double limit=5; wxTextEntryDialog limitDialog(this,_T("Enter maximum shift in Degrees\n The limits are taken symmetrically around current position:\n X0-l < X < X0+l "), _T("Set limits (relative) for dihedral angles"),_T(".1"),wxOK | wxCANCEL); limitDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC)); if(wxID_OK!=limitDialog.ShowModal()) { VFN_DEBUG_EXIT("WXZScatterer::OnMenuSetLimits():Cancelled",6) return; } limitDialog.GetValue().ToDouble(&limit); if(limit<=0) { wxMessageDialog dumbUser(this,_T("Limit must be > 0 !"), _T("Whooops"),wxOK|wxICON_EXCLAMATION); dumbUser.ShowModal(); return; } limit *=DEG2RAD; mpZScatterer->SetLimitsRelative(gpRefParTypeScattConformDihedAngle,-limit,limit); } } void WXZScatterer::OnMenuChangePivotAtom(wxCommandEvent &WXUNUSED(event)) { WXCrystValidateAllUserInput(); int pivot=mpZScatterer->mCenterAtomIndex; const ZAtom *atom=WXDialogChooseFromRegistry(mpZScatterer->GetZAtomRegistry(), this,"Choose the new Pivot atom",pivot); if(0==atom) { VFN_DEBUG_EXIT("WXZScatterer::OnMenuAddZAtom():Cancelled",6) return; } mpZScatterer->mCenterAtomIndex=pivot; mpZScatterer->mClockScatterer.Click(); } void WXZScatterer::OnMenuImportZMatrix(wxCommandEvent &WXUNUSED(event)) { wxFileDialog open(this,_T("Choose a file"),_T(""),_T(""),_T("*.fhz"), wxFD_OPEN | wxFD_FILE_MUST_EXIST); if(open.ShowModal() != wxID_OK) return; ifstream fin (open.GetPath().ToAscii()); if(!fin) { throw ObjCrystException("WXZScatterer::OnMenuImportZMatrix() : \ Error opening file for input:"+string(open.GetPath().ToAscii())); } mpZScatterer->ImportFenskeHallZMatrix(fin); fin.close(); } void WXZScatterer::OnMenuExportZMatrix(wxCommandEvent &WXUNUSED(event)) { wxFileDialog save(this,_T("Choose a file"),_T(""),_T(""),_T("*.fhz"),wxFD_SAVE); if(save.ShowModal() != wxID_OK) return; ofstream fout (save.GetPath().ToAscii()); if(!fout) { throw ObjCrystException("WXZScatterer::OnMenuExportZMatrix() : \ Error opening file for input:"+string(save.GetPath().ToAscii())); } fout.imbue(std::locale::classic()); mpZScatterer->ExportFenskeHallZMatrix(fout); fout.close(); } void WXZScatterer::OnMenuConvert2Molecule(wxCommandEvent &WXUNUSED(event)) { Molecule *mol=ZScatterer2Molecule(mpZScatterer); mpZScatterer->GetCrystal().RemoveScatterer(mpZScatterer); mol->GetCrystal().AddScatterer(mol); //mol->GetCrystal().UpdateDisplay(); } }// namespace objcryst-2022.1/ObjCryst/wxCryst/wxZScatterer.h000066400000000000000000000043621430515525000215040ustar00rootroot00000000000000/* ObjCryst++ Object-Oriented Crystallographic Library (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net 2000-2001 University of Geneva (Switzerland) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _VFN_WX_ZSCATTERER_H_ #define _VFN_WX_ZSCATTERER_H_ #include "ObjCryst/wxCryst/wxScatterer.h" #include "ObjCryst/ObjCryst/ZScatterer.h" #include "ObjCryst/ObjCryst/Molecule.h" namespace ObjCryst { class WXZAtom:public WXCrystObjBasic { public: WXZAtom(wxWindow *parent, ZAtom*); virtual void CrystUpdate(const bool updateUI=false,const bool mutexlock=false); virtual void UpdateUI(const bool mutexlock=false); void OnChangeScattPow(wxCommandEvent & WXUNUSED(event)); private: ZAtom *mpZAtom; wxBoxSizer *mpSizer; WXCrystObjBasicList mList; WXFieldString *mpFieldName; WXFieldChoice* mpFieldScattPower; DECLARE_EVENT_TABLE() }; /// wxCryst class for ZScatterer objects class WXZScatterer: public WXScatterer { public: WXZScatterer(wxWindow *parent, ZScatterer*); void OnMenuAddZAtom(wxCommandEvent & WXUNUSED(event)); void OnMenuSetLimits(wxCommandEvent &event); void OnMenuChangePivotAtom(wxCommandEvent &WXUNUSED(event)); void OnMenuImportZMatrix(wxCommandEvent &WXUNUSED(event)); void OnMenuExportZMatrix(wxCommandEvent &WXUNUSED(event)); void OnMenuConvert2Molecule(wxCommandEvent &WXUNUSED(event)); private: ZScatterer* mpZScatterer; WXRegistry *mpWXZAtomRegistry; DECLARE_EVENT_TABLE() }; } //namespace #endif //_VFN_WX_ZSCATTERER_H_ objcryst-2022.1/README.rst000066400000000000000000000062441430515525000151340ustar00rootroot00000000000000===================================== F.O.X.: Free Objects for Xtallography ===================================== Introduction ============ Fox, 'Free Objects for Crystallography' is a free, open-source program for the ab initio structure determination from powder diffraction. The FOX program (for Linux, MacOS X and windows) was made for the ab initio crystal structure solution from diffraction data (mostly powder diffraction data). Features ======== The most interesting features for ab initio structure determination are: - a versatile description of the crystal contents: either isolated atoms , molecules described using a bond length, bond angles and dihedral angles, and polyhedra for inorganic compounds. You can describe your structure by using any combination of groups of atoms, using a chemist's or crystallographer knowledge about the connectivity in your sample to constrain possible solutions.. - an automatic correction for special positions and shared atoms between polyhedra, suitable for global optimization algorithms. - the ability to find peaks in a powder pattern, index the unit cell, and explore possible spacegroups - the ability to use simultaneously multiple powder patterns (X-rays, neutrons), as well as single crystal data (e.g. extracted from a powder pattern) - smart global optimization algorithms which can get out of false minima. - a graphical interface (see the screenshots) with a 3D crystal structure view, with live updates during the optimization process. - the ability to view CIF files So, if you: - have an unknown compound but with (approximately) known composition. - have a powder pattern (X-Ray or neutron or both) - would like to solve the structure (i.e. find the atom -or group of atoms- positions, before refining them with another package). Then Fox can help you. Viewing crystal structure, diffraction data and CIF files ========================================================= FOX can also be used to display CIF (Crystallographic Information Files). It can thus be used also for educational purposes, to show a 3D display of Crystal structures, and the associated powder pattern(s) (see how adding atoms, changing the lattice, or changing the spacegroup affects the powder pattern and the 3D structure). In the latest version (2016.1), it is possible to query directly the Crystallography Open Database (http://www.crystallography.net) from FOX, and open the associated crystal structures. Development =========== If you would also like to choose your own criterion and algorithm to solve the structure, then it will be even better : FOX is built on a very customizable and expandable library (ObjCryst++), which allows you to evaluate your Crystal structure following a combination of criteria from diffraction data and interatomic distances. Other criteria for optimization and other algorithms can easily be added. The main API documentation can be found at: https://vincefn.net/ObjCryst/classes.html Documentation ============= The main documentation for FOX can be found at: https://fox.vincefn.net Installation ============ Follow the instructions at: http://fox.vincefn.net/Install Tutorials ========= New to FOX ? See: http://fox.vincefn.net/Tutorials objcryst-2022.1/cctbx/000077500000000000000000000000001430515525000145425ustar00rootroot00000000000000objcryst-2022.1/cctbx/gnu.mak000066400000000000000000000057441430515525000160370ustar00rootroot00000000000000 CXXFLAGS = -O3 -Wall -pedantic -Iinclude -Wno-long-long OBJ_ELTBX= cctbx/eltbx/basic.o cctbx/eltbx/icsd_radii.o cctbx/eltbx/covalent_radii.o cctbx/eltbx/tiny_pse.o cctbx/eltbx/fp_fdp.o \ cctbx/eltbx/neutron.o cctbx/eltbx/wavelengths.o \ cctbx/eltbx/xray_scattering/it1992.o cctbx/eltbx/xray_scattering/n_gaussian.o \ cctbx/eltbx/xray_scattering/n_gaussian_raw.o cctbx/eltbx/xray_scattering/wk1995.o \ cctbx/eltbx/henke.o cctbx/eltbx/henke_tables_25_36.o cctbx/eltbx/henke_tables_61_72.o \ cctbx/eltbx/henke_tables_01_12.o cctbx/eltbx/henke_tables_37_48.o cctbx/eltbx/henke_tables_73_84.o \ cctbx/eltbx/henke_tables_13_24.o cctbx/eltbx/henke_tables_49_60.o cctbx/eltbx/henke_tables_85_92.o \ cctbx/eltbx/sasaki.o cctbx/eltbx/sasaki_tables_25_36.o cctbx/eltbx/sasaki_tables_61_72.o \ cctbx/eltbx/sasaki_tables_01_12.o cctbx/eltbx/sasaki_tables_37_48.o cctbx/eltbx/sasaki_tables_73_82.o \ cctbx/eltbx/sasaki_tables_13_24.o cctbx/eltbx/sasaki_tables_49_60.o OBJ_SGTBX = cctbx/sgtbx/bricks.o cctbx/sgtbx/miller.o cctbx/sgtbx/select_generators.o \ cctbx/sgtbx/tr_group.o cctbx/sgtbx/change_of_basis_op.o cctbx/sgtbx/reciprocal_space_asu.o \ cctbx/sgtbx/seminvariant.o cctbx/sgtbx/tr_vec.o \ cctbx/sgtbx/find_affine.o cctbx/sgtbx/reciprocal_space_ref_asu.o cctbx/sgtbx/site_symmetry.o cctbx/sgtbx/utils.o \ cctbx/sgtbx/group_codes.o cctbx/sgtbx/rot_mx.o cctbx/sgtbx/space_group.o cctbx/sgtbx/wyckoff.o \ cctbx/sgtbx/hall_in.o cctbx/sgtbx/rot_mx_info.o cctbx/sgtbx/space_group_type.o \ cctbx/sgtbx/lattice_symmetry.o cctbx/sgtbx/row_echelon_solve.o cctbx/sgtbx/symbols.o \ cctbx/sgtbx/lattice_tr.o cctbx/sgtbx/rt_mx.o cctbx/sgtbx/tensor_rank_2.o \ cctbx/sgtbx/reference_settings/hall_symbol_table.o cctbx/sgtbx/reference_settings/normalizer.o \ cctbx/sgtbx/reference_settings/matrix_group_code_table.o cctbx/sgtbx/reference_settings/wyckoff.o OBJ_MILLER = cctbx/miller/asu.o cctbx/miller/index_generator.o cctbx/miller/match_bijvoet_mates.o \ cctbx/miller/sym_equiv.o cctbx/miller/bins.o cctbx/miller/index_span.o cctbx/miller/match_indices.o OBJ_UCTBX = cctbx/uctbx/uctbx.o cctbx/uctbx/spoil_optimization.o OBJ = $(OBJ_ELTBX) $(OBJ_SGTBX) $(OBJ_MILLER) $(OBJ_UCTBX) MAKEDEPEND = gcc -MM ${CXXFLAGS} $< > $*.dep %.o : %.cpp @$(MAKEDEPEND) ${CXX} ${CPPFLAGS} ${CXXFLAGS} -c $< -o $@ libcctbx.a : ${OBJ} @${RM} $@ ${AR} crs $@ ${filter-out %.a %.so, $^} -include $(OBJ:.o=.dep) lib: libcctbx.a install:lib cp -f libcctbx.a ../static-libs/lib/ rm -Rf ../static-libs/include/boost ../static-libs/include/cctbx ../static-libs/include/scitbx cp -Rf include/* ../static-libs/include/ # target for removing all object files .PHONY : tidy tidy:: @${RM} -f core ${OBJ} *.dep */*.dep */*/*.dep # target for removing all object files and libraries .PHONY : clean clean:: tidy @${RM} *.a #scitbx.constants.h objcryst-2022.1/cctbx/mkcctbx.sh000077500000000000000000000055651430515525000165470ustar00rootroot00000000000000#!/bin/bash # This script will create the cctbx and scitbx sub-directory from an installed cctbx in /usr/local/cctbx/, #including the required boost headers rm -Rf cctbx scitbx include *.a rsync -ar /usr/local/cctbx/cctbx_sources/cctbx --filter="+ */" --filter="- adp_restraints/" --filter="- adptbx/" --filter="- boost_python/" --filter="- command_line/" --filter="- crystal/" --filter="- development/" --filter="- dmtbx/" --filter="- examples/" --filter="- geometry_restraints/" --filter="- macro_mol/" --filter="- maptbx/" --filter="- neutron/" --filter="- reference/" --filter="- regression/" --filter="- source_generators/" --filter="- translation_search/" --filter="- web/" --filter="+ *.cpp" --filter="- *" ./ cp /usr/local/cctbx/cctbx_build/cctbx/eltbx/*.cpp cctbx/eltbx/ mkdir include rsync -ar /usr/local/cctbx/cctbx_sources/cctbx --filter="+ */" --filter="- adp_restraints/" --filter="- adptbx/" --filter="- boost_python/" --filter="- command_line/" --filter="- crystal/" --filter="- development/" --filter="- dmtbx/" --filter="- examples/" --filter="- geometry_restraints/" --filter="- macro_mol/" --filter="- maptbx/" --filter="- neutron/" --filter="- reference/" --filter="- regression/" --filter="- source_generators/" --filter="- translation_search/" --filter="- web/" --filter="+ *.h" --filter="- *" include/ mkdir -p scitbx/include/ rsync -ar /usr/local/cctbx/cctbx_sources/scitbx --filter="+ */" --filter="- boost_python/" --filter="+ *.h" --filter="- *" include/ cp -Rf /usr/local/cctbx/cctbx_build/include/scitbx include/ cp /usr/local/cctbx/cctbx_sources/cctbx/LICENSE_2_0.txt CCTBX_LICENSE_2_0.txt # Now copy the boost parts cctbx needs rsync -ar /usr/local/cctbx/cctbx_sources/boost/boost --exclude="accumulators/" --exclude="algorithm/" --exclude="archive/" --exclude="asio/" --exclude="asign/" --exclude="bimap/" --exclude="bind/" --exclude="circular_buffer/" --exclude="concept/" --exclude="concept_check/" --exclude="dynamic_bitset/" --exclude="filesystem/" --exclude="flyweight/" --exclude="function/" --exclude="function_types/" --exclude="gil/" --exclude="graph/" --exclude="interprocess/" --exclude="intrusive/" --exclude="iostreams/" --exclude="lambda/" --exclude="logic/" --exclude="mpi/" --exclude="parameter/" --exclude="pending/" --exclude="pool/" --exclude="program_options/" --exclude="property_tree/" --exclude="proto/" --exclude="ptr_container/" --exclude="python/" --exclude="random/" --exclude="range/" --exclude="regex/" --exclude="serialization/" --exclude="signals/" --exclude="spirit/" --exclude="statechart/" --exclude="system/" --exclude="test/" --exclude="thread/" --exclude="units/" --exclude="unordered/" --exclude="variant/" --exclude="wave/" --exclude="xpressive/" --filter="+ */" --filter="+ *.hpp" --filter="+ *.ipp" --filter="- *" include/ cp /usr/local/cctbx/cctbx_sources/boost/LICENSE_1_0.txt BOOST_LICENSE.txt cd .. ; tar -cjf cctbx.tar.bz2 cctbx ; cd cctbx