# -*- coding: utf-8 -*-
r"""
Wrapper for IDL style C libary code
``{return_type} {func_name}(int argv, void *argc[]);``
with argv - number of parameters
and argc - list of pointers to those parameters
"""
import ctypes as ct
import logging
import platform
import warnings
import numpy as np
from .smelib.libtools import load_library
logger = logging.getLogger(__name__)
[docs]class IDL_String(ct.Structure):
"""
IDL strings are actually structures like this one,
for correct passing of values we need to define this structure
NOTE: the definition might have changed with IDL version,
so make sure to use the same one as in the C code
"""
_fields_ = [("slen", ct.c_int), ("stype", ct.c_ushort), ("s", ct.c_char_p)]
MAX_ELEM = 100
MOSIZE = 288
MUSIZE = 77
MAX_PATHLEN = 512
MAX_OUT_LEN = 511
SP_LEN = 8
[docs]class GlobalState(ct.Structure):
_fields_ = [
("NRHOX", ct.c_short),
("NRHOX_allocated", ct.c_short),
("MOTYPE", ct.c_short),
("TEFF", ct.c_double),
("GRAV", ct.c_double),
("WLSTD", ct.c_double),
("RADIUS", ct.c_double),
("NumberSpectralSegments", ct.c_int),
("NLINES", ct.c_int),
("NWAVE_C", ct.c_int),
("WFIRST", ct.c_double),
("WLAST", ct.c_double),
("VW_SCALE", ct.c_double),
("N_SPLIST", ct.c_int),
("IXH1", ct.c_int),
("IXH2", ct.c_int),
("IXH2mol", ct.c_int),
("IXH2pl", ct.c_int),
("IXHMIN", ct.c_int),
("IXHE1", ct.c_int),
("IXHE2", ct.c_int),
("IXHE3", ct.c_int),
("IXC1", ct.c_int),
("IXAL1", ct.c_int),
("IXSI1", ct.c_int),
("IXSI2", ct.c_int),
("IXCA1", ct.c_int),
("IXMG1", ct.c_int),
("IXMG2", ct.c_int),
("IXCA2", ct.c_int),
("IXN1", ct.c_int),
("IXFE1", ct.c_int),
("IXO1", ct.c_int),
("IXCH", ct.c_int),
("IXNH", ct.c_int),
("IXOH", ct.c_int),
("PATHLEN", ct.c_int),
("change_byte_order", ct.c_int),
("allocated_NLTE_lines", ct.c_int),
("flagMODEL", ct.c_short),
("flagWLRANGE", ct.c_short),
("flagABUND", ct.c_short),
("flagLINELIST", ct.c_short),
("flagIONIZ", ct.c_short),
("flagCONTIN", ct.c_short),
("lineOPACITIES", ct.c_short),
("flagH2broad", ct.c_short),
("initNLTE", ct.c_short),
("IFOP", ct.c_short * 20),
("ABUND", ct.c_float * MAX_ELEM),
("RHOX", ct.c_double * MOSIZE),
("T", ct.c_double * MOSIZE),
("XNE", ct.c_double * MOSIZE),
("XNA", ct.c_double * MOSIZE),
("RHO", ct.c_double * MOSIZE),
("VTURB", ct.c_double * MOSIZE),
("RAD_ATMO", ct.c_double * MOSIZE),
("XNA_eos", ct.c_double * MOSIZE),
("XNE_eos", ct.c_double * MOSIZE),
("RHO_eos", ct.c_double * MOSIZE),
("AHYD", ct.c_double * MOSIZE),
("AH2P", ct.c_double * MOSIZE),
("AHMIN", ct.c_double * MOSIZE),
("SIGH", ct.c_double * MOSIZE),
("AHE1", ct.c_double * MOSIZE),
("AHE2", ct.c_double * MOSIZE),
("AHEMIN", ct.c_double * MOSIZE),
("SIGHE", ct.c_double * MOSIZE),
("ACOOL", ct.c_double * MOSIZE),
("ALUKE", ct.c_double * MOSIZE),
("AHOT", ct.c_double * MOSIZE),
("SIGEL", ct.c_double * MOSIZE),
("SIGH2", ct.c_double * MOSIZE),
("TKEV", ct.c_double * MOSIZE),
("TK", ct.c_double * MOSIZE),
("HKT", ct.c_double * MOSIZE),
("TLOG", ct.c_double * MOSIZE),
("FREQ", ct.c_double),
("FREQLG", ct.c_double),
("EHVKT", ct.c_double * MOSIZE),
("STIM", ct.c_double * MOSIZE),
("BNU", ct.c_double * MOSIZE),
("H1FRACT", ct.c_float * MOSIZE),
("HE1FRACT", ct.c_float * MOSIZE),
("H2molFRACT", ct.c_float * MOSIZE),
("COPBLU", ct.c_double * MOSIZE),
("COPRED", ct.c_double * MOSIZE),
("COPSTD", ct.c_double * MOSIZE),
("LINEOP", ct.POINTER(ct.c_double) * MOSIZE),
("AVOIGT", ct.POINTER(ct.c_double) * MOSIZE),
("VVOIGT", ct.POINTER(ct.c_double) * MOSIZE),
("LTE_b", ct.c_double * MOSIZE),
("PATH", ct.c_char * MAX_PATHLEN),
("debug_print", ct.c_int),
("ATOTAL", ct.POINTER(ct.POINTER(ct.c_double))),
("INDX_C", ct.POINTER(ct.c_int)),
("YABUND", ct.POINTER(ct.c_double)),
("XMASS", ct.POINTER(ct.c_double)),
("EXCUP", ct.POINTER(ct.c_double)),
("ENU4", ct.POINTER(ct.c_double)),
("ENL4", ct.POINTER(ct.c_double)),
("BNLTE_low", ct.POINTER(ct.POINTER(ct.c_double))),
("BNLTE_upp", ct.POINTER(ct.POINTER(ct.c_double))),
("FRACT", ct.POINTER(ct.POINTER(ct.c_float))),
("PARTITION_FUNCTIONS", ct.POINTER(ct.POINTER(ct.c_float))),
("POTION", ct.POINTER(ct.c_float)),
("MOLWEIGHT", ct.POINTER(ct.c_float)),
("MARK", ct.POINTER(ct.c_short)),
("AUTOION", ct.POINTER(ct.c_short)),
("IDLHEL", ct.POINTER(ct.c_short)),
("ION", ct.POINTER(ct.c_int)),
("ANSTEE", ct.POINTER(ct.c_int)),
("WLCENT", ct.POINTER(ct.c_double)),
("EXCIT", ct.POINTER(ct.c_double)),
("GF", ct.POINTER(ct.c_double)),
("GAMRAD", ct.POINTER(ct.c_double)),
("GAMQST", ct.POINTER(ct.c_double)),
("GAMVW", ct.POINTER(ct.c_double)),
("ALMAX", ct.POINTER(ct.c_double)),
("Wlim_left", ct.POINTER(ct.c_double)),
("Wlim_right", ct.POINTER(ct.c_double)),
("SPLIST", ct.c_char_p),
("spname", ct.c_char_p),
("SPINDEX", ct.POINTER(ct.c_int)),
("flagNLTE", ct.POINTER(ct.c_short)),
("result", ct.c_char * (MAX_OUT_LEN + 1)),
]
[docs] def free_linelist(self):
if self.flagLINELIST:
self.spname = None
self.SPINDEX = None
self.ION = None
self.MARK = None
self.AUTOION = None
self.WLCENT = None
self.EXCIT = None
self.GF = None
self.GAMRAD = None
self.GAMQST = None
self.GAMVW = None
self.ANSTEE = None
self.IDLHEL = None
self.ALMAX = None
self.Wlim_left = None
self.Wlim_right = None
self.flagLINELIST = 0
[docs] def free_ionization(self):
if self.flagIONIZ:
self.SPLIST = None
for i in range(self.NRHOX_allocated):
self.FRACT[i] = None
self.PARTITION_FUNCTIONS[i] = None
self.FRACT = None
self.PARTITION_FUNCTIONS = None
self.POTION = None
self.MOLWEIGHT = None
self.flagIONIZ = 0
[docs] def free_opacities(self):
if self.lineOPACITIES:
for i in range(self.NRHOX):
self.LINEOP[i] = None
self.AVOIGT[i] = None
self.VVOIGT[i] = None
self.lineOPACITIES = 0
[docs]def get_lib_name():
"""Get the name of the sme C library"""
system = platform.system().lower()
arch = platform.machine()
bits = 64 # platform.architecture()[0][:-3]
return "sme_synth.so.{system}.{arch}.{bits}".format(
system=system, arch=arch, bits=bits
)
[docs]def get_typenames(arg):
"""
Return internal typename based on the type of the argument
strings -> "unicode"
floating points -> "double"
integers -> "int"
"""
if isinstance(arg, (str, np.str)) or (
isinstance(arg, np.ndarray) and np.issubdtype(arg.dtype, np.str)
):
return "unicode"
if isinstance(arg, (float, np.floating)) or (
isinstance(arg, np.ndarray) and np.issubdtype(arg.dtype, np.floating)
):
return "double"
if isinstance(arg, (int, np.integer)) or (
isinstance(arg, np.ndarray) and np.issubdtype(arg.dtype, np.integer)
):
return "int"
raise ValueError("argument datatype not understood")
[docs]def get_dtype(type):
"""
Get the ctypes dtype appropiate for the passed type string
Parameters
-------
type : str
One of 'int', 'short', 'long', 'float', 'double',
'unicode' or one of the first letters 'islfdu'
Returns
------
type: class
corresponding ctypes type
"""
if type in ["i", "int", int]:
return ct.c_int
elif type in ["s", "short"]:
return ct.c_short
elif type in ["l", "long"]:
return ct.c_long
elif type in ["f", "float"]:
return ct.c_float
elif type in ["d", "double", float]:
return ct.c_double
elif type in ["u", "unicode", "str", str]:
return IDL_String
elif type in ["state", GlobalState]:
return ct.POINTER(GlobalState)
else:
raise ValueError("Data type {type} not understood".format(type=type))
[docs]def is_nullptr(ptr):
try:
# If we can access it without an exception its not a null ptr
tmp = ptr[0]
return False
except ValueError:
return True
[docs]def get_c_dtype(ptr):
if isinstance(ptr, bytes):
return ct.c_char
while hasattr(ptr, "contents"):
ptr = ptr._type_
return ptr
[docs]def get_c_shape(field, ptr, state):
if isinstance(ptr, bytes):
return (len(ptr),)
if isinstance(ptr, ct._Pointer):
if isinstance(ptr[0], ct._Pointer):
size1 = state.contents.NRHOX
size2 = state.contents.N_SPLIST
return (size1, size2)
else:
size = state.contents.NLINES
return (size,)
return None
[docs]def idl_call_external(funcname, *args, restype="str", type=None, lib=None, state=None):
r"""
Call an external C library (here the SME lib) function that uses the IDL type interface
i.e. restype func(int n, void \*args[]), where n is the number of arguments, and args is a list of pointers to the arguments
Input arrays will be converted to the required datatype for the C function (see type keyword),
and any changes to input arrays will be written back if possible.
Input arrays that are already in the correct datatype will not be copied (and the values can therefore change in the C call)
Note that all strings are converted into IDL_String objects, even those that are in arrays
Parameters
----------
funcname : str
Name of the function to call in the library
restype : str, optional
expected type of the return value (default: "str")
type : str, list(str), optional
type of the input parameters, will default to int/double for all integer/floating point values.
Accepted values are ('short', 'int', 'long', 'float', 'double', 'unicode') or their respective first letters.
This means one can use a string as shorthand, e.g. "iidds"
Returns
-------
value : restype
return value of the function call
"""
# Load library if that wasn't done yet
if lib is None:
lib = load_library()
# prepare input arguments
args = list(args)
staying_alive = [a for a in args]
original = [a for a in args]
# datatype is determined by passed type keyword
# defaults to 'int' for all integer type values and 'double' for all floating point values
if type is None:
type = [get_typenames(a) for a in args]
elif type in ["short", "int", "long", "float", "double"]:
type = [type for i in range(len(args))]
# Parse arguments into c values
# keep Python elements in staying alive, so they are not discarded by the garbage collection
for i in range(len(args)):
# Single values
if isinstance(args[i], (int, float, np.number)):
dtype = get_dtype(type[i])
staying_alive[i] = np.array(args[i]).astype(dtype, copy=False).ctypes
args[i] = staying_alive[i].data
elif isinstance(args[i], str):
staying_alive[i] = IDL_String(
slen=len(args[i]), stype=1, s=args[i].encode()
)
args[i] = ct.addressof(staying_alive[i])
# Arrays
elif isinstance(args[i], (list, np.ndarray)):
if isinstance(args[i], list):
# enforce numpy arrays
args[i] = np.array(args[i])
if np.issubdtype(args[i].dtype, np.number) or np.issubdtype(
args[i].dtype, np.bool_
):
dtype = get_dtype(type[i])
args[i] = np.require(
args[i], dtype=dtype, requirements=["C", "A", "W", "O"]
)
staying_alive[i] = args[i].ctypes
args[i] = staying_alive[i].data
elif np.issubdtype(args[i].dtype, np.str_) or np.issubdtype(
args[i].dtype, np.bytes_
):
args[i] = args[i].astype("S")
staying_alive.append(args[i])
length = [len(a) for a in args[i]]
args[i] = [
IDL_String(slen=l, stype=1, s=s) for s, l in zip(args[i], length)
]
staying_alive.append(args[i])
strarr = (IDL_String * len(args[i]))()
for j in range(len(args[i])):
strarr[j] = args[i][j]
staying_alive[i] = strarr
args[i] = ct.addressof(strarr)
else:
raise TypeError("Array datatype not understood")
else:
raise TypeError("Argument type not understood")
# Load function and define parameters
func = getattr(lib, funcname)
if state is not None:
func.argtypes = (
ct.c_int,
ct.POINTER(ct.c_void_p),
ct.POINTER(GlobalState),
)
else:
func.argtypes = (ct.c_int, ct.POINTER(ct.c_void_p))
if restype in ["str", str]:
func.restype = ct.c_char_p
else:
func.restype = get_dtype(restype)
# Convert input parameters to list of void pointers
a = np.array(args, dtype=ct.c_void_p)
a = np.ascontiguousarray(a)
argc = len(args)
argv = a.ctypes.data_as(ct.POINTER(ct.c_void_p))
# C function call
if state is not None:
res = func(argc, argv, state)
else:
res = func(argc, argv)
# Try to copy back data to the original array memory (if necessary)
for i in range(len(original)):
if isinstance(original[i], np.ndarray):
if np.issubdtype(original[i].dtype, np.number) or np.issubdtype(
original[i].dtype, np.bool_
):
# do nothing if its the same array
if original[i] is staying_alive[i]._arr:
continue
arr = staying_alive[i]._arr
elif np.issubdtype(original[i].dtype, np.str_):
# For string arrays recover the strings from the IDL_String structure
arr = [s.s.decode() for s in staying_alive[i]]
else:
# Shouldn't happen
continue
# If nothing was changed then all is good
if not np.all(original[i] == arr):
try:
original[i][:] = arr
except ValueError as ve:
print(
"WARNING: Array values changed, but could not be written back to the original array\n{ve}".format(
ve=str(ve)
)
)
return res
[docs]class IDL_DLL:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = object.__new__(cls)
IDL_DLL.init(cls._instance, *args, **kwargs)
return cls._instance
[docs] @staticmethod
def init(self, libfile=None):
self.libfile = libfile
self.lib = load_library(libfile)
# Pick best interface
self.interfaces = self.get_interfaces()
if "Parallel" in self.interfaces:
self.interface = "Parallel"
elif "IDL" in self.interfaces:
self.interface = "IDL"
else:
self.interface = self.interfaces[0]
def __getattr__(self, name):
return lambda *args, **kwargs: self.call(name, *args, **kwargs)
[docs] def call(self, name, *args, raise_error=True, raise_warning=False, **kwargs):
"""
run idl_call_external and check for errors in the output
Parameters
----------
name : str
name of the external C function to call
args
parameters for the function
kwargs
keywords for the function
Raises
--------
ValueError
If the returned string is not empty, it means an error occured in the C library
"""
error = ""
try:
error = idl_call_external(
self.get_name(name), *args, lib=self.lib, **kwargs
)
except AttributeError as ex:
error = "Using obsolete SME Library; {ex}".format(ex=ex)
raise_error = False
raise_warning = True
if error != b"":
if hasattr(error, "decode"):
error = error.decode()
if raise_error:
raise ValueError(
"{name} (call external): {error}".format(name=name, error=error)
)
if raise_warning:
warnings.warn(
"{name} (call external): {error}".format(name=name, error=error)
)
return error
[docs] def get_name(self, funname):
if self.interface == "Parallel":
return f"Parallel_{funname}"
elif self.interface == "IDL":
return funname
elif self.interface == "Cython":
return f"Cython_{funname}"
else:
raise ValueError
[docs] def new_state(self):
# ctypes initializes the fields to 0/NULL by default
state = GlobalState()
return ct.pointer(state)
[docs] def free_state(self, state):
del state
[docs] def copy_state(self, state):
new = GlobalState()
new.NRHOX = state.contents.NRHOX
new.NRHOX_allocated = state.contents.NRHOX_allocated
new.MOTYPE = state.contents.MOTYPE
new.TEFF = state.contents.TEFF
new.GRAV = state.contents.GRAV
new.WLSTD = state.contents.WLSTD
new.RADIUS = state.contents.RADIUS
new.NumberSpectralSegments = state.contents.NumberSpectralSegments
new.NLINES = state.contents.NLINES
new.NWAVE_C = state.contents.NWAVE_C
new.WFIRST = state.contents.WFIRST
new.WLAST = state.contents.WLAST
new.VW_SCALE = state.contents.VW_SCALE
new.N_SPLIST = state.contents.N_SPLIST
new.IXH1 = state.contents.IXH1
new.IXH2 = state.contents.IXH2
new.IXH2mol = state.contents.IXH2mol
new.IXH2pl = state.contents.IXH2pl
new.IXHMIN = state.contents.IXHMIN
new.IXHE1 = state.contents.IXHE1
new.IXHE2 = state.contents.IXHE2
new.IXHE3 = state.contents.IXHE3
new.IXC1 = state.contents.IXC1
new.IXAL1 = state.contents.IXAL1
new.IXSI1 = state.contents.IXSI1
new.IXSI2 = state.contents.IXSI2
new.IXCA1 = state.contents.IXCA1
new.IXMG1 = state.contents.IXMG1
new.IXMG2 = state.contents.IXMG2
new.IXCA2 = state.contents.IXCA2
new.IXN1 = state.contents.IXN1
new.IXFE1 = state.contents.IXFE1
new.IXO1 = state.contents.IXO1
new.IXCH = state.contents.IXCH
new.IXNH = state.contents.IXNH
new.IXOH = state.contents.IXOH
new.PATHLEN = state.contents.PATHLEN
new.change_byte_order = state.contents.change_byte_order
new.allocated_NLTE_lines = state.contents.allocated_NLTE_lines
new.flagMODEL = state.contents.flagMODEL
new.flagWLRANGE = state.contents.flagWLRANGE
new.flagABUND = state.contents.flagABUND
new.flagLINELIST = state.contents.flagLINELIST
new.flagIONIZ = state.contents.flagIONIZ
new.flagCONTIN = state.contents.flagCONTIN
new.lineOPACITIES = state.contents.lineOPACITIES
new.flagH2broad = state.contents.flagH2broad
new.initNLTE = state.contents.initNLTE
new.FREQ = state.contents.FREQ
new.FREQLG = state.contents.FREQLG
new.debug_print = state.contents.debug_print
ct.memmove(new.IFOP, state.contents.IFOP, ct.sizeof(new.IFOP))
ct.memmove(new.ABUND, state.contents.ABUND, ct.sizeof(new.ABUND))
ct.memmove(new.RHOX, state.contents.RHOX, ct.sizeof(new.RHOX))
ct.memmove(new.T, state.contents.T, ct.sizeof(new.T))
ct.memmove(new.XNE, state.contents.XNE, ct.sizeof(new.XNE))
ct.memmove(new.XNA, state.contents.XNA, ct.sizeof(new.XNA))
ct.memmove(new.RHO, state.contents.RHO, ct.sizeof(new.RHO))
ct.memmove(new.VTURB, state.contents.VTURB, ct.sizeof(new.VTURB))
ct.memmove(new.RAD_ATMO, state.contents.RAD_ATMO, ct.sizeof(new.RAD_ATMO))
ct.memmove(new.XNA_eos, state.contents.XNA_eos, ct.sizeof(new.XNA_eos))
ct.memmove(new.XNE_eos, state.contents.XNE_eos, ct.sizeof(new.XNE_eos))
ct.memmove(new.RHO_eos, state.contents.RHO_eos, ct.sizeof(new.RHO_eos))
ct.memmove(new.AHYD, state.contents.AHYD, ct.sizeof(new.AHYD))
ct.memmove(new.AH2P, state.contents.AH2P, ct.sizeof(new.AH2P))
ct.memmove(new.AHMIN, state.contents.AHMIN, ct.sizeof(new.AHMIN))
ct.memmove(new.SIGH, state.contents.SIGH, ct.sizeof(new.SIGH))
ct.memmove(new.AHE1, state.contents.AHE1, ct.sizeof(new.AHE1))
ct.memmove(new.AHE2, state.contents.AHE2, ct.sizeof(new.AHE2))
ct.memmove(new.AHEMIN, state.contents.AHEMIN, ct.sizeof(new.AHEMIN))
ct.memmove(new.SIGHE, state.contents.SIGHE, ct.sizeof(new.SIGHE))
ct.memmove(new.ACOOL, state.contents.ACOOL, ct.sizeof(new.ACOOL))
ct.memmove(new.ALUKE, state.contents.ALUKE, ct.sizeof(new.ALUKE))
ct.memmove(new.AHOT, state.contents.AHOT, ct.sizeof(new.AHOT))
ct.memmove(new.SIGEL, state.contents.SIGEL, ct.sizeof(new.SIGEL))
ct.memmove(new.SIGH2, state.contents.SIGH2, ct.sizeof(new.SIGH2))
ct.memmove(new.TKEV, state.contents.TKEV, ct.sizeof(new.TKEV))
ct.memmove(new.TK, state.contents.TK, ct.sizeof(new.TK))
ct.memmove(new.HKT, state.contents.HKT, ct.sizeof(new.HKT))
ct.memmove(new.TLOG, state.contents.TLOG, ct.sizeof(new.TLOG))
ct.memmove(new.EHVKT, state.contents.EHVKT, ct.sizeof(new.EHVKT))
ct.memmove(new.STIM, state.contents.STIM, ct.sizeof(new.STIM))
ct.memmove(new.BNU, state.contents.BNU, ct.sizeof(new.BNU))
ct.memmove(new.H1FRACT, state.contents.H1FRACT, ct.sizeof(new.H1FRACT))
ct.memmove(new.HE1FRACT, state.contents.HE1FRACT, ct.sizeof(new.HE1FRACT))
ct.memmove(
new.H2molFRACT,
state.contents.H2molFRACT,
ct.sizeof(new.H2molFRACT),
)
ct.memmove(new.COPBLU, state.contents.COPBLU, ct.sizeof(new.COPBLU))
ct.memmove(new.COPRED, state.contents.COPRED, ct.sizeof(new.COPRED))
ct.memmove(new.COPSTD, state.contents.COPSTD, ct.sizeof(new.COPSTD))
ct.memmove(new.LTE_b, state.contents.LTE_b, ct.sizeof(new.LTE_b))
nrhox = state.contents.NRHOX
nsplist = state.contents.N_SPLIST
nlines = state.contents.NLINES
def ct_copy(new, state, field, shape, dtype=None):
value = getattr(state.contents, field)
dtype = get_c_dtype(value) if dtype is None else dtype
if is_nullptr(value):
return None
if len(shape) == 1:
copy = (dtype * shape[0])()
ct.memmove(copy, value, shape[0] * ct.sizeof(dtype))
if len(shape) == 2:
copy = (ct.POINTER(dtype) * shape[0])()
for i in range(shape[0]):
copy[i] = (dtype * shape[1])()
ct.memmove(copy[i], value[i], shape[1] * ct.sizeof(dtype))
return copy
for i in range(nrhox):
new.LINEOP[i] = (ct.c_double * nlines)()
ct.memmove(
new.LINEOP[i],
state.contents.LINEOP[i],
nlines * ct.sizeof(ct.c_double),
)
new.AVOIGT[i] = (ct.c_double * nlines)()
ct.memmove(
new.AVOIGT[i],
state.contents.AVOIGT[i],
nlines * ct.sizeof(ct.c_double),
)
new.VVOIGT[i] = (ct.c_double * nlines)()
ct.memmove(
new.VVOIGT[i],
state.contents.VVOIGT[i],
nlines * ct.sizeof(ct.c_double),
)
new.ATOTAL = ct_copy(new, state, "ATOTAL", (nrhox, nsplist), ct.c_double)
new.INDX_C = ct_copy(new, state, "INDX_C", (nlines,), ct.c_int)
new.YABUND = ct_copy(new, state, "YABUND", (nlines,), ct.c_double)
new.XMASS = ct_copy(new, state, "XMASS", (nlines,), ct.c_double)
new.EXCUP = ct_copy(new, state, "EXCUP", (nlines,), ct.c_double)
new.ENU4 = ct_copy(new, state, "ENU4", (nlines,), ct.c_double)
new.ENL4 = ct_copy(new, state, "ENL4", (nlines,), ct.c_double)
new.BNLTE_low = ct_copy(new, state, "BNLTE_low", (nlines, nrhox), ct.c_double)
new.BNLTE_upp = ct_copy(new, state, "BNLTE_upp", (nlines, nrhox), ct.c_double)
new.FRACT = ct_copy(new, state, "FRACT", (nrhox, nsplist), ct.c_float)
new.PARTITION_FUNCTIONS = ct_copy(
new, state, "PARTITION_FUNCTIONS", (nrhox, nsplist), ct.c_float
)
new.POTION = ct_copy(new, state, "POTION", (nsplist,), ct.c_float)
new.MOLWEIGHT = ct_copy(new, state, "MOLWEIGHT", (nsplist,), ct.c_float)
new.MARK = ct_copy(new, state, "MARK", (nlines,), ct.c_short)
new.AUTOION = ct_copy(new, state, "AUTOION", (nlines,), ct.c_short)
new.IDLHEL = ct_copy(new, state, "IDLHEL", (nlines,), ct.c_short)
new.ION = ct_copy(new, state, "ION", (nlines,), ct.c_int)
new.ANSTEE = ct_copy(new, state, "ANSTEE", (nlines,), ct.c_int)
new.WLCENT = ct_copy(new, state, "WLCENT", (nlines,), ct.c_double)
new.EXCIT = ct_copy(new, state, "EXCIT", (nlines,), ct.c_double)
new.GF = ct_copy(new, state, "GF", (nlines,), ct.c_double)
new.GAMRAD = ct_copy(new, state, "GAMRAD", (nlines,), ct.c_double)
new.GAMQST = ct_copy(new, state, "GAMQST", (nlines,), ct.c_double)
new.GAMVW = ct_copy(new, state, "GAMVW", (nlines,), ct.c_double)
new.ALMAX = ct_copy(new, state, "ALMAX", (nlines,), ct.c_double)
new.Wlim_left = ct_copy(new, state, "Wlim_left", (nlines,), ct.c_double)
new.Wlim_right = ct_copy(new, state, "Wlim_right", (nlines,), ct.c_double)
new.SPINDEX = ct_copy(new, state, "SPINDEX", (nlines,), ct.c_int)
new.flagNLTE = ct_copy(new, state, "flagNLTE", (nlines,), ct.c_short)
new.SPLIST = state.contents.SPLIST
new.spname = state.contents.spname
new.PATH = state.contents.PATH
new.result = state.contents.result
return ct.pointer(new)
[docs] def get_interfaces(self):
try:
interfaces = idl_call_external("GetInterfaces")
interfaces = interfaces.decode()
interfaces = interfaces.split(";")
except AttributeError:
# Old Library without that function
interfaces = ["IDL"]
return interfaces