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