Source code for medeq.base
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# File : base.py
# License: GNU v3.0
# Author : Andrei Leonard Nicusan <a.l.nicusan@bham.ac.uk>
# Date : 29.03.2022
import shutil
import textwrap
import pathlib
import subprocess
import numpy as np
import pandas as pd
from .__version__ import __version__
def install(verbose = True):
try:
import pysr
pysr.install(None, not(verbose))
except ImportError:
print((
"PySR / Julia not found - please follow installation instructions "
"from the docs."
))
raise
# Create separate Julia environment for MED, as using GLMakie through
# PyJulia segfaults
julia = get_julia_executable()
io = "stderr" if verbose else "devnull"
subprocess.run([
julia,
"-e",
f'''
using Pkg
Pkg.add("GLMakie", io={io})
Pkg.add("Colors", io={io})
Pkg.instantiate(io={io})
Pkg.precompile(io={io})
'''
])
def get_julia_executable():
candidates = ["julia", "julia.exe", "julia.cmd"]
for c in candidates:
executable = shutil.which(c)
if executable is not None:
return executable
raise FileNotFoundError
def get_julia_project(julia_project):
if julia_project is None:
is_shared = True
julia_project = f"medeq-{__version__}"
else:
is_shared = False
julia_project = pathlib.Path(julia_project)
return julia_project, is_shared
[docs]def create_parameters(
variables = [],
minimums = [],
maximums = [],
values = None,
**kwargs,
):
'''Create a ``pandas.DataFrame`` storing ``MED`` free parameters' names,
bounds.
This is simply a helper returning a ``pandas.DataFrame`` with the format
required by e.g. ``medeq.Sampling``.
Only the `variables`, `minimums` and `maximums` are necessary. If unset,
the initial ``values`` are set to halfway between the lower and upper.
Parameters
----------
variables : list[str], default []
A list of the free parameters' names.
minimums : list[float], default []
A list with the same length as ``variables`` storing the lower bound
for each corresponding variable.
maximums : list[float], default []
A list with the same length as ``variables`` storing the lower bound
for each corresponding variable.
values : list[float], optional
The optimisation starting values; not essential as ACCES samples the
space randomly anyways. If unset, they are set to halfway between
``minimums`` and ``maximums``.
**kwargs : other keyword arguments
Other columns to include in the returned parameters DataFrame, given
as other lists with the same length as ``variables``.
Returns
-------
pandas.DataFrame
A table storing the intial ``value``, ``min``, ``max`` and ``sigma``
(columns) for each free parameter (rows).
Examples
--------
Create a DataFrame storing two free parameters, specifying the minimum and
maximum bounds; notice that the starting guess and uncertainty are set
automatically.
>>> import coexist
>>> parameters = coexist.create_parameters(
>>> variables = ["cor", "separation"],
>>> minimums = [-3, -7],
>>> maximums = [+5, +3],
>>> )
>>> parameters
value min max sigma
cor 1.0 -3.0 5.0 3.2
separation -2.0 -7.0 3.0 4.0
'''
if not len(variables) == len(minimums) == len(maximums) or \
(values is not None and len(values) != len(variables)):
raise ValueError(textwrap.fill((
"The input iterables `variables`, `minimums`, `maximums` and "
"`values` (if defined) must all have the same lengths."
)))
minimums = np.array(minimums, dtype = float)
maximums = np.array(maximums, dtype = float)
if values is None:
values = (maximums + minimums) / 2
else:
values = np.array(values, dtype = float)
if not np.all(minimums < maximums):
raise ValueError(textwrap.fill((
"The input `minimums` must contain values strictly smaller than "
"those in `maximums`."
)))
parameters = pd.DataFrame(
data = {
"value": values,
"min": minimums,
"max": maximums,
**kwargs,
},
index = variables,
)
return parameters