1# coding: utf-8 2# Copyright (c) Pymatgen Development Team. 3# Distributed under the terms of the MIT License. 4 5""" 6This module is used to estimate the Herfindahl-Hirschman Index, or HHI, of 7chemical compounds. The HHI is a measure of how geographically confined or 8dispersed the elements comprising a compound are. A low HHI is desirable 9because it means the component elements are geographically dispersed. 10 11Data/strategy from "Data-Driven Review of Thermoelectric Materials: 12Performance and Resource Considerations" by Gaultois et al., published 13in Chemistry of Materials (2013). 14""" 15 16import os 17 18from monty.design_patterns import singleton 19 20from pymatgen.core.composition import Composition 21from pymatgen.core.periodic_table import Element 22 23__author__ = "Anubhav Jain" 24__copyright__ = "Copyright 2014, The Materials Project" 25__version__ = "0.1" 26__maintainer__ = "Anubhav Jain" 27__email__ = "ajain@lbl.gov" 28__date__ = "Oct 27, 2014" 29 30 31csv_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "hhi_data.csv") 32 33 34@singleton 35class HHIModel: 36 """ 37 HHI calculator. 38 """ 39 40 def __init__(self): 41 """ 42 Init for HHIModel. 43 """ 44 self.symbol_hhip_hhir = {} # symbol->(HHI_production, HHI reserve) 45 46 with open(csv_path) as f: 47 for line in f: 48 if line[0] != "#": 49 symbol, hhi_production, hhi_reserve = line.split(",") 50 self.symbol_hhip_hhir[symbol] = ( 51 float(hhi_production), 52 float(hhi_reserve), 53 ) 54 55 def _get_hhi_el(self, el_or_symbol): 56 """ 57 Returns the tuple of HHI_production, HHI reserve for a single element only 58 """ 59 if isinstance(el_or_symbol, Element): 60 el_or_symbol = el_or_symbol.symbol 61 62 return ( 63 self.symbol_hhip_hhir[el_or_symbol][0], 64 self.symbol_hhip_hhir[el_or_symbol][1], 65 ) 66 67 def get_hhi(self, comp_or_form): 68 """ 69 Gets the reserve and production HHI for a compound. 70 71 Args: 72 comp_or_form (Composition or String): A Composition or String formula 73 74 Returns: 75 A tuple representing the (HHI_production, HHI_reserve) 76 """ 77 78 try: 79 if not isinstance(comp_or_form, Composition): 80 comp_or_form = Composition(comp_or_form) 81 82 hhi_p = 0 83 hhi_r = 0 84 85 for e in comp_or_form.elements: 86 percent = comp_or_form.get_wt_fraction(e) 87 dp, dr = self._get_hhi_el(e) 88 hhi_p += dp * percent 89 hhi_r += dr * percent 90 return hhi_p, hhi_r 91 92 except Exception: 93 return None, None 94 95 def get_hhi_production(self, comp_or_form): 96 """ 97 Gets the production HHI for a compound. 98 99 Args: 100 comp_or_form (Composition or String): A Composition or String formula 101 102 Returns: 103 The HHI production value 104 """ 105 return self.get_hhi(comp_or_form)[0] 106 107 def get_hhi_reserve(self, comp_or_form): 108 """ 109 Gets the reserve HHI for a compound. 110 111 Args: 112 comp_or_form (Composition or String): A Composition or String formula 113 114 Returns: 115 The HHI reserve value 116 """ 117 return self.get_hhi(comp_or_form)[1] 118 119 @staticmethod 120 def get_hhi_designation(hhi): 121 """ 122 Gets a designation for low, medium, high HHI, as specified in "U.S. 123 Department of Justice and the Federal Trade Commission, Horizontal 124 merger guidelines; 2010." 125 126 Args: 127 hhi (float): HHI value 128 129 Returns: 130 The designation as String 131 """ 132 133 if hhi is None: 134 return None 135 136 if 0 <= hhi < 1500: 137 return "low" 138 139 if 1500 <= hhi <= 2500: 140 return "medium" 141 142 return "high" 143