# Path: openmmtools/utils.py
# def typename(atype):
#     """Convert a type object into a fully qualified typename.
# 
#     Parameters
#     ----------
#     atype : type
#         The type to convert
# 
#     Returns
#     -------
#     typename : str
#         The string typename.
# 
#     For example,
# 
#     >>> typename(type(1))
#     'int'
# 
#     >>> import numpy
#     >>> x = numpy.array([1,2,3], numpy.float32)
#     >>> typename(type(x))
#     'numpy.ndarray'
# 
#     """
#     if not isinstance(atype, type):
#         raise Exception('Argument is not a type')
# 
#     modulename = atype.__module__
#     typename = atype.__name__
# 
#     if modulename not in ['__builtin__', 'builtins']:
#         typename = modulename + '.' + typename
# 
#     return typename
# 
# def quantity_from_string(expression):
#     """Special call to the math_eval function designed to handle openmm.unit Quantity strings
# 
#     All the functions in the standard module math are available together with
#     most of the methods inside the openmm.unit module.
# 
#     Parameters
#     ----------
#     expression : str
#         The mathematical expression to rebuild a Quantityas a string.
# 
#     Returns
#     -------
#     Quantity
#         The result of the evaluated expression.
# 
#     Examples
#     --------
#     >>> expr = '4 * kilojoules / mole'
#     >>> quantity_from_string(expr)
#     Quantity(value=4.000000000000002, unit=kilojoule/mole)
# 
#     """
# 
#     # Supported functions, not defined in math.
#     functions = _VALID_UNIT_FUNCTIONS
# 
#     # Define the units from openmm.unit as the variables
#     variables = _VALID_UNITS
# 
#     # Eliminate nested quotes and excess whitespace
#     expression = expression.strip('\'" ')
# 
#     # Handle a special case of the unit when it is just "inverse unit", e.g. Hz == /second
#     if expression[0] == '/':
#         expression = '(' + expression[1:] + ')**(-1)'
# 
#     return math_eval(expression, variables=variables, functions=functions)


import os
import abc
import yaml
import warnings
import importlib
import collections
import numpy as np
import netCDF4 as nc
from sys import getsizeof
    from yaml import CLoader as Loader, CDumper as Dumper
    from yaml import Loader, Dumper
    from openmm import unit
    from simtk import unit
from ..utils import typename, quantity_from_string
            self._value_decoder = scalar_decoder_generator(int)
        elif stype == 'float':
            self._value_encoder = simple_encoder
            self._value_decoder = scalar_decoder_generator(float)
        elif stype == 'list' or stype == 'tuple':
            self._value_encoder = simple_encoder
            self._value_decoder = nc_iterable_decoder
        elif 'ndarray' in stype:
            self._value_encoder = simple_encoder
            self._value_decoder = nc_numpy_array_decoder
        else:
            raise TypeError("NCQuantity does not know how to handle a quantity of type {}!".format(stype))

    @property
    def _encoder(self):
        return self._quantity_encoder

    @property
    def _decoder(self):
        return self._quantity_decoder

    def _quantity_encoder(self, data):
        # Strip Unit
        data_unit = data.unit
        data_value = data / data_unit
        return self._value_encoder(data_value)

    def _quantity_decoder(self, bound_target):
        data = self._value_decoder(bound_target)
        unit_name = bound_target.getncattr('IODriver_Unit')

# Path: openmmtools/utils.py
# def typename(atype):
#     """Convert a type object into a fully qualified typename.
# 
#     Parameters
#     ----------
#     atype : type
#         The type to convert
# 
#     Returns
#     -------
#     typename : str
#         The string typename.
# 
#     For example,
# 
#     >>> typename(type(1))
#     'int'
# 
#     >>> import numpy
#     >>> x = numpy.array([1,2,3], numpy.float32)
#     >>> typename(type(x))
#     'numpy.ndarray'
# 
#     """
#     if not isinstance(atype, type):
#         raise Exception('Argument is not a type')
# 
#     modulename = atype.__module__
#     typename = atype.__name__
# 
#     if modulename not in ['__builtin__', 'builtins']:
#         typename = modulename + '.' + typename
# 
#     return typename
# 
# def quantity_from_string(expression):
#     """Special call to the math_eval function designed to handle openmm.unit Quantity strings
# 
#     All the functions in the standard module math are available together with
#     most of the methods inside the openmm.unit module.
# 
#     Parameters
#     ----------
#     expression : str
#         The mathematical expression to rebuild a Quantityas a string.
# 
#     Returns
#     -------
#     Quantity
#         The result of the evaluated expression.
# 
#     Examples
#     --------
#     >>> expr = '4 * kilojoules / mole'
#     >>> quantity_from_string(expr)
#     Quantity(value=4.000000000000002, unit=kilojoule/mole)
# 
#     """
# 
#     # Supported functions, not defined in math.
#     functions = _VALID_UNIT_FUNCTIONS
# 
#     # Define the units from openmm.unit as the variables
#     variables = _VALID_UNITS
# 
#     # Eliminate nested quotes and excess whitespace
#     expression = expression.strip('\'" ')
# 
#     # Handle a special case of the unit when it is just "inverse unit", e.g. Hz == /second
#     if expression[0] == '/':
#         expression = '(' + expression[1:] + ')**(-1)'
# 
#     return math_eval(expression, variables=variables, functions=functions)


# Path: openmmtools/storage/iodrivers.py
import os
import abc
import yaml
import warnings
import importlib
import collections
import numpy as np
import netCDF4 as nc
from sys import getsizeof
    from yaml import CLoader as Loader, CDumper as Dumper
    from yaml import Loader, Dumper
    from openmm import unit
    from simtk import unit
from ..utils import typename, quantity_from_string

            self._value_decoder = scalar_decoder_generator(int)
        elif stype == 'float':
            self._value_encoder = simple_encoder
            self._value_decoder = scalar_decoder_generator(float)
        elif stype == 'list' or stype == 'tuple':
            self._value_encoder = simple_encoder
            self._value_decoder = nc_iterable_decoder
        elif 'ndarray' in stype:
            self._value_encoder = simple_encoder
            self._value_decoder = nc_numpy_array_decoder
        else:
            raise TypeError("NCQuantity does not know how to handle a quantity of type {}!".format(stype))

    @property
    def _encoder(self):
        return self._quantity_encoder

    @property
    def _decoder(self):
        return self._quantity_decoder

    def _quantity_encoder(self, data):
        # Strip Unit
        data_unit = data.unit
        data_value = data / data_unit
        return self._value_encoder(data_value)

    def _quantity_decoder(self, bound_target):
        data = self._value_decoder(bound_target)
        unit_name = bound_target.getncattr('IODriver_Unit')

        cast_unit = quantity_from_string(unit_name)