Source code for schrodinger.application.matsci.stress_strain
"""
Utilities for stress strain.
Copyright Schrodinger, LLC. All rights reserved.
"""
import os
from collections import defaultdict
import numpy
from schrodinger.application.matsci import jobutils
from schrodinger.application.matsci import msprops
AXIS_HEADER = 'Axis %s'
AXIS_HEADERS = [AXIS_HEADER % axis for axis in 'abc']
AXIS_AVG = 'Average'
STRESS_EFF_XDATA = {'Effective': (0, 5), 'Normal': (1, 5), 'Transverse': (3, 5)}
RESIDUAL_STRAIN_Y_COL = 16
# Without and with residual strain
CSV_DATA_NCOLS = [16, 17]
[docs]def get_CSV_path(st):
    """
    Return the CSV path from the structure.
    :type st: schrodinger.structure.Structure
    :param st: the structure
    :rtype: str or None
    :return: the CSV path or None if one can not be found
    """
    cms_fn = st.property.get(msprops.ORIGINAL_CMS_PROP, '')
    if cms_fn.endswith('-out.cms'):
        csv_fn = cms_fn.replace('-out.cms', '.csv')
        source_path = jobutils.get_source_path(st)
        csv_fn = os.path.join(source_path, csv_fn)
        if os.path.exists(csv_fn):
            return csv_fn 
[docs]def parse_CSV(csv_fn):
    """
    Parse CSV file from the calculation.
    :type csv_fn: str
    :param csv_fn: Path to CSV file
    :rtype: dict, dict
    :return: Both dictionaries keys are main axis name. First dictionary with
        values is the associated data for the axis and second dictionary
        the header string for the axis.
    :raise ValueError: If parsing of CSV file fails
    """
    data = {}
    headers = defaultdict(str)
    start_reading = False
    with open(csv_fn) as csv_fh:
        for line in csv_fh:
            if 'Main axis =' in line:
                tmp = line.split(',')
                direction = AXIS_HEADER % tmp[1].strip()
                if direction not in AXIS_HEADERS:
                    raise ValueError('Unknown axis: %s' % direction)
                start_reading = True
            if start_reading:
                headers[direction] += line
            if 'eps_eff' in line:
                while True:
                    line = csv_fh.readline().strip()
                    if not line:
                        break
                    tmp = list(map(float, line.split(',')))
                    if len(tmp) not in CSV_DATA_NCOLS:
                        raise ValueError('Different CSV format.')
                    if direction not in data:
                        data[direction] = numpy.array([tmp])
                    else:
                        data[direction] = numpy.append(data[direction], [tmp],
                                                       axis=0)
    if not data:
        raise ValueError('Could not parse CSV file.')
    nkeys = len(data.keys())
    if nkeys == 1:
        return data, headers
    avg_data = None
    for key, val in data.items():
        if avg_data is None:
            avg_data = numpy.array(val)
        else:
            avg_data += numpy.array(val)
    avg_data /= nkeys
    data[AXIS_AVG] = avg_data
    return data, headers