### SpaceGroupExplorer Output Example Source: https://pyobjcryst.readthedocs.io/en/latest/examples/structure-solution-multiprocessing.html Example output showing the exploration process, goodness-of-fit metrics for various spacegroups, and the final selection. ```text Beginning spacegroup exploration... 37 to go... (# 1) P 1 : Rwp= 6.80% GoF= 14.98 nGoF= 3.24 (186 reflections, 0 extinct) (# 2) P -1 : Rwp= 6.80% GoF= 14.98 nGoF= 3.24 (186 reflections, 0 extinct) [same extinctions as:P 1] (# 3) P 1 2 1 : Rwp= 6.69% GoF= 14.46 nGoF= 1.84 (105 reflections, 0 extinct) (# 4) P 1 21 1 : Rwp= 6.61% GoF= 14.11 nGoF= 1.65 (101 reflections, 2 extinct) (# 5) C 1 2 1 : Rwp= 62.70% GoF= 1246.13 nGoF= 311.68 ( 52 reflections, 84 extinct) (# 5) A 1 2 1 : Rwp= 62.83% GoF= 1253.74 nGoF= 313.87 ( 53 reflections, 85 extinct) (# 5) I 1 2 1 : Rwp= 60.91% GoF= 1196.43 nGoF= 246.94 ( 52 reflections, 87 extinct) (# 6) P 1 m 1 : Rwp= 6.69% GoF= 14.46 nGoF= 1.84 (105 reflections, 0 extinct) [same extinctions as:P 1 2 1] (# 7) P 1 c 1 : Rwp= 6.58% GoF= 13.92 nGoF= 1.66 ( 96 reflections, 15 extinP 1 21/c 1 nGoF= 1.4866 GoF= 13.575 Rw= 6.50 [ 92 reflections, extinct446= 17] P 1 21 1 nGoF= 1.6488 GoF= 14.108 Rw= 6.61 [101 reflections, extinct446= 2] P 1 21/m 1 nGoF= 1.6488 GoF= 14.108 Rw= 6.61 [101 reflections, extinct446= 2] P 1 c 1 nGoF= 1.6649 GoF= 13.922 Rw= 6.58 [ 96 reflections, extinct446= 15] P 1 2/c 1 nGoF= 1.6649 GoF= 13.922 Rw= 6.58 [ 96 reflections, extinct446= 15] P 1 2 1 nGoF= 1.8392 GoF= 14.458 Rw= 6.69 [105 reflections, extinct446= 0] P 1 m 1 nGoF= 1.8392 GoF= 14.458 Rw= 6.69 [105 reflections, extinct446= 0] P 1 2/m 1 nGoF= 1.8392 GoF= 14.458 Rw= 6.69 [105 reflections, extinct446= 0] P 1 nGoF= 3.2428 GoF= 14.982 Rw= 6.80 [186 reflections, extinct446= 0] P -1 nGoF= 3.2428 GoF= 14.982 Rw= 6.80 [186 reflections, extinct446= 0] P 1 21/n 1 nGoF= 5.4155 GoF= 26.697 Rw= 9.11 [ 92 reflections, extinct446= 19] P 1 2/n 1 nGoF= 5.7672 GoF= 27.063 Rw= 9.17 [ 96 reflections, extinct446= 17] P 1 n 1 nGoF= 5.7672 GoF= 27.063 Rw= 9.17 [ 96 reflections, extinct446= 17] Chosen spacegroup (smallest nGoF): P 1 21/c 1 ct) (# 7) P 1 n 1 : Rwp= 9.17% GoF= 27.06 nGoF= 5.77 ( 96 reflections, 17 extinct) (# 7) P 1 a 1 : Rwp= 9.26% GoF= 27.58 nGoF= 5.97 ( 97 reflections, 14 extinct) (# 8) C 1 m 1 : Rwp= 62.70% GoF= 1246.13 nGoF= 311.68 ( 52 reflections, 84 extinct) [same extinctions as:C 1 2 1] (# 8) A 1 m 1 : Rwp= 62.83% GoF= 1253.74 nGoF= 313.87 ( 53 reflections, 85 extinct) [same extinctions as:A 1 2 1] (# 8) I 1 m 1 : Rwp= 60.91% GoF= 1196.43 nGoF= 246.94 ( 52 reflections, 87 extinct) [same extinctions as:I 1 2 1] (# 9) C 1 c 1 : Rwp= 62.51% GoF= 1236.15 nGoF= 280.76 ( 47 reflections, 93 extinct) (# 9) A 1 n 1 : Rwp= 62.99% GoF= 1258.62 nGoF= 291.60 ( 49 reflections, 93 extinct) (# 9) I 1 a 1 : Rwp= 59.00% GoF= 1120.91 nGoF= 221.05 ( 48 reflections, 93 extinct) (# 9) A 1 a 1 : Rwp= 62.99% GoF= 1258.62 nGoF= 291.60 ( 49 reflections, 93 extinct) [same extinctions as:A 1 n 1] (# 9) C 1 n 1 : Rwp= 62.51% GoF= 1236.15 nGoF= 280.76 ( 47 reflections, 93 extinct) [same extinctions as:C 1 c 1] (# 9) I 1 c 1 : Rwp= 59.00% GoF= 1120.91 nGoF= 221.05 ( 48 reflections, 93 extinct) [same extinctions as:I 1 a 1] (# 10) P 1 2/m 1 : Rwp= 6.69% GoF= 14.46 nGoF= 1.84 (105 reflections, 0 extinct) [same extinctions as:P 1 2 1] (# 11) P 1 21/m 1 : Rwp= 6.61% GoF= 14.11 nGoF= 1.65 (101 reflections, 2 extinct) [same extinctions as:P 1 21 1] (# 12) C 1 2/m 1 : Rwp= 62.70% GoF= 1246.13 nGoF= 311.68 ( 52 reflections, 84 extinct) [same extinctions as:C 1 2 1] (# 12) A 1 2/m 1 : Rwp= 62.83% GoF= 1253.74 nGoF= 313.87 ( 53 reflections, 85 extinct) [same extinctions as:A 1 2 1] (# 12) I 1 2/m 1 : Rwp= 60.91% GoF= 1196.43 nGoF= 246.94 ( 52 reflections, 87 extinct) [same extinctions as:I 1 2 1] (# 13) P 1 2/c 1 : Rwp= 6.58% GoF= 13.92 nGoF= 1.66 ( 96 reflections, 15 extinct) [same extinctions as:P 1 c 1] (# 13) P 1 2/n 1 : Rwp= 9.17% GoF= 27.06 nGoF= 5.77 ( 96 reflections, 17 extinct) [same extinctions as:P 1 n 1] ``` -------------------------------- ### Activate environment and launch Jupyter Source: https://pyobjcryst.readthedocs.io/en/latest/index.html Activate the created environment and start the Jupyter Lab interface. ```bash conda activate pyobjcryst jupyter-lab ``` -------------------------------- ### Install pyobjcryst via diffpy channel Source: https://pyobjcryst.readthedocs.io/en/latest/index.html Install the library using the diffpy channel. ```bash conda install -c diffpy libobjcryst pyobjcryst ``` -------------------------------- ### Setup and import libraries for parallel structure solution Source: https://pyobjcryst.readthedocs.io/en/latest/examples/structure-solution-multiprocessing.html Imports required packages including multiprocess (instead of standard multiprocessing due to IPython issues), pyobjcryst, numpy, matplotlib, and optional ipywidgets. It also calculates the number of processor cores available, using psutil if available, and prints the count. This setup is necessary before running the meta-structure solution workflow. ```python %matplotlib widget import os import sys import io import timeit # Note: we need 'multiprocess' instead of standard multiprocessing because of the # following issue (specific to ipython or notebooks): # https://bugs.python.org/issue25053 # https://stackoverflow.com/questions/41385708/multiprocessing-example-giving-attributeerror # # In a python script (not in ipython or a notebook) multiprocessing could be used instead try: from multiprocess import Pool, current_process except ImportError: print("Please install `multiprocess` using 'pip', 'conda' or 'mamba' to run this notebook") print() sys.exit() import pyobjcryst import numpy as np import matplotlib.pyplot as plt from pyobjcryst.crystal import * from pyobjcryst.powderpattern import * from pyobjcryst.indexing import * from pyobjcryst.molecule import * from pyobjcryst.globaloptim import MonteCarlo from pyobjcryst.io import xml_cryst_file_save_global try: import ipywidgets as widgets except ImportError: widgets = None try: # Get the real number of processor cores available - requires psutil # os.sched_getaffinity is only available on some *nix platforms import psutil nproc = len(os.sched_getaffinity(0)) * psutil.cpu_count(logical=False) // psutil.cpu_count(logical=True) except: nproc = os.cpu_count() print("Number of processors or cores available: ", nproc) ``` ```text Number of processors or cores available: 8 ``` -------------------------------- ### XML Loading Output Source: https://pyobjcryst.readthedocs.io/en/latest/examples/structure-solution-multiprocessing.html Example output showing the loading of a crystal structure from XML. ```text XML: Loading Crystal: XML: Loading Crystal:(spg:P 1 21/c 1) Input ScatteringPowerAtom:C(C) Input ScatteringPowerAtom:N(N) Input ScatteringPowerAtom:S(S) ``` -------------------------------- ### Importing pyobjcryst and dependencies Source: https://pyobjcryst.readthedocs.io/en/latest/examples/structure-solution-powder-cimetidine.html Initial setup for the notebook, including matplotlib configuration for interactive plotting and necessary pyobjcryst modules. ```python # 'widget' allows live update and works in both classical notebooks and jupyter-lab. # Otherwise 'notebook', 'ipympl', 'inline' can be used %matplotlib widget import os import pyobjcryst import numpy as np import matplotlib.pyplot as plt from pyobjcryst.crystal import * from pyobjcryst.powderpattern import * from pyobjcryst.indexing import * from pyobjcryst.molecule import * from pyobjcryst.globaloptim import MonteCarlo from pyobjcryst.io import xml_cryst_file_save_global ``` -------------------------------- ### Imports and matplotlib backend setup Source: https://pyobjcryst.readthedocs.io/en/latest/examples/structure-solution-powder-pbso4.html Sets up the matplotlib backend for live updates in notebooks and imports the necessary pyobjcryst modules and standard libraries. The '%matplotlib widget' line enables interactive plots; alternatives include 'notebook', 'ipympl', or 'inline'. ```python # 'widget' allows live update and works in both classical notebooks and jupyter-lab. # Otherwise 'notebook', 'ipympl', 'inline' can be used %matplotlib widget import os import pyobjcryst import numpy as np import matplotlib.pyplot as plt from pyobjcryst.crystal import * from pyobjcryst.scatteringpower import ScatteringPowerAtom from pyobjcryst.atom import Atom from pyobjcryst.polyhedron import MakeTetrahedron from pyobjcryst.powderpattern import * from pyobjcryst.radiation import RadiationType from pyobjcryst.indexing import * from pyobjcryst.molecule import * from pyobjcryst.globaloptim import MonteCarlo from pyobjcryst.io import xml_cryst_file_save_global ``` -------------------------------- ### Run multiple optimizations with automatic LSQ and live widgets Source: https://pyobjcryst.readthedocs.io/en/latest/examples/structure-solution-powder-cimetidine.html Configures automatic least squares refinement every 150k trials, displays the 3D structure and progress widgets, then runs 3 parallel tempering runs of 1 million trials each. Each run starts from a randomized configuration. The output shows the LSQ option and final log-likelihood. ```python mc.GetOption("Automatic Least Squares Refinement").SetChoice(2) print("LSQ option: ", mc.GetOption("Automatic Least Squares Refinement").GetChoiceName(2)) # 3D structure view which will be live-updated with the best # configuration of the current run display(c.widget_3d()) # Small widget to see the progress of the optimisation, with the current run # best log-likelihood, the run number and remaining number of trials. display(mc.widget()) # The powder pattern plot a few cells above should also be updated for each run best solution mc.MultiRunOptimize(nb_run=3, nb_step=1e6) print("Final LLK: %.2f" % mc.GetLogLikelihood()) ``` ```text LSQ option: Every 150000 trials, and at the end of each run ``` ```text Final LLK: 18608.95 ``` -------------------------------- ### Setup and Spacegroup Optimization Function Source: https://pyobjcryst.readthedocs.io/en/latest/examples/structure-solution-multiprocessing.html This code downloads the cimetidine z-matrix, configures the Monte-Carlo optimization, and defines a function to test specific spacegroups by adjusting the number of independent molecules and running parallel optimizations. ```python # Get the cimetidine z-matrix if not os.path.exists("cime.fhz"): os.system("curl -O https://raw.githubusercontent.com/vincefn/objcryst/master/Fox/example/tutorial-cimetidine/cime.fhz") # Disable dynamical occupancy correction (no special position expected, usual in organic structures) c.GetOption(1).SetChoice(0) # Create the Monte-Carlo object with the crystal and the powder pattern mc = MonteCarlo() mc.AddRefinableObj(c) mc.AddRefinableObj(p) mc.GetOption("Automatic Least Squares Refinement").SetChoice(2) nb_step = 1e6 # Increase this for more complex problems - it's ok if the spacegroup is correct (1 independent molecule) # Disable profile fitting for the powder pattern (or nothing gets optimised !) pdiff.SetExtractionMode(False) def solve_for_spacegroup(spgname): # Set spacegroup spg = c.GetSpaceGroup() spg.ChangeSpaceGroup(spgname) # Multiplicity mult = spg.GetNbSymmetrics() # Empty Crystal of existing scatterers (should not be necessary here) for i in range(c.GetNbScatterer()): c.RemoveScatterer(c.GetScatterer(0)) # Add 4/mult independent cimetidine molecules nb_mol = 4//mult for i in range(nb_mol): m = ImportFenskeHallZMatrix(c,"cime.fhz") # Disable all display update if not in the Main process-or strange things happen ! if current_process().name != 'MainProcess': # we must do that for the crystal, monte-carlo and powder pattern object for o in (c, mc, p): o.disable_display_update() # Run the parallel tempering optimisation # We could run multiple times the optimisation (using nb_run), but it is more # efficient to distribute that using the multiprocessing pool nb_run = 1 t0 = timeit.default_timer() for i in range(nb_run): mc.MultiRunOptimize(nb_run=1, nb_step=nb_step) dt = timeit.default_timer() - t0 print("Spacegroup: %12s LLK: %12.2f dt=%3.0fs" % # /run (%3.0fs remaining) (spgname,mc.GetLogLikelihood(), dt,)) # dt/(i+1) * (nb_run-i-1) # Extract all solutions as the XML output of the crystal vsol = [] for i in range(mc.GetNbParamSet()-nb_run, mc.GetNbParamSet()): mc.RestoreParamSet(i, update_display=False) s = c.xml() llk = mc.GetLogLikelihood() vsol.append({'xml': s, 'llk': llk, 'spg': spgname, 'nb_mol': nb_mol}) return vsol ``` -------------------------------- ### Create powder pattern and download data (pbso4-x.dat) Source: https://pyobjcryst.readthedocs.io/en/latest/examples/structure-solution-powder-pbso4.html Initializes a PowderPattern, downloads the X-ray data file 'pbso4-x.dat' if not present, imports it with ImportPowderPatternFullprof, sets the wavelength to 'Cu', prints the radiation, and plots the pattern. ```python px = PowderPattern() if not os.path.exists("pbso4-x.dat"): os.system("curl -o pbso4-x.dat https://raw.githubusercontent.com/vincefn/objcryst/master/Fox/example/tutorial-pbso4/xray.dat") px.ImportPowderPatternFullprof("pbso4-x.dat") px.SetWavelength("Cu") # Valid strings for X-ray tubes are "Cu", "CuA1",... print(px.GetRadiation()) # Better check the string was understood px.plot() ``` -------------------------------- ### Install pyobjcryst via conda-forge Source: https://pyobjcryst.readthedocs.io/en/latest/index.html Install the library using the conda-forge channel, which is recommended for frequent updates. ```bash conda install -c conda-forge libobjcryst pyobjcryst ``` -------------------------------- ### Fit profile and background with quick_fit_profile Source: https://pyobjcryst.readthedocs.io/en/latest/examples/structure-solution-powder-pbso4.html Fits the profile and background using a maximum sin(theta)/lambda of 0.3. The first call adds an automatic background and initializes the profile; the second refines asymmetry and displacement. The output shows the fit result and a reminder to disable profile fitting before structure optimization. ```python px.SetMaxSinThetaOvLambda(0.3) px.quick_fit_profile(auto_background=True,plot=False, init_profile=True,verbose=True) px.quick_fit_profile(plot=False, init_profile=False, asym=True, displ_transl=True, verbose=False) # Plot in new figure px.plot(diff=True, fig=None, hkl=True) print("Fit result: Rw=%6.2f%% Chi2=%10.2f GoF=%8.2f LLK=%10.3f" % (px.rw * 100, px.chi2, px.chi2/px.GetNbPointUsed(), px.llk)) ``` ```text No background, adding one automatically Selected PowderPatternDiffraction: with Crystal: Profile fitting finished. Remember to use SetExtractionMode(False) on the PowderPatternDiffraction object to disable profile fitting and optimise the structure. Fit result: Rw= 8.06% Chi2= 7704.09 GoF= 1.28 LLK= 1194.686 ``` -------------------------------- ### Create powder pattern, index, and fit profile Source: https://pyobjcryst.readthedocs.io/en/latest/examples/structure-solution-multiprocessing.html This snippet imports a powder pattern from 'cime.dat' (downloaded if missing), sets the wavelength, finds peaks, indexes the unit cell, creates a crystal, adds a powder pattern diffraction, fits the profile, and plots the result. It prints the indexed unit cell and fit statistics (Rw, Chi2, GoF, LLK). ```python p = PowderPattern() if not os.path.exists("cime.dat"): os.system("curl -O https://raw.githubusercontent.com/vincefn/objcryst/master/Fox/example/tutorial-cimetidine/cime.dat") p.ImportPowderPatternFullprof("cime.dat") p.SetWavelength(1.52904) # Index pl = p.FindPeaks(1.5, -1, 1000, verbose=False) if len(pl) > 20: pl.resize(20) # Only keep 20 peaks ex = quick_index(pl, verbose=False) print("Indexed unit cell:") for s in ex.GetSolutions(): print(s) # Use solution to create a crystal uc = ex.GetSolutions()[0][0].DirectUnitCell() c = Crystal(uc[0], uc[1], uc[2], uc[3], uc[4], uc[5], "P1") pdiff = p.AddPowderPatternDiffraction(c) # Fit profile p.SetMaxSinThetaOvLambda(0.3) p.quick_fit_profile(auto_background=True,plot=False, init_profile=True,verbose=True) p.quick_fit_profile(plot=False, init_profile=False, asym=True, displ_transl=True, verbose=False) # Plot p.plot(diff=True, fig=None, hkl=True) print("Fit result: Rw=%6.2f%% Chi2=%10.2f GoF=%8.2f LLK=%10.3f" % (p.rw * 100, p.chi2, p.chi2/p.GetNbPointUsed(), p.llk)) ``` ```text Imported powder pattern: 7699 points, 2theta= 8.010 -> 84.990, step= 0.010 Indexed unit cell: ( 6.83 18.82 10.39 90.0 106.4 90.0 V=1281 MONOCLINIC P, 130.0296630859375) No background, adding one automatically Selected PowderPatternDiffraction: with Crystal: Profile fitting finished. Remember to use SetExtractionMode(False) on the PowderPatternDiffraction object to disable profile fitting and optimise the structure. Fit result: Rw= 5.51% Chi2= 34095.69 GoF= 4.43 LLK= 6397.991 ``` -------------------------------- ### Set up notebook environment and import pyobjcryst modules Source: https://pyobjcryst.readthedocs.io/en/latest/examples/Quantitative-phase-analysis.html Use this snippet to enable live plotting with %matplotlib widget and import the required pyobjcryst, numpy, and matplotlib modules. The widget backend allows live updates in classical notebooks and Jupyter Lab; alternatives include 'notebook', 'ipympl', and 'inline'. ```python # 'widget' allows live update and works in both classical notebooks and jupyter-lab. # Otherwise 'notebook', 'ipympl', 'inline' can be used %matplotlib widget import os import pyobjcryst import numpy as np import matplotlib.pyplot as plt from pyobjcryst.crystal import * from pyobjcryst.powderpattern import * from pyobjcryst.indexing import * from pyobjcryst.molecule import * from pyobjcryst.globaloptim import MonteCarlo from pyobjcryst.io import xml_cryst_file_save_global from pyobjcryst.lsq import LSQ from pyobjcryst.refinableobj import refpartype_scattdata_scale ``` -------------------------------- ### Refine profile and lattice parameters with LSQ Source: https://pyobjcryst.readthedocs.io/en/latest/examples/Quantitative-phase-analysis.html Sets up an LSQ refinement, fixes all parameters, then unfixes the scale, W, Zero, Eta0, a, b, and c parameters. Uses SafeRefine with Levenberg-Marquardt for 10 cycles. The comment notes that parameter names are unique and get renamed with tildes for multiple phases. ```python lsq = LSQ() lsq.SetRefinedObj(p, 0, True, True) lsq.PrepareRefParList(True) # lsq.GetCompiledRefinedObj().Print() lsqr = lsq.GetCompiledRefinedObj() lsqr.FixAllPar() # lsqr.Print() # print(lsq.ChiSquare()) lsq.SetParIsFixed(refpartype_scattdata_scale, False) for par in ["W", "Zero", "Eta0", "a", "b", "c"]: for i in range(p.GetNbPowderPatternComponent()): # This is a KLUDGE - we need this because parameter names are # unique, and thus "U" gets renamed to "U~", "U~~" in case of 2,3 phases.. lsq.SetParIsFixed(par + "~"*i, False) lsq.SafeRefine(nbCycle=10, useLevenbergMarquardt=True, silent=True) p.UpdateDisplay() ``` -------------------------------- ### Create PowderPattern and import cimetidine data Source: https://pyobjcryst.readthedocs.io/en/latest/examples/structure-solution-powder-cimetidine.html Creates a PowderPattern object, downloads the cimetidine data file if it does not exist, imports it using ImportPowderPatternFullprof, sets the wavelength to 1.52904, and plots the pattern. ```python p = PowderPattern() if not os.path.exists("cime.dat"): os.system("curl -O https://raw.githubusercontent.com/vincefn/objcryst/master/Fox/example/tutorial-cimetidine/cime.dat") p.ImportPowderPatternFullprof("cime.dat") p.SetWavelength(1.52904) p.plot() ``` -------------------------------- ### Display 3D crystal structure widget Source: https://pyobjcryst.readthedocs.io/en/latest/examples/structure-solution-powder-cimetidine.html Displays the 3D crystal structure widget in a Jupyter notebook. Requires installing ipywidgets and py3Dmol via pip (conda-forge version is obsolete as of 2021/05). The widget updates live during optimization and when RestoreParamSet() is called. The display() call is only needed if c.widget_3d() is not the last command in the cell. ```python display(c.widget_3d()) ``` -------------------------------- ### Create Powder Pattern and Plot Source: https://pyobjcryst.readthedocs.io/en/latest/examples/Quantitative-phase-analysis.html Creates a PowderPattern object, downloads the data file if needed, imports the observed pattern, sets the wavelength to Cu K-alpha1+alpha2, prints the wavelength, and plots with hkl markers. ```python p = PowderPattern() if not os.path.exists(data_file): os.system("curl -O https://www.iucr.org/__data/iucr/powder/QARR/col/%s" % data_file) p.ImportPowderPattern2ThetaObs(data_file) # Copper K-alpha1+alpha2. Use "Cua1" for Cu-alpha1 only p.SetWavelength("Cu") print(p.GetWavelength()) p.plot(hkl=True) ``` ```text 1.5418366591135662 Imported powder pattern: 7251 points, 2theta= 5.000 -> 150.000, step= 0.020 ``` -------------------------------- ### Activate environment and launch Jupyter Lab Source: https://pyobjcryst.readthedocs.io Activates the pyobjcryst environment and launches Jupyter Lab. Run these commands after creating the environment with mamba. ```bash conda activate pyobjcryst jupyter-lab ``` -------------------------------- ### Create neutron powder pattern and fit profile Source: https://pyobjcryst.readthedocs.io/en/latest/examples/structure-solution-powder-pbso4.html This snippet imports the neutron data, sets the radiation to neutron and wavelength to 1.909, adds the powder pattern diffraction, fixes the W profile parameter, and performs profile fitting. It prints the final fit results (Rw, Chi2, GoF, LLK). The output shows the download progress and the imported pattern details. ```python pn = PowderPattern() if not os.path.exists("pbso4-n.dat"): os.system("curl -o pbso4-n.dat https://raw.githubusercontent.com/vincefn/objcryst/master/Fox/example/tutorial-pbso4/neutron.dat") pn.ImportPowderPatternFullprof("pbso4-n.dat") pn.GetRadiation().SetRadiationType(RadiationType.RAD_NEUTRON) pn.SetWavelength(1.909) pn.SetMaxSinThetaOvLambda(0.3) pdiffn = pn.AddPowderPatternDiffraction(c) # pdiffn.GetProfile().GetPar("W").SetValue(0.001) pn.FitScaleFactorForIntegratedRw() # Plot pn.plot(diff=True, fig=None, hkl=True) # Fit profile - we keep the unit cell fixed as it was already refined pn.quick_fit_profile(auto_background=True,plot=True, init_profile=True, cell=False, verbose=True) pn.quick_fit_profile(plot=False, init_profile=False, cell=False, asym=True, displ_transl=True, backgd=False, verbose=False) print("Fit result: Rw=%6.2f%% Chi2=%10.2f GoF=%8.2f LLK=%10.3f" % (pn.rw * 100, pn.chi2, pn.chi2/pn.GetNbPointUsed(), pn.llk)) ``` ```text % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 17902 100 17902 0 0 45463 0 --:--:-- --:--:-- --:--:-- 45552 ``` ```text Imported powder pattern: 2920 points, 2theta= 10.000 -> 155.950, step= 0.050 No background, adding one automatically Selected PowderPatternDiffraction: with Crystal: Profile fitting finished. Remember to use SetExtractionMode(False) on the PowderPatternDiffraction object to disable profile fitting and optimise the structure. Fit result: Rw= 4.51% Chi2= 874.61 GoF= 0.30 LLK= 219.850 ``` -------------------------------- ### Create pyobjcryst environment and launch jupyter-lab Source: https://pyobjcryst.readthedocs.io/en/latest/_sources/index.rst.txt Create a new conda environment named pyobjcryst with all useful dependencies, then activate it and launch jupyter-lab. This is the fastest way to use pyobjcryst. ```bash mamba create -n pyobjcryst python=3.11 pyobjcryst matplotlib py3dmol jupyterlab ipympl multiprocess ``` ```bash conda activate pyobjcryst jupyter-lab ``` -------------------------------- ### Find peaks and index reflections with quick_index Source: https://pyobjcryst.readthedocs.io/en/latest/examples/structure-solution-powder-cimetidine.html Finds peaks using FindPeaks with a threshold of 1.5, keeps only the first 20 peaks, prints each peak, and then indexes the unit cell using quick_index, printing the solutions. ```python # Index pl = p.FindPeaks(1.5, -1, 1000) if len(pl) > 20: pl.resize(20) # Only keep 20 peaks for peak in pl: print(peak) ex = quick_index(pl) print("Solutions:") for s in ex.GetSolutions(): print(s) ``` -------------------------------- ### Add Crystalline Phases from CIF Files Source: https://pyobjcryst.readthedocs.io/en/latest/examples/Quantitative-phase-analysis.html Loops over COD IDs, creates crystal structures from CIF URLs, adds them as diffraction components, fits scale factors, and updates the display. ```python for cod_id in cod_phases: c = CreateCrystalFromCIF("http://crystallography.net/cod/%d.cif" % cod_id) #print(c,"\n") p.AddPowderPatternDiffraction(c) p.FitScaleFactorForRw() p.UpdateDisplay() ``` ```text ========================== WARNING ========================= In ScatteringPowerAtom::GetTemperatureFactor(): Anisotropic Displacement Parameters are not currently properly handled for Debye-Waller calculations (no symmetry handling for ADPs). =>The Debye-Waller calculations will instead use only isotropic DPs ```