def __init__(self, fault_dict):
     '''Parses the fault dictionary representation into the corresponding
     fault class attributes'''
     self.fault_id = fault_dict['ID']
     self.fault_name = fault_dict['Fault_Name']
     self.fault_region = fault_dict['tectonic_region']
     self.typology = fault_dict['Fault_Geometry']['Fault_Typology']
     self.fault_geometry = Simple()
     self.slip_type = fault_dict['slip_type']
     self.slip_completeness = fault_dict['slip_completeness_factor']
     self.rake = fault_dict['rake']
     self.MFD = []
     self.slip = None
     self.slip_min = None
     self.slip_max = None
     self.slip_quality = None
     self.aseismic = None
     self.aseismic_completeness = None
     self.megazone = fault_dict['Megazone']
     self.shear_modulus = fault_dict['Shear_Modulus']
     self.msr = fault_dict['MagnitudeScalingRelation']
     self.aspect_ratio = fault_dict['AspectRatio']
     self.disp_length_ratio = fault_dict['DisplacementLengthRatio']
     self.recurrence_model = []
class Fault(object):
    '''Creates the fault definition'''
    def __init__(self, fault_dict):
        '''Parses the fault dictionary representation into the corresponding
        fault class attributes'''
        self.fault_id = fault_dict['ID']
        self.fault_name = fault_dict['Fault_Name']
        self.fault_region = fault_dict['tectonic_region']
        self.typology = fault_dict['Fault_Geometry']['Fault_Typology']
        self.fault_geometry = Simple()
        self.slip_type = fault_dict['slip_type']
        self.slip_completeness = fault_dict['slip_completeness_factor']
        self.rake = fault_dict['rake']
        self.MFD = []
        self.slip = None
        self.slip_min = None
        self.slip_max = None
        self.slip_quality = None
        self.aseismic = None
        self.aseismic_completeness = None
        self.megazone = fault_dict['Megazone']
        self.shear_modulus = fault_dict['Shear_Modulus']
        self.msr = fault_dict['MagnitudeScalingRelation']
        self.aspect_ratio = fault_dict['AspectRatio']
        self.disp_length_ratio = fault_dict['DisplacementLengthRatio']
        self.recurrence_model = []

    def create_fault_definition(self, fault_dict, tect_regions):
        '''Filles out the general fault definitions'''
        # Slip model
        self._parse_fault_slip(fault_dict['slip']) 
        # Aseismic Data
        self._parse_aseismic_slip(fault_dict['aseismic'])
        # Define the fault geometries
        self.fault_geometry.get_fault_extent(fault_dict['Fault_Geometry'])
        self.fault_geometry.get_basic_parameters(fault_dict['Fault_Geometry'])
        # Fill in missing attributes - check if fault has a corresponing
        if not self.fault_region in tect_regions.key_list:
            print self.fault_region
            raise ValueError(
                'Unspecified tectonic region - I told you so bitches!')
        
        if not self.shear_modulus:
            self.shear_modulus = \
                tect_regions.tect_reg[self.fault_region]['Shear_Modulus']
            # Ultimately we would like to support multiple values in a logic 
            # tree (TODO)- but for now just take highest weighted value
            if isinstance(self.shear_modulus, list) and \
                len(self.shear_modulus) > 1:
                max_loc = np.argmax(np.array(
                    tect_regions.tect_reg[self.fault_region]\
                    ['Shear_Modulus_Weight']))
                self.shear_modulus = self.shear_modulus[max_loc]

        if not self.disp_length_ratio:
            self.disp_length_ratio = \
                tect_regions.tect_reg[self.fault_region]['Strain_Drop_Values']
            # Ultimately we would like to support multiple values in a logic 
            # tree (TODO)- but for now just take highest weighted value
            if isinstance(self.disp_length_ratio, list) and \
                len(self.disp_length_ratio) > 1:
                max_loc = np.argmax(np.array(
                    tect_regions.tect_reg[self.fault_region]\
                    ['Strain_Drop_Weight']))
                self.disp_length_ratio = self.disp_length_ratio[max_loc]
            
        if not self.msr:
            self.msr = \
                tect_regions.tect_reg[self.fault_region]\
                ['MSR_Models']
            # Ultimately we would like to support multiple values in a logic 
            # tree (TODO)- but for now just take highest weighted value
            if isinstance(self.msr, list) and len(self.msr) > 1:
                max_loc = np.argmax(np.array(
                    tect_regions.tect_reg[self.fault_region]\
                    ['MSR_Models_Weight']))
                self.msr = self.msr[max_loc]
                   
 
    def _parse_aseismic_slip(self, aseismic_input):
        '''Parses the aseismic slip information'''
        if isinstance(aseismic_input, list) and len(aseismic_input) == 2:
            self.aseismic = aseismic_input[0]
            self.aseismic_completeness = aseismic_input[1]
        else:
            self.aseismic = float(aseismic_input)
        

    def _parse_fault_slip(self, slip_input):
        '''Parses the fault slip data into the correct format'''
        if isinstance(slip_input, list) and \
                len(slip_input) == 4:
            self.slip = slip_input[0]
            self.slip_min = slip_input[1]
            self.slip_max = slip_input[2]
            self.slip_quality = slip_input[3]
        else:
            self.slip = slip_input

    def get_recurrence_model(self, fault_dict):
        '''Calculates MFD for the fault'''
        #Temporary: Fix msr to WC1994()
        self.msr = WC1994()

        # Parse recurrence_params
        self.mfd_model = {'AndersonLucoType1': AndersonLucoType1(),
                          'AndersonLucoType2': AndersonLucoType2(),
                          'AndersonLucoType3': AndersonLucoType3(),
                          'Characteristic': Characteristic(),
                          'YoungsCoppersmith': YoungsCoppersmith()}

        if __name__ == "__main__":
            self.mfd_choice = self.mfd_type

        # Reduce slip rate by using proportion of aseismic slip
        seismic_slip = self.slip * (1.0 - self.aseismic) 
        for mfd_config in fault_dict['MFD_Model']:
           mfd = self.mfd_model[mfd_config['Model_Type']]
           mfd.setUp(mfd_config)
           mfd.get_mmax(mfd_config, self.msr, self.rake, 
                        self.fault_geometry.area)

           if 'AndersonLuco' in mfd_config['Model_Type']:
               mfd.get_mfd(seismic_slip, self.disp_length_ratio, 
                           self.shear_modulus, self.fault_geometry.width)
           else:
               mfd.get_mfd(seismic_slip, self.shear_modulus, 
                           self.fault_geometry.area)

           self.recurrence_model.append(mfd)