Source code for mosdef_cassandra.analysis.thermo

import os
import numpy as np
import unyt as u


[docs]class ThermoProps: """Store thermodynamic properties from a Cassandra .prp file""" def __init__(self, filename): """Create ThermoProps from a .prp file Parameters ---------- filename : string path to the .prp file Returns ------- ThermoProps object containing the contents of the .prp file """ self.filename = filename # Read headers prp_headers = [] with open(self.filename) as f: for (idx, line) in enumerate(f): if idx == 1 or idx == 2: prp_headers.append(line) if idx > 2: break # Extract column names and units column_names = prp_headers[0][1:].split() column_units = [""] n_columns = len(column_names) for icol in range(1, n_columns): col_start = 12 + 18 * (icol - 1) col_end = 12 + 18 * icol column_units.append(prp_headers[1][col_start:col_end].strip()) prp_data = np.genfromtxt(self.filename, skip_header=3) assert prp_data.shape[1] == len(column_names) assert prp_data.shape[1] == len(column_units) # Unyt mapping units_to_unyts = { "(kJ/mol)-Ext": u.Unit("kJ/mol"), "(bar)": u.bar, "": u.dimensionless, "(A^3)": u.angstrom**3, "(kg/m^3)": u.Unit("kg/m**3"), "(molec/A^3)": u.Unit("count/angstrom**3"), } self._properties = column_names unyts = [] for unit in column_units: try: unyts.append(units_to_unyts[unit]) except KeyError: unyts.append(u.dimensionless) self._units = column_units self._unyts = unyts self._data = prp_data def print_props(self): """Print the available properties""" for prop in self._properties: print(prop) def prop(self, prp_name, start=None, end=None, units=True): """Extract the specified property Parameters ---------- prp_name : string the property to extract start : int the starting step/sweep/etc. end : int the ending step/sweep/etc. Returns ------- unyt_array the property with units """ if prp_name not in self._properties: raise ValueError( "{} is not an available property. Please select from: {}".format( prp_name, self._properties ) ) col_idx = self._properties.index(prp_name) if start is not None: start_idx = np.where(self._data[:, 0] >= start)[0][0] else: start_idx = None if end is not None: end_idx = np.where(self._data[:, 0] <= end)[0][-1] + 1 else: end_idx = None return self._data[start_idx:end_idx, col_idx] * self._unyts[col_idx] def to_df(self): """Convert ThermoProps to a pandas.DataFrame""" try: import pandas as pd except ModuleNotFoundError: raise ModuleNotFoundError( "The pandas package is required to convert to a pandas.DataFrame. " "pandas can be installed with 'conda install -c conda-forge pandas'" ) arrays = [(self._properties), (self._units)] multi_index = pd.MultiIndex.from_arrays( arrays, names=("property", "units") ) return pd.DataFrame(self._data, columns=multi_index) @property def filename(self): return self._filename @filename.setter def filename(self, filename): if os.path.exists(filename): self._filename = filename else: raise FileNotFoundError( "File {} could not be found".format(filename)
)