Source code for salishsea_tools.gsw_calls

# Module to call matlab gsw functions from python..
# The function generic_gsw_caller can handle calling any single variable output
# gsw functions.
# The _call_... python functions have been replaced by generic_gsw_caller()
import logging
import os
import shlex
import subprocess as sp

import numpy as np


logger = logging.getLogger(__name__)
logger.addHandler(logging.NullHandler())


[docs]def generic_gsw_caller( gsw_function_name, input_vars, matlab_gsw_dir='/ocean/rich/home/matlab/gsw3', ): """ A generic function for calling matlab gsw functions. Only works with gsw functions that have a single variable as output. :arg str gsw_function_name: The name of the matlab gsw function. e.g. gsw_p_from_z.m :arg input_vars: A list of the input variables in the same order as expected from the gsw matlab function. :type input_vars: list of numpy arrays :arg str matlab_gsw_dir: The directory where the matlab gsw scripts are stored. :returns: A numpy array containing the output from call to gsw function. """ # save inputs to a file for reading into matlab tmp_files = [] for count, var_data in enumerate(input_vars): tmp_fname = 'input{}'.format(count) tmp_files.append(tmp_fname) np.savetxt(tmp_fname, var_data.flatten(), delimiter=',') shape = input_vars[0].shape # create matlab wrapper gsw_function_name = ( gsw_function_name if gsw_function_name.endswith('.m') else '{}.m'.format(gsw_function_name)) output = 'output_file' matlab_wrapper_name = _create_matlab_wrapper(gsw_function_name, output, tmp_files, matlab_gsw_dir) # create string of input arguments arg_strings = "('{}'".format(output) for tmp_fname in tmp_files: arg_strings += ",'{}'".format(tmp_fname) arg_strings += ');exit' # create string for calling matlab functioncall = '{}{}'.format(matlab_wrapper_name[:-2], arg_strings) _run_matlab(functioncall) # load output from matlab output_data = np.loadtxt(output, delimiter=',') # remove tmp files for f in tmp_files: os.remove(f) os.remove(output) os.remove(matlab_wrapper_name) return output_data.reshape(shape)
def _create_matlab_wrapper( gsw_function_name, outfile, input_files, matlab_gsw_dir, ): # Create a matlab wrapper file wrapper_file_name = 'mw_{}'.format(gsw_function_name) f = open(wrapper_file_name, 'w') header = 'function [] = {}({},'.format(wrapper_file_name[:-2], outfile) for input_file in input_files: header += "{},".format(input_file) header = header[:-1] + ')\n' f.write(header) # Add directories to matlab path f.write('addpath {}\n'.format(matlab_gsw_dir)) for subdir in ['html', 'library', 'thermodynamics_from_t', 'pdf']: f.write('addpath {}\n'.format(os.path.join(matlab_gsw_dir, subdir))) # reading input files input_args = '' for count, input_file in enumerate(input_files): f.write("in{} = dlmread({},',');\n".format(count, input_file)) input_args += 'in{},'.format(count) # call matlab gsw function f.write('y = {}({});\n'.format(gsw_function_name[:-2], input_args[:-1])) f.write("dlmwrite({},y,',');\n".format(outfile)) return wrapper_file_name def _run_matlab(functioncall): cmd = shlex.split('matlab -nosplash -nodesktop -nodisplay -nojvm -r') cmd.append(functioncall) logger.debug('executing {}'.format(cmd)) try: cmd_output = sp.check_output( cmd, stderr=sp.STDOUT, universal_newlines=True) except sp.CalledProcessError as e: logger.error( 'matlab command failed with return code {.returncode}'.format(e)) cmd_output = e.output finally: for line in cmd_output.splitlines(): line = line.strip() if line: logger.debug(line) def _call_p_from_z(z, lat): fname = "'pout'" zfile = "'zfile'" latfile = "'latfile'" for f, var in zip([zfile, latfile], [z, lat]): np.savetxt(f[1:-1], var.flatten(), delimiter=',') shape = z.shape functioncall = 'mw_gsw_p_from_z({},{},{});exit'.format(fname, zfile, latfile) _run_matlab(functioncall) pressure = np.loadtxt(fname[1:-1], delimiter=',') for f in [fname, zfile, latfile]: os.remove(f[1:-1]) return pressure.reshape(shape) def _call_SR_from_SP(SP): fname = "'SRout'" SPfile = "'SPfile'" for f, var in zip([SPfile, ], [SP, ]): np.savetxt(f[1:-1], var.flatten(), delimiter=',') shape = SP.shape functioncall = 'mw_gsw_SR_from_SP({},{});exit'.format(fname, SPfile,) _run_matlab(functioncall) sal_ref = np.loadtxt(fname[1:-1], delimiter=',') for f in [fname, SPfile, ]: os.remove(f[1:-1]) return sal_ref.reshape(shape) def _call_SA_from_SP(SP, p, long, lat): fname = "'SAout'" SPfile = "'SPfile'" pfile = "'pfile'" longfile = "'longfile'" latfile = "'latfile'" for f, var in zip([SPfile, pfile, longfile, latfile], [SP, p, long, lat]): np.savetxt(f[1:-1], var.flatten(), delimiter=',') shape = SP.shape functioncall = 'mw_gsw_SA_from_SP({},{},{},{},{});exit'.format(fname, SPfile, pfile, longfile, latfile) _run_matlab(functioncall) SA = np.loadtxt(fname[1:-1], delimiter=',') for f in [fname, SPfile, pfile, longfile, latfile]: os.remove(f[1:-1]) return SA.reshape(shape) def _call_CT_from_PT(SA, PT): fname = "'CTout'" SAfile = "'SAfile'" PTfile = "'PTfile'" for f, var in zip([SAfile, PTfile], [SA, PT]): np.savetxt(f[1:-1], var.flatten(), delimiter=',') shape = PT.shape functioncall = 'mw_gsw_CT_from_pt({},{},{});exit'.format(fname, SAfile, PTfile) _run_matlab(functioncall) CT = np.loadtxt(fname[1:-1], delimiter=',') for f in [fname, SAfile, PTfile]: os.remove(f[1:-1]) return CT.reshape(shape)