Beispiel #1
0
class GenericFeaturizer(BaseFeaturizer):
	"""
	Featurizer to use generic properties available in matminer featurizers; no features from BCA class utilized
	"""
	def __init__(self,normalize_formula=False):
		self.normalize_formula = normalize_formula
		# don't need ValenceOrbital - valence counts etc. covered in ElementProperty.from_preset('magpie')
		# self.ValenceOrbital = ValenceOrbital()
		self.AtomicOrbitals = AtomicOrbitalsMod()
		self.CohesiveEnergy = CohesiveEnergy()
		self.BandCenter = BandCenter()
		self.ValenceOrbitalEnergy = ValenceOrbitalEnergy()
		# ElementProperty featurizer with magpie properties plus additional properties
		self.ElementProperty = ElementProperty.from_preset('magpie')
		self.ElementProperty.features += ['BoilingT', 
					'BulkModulus', 'ShearModulus', 
					'Density','MolarVolume',
					'FusionEnthalpy','HeatVaporization',
					'Polarizability', 
					'ThermalConductivity']
		# range, min, max are irrelevant inside the ternary
		# self.ElementProperty.stats = ['mean', 'avg_dev','mode']

		# check matminer featurizers
		self.check_matminer_featurizers()
		
	def featurize(self,composition):
		# use BCA just to get composition and metal_composition
		bca = BCA(composition,'ionic_radius',self.normalize_formula)
		
		ao_features = self.AtomicOrbitals.featurize(bca.metal_composition) # H**O and LUMO character and energy levels for metals from atomic orbitals)
		ao_features = [ao_features[i] for i in range(len(ao_features)) if i not in (0,1,3,4)] # exclude HOMO_character,HOMO_element, LUMO_character, LUMO_element - categoricals
		ce_features = self.CohesiveEnergy.featurize(bca.metal_composition,formation_energy_per_atom=1e-10) # avg metal elemental cohesive energy
		bc_features = self.BandCenter.featurize(bca.metal_composition) + self.BandCenter.featurize(bca.composition)
		ve_features = self.ValenceOrbitalEnergy.featurize(bca.metal_composition) + self.ValenceOrbitalEnergy.featurize(bca.composition)
		ep_features = self.ElementProperty.featurize(bca.metal_composition) + self.ElementProperty.featurize(bca.composition)
		
		mm_features = ao_features + ce_features + bc_features + ve_features + ep_features 
		
		return mm_features
	
	def feature_labels(self):
		"""
		Feature labels for matminer-derived features
		"""
		labels = [
			#AtomicOrbitals labels
			#'M_HOMO_character',
			'M_HOMO_energy',
			#'M_LUMO_character',
			'M_LUMO_energy',
			'M_AO_gap',
			#CohesiveEnergy labels
			'M_cohesive_energy_mean',
			#BandCenter labels
			'M_BandCenter',
			'BCA_BandCenter',
			#ValenceOrbitalEnergy labels
			'M_ValenceEnergy_mean',
			'BCA_ValenceEnergy_mean'
			]
			
		labels += [f'M {l}' for l in self.ElementProperty.feature_labels()]
		labels += [f'BCA {l}' for l in self.ElementProperty.feature_labels()]
		
		return labels	
	
	@property
	def matminer_units(self):
		"""
		Feature units for matminer-derived features
		"""
		units = [
			#ValenceOrbital units
			'none',
			'none',
			'none',
			'none',
			'none',
			'none',
			'none',
			'none',
			'none',
			#AtomicOrbitals units
			#'M_HOMO_character',
			'energy',
			#'M_LUMO_character',
			'energy',
			'energy',
			#CohesiveEnergy units
			'energy',
			#BandCenter units
			'energy',
			'energy',
			#ValenceOrbitalEnergy units
			'energy',
			'energy'
			]
			
		units += self.ElementProperty_units
		
		return units
		
	def feature_units(self):
		bca_units = BCA(mg.Composition('BaO')).feature_units()
		
		return bca_units + self.matminer_units
		
	def check_matminer_featurizers(self):
		"""
		Check that features and feature order for matminer featurizers are as expected
		If features or feature order have changed, featurize() may return unexpected features that do not align with feature_labels()
		"""
		#verify that matminer feature labels haven't changed
		if self.AtomicOrbitals.feature_labels() != ['HOMO_character',
											 'HOMO_element',
											 'HOMO_energy',
											 'LUMO_character',
											 'LUMO_element',
											 'LUMO_energy',
											 'gap_AO']:
			raise Exception('AtomicOrbitals features or labels have changed')

		if self.CohesiveEnergy.feature_labels() != ['cohesive energy']:
			raise Exception('CohesiveEnergy features or labels have changed')
			
		if self.BandCenter.feature_labels() != ['band center']:
			raise Exception('BandCenter features or labels have changed')
			
	def citations(self):
		featurizers = [self.AtomicOrbitals, self.CohesiveEnergy, self.BandCenter, self.ValenceOrbitalEnergy]
		citations = sum([f.citations() for f in featurizers],[])
		# add pymatgen citation
		citations += [
			"@article{Ong2012b,"
				"author = {Ong, Shyue Ping and Richards, William Davidson and Jain, Anubhav and Hautier, Geoffroy and Kocher, Michael and Cholia, Shreyas and Gunter, Dan and Chevrier, Vincent L. and Persson, Kristin A. and Ceder, Gerbrand},"
				"doi = {10.1016/j.commatsci.2012.10.028},"
				"file = {:Users/shyue/Mendeley Desktop/Ong et al/Computational Materials Science/2013 - Ong et al. - Python Materials Genomics (pymatgen) A robust, open-source python library for materials analysis.pdf:pdf;:Users/shyue/Mendeley Desktop/Ong et al/Computational Materials Science/2013 - Ong et al. - Python Materials Genomics (pymatgen) A robust, open-source python library for materials analysis(2).pdf:pdf},"
				"issn = {09270256},"
				"journal = {Computational Materials Science},"
				"month = feb,"
				"pages = {314--319},"
				"title = {{Python Materials Genomics (pymatgen): A robust, open-source python library for materials analysis}},"
				"url = {http://linkinghub.elsevier.com/retrieve/pii/S0927025612006295},"
				"volume = {68},"
				"year = {2013}"
			"}"
			]
		return list(np.unique(citations))
Beispiel #2
0
class BCA_Featurizer(BaseFeaturizer):
	def __init__(self,radius_type='ionic_radius',normalize_formula=False):
		self.radius_type = radius_type
		self.normalize_formula = normalize_formula
		self.ValenceOrbital = ValenceOrbital()
		self.AtomicOrbitals = AtomicOrbitalsMod()
		self.CohesiveEnergy = CohesiveEnergy()
		self.BandCenter = BandCenter()
		self.ValenceOrbitalEnergy = ValenceOrbitalEnergy()
		#custom ElementProperty featurizer
		elemental_properties = ['BoilingT', 'MeltingT',
			'BulkModulus', 'ShearModulus', 
			'Row', 'Column', 'Number', 'MendeleevNumber', 'SpaceGroupNumber',
			'Density','MolarVolume',
			'FusionEnthalpy','HeatVaporization',
			'Polarizability', 
			'ThermalConductivity']
		self.ElementProperty = ElementProperty(data_source='magpie',features=elemental_properties,
						  stats=["mean", "std_dev"])
		#check matminer featurizers
		self.check_matminer_featurizers()
		
	def featurize(self,composition):
		bca = BCA(composition,self.radius_type,self.normalize_formula)
		bca_features = bca.featurize()
		
		vo_features = self.ValenceOrbital.featurize(bca.metal_composition) #avg and frac s, p , d, f electrons for metals
		vo_features += [sum(vo_features[0:3])] #avg total valence electrons for metals
		ao_features = self.AtomicOrbitals.featurize(bca.metal_composition) #H**O and LUMO character and energy levels for metals from atomic orbitals)
		ao_features = [ao_features[i] for i in range(len(ao_features)) if i not in (0,1,3,4)]#exclude HOMO_character,HOMO_element, LUMO_character, LUMO_element - categoricals
		ce_features = self.CohesiveEnergy.featurize(bca.metal_composition,formation_energy_per_atom=1e-10) #avg metal elemental cohesive energy
		bc_features = self.BandCenter.featurize(bca.metal_composition) + self.BandCenter.featurize(bca.composition)
		ve_features = self.ValenceOrbitalEnergy.featurize(bca.metal_composition) + self.ValenceOrbitalEnergy.featurize(bca.composition)
		ep_features = self.ElementProperty.featurize(bca.metal_composition) + self.ElementProperty.featurize(bca.composition)
		
		mm_features = vo_features + ao_features + ce_features + bc_features + ve_features + ep_features 
		
		return list(bca_features.values()) + mm_features
		
	@property
	def ElementProperty_custom_labels(self):
		"""
		Generate custom labels for ElementProperty featurizer that follow same naming convention as Perovskite class
		"""
		elemental_property_label_map = {'BoilingT':'boil_temp','MeltingT':'melt_temp',
							'BulkModulus':'bulk_mod','ShearModulus':'shear_mod',
							'Row':'row','Column':'column','Number':'number','MendeleevNumber':'mendeleev','SpaceGroupNumber':'space_group',
							'Density':'density','MolarVolume':'molar_vol',
							'FusionEnthalpy':'H_fus','HeatVaporization':'H_vap',
							'Polarizability':'polarizability',
							'ThermalConductivity':'sigma_therm'}
							
		element_property_labels = list(map(elemental_property_label_map.get,self.ElementProperty.features))
		labels = []
		for attr in element_property_labels:
			for stat in self.ElementProperty.stats:
				if stat=='std_dev':
					stat = 'std'
				labels.append(f'M_{attr}_{stat}')
		for attr in element_property_labels:
			for stat in self.ElementProperty.stats:
				if stat=='std_dev':
					stat = 'std'
				labels.append(f'BCA_{attr}_{stat}')
		return labels
		
	@property
	def ElementProperty_units(self):
		"""
		Generate units for ElementProperty featurizer that follow same naming convention as Perovskite class
		"""
		elemental_property_unit_map = {'BoilingT':'temperature','MeltingT':'temperature',
							'BulkModulus':'pressure','ShearModulus':'pressure',
							'Row':'none','Column':'none','Number':'none','MendeleevNumber':'none','SpaceGroupNumber':'none',
							'Density':'density','MolarVolume':'volume',
							'FusionEnthalpy':'energy','HeatVaporization':'energy',
							'Polarizability':'polarizability',
							'ThermalConductivity':'therm'}
							
		element_property_units = list(map(elemental_property_unit_map.get,self.ElementProperty.features))
		units = []
		for ep_unit in element_property_units:
			for stat in self.ElementProperty.stats:
				units.append(ep_unit)
		return units*2
		
	def ElementProperty_label_check(self):
		"""
		Check that ElementProperty feature labels are as expected
		If not, features may not align with feature labels
		"""
		#ElementProperty.feature_labels() code as of 1/24/20
		labels = []
		for attr in self.ElementProperty.features:
			src = self.ElementProperty.data_source.__class__.__name__
			for stat in self.ElementProperty.stats:
				labels.append("{} {} {}".format(src, stat, attr))
		
		if labels!=self.ElementProperty.feature_labels():
			raise Exception('ElementProperty features or labels have changed')
	
	
	@property
	def matminer_labels(self):
		"""
		Feature labels for matminer-derived features
		"""
		labels = [
			#ValenceOrbital labels
			'M_ValenceElec_s_mean',
			'M_ValenceElec_p_mean',
			'M_ValenceElec_d_mean',
			'M_ValenceElec_f_mean',
			'M_ValenceElec_s_frac',
			'M_ValenceElec_p_frac',
			'M_ValenceElec_d_frac',
			'M_ValenceElec_f_frac',
			'M_ValenceElec_tot_mean',
			#AtomicOrbitals labels
			#'M_HOMO_character',
			'M_HOMO_energy',
			#'M_LUMO_character',
			'M_LUMO_energy',
			'M_AO_gap',
			#CohesiveEnergy labels
			'M_cohesive_energy_mean',
			#BandCenter labels
			'M_BandCenter',
			'BCA_BandCenter',
			#ValenceOrbitalEnergy labels
			'M_ValenceEnergy_mean',
			'BCA_ValenceEnergy_mean'
			]
			
		labels += self.ElementProperty_custom_labels
		
		return labels	
	
	@property
	def matminer_units(self):
		"""
		Feature units for matminer-derived features
		"""
		units = [
			#ValenceOrbital units
			'none',
			'none',
			'none',
			'none',
			'none',
			'none',
			'none',
			'none',
			'none',
			#AtomicOrbitals units
			#'M_HOMO_character',
			'energy',
			#'M_LUMO_character',
			'energy',
			'energy',
			#CohesiveEnergy units
			'energy',
			#BandCenter units
			'energy',
			'energy',
			#ValenceOrbitalEnergy units
			'energy',
			'energy'
			]
			
		units += self.ElementProperty_units
		
		return units
	
	def feature_labels(self):
		bca_feature_labels = list(BCA(mg.Composition('BaO'),self.radius_type,self.normalize_formula).featurize().keys())
		
		return bca_feature_labels + self.matminer_labels
		
	def feature_units(self):
		bca_units = BCA(mg.Composition('BaO')).feature_units()
		
		return bca_units + self.matminer_units
		
	def check_matminer_featurizers(self):
		"""
		Check that features and feature order for matminer featurizers are as expected
		If features or feature order have changed, featurize() may return unexpected features that do not align with feature_labels()
		"""
		#verify that matminer feature labels haven't changed
		if self.ValenceOrbital.feature_labels() != ['avg s valence electrons',
											 'avg p valence electrons',
											 'avg d valence electrons',
											 'avg f valence electrons',
											 'frac s valence electrons',
											 'frac p valence electrons',
											 'frac d valence electrons',
											 'frac f valence electrons']:
			raise Exception('ValenceOrbital features or labels have changed')
			
		if self.AtomicOrbitals.feature_labels() != ['HOMO_character',
											 'HOMO_element',
											 'HOMO_energy',
											 'LUMO_character',
											 'LUMO_element',
											 'LUMO_energy',
											 'gap_AO']:
			raise Exception('AtomicOrbitals features or labels have changed')

		if self.CohesiveEnergy.feature_labels() != ['cohesive energy']:
			raise Exception('CohesiveEnergy features or labels have changed')
			
		if self.BandCenter.feature_labels() != ['band center']:
			raise Exception('BandCenter features or labels have changed')
	
		self.ElementProperty_label_check()
		
	def citations(self):
		featurizers = [self.ValenceOrbital, self.AtomicOrbitals, self.CohesiveEnergy, self.BandCenter, self.ValenceOrbitalEnergy, BCA(mg.Composition('BaO'))]
		return list(np.unique(sum([f.citations() for f in featurizers],[])))