hexrd icon indicating copy to clipboard operation
hexrd copied to clipboard

A more user friendly initialization method for material.Material objects

Open argerlt opened this issue 1 year ago • 4 comments

I had a feature I wanted to add, but I want to make sure it doesn't already exist in a way I don't know about, and possibly have some experts weigh in on what to watch out for so I don't break any important features.

@donald-e-boyce @psavery @saransh13

Elevator Pitch of the Issue:

Allow users to more easily initalize Material Class objects without initializing from an h5 or CIF. The method commonly used in example scripts involves creating a default Nickel material, then selectively overwriting the relevant attributes. This requires some a-priori understanding of how the Materials class is organized and calculated in HEXRD, and can occasionally cause program-breaking errors if additional hidden attributes (eg, PlaneData and UnitCell objects) are not also overwritten in the correct order.

Longer Description

currently, initializing a material class WITHOUT an already existing hdf5 or cif calls Materials.init with the following defaults:

    DFLT_NAME = 'material.xtal'
    DFLT_XTAL = 'Ni'
    DFLT_SGNUM = 225
    DFLT_LPARMS = [_angstroms(3.61), _angstroms(3.61), _angstroms(3.61),
                   _degrees(90.0), _degrees(90.0), _degrees(90.0)]
    DFLT_SSMAX = 100
    DFLT_KEV = valWUnit('wavelength', 'energy', 80.725e0, 'keV')
    DFLT_STR = 0.0025
    DFLT_TTH = numpy.radians(0.25)
    DFLT_TTHMAX = None
    DFLT_ATOMINFO = numpy.array([[0., 0., 0., 1.]])
    DFLT_U = numpy.array([6.33E-3])
    DFLT_ATOMTYPE = numpy.array([28])
    DFLT_CHARGE = numpy.array(["0"])
    DFLT_DMIN = _angstroms(0.75)
    DFLT_STIFFNESS = numpy.eye(6)
    DFLT_SGSETTING = 0

If users want to create a new material outside of hexrdgui (say, testing a toy problem with randomly generated crystal structures or testing different beam energies), the easiest way is usually:

  1. create a default nickel material
  2. overwrite relevant default values
  3. know enough about how the material class works to know to rerun the relevant secondary initialization functions to regenerate the correct PlaneData, Unitcell, etc.

Often, users will write some variation of a generator function like the one below to automate this:

def make_matl(mat_name, sgnum, lparms, hkl_ssq_max=50):
    matl = material.Material(mat_name)
    matl.sgnum = sgnum
    matl.latticeParameters = lparms
    matl.hklMax = hkl_ssq_max
    nhkls = len(matl.planeData.exclusions)
    matl.planeData.set_exclusions(np.zeros(nhkls, dtype=bool))
    return matl

This works, but it's clunky, and its also alienating to new users who do not know a priori how this function works or how to properly overwrite the correct values.

Synopsis of My Solution:

Instead of 20-odd default values that clutter up the namespace, there should just be a default values dictionary, and users should be able to selectively overwrite the values they want on initialization, as opposed to after the fact. this can be done both through custom dictionaries of changed values, or just by passing in wildcard keywords

Initial rules should stay unchanged: all the same inputs are still allowed, and values taken from a CIF or HDF5 still overwrite defaults. All I want is the ability to pass any of the following single lines and have all of them give a reasonable result

from hexrd.material import Material

ruby_1 = Material('Ruby', kev=78.6)
ruby_2 = Material('Ruby', kev=valWUnit("wavelength","ENERGY",78.6,"keV")
Mg1 = Material("Mg_alloy", sgsetting=[0.333,0.667,0.25,] A=3.17, B=3.17, C=5.14, alpha=90, beta=90, gamma=90)
Mg_alloy_from_file = Material("Mg_stretched,
different_me3 = Material('ME3', "materials.h5"], name="doped_me3",C=5.20)

DO NOTE: I am aware now that there are ways to initialize these materials using HEXRD as is, but they are not well documented or intuitive, and they slowed me down a lot while learning. this is less about expanding the capabilities, and more about simplifying the process and adding documentation so new users can have an easier time learning on their own.

argerlt avatar Oct 05 '23 18:10 argerlt

I do support a simpler interface. If you have improvements then do submit a PR! One concern I have in giving users too much freedom. For eg., if only alpha angle is specified together with lattice parameters a and b, then that limits the space group to a subset of the 230. It just seems a lot of extra work to go through that.

I will point you to hexrd.mksupport.mk for a command line tool for making a material. Here's how it looks for a FCC material

In [1]: from hexrd.mksupport import mk

In [2]: filename = "test.h5"

In [3]: xtalname = "testxtal"

In [4]: mk(filename, xtalname)


    This is a program to create a HDF5 file for storing crystallographic information.
  This format is the same format as used in the EMsoft (electron microscoy) suite.
  The following inputs are required:
          Crystal System:
                 1. Cubic
                 2. Tetragonal
                 3. Orthorhombic
                 4. Hexagonal
                 5. Trigonal
                 6. Monoclinic
                 7. Triclinic

         Space group number
         Atomic number (Z) for all species in unit cell
         Asymmetric positions for all atoms in unit cell
         Debye-Waller factors for all atoms in the unit cell
         You'll be prompted for these values now


 Note about the trigonal system:
 -------------------------------
 Primitive trigonal crystals are defined with respect to a HEXAGONAL
 reference frame.  Rhombohedral crystals can be referenced with
 respect to a HEXAGONAL basis (first setting), or with respect to
 a RHOMBOHEDRAL basis (second setting).  The default setting for
 trigonal symmetry is the hexagonal setting.  When you select
 crystal system 5 above, you will be prompted for the setting. 

Crystal System (1-7 use the legend above): 1
a [nm] : 3


195: P 2 3     	196: F 2 3     	197: I 2 3     	198: P 21 3    	
199: I 21 3    	200: P m 3     	201: P n 3     	202: F m 3     	
203: F d 3     	204: I m 3     	205: P a 3     	206: I a 3     	
207: P 4 3 2   	208: P 42 3 2  	209: F 4 3 2   	210: F 41 3 2  	
211: I 4 3 2   	212: P 43 3 2  	213: P 41 3 2  	214: I 41 3 2  	
215: P -4 3 m  	216: F -4 3 m  	217: I -4 3 m  	218: P -4 3 n  	
219: F -4 3 c  	220: I -4 3 d  	221: P m 3 m   	222: P n 3 n   	
223: P m 3 n   	224: P n 3 m   	225: F m 3 m   	226: F m 3 c   	
227: F d 3 m   	228: F d 3 c   	229: I m 3 m   	230: I a 3 d   	


Space group number (use legend above): 225
 ------------------------------------ Periodic Table of the Elements --------------------------------------
1:H                                                                                                    2:He
3:Li  4:Be                                                               5:B   6:C   7:N   8:O   9:F  10:Ne
11:Na 12:Mg                                                             13:Al 14:Si 15:P  16:S  17:Cl 18:Ar
19:K  20:Ca 21:Sc 22:Ti 23:V  24:Cr 25:Mn 26:Fe 27:Co 28:Ni 29:Cu 30:Zn 31:Ga 32:Ge 33:As 34:Se 35:Br 36:Kr
37:Rb 38:Sr 39:Y  40:Zr 41:Nb 42:Mo 43:Tc 44:Ru 45:Rh 46:Pd 47:Ag 48:Cd 49:In 50:Sn 51:Sb 52:Te 53: I 54:Xe
55:Cs 56:Ba ----- 72:Hf 73:Ta 74:W  75:Re 76:Os 77:Ir 78:Pt 79:Au 80:Hg 81:Tl 82:Pb 83:Bi 84:Po 85:At 86:Rn
87:Fr 88:Ra -----
57:La 58:Ce 59:Pr 60:Nd 61:Pm 62:Sm 63:Eu 64:Gd 65:Tb 66:Dy 67:Ho 68:Er 69:Tm 70:Yb 71:Lu
89:Ac 90:Th 91:Pa 92:U
 ----------------------------------------------------------------------------------------------------------
Enter atomic number of species :   28
Enter asymmetric position of atom in unit cell          separated by comma (fractional coordinates) :  0,0,0
Enter site occupation :    1
Isotropic or anisotropic Debye-Waller factor? 
              1 for isotropic, 2 for anisotropic : 1
Enter isotropic Debye-Waller factor [nm^(-2)] : 0
Another atom? (y/n) : n

This creates a test.h5 file (screenshot below) Screenshot 2023-10-06 at 11 58 08 AM

saransh13 avatar Oct 06 '23 18:10 saransh13

hmmmmm......... I didn't know about this. I might try wrapping a part of this into a generator.

My fear is that drastic changes are going to break some part of HEXRD I am unfamiliar with, and because HEXRD isn't fully covered by tests, It won't be obvious until someone reports some catastrophic break to their pipeline I hadn't considered.

My approach would retain all the existing keyword inputs, so it's guaranteed (in theory) not to break anything currently in place.

Modeling off the CL version is much nicer though, and having the CL and module methods use identical functions for generation would be a big improvement for maintainable code.....

I'll try both ways, see what happens, and start a PR.

argerlt avatar Oct 09 '23 17:10 argerlt

@argerlt I would like to incorporate these changes into our upcoming restructuring of the library. Is this still on your radar? Would like to sync up about it at some point over the migration process.

ZackAttack614 avatar Jul 30 '24 18:07 ZackAttack614

@ZackAttack614, Sorry for the slow response. It is, but it took a major back seat to other work.

I can submit a PR of how I think such the class should be laid out, and you can keep/toss what you want. Just let me know what branch is best to work off of, in light of the restructuring. Also, if I'm going slow, feel free to lap me and do it yourself, I'm working on finishing my Thesis right now so I'm a bit slow in general.

In short though, I think as long as the end result:

  1. is ITOC-compliant
  2. Has basic unittests for testing Laue/Space/Point group combinations
  3. the CLI and the initiate-from-class approach produce identical results from the same inputs (not currently true in my experience)
  4. there is at least minimal documentation

I will be happy.

argerlt avatar Aug 06 '24 15:08 argerlt