Beispiel #1
0
    def calculate_dissolved_volatiles(self, temperature, pressure, X_fluid=1, print_status=True, model='MagmaSat', record_errors=False, **kwargs):
        """
        Calculates the amount of H2O and CO2 dissolved in a magma at the given P/T conditions and fluid composition. Fluid composition
        will be matched to within 0.0001 mole fraction.

        Parameters
        ----------
        temperature: float, int, or str
            Temperature, in degrees C. Can be passed as float, in which case the
            passed value is used as the temperature for all samples. Alternatively, temperature information for each individual
            sample may already be present in the BatchFile object. If so, pass the str value corresponding to the column
            title in the BatchFile object.

        presure: float, int, or str
            Pressure, in bars. Can be passed as float or int, in which case the
            passed value is used as the pressure for all samples. Alternatively, pressure information for each individual
            sample may already be present in the BatchFile object. If so, pass the str value corresponding to the column
            title in the BatchFile object.

        X_fluid: float, int, or str
            OPTIONAL: Default value is 1. The mole fraction of H2O in the H2O-CO2 fluid. X_fluid=1 is a pure H2O fluid. X_fluid=0 is a
            pure CO2 fluid. Can be passed as a float or int, in which case the passed value is used as the X_fluid for all samples.
            Alternatively, X_fluid information for each individual sample may already be present in the BatchFile object. If so, pass
            the str value corresponding to the column title in the BatchFile object.

        print_status: bool
            OPTIONAL: The default value is True, in which case the progress of the calculation will be printed to the terminal.
            If set to False, nothing will be printed. MagmaSat calculations tend to be slow, and so a value of True is recommended
            for most use cases.

        model: string
            OPTIONAL: Default is 'MagmaSat'. Any other model name can be passed here.

        record_errors: bool
            OPTIONAL: If True, any errors arising during the calculation will be recorded as a column.

        Returns
        -------
        pandas DataFrame
            Original data passed plus newly calculated values are returned.
        """
        dissolved_data = self.get_data().copy()

        if isinstance(temperature, str):
            file_has_temp = True
            temp_name = temperature
        elif isinstance(temperature, float) or isinstance(temperature, int):
            file_has_temp = False
        else:
            raise core.InputError("temp must be type str or float or int")

        if isinstance(pressure, str):
            file_has_press = True
            press_name = pressure
        elif isinstance(pressure, float) or isinstance(pressure, int):
            file_has_press = False
        else:
            raise core.InputError("pressure must be type str or float or int")

        if isinstance(X_fluid, str):
            file_has_X = True
            X_name = X_fluid
        elif isinstance(X_fluid, float) or isinstance(X_fluid, int):
            file_has_X = False
            if X_fluid != 0 and X_fluid !=1:
                if X_fluid < 0.001 or X_fluid > 0.999:
                    raise core.InputError("X_fluid is calculated to a precision of 0.0001 mole fraction. \
                                     Value for X_fluid must be between 0.0001 and 0.9999.")
        else:
            raise core.InputError("X_fluid must be type str or float or int")

        # Check if the model passed as the attribute "model_type"
        # Currently only implemented for MagmaSat type models
        if hasattr(model, 'model_type') is True:
        	model = model.model_type

        H2Ovals = []
        CO2vals = []
        warnings = []
        errors = []
        if model in models.get_model_names(model='mixed'):
            for index, row in dissolved_data.iterrows():
                try:
                    if file_has_temp == True:
                        temperature = row[temp_name]

                    if file_has_press == True:
                        pressure = row[press_name]

                    if file_has_X == True:
                        X_fluid = row[X_name]

                    # Get sample comp as Sample class with defaults
                    bulk_comp = self.get_sample_composition(index, 
                                                            normalization=self.default_normalization, 
                                                            units='wtpt_oxides', 
                                                            asSampleClass=True)
                    bulk_comp.set_default_units(self.default_units)
                    bulk_comp.set_default_normalization(self.default_normalization)
                    calc = calculate_classes.calculate_dissolved_volatiles(sample=bulk_comp, pressure=pressure, temperature=temperature,
                                                                    X_fluid=(X_fluid, 1-X_fluid), model=model,
                                                                    silence_warnings=True, **kwargs)
                    H2Ovals.append(calc.result['H2O_liq'])
                    CO2vals.append(calc.result['CO2_liq'])
                    warnings.append(calc.calib_check)
                    errors.append('')
                except Exception as inst:
                    H2Ovals.append(np.nan)
                    CO2vals.append(np.nan)
                    warnings.append('Calculation Failed.')
                    errors.append(sys.exc_info()[0])
            dissolved_data["H2O_liq_VESIcal"] = H2Ovals
            dissolved_data["CO2_liq_VESIcal"] = CO2vals

            if file_has_temp == False:
                dissolved_data["Temperature_C_VESIcal"] = temperature
            if file_has_press == False:
                dissolved_data["Pressure_bars_VESIcal"] = pressure
            if file_has_X == False:
                dissolved_data["X_fluid_input_VESIcal"] = X_fluid
            dissolved_data["Model"] = model
            dissolved_data["Warnings"] = warnings
            if record_errors == True:
                dissolved_data["Errors"] = errors

            return dissolved_data

        elif model == 'MagmaSat':
            XH2Ovals = []
            XCO2vals = []
            FluidProportionvals = []
            iterno = 0
            for index, row in dissolved_data.iterrows():
                iterno += 1
                if print_status == True:
                    percent = iterno/len(dissolved_data.index)
                    batchfile.status_bar.status_bar(percent, index)

                if file_has_temp == True:
                    temperature = row[temp_name]
                if temperature <= 0:
                    H2Ovals.append(np.nan)
                    CO2vals.append(np.nan)
                    XH2Ovals.append(np.nan)
                    XCO2vals.append(np.nan)
                    FluidProportionvals.append(np.nan)
                    warnings.append("Sample skipped. Bad temperature.")
                    errors.append(sys.exc_info()[0])
                    w.warn("Temperature for sample " + str(index) + " is <=0. Skipping sample.", stacklevel=2)

                if file_has_press == True:
                    pressure = row[press_name]
                if temperature >0 and pressure <= 0:
                    H2Ovals.append(np.nan)
                    CO2vals.append(np.nan)
                    XH2Ovals.append(np.nan)
                    XCO2vals.append(np.nan)
                    FluidProportionvals.append(np.nan)
                    warnings.append("Sample skipped. Bad pressure.")
                    errors.append(sys.exc_info()[0])
                    w.warn("Pressure for sample " + str(index) + " is <=0. Skipping sample.", stacklevel=2)

                if file_has_X == True:
                    X_fluid = row[X_name]
                if temperature >0 and pressure >0 and X_fluid <0:
                    H2Ovals.append(np.nan)
                    CO2vals.append(np.nan)
                    XH2Ovals.append(np.nan)
                    XCO2vals.append(np.nan)
                    FluidProportionvals.append(np.nan)
                    warnings.append("Sample skipped. Bad X_fluid.")
                    errors.append(sys.exc_info()[0])
                    w.warn("X_fluid for sample " + str(index) + " is <0. Skipping sample.", stacklevel=2)

                if temperature >0 and pressure >0 and X_fluid >1:
                    H2Ovals.append(np.nan)
                    CO2vals.append(np.nan)
                    XH2Ovals.append(np.nan)
                    XCO2vals.append(np.nan)
                    FluidProportionvals.append(np.nan)
                    warnings.append("Sample skipped. Bad X_fluid.")
                    errors.append(sys.exc_info()[0])
                    w.warn("X_fluid for sample " + str(index) + " is >1. Skipping sample.", stacklevel=2)

                if temperature > 0 and pressure > 0 and X_fluid >=0 and X_fluid <=1:
                    try:
                        # Get sample comp as Sample class with defaults
                        bulk_comp = self.get_sample_composition(index, 
                                                                normalization=self.default_normalization, 
                                                                units='wtpt_oxides', 
                                                                asSampleClass=True)
                        bulk_comp.set_default_units(self.default_units)
                        bulk_comp.set_default_normalization(self.default_normalization)
                        calc = calculate_classes.calculate_dissolved_volatiles(sample=bulk_comp, pressure=pressure, temperature=temperature,
                                                                        X_fluid=X_fluid, model=model, silence_warnings=True,
                                                                        verbose=True)
                        H2Ovals.append(calc.result['H2O_liq'])
                        CO2vals.append(calc.result['CO2_liq'])
                        XH2Ovals.append(calc.result['XH2O_fl'])
                        XCO2vals.append(calc.result['XCO2_fl'])
                        FluidProportionvals.append(calc.result['FluidProportion_wt'])
                        warnings.append(calc.calib_check)
                        errors.append('')
                    except Exception as inst:
                        H2Ovals.append(np.nan)
                        CO2vals.append(np.nan)
                        XH2Ovals.append(np.nan)
                        XCO2vals.append(np.nan)
                        FluidProportionvals.append(np.nan)
                        warnings.append('Calculation Failed.')
                        errors.append(sys.exc_info()[0])
            dissolved_data["H2O_liq_VESIcal"] = H2Ovals
            dissolved_data["CO2_liq_VESIcal"] = CO2vals

            if file_has_temp == False:
                dissolved_data["Temperature_C_VESIcal"] = temperature
            if file_has_press == False:
                dissolved_data["Pressure_bars_VESIcal"] = pressure
            if file_has_X == False:
                dissolved_data["X_fluid_input_VESIcal"] = X_fluid
            dissolved_data["Model"] = model
            dissolved_data["Warnings"] = warnings
            if record_errors == True:
                dissolved_data["Errors"] = errors

            return dissolved_data
        
        else:
            XH2Ovals = []
            XCO2vals = []
            FluidProportionvals = []
            for index, row in dissolved_data.iterrows():
                if file_has_temp == True:
                    temperature = row[temp_name]
                if file_has_press == True:
                    pressure = row[press_name]
                if file_has_X == True:
                    X_fluid = row[X_name]
                # Get sample comp as Sample class with defaults
                bulk_comp = self.get_sample_composition(index, 
                                                        normalization=self.default_normalization, 
                                                        units='wtpt_oxides', 
                                                        asSampleClass=True)
                bulk_comp.set_default_units(self.default_units)
                bulk_comp.set_default_normalization(self.default_normalization)
                if 'Water' in model:
                    try:
                        calc = calculate_classes.calculate_dissolved_volatiles(sample=bulk_comp, pressure=pressure, temperature=temperature,
                                                             X_fluid=X_fluid, model=model, silence_warnings=True)
                        H2Ovals.append(calc.result)
                        warnings.append(calc.calib_check)
                    except:
                        H2Ovals.append(0)
                        warnings.append('Calculation Failed #001')
                if 'Carbon' in model:
                    try:
                        calc = calculate_classes.calculate_dissolved_volatiles(sample=bulk_comp, pressure=pressure, temperature=temperature,
                                                             X_fluid=X_fluid, model=model, silence_warnings=True)
                        CO2vals.append(calc.result)
                        warnings.append(calc.calib_check)
                    except:
                        CO2vals.append(0)
                        warnings.append('Calculation Failed #002')

            if 'Water' in model:
                dissolved_data["H2O_liq_VESIcal"] = H2Ovals
            if 'Carbon' in model:
                dissolved_data["CO2_liq_VESIcal"] = CO2vals
            if file_has_temp == False:
                dissolved_data["Temperature_C_VESIcal"] = temperature
            if file_has_press == False:
                dissolved_data["Pressure_bars_VESIcal"] = pressure
            if file_has_X == False:
                dissolved_data["X_fluid_input_VESIcal"] = X_fluid
            dissolved_data["Model"] = model
            dissolved_data["Warnings"] = warnings

            return dissolved_data
Beispiel #2
0
    def return_default_units(self, sample, calc_result, **kwargs):
        """ Checkes the default units set for the sample_class.Sample
        object and returns the result of a calculation in those units.

        Parameters
        ----------
        sample: Sample class
            The rock composition as a Sample object.

        calc_result: dict or float
            Result of a calculate_dissolved_volatiles() calculation on a
            sample.
        """
        default_units = sample.default_units

        # get the composition of
        bulk_comp = deepcopy(sample)

        # check if calculation result is H2O-only, CO2-only, or mixed
        # H2O-CO2
        if isinstance(self.model_name, str):
            if self.model_name in models.get_model_names(model='mixed'):
                # set dissolved H2O and CO2 values.
                # this action assumes they are input as wt% but updates the
                # composition in its default units.
                bulk_comp.change_composition({
                    'H2O': calc_result['H2O_liq'],
                    'CO2': calc_result['CO2_liq']
                })
                return {
                    'H2O_liq':
                    bulk_comp.get_composition(species='H2O',
                                              units=default_units),
                    'CO2_liq':
                    bulk_comp.get_composition(species='CO2',
                                              units=default_units)
                }
            elif 'Water' in self.model_name:
                bulk_comp.change_composition({'H2O': calc_result})
                return bulk_comp.get_composition(species='H2O',
                                                 units=default_units)
            elif 'Carbon' in self.model_name:
                bulk_comp.change_composition({'CO2': calc_result})
                return bulk_comp.get_composition(species='CO2',
                                                 units=default_units)
            elif self.model_name == 'MagmaSat':
                bulk_comp.change_composition({
                    'H2O': calc_result['H2O_liq'],
                    'CO2': calc_result['CO2_liq']
                })
                # check if verbose method has been chosen
                if 'verbose' in kwargs and kwargs['verbose']:
                    return {
                        'H2O_liq':
                        bulk_comp.get_composition(species='H2O',
                                                  units=default_units),
                        'CO2_liq':
                        bulk_comp.get_composition(species='CO2',
                                                  units=default_units),
                        'XH2O_fl':
                        calc_result['XH2O_fl'],
                        'XCO2_fl':
                        calc_result['XCO2_fl'],
                        'FluidProportion_wt':
                        calc_result['FluidProportion_wt']
                    }
                else:
                    return {
                        'H2O_liq':
                        bulk_comp.get_composition(species='H2O',
                                                  units=default_units),
                        'CO2_liq':
                        bulk_comp.get_composition(species='CO2',
                                                  units=default_units)
                    }
        else:
            # if self.model_name is not a string, most likely this is a
            # user-created model class, and so we cannot interrogate it for
            # model type (H2O, CO2, or mixed).
            # TODO: create model type parameter so that we can ID model type
            # this way instead of via strings in a list!
            return calc_result
Beispiel #3
0
    def calculate_equilibrium_fluid_comp(self, temperature, pressure=None, print_status=False, model='MagmaSat', **kwargs):
        """
        Returns H2O and CO2 concentrations in wt% or mole fraction in a fluid in equilibrium with the given sample(s) at the given P/T condition.

        Parameters
        ----------
        sample: BatchFile object
            Compositional information on samples in oxides.

        temperature: float, int, or str
            Temperature, in degrees C. Can be passed as float, in which case the
            passed value is used as the temperature for all samples. Alternatively, temperature information for each individual
            sample may already be present in the BatchFile object. If so, pass the str value corresponding to the column
            title in the  BatchFile object.

        presure: float, int, or str
            Pressure, in bars. Can be passed as float or int, in which case the
            passed value is used as the pressure for all samples. Alternatively, pressure information for each individual
            sample may already be present in the BatchFile object. If so, pass the str value corresponding to the column
            title in the BatchFile object.

        model: string
            OPTIONAL: Default is 'MagmaSat'. Any other model name can be passed here.

        Returns
        -------
        pandas DataFrame
            Original data passed plus newly calculated values are returned.
        """
        fluid_data = self.get_data().copy()

        # Check if the model passed as the attribute "model_type"
        # Currently only implemented for MagmaSat type models
        if hasattr(model, 'model_type') is True:
        	model = model.model_type

        if isinstance(temperature, str):
            file_has_temp = True
            temp_name = temperature
        elif isinstance(temperature, float) or isinstance(temperature, int):
            file_has_temp = False
        else:
            raise core.InputError("temp must be type str or float or int")

        if isinstance(pressure, str):
            file_has_press = True
            press_name = pressure
        elif isinstance(pressure, float) or isinstance(pressure, int) or type(pressure) == type(None):
            file_has_press = False
        else:
            raise core.InputError("pressure must be type str or float or int")

        H2Ovals = []
        CO2vals = []
        warnings = []
        if model in  models.get_model_names(model='mixed') or model == "MooreWater":
            for index, row in fluid_data.iterrows():
                try:
                    if file_has_temp == True:
                        temperature = row[temp_name]
                    if file_has_press == True:
                        pressure = row[press_name]
                    # Get sample comp as Sample class with defaults
                    bulk_comp = self.get_sample_composition(index, 
                                                            normalization=self.default_normalization, 
                                                            units='wtpt_oxides', 
                                                            asSampleClass=True)
                    bulk_comp.set_default_units(self.default_units)
                    bulk_comp.set_default_normalization(self.default_normalization)

                    calc = calculate_classes.calculate_equilibrium_fluid_comp(sample=bulk_comp, pressure=pressure, temperature=temperature,
                                                            model=model, silence_warnings=True, **kwargs)

                    H2Ovals.append(calc.result['H2O'])
                    CO2vals.append(calc.result['CO2'])
                    if calc.result['H2O'] == 0 and calc.result['CO2'] == 0:
                        warnings.append(calc.calib_check + "Sample not saturated at these conditions")
                    else:
                        warnings.append(calc.calib_check)
                except:
                    H2Ovals.append(np.nan)
                    CO2vals.append(np.nan)
                    warnings.append("Calculation Failed.")
            fluid_data["XH2O_fl_VESIcal"] = H2Ovals
            fluid_data["XCO2_fl_VESIcal"] = CO2vals
            if file_has_temp == False:
                fluid_data["Temperature_C_VESIcal"] = temperature
            if file_has_press == False:
                fluid_data["Pressure_bars_VESIcal"] = pressure
            fluid_data["Model"] = model
            fluid_data["Warnings"] = warnings

            return fluid_data
        elif model == 'MagmaSat':
            iterno = 0
            for index, row in fluid_data.iterrows():
                iterno += 1
                if print_status == True:
                    percent = iterno/len(fluid_data.index)
                    batchfile.status_bar.status_bar(percent, index)

                if file_has_temp == True:
                    temperature = row[temp_name]
                if temperature <= 0:
                    H2Ovals.append(np.nan)
                    CO2vals.append(np.nan)
                    warnings.append("Calculation skipped. Bad temperature.")
                    w.warn("Temperature for sample " + str(index) + " is <=0. Skipping sample.", stacklevel=2)

                if file_has_press == True:
                    pressure = row[press_name]
                if temperature >0 and pressure <= 0:
                    H2Ovals.append(np.nan)
                    CO2vals.append(np.nan)
                    warnings.append("Calculation skipped. Bad pressure.")
                    w.warn("Pressure for sample " + str(index) + " is <=0. Skipping sample.", stacklevel=2)

                if temperature > 0 and pressure > 0:
                    try:
                        # Get sample comp as Sample class with defaults
                        bulk_comp = self.get_sample_composition(index, 
                                                                normalization=self.default_normalization, 
                                                                units='wtpt_oxides', 
                                                                asSampleClass=True)
                        bulk_comp.set_default_units(self.default_units)
                        bulk_comp.set_default_normalization(self.default_normalization)

                        calc = calculate_classes.calculate_equilibrium_fluid_comp(sample=bulk_comp, pressure=pressure, temperature=temperature, model=model, silence_warnings=True)

                        H2Ovals.append(calc.result['H2O'])
                        CO2vals.append(calc.result['CO2'])
                        if calc.result['H2O'] == 0 and calc.result['CO2'] == 0:
                            warnings.append(calc.calib_check + "Sample not saturated at these conditions")
                        else:
                            warnings.append(calc.calib_check)
                    except:
                        H2Ovals.append(np.nan)
                        CO2vals.append(np.nan)
                        warnings.append("Calculation Failed.")

            fluid_data["XH2O_fl_VESIcal"] = H2Ovals
            fluid_data["XCO2_fl_VESIcal"] = CO2vals
            if file_has_temp == False:
                fluid_data["Temperature_C_VESIcal"] = temperature
            if file_has_press == False:
                fluid_data["Pressure_bars_VESIcal"] = pressure
            fluid_data["Model"] = model
            fluid_data["Warnings"] = warnings

            return fluid_data

        else:
            saturated = []
            for index, row in fluid_data.iterrows():
                try:
                    if file_has_temp == True:
                        temperature = row[temp_name]
                    if file_has_press == True:
                        pressure = row[press_name]
                    # Get sample comp as Sample class with defaults
                    bulk_comp = self.get_sample_composition(index, 
                                                            normalization=self.default_normalization, 
                                                            units='wtpt_oxides', 
                                                            asSampleClass=True)
                    bulk_comp.set_default_units(self.default_units)
                    bulk_comp.set_default_normalization(self.default_normalization)

                    calc = calculate_classes.calculate_equilibrium_fluid_comp(sample=bulk_comp, pressure=pressure, temperature=temperature, model=model, silence_warnings=True)
                    saturated.append(calc.result)
                    warnings.append(calc.calib_check)
                except:
                    saturated.append(np.nan)
                    warnings.append("Calculation Failed.")
            fluid_data["Saturated_VESIcal"] = saturated
            if file_has_temp == False:
                fluid_data["Temperature_C_VESIcal"] = temperature
            if file_has_press == False:
                fluid_data["Pressure_bars_VESIcal"] = pressure
            fluid_data["Model"] = model
            fluid_data["Warnings"] = warnings

            return fluid_data
Beispiel #4
0
def get_model_names(model='all'):
    return models.get_model_names(model=model)