agd.Eikonal.LibraryCall

  1# Copyright 2020 Jean-Marie Mirebeau, University Paris-Sud, CNRS, University Paris-Saclay
  2# Distributed WITHOUT ANY WARRANTY. Licensed under the Apache License, Version 2.0, see http://www.apache.org/licenses/LICENSE-2.0
  3
  4import numpy as np
  5import numbers
  6import importlib
  7import importlib.util
  8import ast
  9import os
 10
 11def SetInput(hfm,params):
 12	for key,val in params.items():
 13		if isinstance(val,np.ndarray) and val.ndim==0: val = val.flat[0]
 14		if isinstance(val,numbers.Number):
 15			hfm.set_scalar(key,val)
 16		elif isinstance(val,str):
 17			hfm.set_string(key,val)
 18		elif isinstance(val,np.ndarray):
 19			hfm.set_array(key,val)
 20		else:
 21			raise ValueError('Invalid type for key ' + key);
 22
 23def GetOutput(hfm):
 24	comp=hfm.computed_keys()
 25	if comp[0]=='(': # Should be patched now
 26		comp=comp.replace('),)',"']]")
 27		comp=comp.replace('),(',')(')
 28		comp=comp.replace(',',"','")
 29		comp=comp.replace(')(',"'],['")
 30		comp=comp.replace('((',"[['")
 31
 32	result = {}
 33	for key,t in ast.literal_eval(comp):
 34		if t=='float':
 35			result[key] = hfm.get_scalar(key)
 36		elif t=='string':
 37			result[key] = hfm.get_string(key)
 38		elif t=='array':
 39			result[key] = hfm.get_array(key)
 40		else:
 41			raise ValueError('Unrecognized type '+ t + ' for key '+ key)
 42	return result
 43
 44def ListToNDArray(params):
 45	for (key,val) in params.items():
 46		if isinstance(val,list):
 47			params[key]=np.array(val)
 48
 49def RunDispatch(params,bin_dir):
 50	modelName = params['model']
 51	ListToNDArray(params)
 52	if bin_dir is None:
 53		moduleName = 'HFMpy.HFM_'+modelName
 54		HFM = importlib.import_module(moduleName)
 55		hfm = HFM.HFMIO()
 56		SetInput(hfm,params)
 57		hfm.run()
 58		return GetOutput(hfm)
 59	else:
 60		from . import FileIO
 61		execName = 'FileHFM_'+modelName
 62		return FileIO.WriteCallRead(params, execName, bin_dir)
 63
 64binary_dir={}
 65
 66def GetBinaryDir(execName,libName):
 67	"""
 68	This function is used due to the special way the HamiltonFastMarching library is used:
 69	- either as a bunch of command line executables, whose name begins with FileHFM.
 70	- or as a python library, named HFMpy
 71
 72	The function will look for a file named "FileHFM_binary_dir.txt" (or a global variable named FileHFM_binary_dir)
 73	- if it exists, the first line is read
 74	  - if the first line is None -> use the HFMpy library
 75	  - otherwise, check that the first line is a valid directory -> should contain the FileHFM executables
 76	- if file cannot be read -> use the HFMpy library
 77	"""
 78	if execName in binary_dir: return binary_dir[execName]
 79	dirName = execName + "_binary_dir"
 80	fileName = dirName + ".txt"
 81	pathExample = "path/to/"+execName+"/bin"
 82	set_directory_msg = f"""
 83You can set the path to the {execName} compiled binaries, as follows : \n
 84>>> {__name__}.binary_dir['{execName}']='{pathExample}'\n
 85\n
 86In order to do this automatically in the future, please set this path 
 87in the first line of a file named '{fileName}' in the current directory\n
 88>>> with open('{fileName}','w+') as file: file.write('{pathExample}')
 89"""
 90	fileName_parent = os.path.join('..',fileName)
 91	if os.path.isfile(fileName_parent) and not os.path.isfile(fileName):
 92		fileName = fileName_parent
 93		
 94	try:
 95		# Try reading the file
 96		with open(fileName,'r') as f:
 97			bin_dir = f.readline().replace('\n','')
 98			if bin_dir=="None":
 99				return None
100			if not os.path.isdir(bin_dir):
101				print(f"ERROR : the path to the {execName} binaries appears to be incorrect.\n")
102				print("Current path : ", bin_dir, "\n")
103				print(set_directory_msg)
104			return bin_dir
105	except OSError as e:
106		# Try importing the library
107		if libName is not None and importlib.util.find_spec(libName) is not None:
108			return None
109		error_msg = "ERROR :"
110		if libName: error_msg+=f" the {libName} library is not found"
111		if libName and execName: error_msg+=", and"
112		if execName: error_msg+=f" the path to the {execName} binaries is not set"
113		print(error_msg)
114		print(set_directory_msg)
115		raise
def SetInput(hfm, params):
12def SetInput(hfm,params):
13	for key,val in params.items():
14		if isinstance(val,np.ndarray) and val.ndim==0: val = val.flat[0]
15		if isinstance(val,numbers.Number):
16			hfm.set_scalar(key,val)
17		elif isinstance(val,str):
18			hfm.set_string(key,val)
19		elif isinstance(val,np.ndarray):
20			hfm.set_array(key,val)
21		else:
22			raise ValueError('Invalid type for key ' + key);
def GetOutput(hfm):
24def GetOutput(hfm):
25	comp=hfm.computed_keys()
26	if comp[0]=='(': # Should be patched now
27		comp=comp.replace('),)',"']]")
28		comp=comp.replace('),(',')(')
29		comp=comp.replace(',',"','")
30		comp=comp.replace(')(',"'],['")
31		comp=comp.replace('((',"[['")
32
33	result = {}
34	for key,t in ast.literal_eval(comp):
35		if t=='float':
36			result[key] = hfm.get_scalar(key)
37		elif t=='string':
38			result[key] = hfm.get_string(key)
39		elif t=='array':
40			result[key] = hfm.get_array(key)
41		else:
42			raise ValueError('Unrecognized type '+ t + ' for key '+ key)
43	return result
def ListToNDArray(params):
45def ListToNDArray(params):
46	for (key,val) in params.items():
47		if isinstance(val,list):
48			params[key]=np.array(val)
def RunDispatch(params, bin_dir):
50def RunDispatch(params,bin_dir):
51	modelName = params['model']
52	ListToNDArray(params)
53	if bin_dir is None:
54		moduleName = 'HFMpy.HFM_'+modelName
55		HFM = importlib.import_module(moduleName)
56		hfm = HFM.HFMIO()
57		SetInput(hfm,params)
58		hfm.run()
59		return GetOutput(hfm)
60	else:
61		from . import FileIO
62		execName = 'FileHFM_'+modelName
63		return FileIO.WriteCallRead(params, execName, bin_dir)
binary_dir = {}
def GetBinaryDir(execName, libName):
 67def GetBinaryDir(execName,libName):
 68	"""
 69	This function is used due to the special way the HamiltonFastMarching library is used:
 70	- either as a bunch of command line executables, whose name begins with FileHFM.
 71	- or as a python library, named HFMpy
 72
 73	The function will look for a file named "FileHFM_binary_dir.txt" (or a global variable named FileHFM_binary_dir)
 74	- if it exists, the first line is read
 75	  - if the first line is None -> use the HFMpy library
 76	  - otherwise, check that the first line is a valid directory -> should contain the FileHFM executables
 77	- if file cannot be read -> use the HFMpy library
 78	"""
 79	if execName in binary_dir: return binary_dir[execName]
 80	dirName = execName + "_binary_dir"
 81	fileName = dirName + ".txt"
 82	pathExample = "path/to/"+execName+"/bin"
 83	set_directory_msg = f"""
 84You can set the path to the {execName} compiled binaries, as follows : \n
 85>>> {__name__}.binary_dir['{execName}']='{pathExample}'\n
 86\n
 87In order to do this automatically in the future, please set this path 
 88in the first line of a file named '{fileName}' in the current directory\n
 89>>> with open('{fileName}','w+') as file: file.write('{pathExample}')
 90"""
 91	fileName_parent = os.path.join('..',fileName)
 92	if os.path.isfile(fileName_parent) and not os.path.isfile(fileName):
 93		fileName = fileName_parent
 94		
 95	try:
 96		# Try reading the file
 97		with open(fileName,'r') as f:
 98			bin_dir = f.readline().replace('\n','')
 99			if bin_dir=="None":
100				return None
101			if not os.path.isdir(bin_dir):
102				print(f"ERROR : the path to the {execName} binaries appears to be incorrect.\n")
103				print("Current path : ", bin_dir, "\n")
104				print(set_directory_msg)
105			return bin_dir
106	except OSError as e:
107		# Try importing the library
108		if libName is not None and importlib.util.find_spec(libName) is not None:
109			return None
110		error_msg = "ERROR :"
111		if libName: error_msg+=f" the {libName} library is not found"
112		if libName and execName: error_msg+=", and"
113		if execName: error_msg+=f" the path to the {execName} binaries is not set"
114		print(error_msg)
115		print(set_directory_msg)
116		raise

This function is used due to the special way the HamiltonFastMarching library is used:

  • either as a bunch of command line executables, whose name begins with FileHFM.
  • or as a python library, named HFMpy

The function will look for a file named "FileHFM_binary_dir.txt" (or a global variable named FileHFM_binary_dir)

  • if it exists, the first line is read
    • if the first line is None -> use the HFMpy library
    • otherwise, check that the first line is a valid directory -> should contain the FileHFM executables
  • if file cannot be read -> use the HFMpy library