diff --git a/.gitignore b/.gitignore index bee8a64..c204fa7 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ __pycache__ +kim-tools.log diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..e69de29 diff --git a/docker/config/excerpts/compute.py b/docker/config/excerpts/compute.py index 799aa0c..d586826 100644 --- a/docker/config/excerpts/compute.py +++ b/docker/config/excerpts/compute.py @@ -27,7 +27,7 @@ import errno from . import util -from . import kimunits +from kim_tools import kimunits from . import kimobjects from . import config as cf diff --git a/docker/config/excerpts/kimunits.py b/docker/config/excerpts/kimunits.py deleted file mode 100644 index 1d1d500..0000000 --- a/docker/config/excerpts/kimunits.py +++ /dev/null @@ -1,164 +0,0 @@ -""" -Simple wrapper for executable for converting arbitrary units to SI units - -Copyright (c) 2014-2022, Regents of the University of Minnesota. All rights -reserved. - -This software may be distributed as-is, without modification. -""" - -VERSION = 0.3 - -import re -import math -import subprocess -import warnings - -warnings.simplefilter("ignore") - - -class UnitConversion(Exception): - """Class for unit conversion errors""" - - -_units_output_expression = re.compile( - r"(?P(?:[-+]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][-+]?\d+)?))(?: (?P.+))?" -) - - -def linear_fit(x, y): - """ - Perform a linear fit between x,y, returning the average error for each data - point as well. This is written this way so as to not add a numpy dependency - """ - n = len(x) - xx = sum([x**2 for x in x]) - sum(x) ** 2 / n - xy = sum(map(lambda x, y: x * y, x, y)) - sum(x) * sum(y) / n - a, b = sum(y) / n - xy / xx * sum(x) / n, xy / xx - yhat = [a + b * x for x in x] - yerr = math.sqrt(sum(map(lambda y, yh: (y - yh) ** 2 / y**2, y, yhat)) / n) - return a, b, yerr - - -def islinear(unit, to_unit=None): - """ - Detect if the conversion from `unit` to `to_unit` is a linear map. Apparently - the units utility is float precision, so if error is less than 1e-7 we know - it is linear. - """ - x = [100 ** (1e-2 * (i - 50)) for i in range(20)] - y = convert_list(x, unit, to_unit=to_unit, dofit=False)[0] - a, b, err = linear_fit(x, y) - - a = convert_list(0, unit, to_unit=to_unit, dofit=False)[0] - b = convert_list(1, unit, to_unit=to_unit, dofit=False)[0] - a - return a, b, err < 1e-7 - - -def convert_units(from_value, from_unit, wanted_unit=None, suppress_unit=False): - """Works with 'units' utility""" - from_sign = from_value < 0 - from_value = str(abs(from_value)) - from_unit = str(from_unit) - - TEMPERATURE_FUNCTION_UNITS = ["degC", "tempC", "degF", "tempF"] - - if from_unit in TEMPERATURE_FUNCTION_UNITS: - args = [ - "units", - "-o", - "%1.15e", - "-qt1", - "".join((from_unit, "(", from_value, ")")), - ] - - else: - args = ["units", "-o", "%1.15e", "-qt1", " ".join((from_value, from_unit))] - - if wanted_unit: - args.append(wanted_unit) - - try: - output = subprocess.check_output(args).decode("utf-8") - except subprocess.CalledProcessError: - tag = wanted_unit if wanted_unit else "SI" - raise UnitConversion( - "Error in unit conversion of {} {} to {}".format(from_value, from_unit, tag) - ) - - matches = _units_output_expression.match(output).groupdict(None) - out = ((-1) ** from_sign * float(matches["value"]), matches["unit"] or wanted_unit) - - if suppress_unit: - return out[0] - return out - - -# Set default behavior -convert = convert_units - - -def convert_list(x, from_unit, to_unit=None, convert=convert, dofit=True): - """Thread conversion over a list, or list of lists""" - # Need a list for scoping reasons - - # Constant shortcut - if from_unit in (1, 1.0, "1"): - to_unit = "1" - - # get the SI unit if none provided - if to_unit is None: - _, to_unit = convert(1.0, from_unit) - - def convert_inner(x, fit=None): - if isinstance(x, (list, tuple)): - return type(x)(convert_inner(i, fit=fit) for i in x) - else: - if to_unit == "1": - return float(x) - else: - if fit is not None: - return fit[0] + fit[1] * x - return float(convert(x, from_unit, to_unit, suppress_unit=True)) - - # setup the linear fit if we are requested to simplify - fit = None - if dofit and isinstance(x, (list, tuple)) and len(x) > 20: - a, b, linear = islinear(from_unit, to_unit) - fit = (a, b) if linear else None - - output = convert_inner(x, fit=fit) - return output, to_unit - - -def add_si_units(doc, convert=convert): - """Given a document, add all of the appropriate si-units fields""" - if isinstance(doc, dict): - # check for a source-unit to defined a value with units - if "source-unit" in doc: - # we've found a place to add - assert "source-value" in doc, "Badly formed doc" - o_value = doc.get("source-value", None) - o_unit = doc.get("source-unit", None) - - if o_value is None: - raise UnitConversion("No source-value provided") - if o_unit is None: - raise UnitConversion("No source-unit provided") - - # convert the units and insert - value, unit = convert_list(o_value, o_unit, convert=convert) - si_dict = {"si-unit": unit, "si-value": value} - doc = doc.copy() - doc.update(si_dict) - return doc - else: - # recurse - return type(doc)( - (key, add_si_units(value)) for key, value in list(doc.items()) - ) - - elif isinstance(doc, (list, tuple)): - return type(doc)(add_si_units(x) for x in doc) - - return doc diff --git a/docker/config/excerpts/query_local/helper_functions.py b/docker/config/excerpts/query_local/helper_functions.py index ea048a0..8e9e84d 100644 --- a/docker/config/excerpts/query_local/helper_functions.py +++ b/docker/config/excerpts/query_local/helper_functions.py @@ -13,7 +13,7 @@ from .. import kimquery from ..kimcodes import parse_kim_code -from ..kimunits import convert_units, convert_list, UnitConversion +from kim_tools.kimunits import convert_units, convert_list, UnitConversion RE_KIMID = r"^(?:([_a-zA-Z][_a-zA-Z0-9]*?)__)?([A-Z]{2})_([0-9]{12})(?:_([0-9]{3}))?$" RE_EXTENDED_ID = r"^[A-Za-z0-9_]+__[A-Z]{2}_[0-9]{12}_[0-9]{3}$" diff --git a/docker/config/excerpts/query_local/queryapi.py b/docker/config/excerpts/query_local/queryapi.py index e401209..82f77ee 100644 --- a/docker/config/excerpts/query_local/queryapi.py +++ b/docker/config/excerpts/query_local/queryapi.py @@ -64,7 +64,7 @@ from bson.code import Code from bson.json_util import dumps, loads -from ..kimunits import convert_units, convert_list +from kim_tools.kimunits import convert_units, convert_list from . import helper_functions as helpers diff --git a/docker/config/excerpts/template.py b/docker/config/excerpts/template.py index 812383a..8e70b4e 100644 --- a/docker/config/excerpts/template.py +++ b/docker/config/excerpts/template.py @@ -36,7 +36,7 @@ from . import kimobjects from . import config as cf from . import util -from .kimunits import convert +from kim_tools.kimunits import convert # ----------------------------------------- diff --git a/test/run_all.sh b/test/run_all.sh index 5d5662a..e90fef3 100644 --- a/test/run_all.sh +++ b/test/run_all.sh @@ -1,2 +1,2 @@ -DOCKER_COMMAND="cd /home/openkim/test_scripts_and_data && cp -r custom_kimitems/* ~ && bash set_up_and_run_$2.sh && export PYTHONPATH=\$PYTHONPATH:/pipeline/ && python compare_dbs.py $2 && bash compare_vcs.sh $2" +DOCKER_COMMAND="echo openkim | sudo -S chown -R openkim test_scripts_and_data && cd /home/openkim/test_scripts_and_data && cp -r custom_kimitems/* ~ && bash set_up_and_run_$2.sh && export PYTHONPATH=\$PYTHONPATH:/pipeline/ && python compare_dbs.py $2 && bash compare_vcs.sh $2" docker run --rm --mount type=bind,src=$PWD/test/test_scripts_and_data,target=/home/openkim/test_scripts_and_data $1 /bin/bash -c "$DOCKER_COMMAND" \ No newline at end of file diff --git a/test/run_cg_example.sh b/test/run_cg_example.sh index 97dc728..fe3316e 100644 --- a/test/run_cg_example.sh +++ b/test/run_cg_example.sh @@ -1,2 +1,2 @@ DOCKER_COMMAND="cd /home/openkim/test-drivers/ && git clone https://github.com/openkim-hackathons/CrystalGenomeASEExample__TD_000000654321_000.git && cd CrystalGenomeASEExample__TD_000000654321_000 && git checkout 09d8cc8a74f83bdf8ad96329fb456e4815800337 && tail -n1 < test_generator.json > test_generator.json_ && mv test_generator.json_ test_generator.json && kimgenie tests --test-driver CrystalGenomeASEExample__TD_000000654321_000 --add-random-kimnums && kimitems install -D LJ_ElliottAkerson_2015_Universal__MO_959249795837_003 && pipeline-run-matches LJ_ElliottAkerson_2015_Universal__MO_959249795837_003 -v && if [[ \$(ls /home/openkim/test-results | wc -l) != "1" ]]; then exit 1; fi" -docker run --rm --mount type=bind,src=$PWD/test/test_scripts_and_data,target=/home/openkim/test_scripts_and_data $1 /bin/bash -c "$DOCKER_COMMAND" \ No newline at end of file +docker run --rm $1 /bin/bash -c "$DOCKER_COMMAND" \ No newline at end of file