From f3f5c9366901e0884d1a85f97151e25134bd04ae Mon Sep 17 00:00:00 2001 From: Mark Driver <mdd31@alumni.cam.ac.uk> Date: Tue, 4 Feb 2020 11:48:42 +0000 Subject: [PATCH] add methods to create phase and solvent XML from system object. --- .../runners/phasexmlcreatorrunner.py | 95 +++++++++ .../runnerstest/phasexmlcreatorrunnertest.py | 196 ++++++++++++++++++ 2 files changed, 291 insertions(+) create mode 100755 phasecalculator/runners/phasexmlcreatorrunner.py create mode 100755 phasecalculator/test/runnerstest/phasexmlcreatorrunnertest.py diff --git a/phasecalculator/runners/phasexmlcreatorrunner.py b/phasecalculator/runners/phasexmlcreatorrunner.py new file mode 100755 index 0000000..b27abed --- /dev/null +++ b/phasecalculator/runners/phasexmlcreatorrunner.py @@ -0,0 +1,95 @@ +# -*- coding: utf-8 -*- +# phasecalculator calculates FGIPs, solvent similarity and VLE with SSIMPLE. +# Copyright (C) 2019 Mark D. Driver +# +# phasecalculator is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +""" +Script for creating Solvent and phase XML for calculations. + +@author: Mark +""" + +import logging +import pathlib +import phasecalculator.io.phasetransferxmlcreator as phasexmlcreate + +logging.basicConfig() +LOGGER = logging.getLogger(__name__) +LOGGER.setLevel(logging.WARN) + + + +def create_phase_and_solvent_files(system_info, filestem="system", **kwargs): + create_scratch_dir(system_info) + phase_file = None + solvent_list = None + if system_info.calc_vle(): + phase_file = create_phase_file(system_info, filestem + "phase", **kwargs) + if system_info.calc_fgip() or system_info.calc_similarity(): + solvent_list = create_solvent_files(system_info, filestem +"solvent", **kwargs) + return phase_file, solvent_list + +def create_phase_file(system_info, filestem, **kwargs): + phase_filename = create_phase_filename(system_info.runtime_information.scratch_dir, filestem) + mole_fractions_by_temp_dict = system_info.get_phases_by_temp_list() + ssip_filename_list = system_info.get_ssip_file_locations() + phasexmlcreate.create_phase_file(mole_fractions_by_temp_dict, phase_filename, ssip_filename_list=ssip_filename_list, **kwargs) + return phase_filename +def create_solvent_files(system_info, filestem, **kwargs): + mole_fractions_by_temp_dict = system_info.get_phase_compositions_by_temperature() + ssip_filename_list = system_info.get_ssip_file_locations() + solvent_list = [] + for temp_info, mole_fraction_dict_list in mole_fractions_by_temp_dict.items(): + solvent_filename = create_solvent_file(mole_fraction_dict_list, + ssip_filename_list, temp_info, + filestem, + system_info.runtime_information.scratch_dir, **kwargs) + solvent_list.append({"filename":solvent_filename, **temp_info.to_dict()}) + return solvent_list + + +def create_solvent_file(mole_fraction_dict_list, ssip_filename_list, temp_info, filestem, scratch_dir, **kwargs): + solvent_filename = create_solvent_filename(scratch_dir, temp_info, filestem) + phasexmlcreate.create_solvent_file(mole_fraction_dict_list, solvent_filename, ssip_filename_list=ssip_filename_list, **kwargs) + return solvent_filename + +def create_scratch_dir(system_info): + """Makes scratch directory for system calculation. + + Parameters + ---------- + system_info : TYPE + DESCRIPTION. + + Returns + ------- + None. + + """ + scratch_path = pathlib.Path(system_info.runtime_information.scratch_dir) + scratch_path.mkdir(parents=True,exist_ok=True) + +def create_solvent_filename(scratch_dir, temp_info, filestem): + temp_string = create_temperaturestring(temp_info.temperature, temp_info.temperature_unit) + filename = filestem + "_" + temp_string + ".xml" + path = (pathlib.Path(scratch_dir) / filename).as_posix() + return path + +def create_phase_filename(scratch_dir, filestem): + filename = filestem + ".xml" + path = (pathlib.Path(scratch_dir) / filename).as_posix() + return path + +def create_temperaturestring(temperature, temperature_unit): + return "{:.1f}{}".format(temperature, "K" if temperature_unit == "KELVIN" else "C") \ No newline at end of file diff --git a/phasecalculator/test/runnerstest/phasexmlcreatorrunnertest.py b/phasecalculator/test/runnerstest/phasexmlcreatorrunnertest.py new file mode 100755 index 0000000..612b2fa --- /dev/null +++ b/phasecalculator/test/runnerstest/phasexmlcreatorrunnertest.py @@ -0,0 +1,196 @@ +# -*- coding: utf-8 -*- +# phasecalculator calculates FGIPs, solvent similarity and VLE with SSIMPLE. +# Copyright (C) 2019 Mark D. Driver +# +# phasecalculator is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +""" +Test case for phasexmlcreatorrunner module. + +@author: mark +""" + +import logging +import unittest +import pathlib +import os +import shutil +from lxml import etree +import puresolventinformation.information as pureinf +from phasecalculator.classes.temperature import Temperature +from phasecalculator.classes.molecule import Molecule +from phasecalculator.classes.phase import Phase +from phasecalculator.classes.phases import Phases +from phasecalculator.classes.runtimeinformation import RuntimeInformation +from phasecalculator.classes.outputinformation import OutputInformation +from phasecalculator.classes.system import System +import phasecalculator.runners.phasexmlcreatorrunner as phasecreaterun + +logging.basicConfig() +LOGGER = logging.getLogger(__name__) +LOGGER.setLevel(logging.WARN) + +class PhaseXMLCreatorRunnerTestCase(unittest.TestCase): + """Test case for phase XML creator runner methods.""" + def setUp(self): + """Set up for tests. + + Returns + ------- + None. + + """ + self.maxDiff = None + ssip_filenames = pureinf.get_ssip_file_dict() + self.water_ssip = ssip_filenames["XLYOFNOQVPJJNP-UHFFFAOYSA-N"] + self.butanol_ssip = ssip_filenames["LRHPLDYGYMQRHN-UHFFFAOYSA-N"] + self.temperature = Temperature(298.0, "KELVIN") + self.water_molecule = Molecule("water", "XLYOFNOQVPJJNP-UHFFFAOYSA-N", self.water_ssip, 0.8354716981132075) + self.butanol_molecule = Molecule("1-butanol", "LRHPLDYGYMQRHN-UHFFFAOYSA-N", self.butanol_ssip, 0.16452830188679246) + self.phase = Phase([self.water_molecule, self.butanol_molecule], self.temperature) + self.phases = Phases([self.phase]) + self.example_jar = "resources/example.jar" + self.runtime_inf = RuntimeInformation(self.example_jar, "scratch", "fgip") + self.out_inf = OutputInformation(True, True, "all", True) + self.system = System(self.phases, self.runtime_inf, self.out_inf) + phasecreaterun.create_scratch_dir(self.system) + parent_directory = pathlib.Path(__file__).parents[1] + self.expected_phase_file = (parent_directory /"resources" / "expected_phase.xml").absolute().as_posix() + self.expected_solvent_file = (parent_directory /"resources" / "expected_solvent.xml").absolute().as_posix() + def tearDown(self): + """Clean up after tests. + + Returns + ------- + None. + + """ + def test_create_phase_and_solvent_files(self): + """Test + + Returns + ------- + None. + + """ + phase_filename, solvent_filename_list = phasecreaterun.create_phase_and_solvent_files(self.system) + self.assertEqual("scratch/systemphase.xml", phase_filename) + with open(phase_filename, "r") as act_file: + actual_contents = act_file.read() + with open(self.expected_phase_file, "r") as exp_file: + expected_contents = exp_file.read() + self.assertMultiLineEqual(expected_contents, actual_contents) + expected_list = [{"filename":"scratch/systemsolvent_298.0K.xml", + 'temperature_units': 'KELVIN', + 'temperature_value': 298.0}] + self.assertListEqual(expected_list, solvent_filename_list) + solvent_filename = solvent_filename_list[0]["filename"] + with open(solvent_filename, "r") as act_file: + actual_contents = act_file.read() + with open(self.expected_solvent_file, "r") as exp_file: + expected_contents = exp_file.read() + self.assertMultiLineEqual(expected_contents, actual_contents) + def test_create_phase_file(self): + """Test + + Returns + ------- + None. + + """ + phase_filename = phasecreaterun.create_phase_file(self.system, "systemphase") + self.assertEqual("scratch/systemphase.xml", phase_filename) + with open(phase_filename, "r") as act_file: + actual_contents = act_file.read() + with open(self.expected_phase_file, "r") as exp_file: + expected_contents = exp_file.read() + self.assertMultiLineEqual(expected_contents, actual_contents) + def test_create_solvent_files(self): + """Test + + Returns + ------- + None. + + """ + expected_list = [{"filename":"scratch/systemsolvent_298.0K.xml", + 'temperature_units': 'KELVIN', + 'temperature_value': 298.0}] + solvent_filename_list = phasecreaterun.create_solvent_files(self.system, "systemsolvent") + self.assertListEqual(expected_list, solvent_filename_list) + solvent_filename = solvent_filename_list[0]["filename"] + with open(solvent_filename, "r") as act_file: + actual_contents = act_file.read() + with open(self.expected_solvent_file, "r") as exp_file: + expected_contents = exp_file.read() + self.assertMultiLineEqual(expected_contents, actual_contents) + def test_create_solvent_file(self): + """Test expected solvent XML created. + + Returns + ------- + None. + + """ + mole_fraction_dict_list = self.system.get_phase_compositions_by_temperature()[self.temperature] + temp_info = self.temperature + ssip_filename_list = self.system.get_ssip_file_locations() + solvent_filename = phasecreaterun.create_solvent_file(mole_fraction_dict_list, ssip_filename_list, temp_info, "systemsolvent", "scratch") + self.assertEqual("scratch/systemsolvent_298.0K.xml", solvent_filename) + with open(solvent_filename, "r") as act_file: + actual_contents = act_file.read() + with open(self.expected_solvent_file, "r") as exp_file: + expected_contents = exp_file.read() + self.assertMultiLineEqual(expected_contents, actual_contents) + def test_create_scratch_dir(self): + """Test scratch dir exists. + + Returns + ------- + None. + + """ + self.assertTrue(pathlib.Path("scratch").is_dir()) + def test_create_solvent_filename(self): + """Test expected string produced. + + Returns + ------- + None. + + """ + expected_filename = "scratch/systemsolvent_298.0K.xml" + actual_filename = phasecreaterun.create_solvent_filename("scratch", self.temperature, "systemsolvent") + self.assertEqual(expected_filename, actual_filename) + def test_create_phase_filename(self): + """Test expected string produced. + + Returns + ------- + None. + + """ + expected_filename = "scratch/systemphase.xml" + actual_filename = phasecreaterun.create_phase_filename("scratch", "systemphase") + self.assertEqual(expected_filename, actual_filename) + def test_create_temperaturestring(self): + """Test expected string produced. + + Returns + ------- + None. + + """ + expected_string = "298.0K" + actual_string = phasecreaterun.create_temperaturestring(298.0, "KELVIN") + self.assertEqual(expected_string, actual_string) \ No newline at end of file -- GitLab