From 8d75ea0d75478508b21b3471abc4c37c871ead90 Mon Sep 17 00:00:00 2001 From: Mark Driver <mdd31@cam.ac.uk> Date: Thu, 20 Jul 2017 16:18:14 +0100 Subject: [PATCH] created script with methods for generating solvation maps (contour plots) from information read in from files. Added tests for methods that do no produce a plot. --- .../solvationmapgenerator.py | 95 ++++++++++++++ .../solvationmapgeneratortest.py | 124 ++++++++++++++++++ .../test/solvationmapcreatortests.py | 2 + 3 files changed, 221 insertions(+) create mode 100644 solventmapcreator/solvationcalculation/solvationmapgenerator.py create mode 100644 solventmapcreator/test/solvationcalculationtest/solvationmapgeneratortest.py diff --git a/solventmapcreator/solvationcalculation/solvationmapgenerator.py b/solventmapcreator/solvationcalculation/solvationmapgenerator.py new file mode 100644 index 0000000..394d8fa --- /dev/null +++ b/solventmapcreator/solvationcalculation/solvationmapgenerator.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Script for reading in the polynomial coefficients, and also the fractional +occupancy, and generating the solvent Maps. Temperature and the ranges of the +two SSIPs forthe x and y axes need to be supplied. + +@author: mark +""" + +import logging +import resultsanalysis.resultsoutput.plottinginput as plottinginput +import solventmapcreator.io.polynomialdatareader as polynomialdatareader +import solventmapcreator.solvationcalculation.fractionaloccupancycalculator as fractionaloccupancycalculator +import solventmapcreator.solvationcalculation.solvationplotinformation as solvationplotinformation + + +logging.basicConfig() +LOGGER = logging.getLogger(__name__) +LOGGER.setLevel(logging.WARN) + +def create_solvation_plot(epsilon_i_list, epsilon_j_list, + solvent_filename, solvent_id, + polynomial_filename, polynomial_order, **kwargs): + """This creates and outputs the solvation plot. + """ + input_data = create_plot_input_data_from_files(epsilon_i_list, epsilon_j_list, + solvent_filename, solvent_id, + polynomial_filename, + polynomial_order, **kwargs) + return plot_and_write_contour_map(input_data, **kwargs) + +def plot_and_write_contour_map(input_data, **kwargs): + """This creates and plots a contour map wit hthe input given. + """ + return plottinginput.create_and_write_contour_plot(input_data, **kwargs) + +def create_plot_input_data_from_files(epsilon_i_list, epsilon_j_list, + solvent_filename, solvent_id, + polynomial_filename, polynomial_order, **kwargs): + """This reads in the information and generates the data for plotting. + """ + theta = calculate_fractional_occupancy_for_phase(solvent_filename, solvent_id, kwargs.get("soluteconcentration", 0.001)) + polynomial_coefficients = parse_polynomial_data_file_extract_polynomial_coefficients(polynomial_filename, polynomial_order) + temperature = kwargs.get("temperature", 298.0) + x_label = kwargs.get("x_label", r"\beta") + y_label = kwargs.get("y_label", r"\alpha") + input_data = create_plot_input_data(epsilon_i_list, epsilon_j_list, + temperature, theta, polynomial_coefficients, + x_label, y_label) + append_output_filename_stem(input_data, solvent_id) + return input_data + +def append_output_filename_stem(plot_input_data, solvent_id): + """This generates the outputfilename stem for the plot, and appends it to + the plotting input data. + """ + plot_input_data['figure_label'] = create_output_filename_stem(solvent_id) + +def create_output_filename_stem(solvent_id): + """This generates the outputfilename stem for the plot. + """ + return solvent_id.replace(',', '_') + +def create_plot_input_data(epsilon_i_list, epsilon_j_list, temperature, theta, + polynomial_coefficients, x_label, y_label): + """This creates a dictionary containing the input data and labels for plotting. + """ + return solvationplotinformation.create_plot_input_data(epsilon_i_list, + epsilon_j_list, + temperature, theta, + polynomial_coefficients, + x_label, y_label) + +def calculate_fractional_occupancy_for_phase(solvent_filename, solvent_id, + solute_concentration): + """This calculates the fractional occupancy of the phase. This is the sum + of the solvent and solute contributions. + """ + return fractionaloccupancycalculator.calculate_fractional_occupancy_for_phase(solvent_filename, + solvent_id, + solute_concentration) + +def parse_polynomial_data_file_extract_polynomial_coefficients(filename, + polynomial_order): + """This parses a polynomial file and gets the coefficients for the given + polynomial order. + """ + return parse_polynomial_data_file(filename)[polynomial_order]["coefficients"] + +def parse_polynomial_data_file(filename): + """This parses a polynomial data file, and extracts the information + relating to the polynomial fits, returning a dictionary. + """ + return polynomialdatareader.parse_polynomial_data_file(filename) diff --git a/solventmapcreator/test/solvationcalculationtest/solvationmapgeneratortest.py b/solventmapcreator/test/solvationcalculationtest/solvationmapgeneratortest.py new file mode 100644 index 0000000..f7ae5d5 --- /dev/null +++ b/solventmapcreator/test/solvationcalculationtest/solvationmapgeneratortest.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Script for testing the functions in the solvationmapgenerator script +that assemble the data. The functions that write plots are not tested. + +@author: mark +""" + +import logging +import unittest +import numpy as np +import solventmapcreator.solvationcalculation.solvationmapgenerator as solvationmapgenerator + +logging.basicConfig() +LOGGER = logging.getLogger(__name__) +LOGGER.setLevel(logging.WARN) + +class SolvationMapGeneratorTestCase(unittest.TestCase): + """Test case for solvationmapgenerator tests. + """ + def setUp(self): + """Set up before tests. + """ + self.expected_data_by_solvent_id = {"expected_poly_fit":{1:{"coefficients":np.array([-0.05, + 1.07142857]), + "RMSE":0.015430334996209221, + "order":1, + "covar":0.0007143}}} + self.epsilon_i_list = np.array([float(x) for x in range(3)]) + self.epsilon_j_list = np.array([float(x) for x in range(2)]) + + def tearDown(self): + """clean up after tests. + """ + del self.expected_data_by_solvent_id + def test_create_plot_input_data_from_files(self): + """Test to see if expected dictionary is produced. + """ + expected_dict = {'x_data':np.array([[0, 1, 2],[0, 1, 2]]), + 'y_data':np.array([[0, 0, 0], [1, 1, 1]]), + 'z_data':np.array([[-4.532289, -3.46086], + [-3.46086, -1.671915], + [-2.389432, 0.06058]]), + "x_label":"\\beta", "y_label":"\\alpha", + "plot_axis_range":((0.0, 2.0), (0.0, 1.0)), + "figure_label":"water"} + actual_dict = solvationmapgenerator.create_plot_input_data_from_files(self.epsilon_i_list, self.epsilon_j_list, + "resources/watersolvent.xml", "water", + "resources/expected_poly_fit.csv", 1) + self.assertListEqual(sorted(expected_dict.keys()), sorted(actual_dict.keys())) + for key in expected_dict.keys(): + if key == "plot_axis_range": + np.testing.assert_array_almost_equal(np.array(expected_dict[key]), np.array(actual_dict[key])) + elif "_data" in key: + np.testing.assert_array_almost_equal(expected_dict[key], actual_dict[key]) + else: + self.assertEqual(expected_dict[key], actual_dict[key]) + def test_append_output_filename_stem(self): + """Test to see if filename stem is appended. + """ + expected_dict = {"figure_label":"water"} + actual_dict = {} + solvationmapgenerator.append_output_filename_stem(actual_dict, "water") + self.assertDictEqual(expected_dict, actual_dict) + def test_create_output_filename_stem(self): + """Test to see if expected file name stem is produced. + """ + expected_filename_stem = "water_" + actual_filename_stem = solvationmapgenerator.create_output_filename_stem("water,") + self.assertEqual(expected_filename_stem, actual_filename_stem) + def test_create_plot_input_data(self): + """Test to see if expected input data is returned. + """ + expected_dict = {'x_data':np.array([[0, 1, 2],[0, 1, 2]]), + 'y_data':np.array([[0, 0, 0], [1, 1, 1]]), + 'z_data':np.array([[-4.004792, -3.004792], + [-3.004792, -1.250065], + [-2.004792, 0.454246]]), + "x_label":"x_label", "y_label":"y_label", + "plot_axis_range":((0.0, 2.0), (0.0, 1.0))} + actual_dict = solvationmapgenerator.create_plot_input_data(self.epsilon_i_list, + self.epsilon_j_list, + 298.0, 1.0, + np.array([0.5, 1.0]), + "x_label", "y_label") + self.assertListEqual(sorted(expected_dict.keys()), sorted(actual_dict.keys())) + for key in expected_dict.keys(): + if key == "plot_axis_range": + np.testing.assert_array_almost_equal(np.array(expected_dict[key]), np.array(actual_dict[key])) + elif "_data" in key: + np.testing.assert_array_almost_equal(expected_dict[key], actual_dict[key]) + else: + self.assertEqual(expected_dict[key], actual_dict[key]) + def test_calculate_fractional_occupancy_for_phase(self): + """Test to see if expected fractional occupancy is returned. + """ + expected_value = (55.35 * 4.0 /300.0) + (0.001/300) + actual_value = solvationmapgenerator.calculate_fractional_occupancy_for_phase("resources/watersolvent.xml", + "water", 0.001) + self.assertAlmostEqual(expected_value, actual_value) + def test_parse_polynomial_data_file_extract_polynomial_coefficients(self): + """Test to see if expected array is returned. + """ + expected_array = self.expected_data_by_solvent_id["expected_poly_fit"][1]["coefficients"] + actual_array = solvationmapgenerator.parse_polynomial_data_file_extract_polynomial_coefficients("resources/expected_poly_fit.csv", 1) + np.testing.assert_array_almost_equal(expected_array, actual_array) + def test_parse_polynomial_data_file(self): + """Test to see if expected dictionary is reutrned. + """ + expected_poly_dictionary = self.expected_data_by_solvent_id["expected_poly_fit"] + actual_poly_dictionary = solvationmapgenerator.parse_polynomial_data_file("resources/expected_poly_fit.csv") + self.assertListEqual(sorted(expected_poly_dictionary.keys()), sorted(actual_poly_dictionary.keys())) + for poly_order in expected_poly_dictionary.keys(): + expected_dictionary = expected_poly_dictionary[poly_order] + actual_dictionary = actual_poly_dictionary[poly_order] + self.assertListEqual(sorted(expected_dictionary.keys()), sorted(actual_dictionary.keys())) + for key in expected_dictionary.keys(): + if key == "RMSE" or key == "covar": + self.assertAlmostEqual(expected_dictionary[key], actual_dictionary[key]) + elif key == "order": + self.assertEqual(expected_dictionary[key], actual_dictionary[key]) + else: + np.testing.assert_array_almost_equal(expected_dictionary[key], actual_dictionary[key]) \ No newline at end of file diff --git a/solventmapcreator/test/solvationmapcreatortests.py b/solventmapcreator/test/solvationmapcreatortests.py index 21684a9..2655f1a 100644 --- a/solventmapcreator/test/solvationmapcreatortests.py +++ b/solventmapcreator/test/solvationmapcreatortests.py @@ -13,6 +13,7 @@ from solventmapcreator.test.iotest.solventxmlreadertest import SolventXMLReaderT from solventmapcreator.test.iotest.polynomialdatawritertest import PolynomialDataWriterTestCase from solventmapcreator.test.iotest.polynomialdatareadertest import PolynomialDataReaderTestCase from solventmapcreator.test.solvationcalculationtest.solvationcalculatortest import SolvationCalculatorTestCase +from solventmapcreator.test.solvationcalculationtest.solvationmapgeneratortest import SolvationMapGeneratorTestCase from solventmapcreator.test.solvationcalculationtest.solvationplotinformationtest import SolvationPlotInformationTestCase from solventmapcreator.test.solvationcalculationtest.fractionaloccupancycalculatortest import FractionalOccupancyCalculatorTestCase from solventmapcreator.test.polynomialanalysistest.polynomialdataanalysistest import PolynomialDataAnalysisTestCase @@ -26,6 +27,7 @@ IO_TEST_CASES = [SolvationEnergyReaderTestCase, SolventXMLReaderTestCase, PolynomialDataWriterTestCase, PolynomialDataReaderTestCase] SOLVATION_CALCULATION_TEST_CASES = [SolvationCalculatorTestCase, + SolvationMapGeneratorTestCase, SolvationPlotInformationTestCase, FractionalOccupancyCalculatorTestCase] -- GitLab