Skip to content

Commit

Permalink
Innate 0.1.2
Browse files Browse the repository at this point in the history
  • Loading branch information
vital committed Jun 25, 2024
1 parent dd7a090 commit 44ead6d
Show file tree
Hide file tree
Showing 15 changed files with 150 additions and 52 deletions.
4 changes: 4 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# MANIFEST.in

include src/innate/config.toml
include src/innate/changelog.txt
3 changes: 3 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ Development
===========

INNATE is currently on an alpha release. Any comment/issue/request can be added as an issue on the github page.

.. _PyPi: https://pypi.org/project/innate-stable/
.. _github: https://github.com/Vital-Fernandez/innate
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
release = '06/25/2024'

# The full version, including alpha/beta/rc tags
release = '0.0.5'
release = '0.1.2'

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
Expand Down
Binary file modified examples/data/emissivity_grids.nc
Binary file not shown.
13 changes: 13 additions & 0 deletions examples/tutorials/3_eqn_regression.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import innate
import pyneb as pn

data_file = '../data/emissivity_grids.nc'
emissivities = innate.DataSet.from_file(data_file)

temp, den = 12250, 122
print('Interpolation', emissivities['O3_5007A'].approx.interp.rgi((temp, den)).eval())

# Compare with the original data
O3, H1 = pn.Atom('O', 3), pn.RecAtom('H', 1)
emiss_ratio = O3.getEmissivity(temp, den, wave=5007)/H1.getEmissivity(temp, den, wave=4861)
print('True value', emiss_ratio)
14 changes: 9 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
[build-system]
requires = ["setuptools>=61.0.0", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "innate-stable"
version = "0.1.1"
version = "0.1.2"
readme = "README.rst"
requires-python = ">=3.10"
license = {file = "COPYING"}
authors = [{name = "Vital Fernández", email = "[email protected]"}]
description = "Interpolator and Neural Network Architecture for TEnsors"

dependencies = ["numpy~=1.24",
"pandas~=2.0",
"toml~=0.10",
dependencies = ["numpy~=1.2",
"h5py~=3.11",
"bokeh==2.4.3",
"h5netcdf~=1.3",
"tomli >= 2.0.0 ; python_version < '3.11'"]

classifiers = ["License :: OSI Approved :: MIT License",
Expand Down
8 changes: 7 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
numpy~=1.24
numpy~=1.2
h5py~=3.11
matplotlib~=3.9
bokeh==2.4.3
astropy~=6.0
h5netcdf~=1.3
tomli >= 2.0.0 ; python_version < "3.11"
35 changes: 0 additions & 35 deletions setup.py

This file was deleted.

6 changes: 3 additions & 3 deletions src/innate/approximation.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@

class Approximator:

def __init__(self, grid, technique_list):
def __init__(self, grid, technique_list, data_cfg=None):

if technique_list is None:
_logger.critical(f'The data set "{grid.label}" does not include the approximation to include the "approximation"'
f'key in the configurations variable or file')

# Methodology approaches
self.interp = Interpolator(grid, technique_list)
self.reg = Regressor(grid, technique_list)
self.interp = Interpolator(grid, technique_list, data_cfg=data_cfg)
self.reg = Regressor(grid, technique_list, data_cfg=data_cfg)

return
2 changes: 1 addition & 1 deletion src/innate/changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@

0.1.1 Side projects:
- NN training example
- documenation base
- documentation base
2 changes: 1 addition & 1 deletion src/innate/config.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[metadata]
version = '0.1.1'
version = '0.1.2'

[parameter_labels]

Expand Down
5 changes: 3 additions & 2 deletions src/innate/interpolation/methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@

class Interpolator:

def __init__(self, grid, technique_list, tensor_library='pytensor'):
def __init__(self, grid, technique_list, tensor_library='pytensor', data_cfg=None):

# Attributes
self.rgi = None
self.eqn = None
self.techniques = []

# Confirm the data is available
if grid.data is None:
Expand All @@ -23,6 +23,7 @@ def __init__(self, grid, technique_list, tensor_library='pytensor'):

# Regular grid Interpolation
if 'rgi' in algorithms:
self.techniques.append('rgi')
self.rgi = interpolation_coordinates(grid.data, list(grid.axes_range.values()), interp_type='point')

return
20 changes: 19 additions & 1 deletion src/innate/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def __init__(self, grid_label, data_array, data_cfg, tensor_library='pytensor'):

# Declare the function attributes treatments
approx_techniques = data_cfg.get('approximation')
self.approx = Approximator(self, approx_techniques)
self.approx = Approximator(self, approx_techniques, data_cfg)

# # Initiate data and interpolators
# grid_path = Path(grid)
Expand Down Expand Up @@ -112,3 +112,21 @@ def _compile_grids(self, array_dict, common_cfg, local_cfg, **kwargs):

return

def extract_approximation(self, technique, label_list=None):

label_list = label_list if label_list is not None else list(self.keys())

approx_dict = {}
for label in label_list:

if technique in self[label].approx.interp.techniques:
approx_dict[label] = getattr(self[label].approx.interp, technique)

elif technique in self[label].approx.reg.techniques:
approx_dict[label] = getattr(self[label].approx.reg, technique)

else:
_logger.critical(f'Input approximation "{technique}" is not available for dataset "{label}"')

return approx_dict

86 changes: 85 additions & 1 deletion src/innate/regression/methods.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,90 @@
import logging
import re
import numpy as np
from .. import _setup_cfg

_logger = logging.getLogger('Innate')


def generate_specific_function(expression, coefficients, variable_names):
# Define the function to only vary with specified variables
def specific_function(*variable_values):
local_vars = coefficients.copy() # Copy the dictionary of fixed variables
# Update variable names with values dynamically from the input
local_vars.update(dict(zip(variable_names, variable_values)))
local_vars['np'] = np # Ensure np is available for np.log10 and other operations
return eval(expression, {}, local_vars)
# The number of inputs is now the number of variable names provided
return np.frompyfunc(specific_function, len(variable_names), 1)


def extract_coef_names(expression):
# Regex to find isolated letters (considered variables)
pattern = r'\b[a-zA-Z]\b'
# Find all matches and return as a set to remove duplicates
matches = set(re.findall(pattern, expression))
return sorted(matches)


def create_coef_dict (coef_names, coef_values):
if len(coef_names)==len(coef_values):
out = dict(zip(coef_names, coef_values))
else:
raise TypeError("length of coefficietns names different from the length of coefficients values")
return(out)


def extract_variables_names(expression, suffix='_range'):
# Construct the regex pattern dynamically to find words ending with the given suffix
pattern = rf'\b\w+{re.escape(suffix)}\b' # Use re.escape to safely include the suffix in the regex
# Find all matches and return as a set to remove duplicates
matches = set(re.findall(pattern, expression))
return sorted(list(matches)) # Return a sorted list of unique matches


def parse_string_equation(data_label, str_eqn, coeffs_eqn, variable_names):

if (str_eqn is not None) or (coeffs_eqn is not None):
coef_names = extract_coef_names(str_eqn)
coeffs_dict = create_coef_dict(coef_names, coeffs_eqn)
eqn = generate_specific_function(str_eqn, coeffs_dict, variable_names)

else:
message = f'Data set "{data_label}" is missing:'
if str_eqn is None:
message += f'\nParametrisation formula ("eqn" key in dataset configuration).'
if coeffs_eqn is None:
message += f'\nParametrisation coefficients ("eqn_coeffs" key in dataset configuration).'
_logger.warning(message)

eqn, coeffs = None, None

return eqn, coeffs_dict


class Regressor:

def __init__(self, grid, method_list):
def __init__(self, grid, technique_list, data_cfg=None):

self.eqn = None
self.coeffs = None
self.techniques = []

# Constrain to regresion techniques
algorithms = list(set(_setup_cfg['parameter_labels']['reg'].keys()) & set(technique_list))

# Regular grid Interpolation
if 'eqn' in algorithms:
self.techniques.append('eqn')

# Reconstruct the string equation into a python function
self.eqn, self.coeffs = parse_string_equation(grid.label,
data_cfg.get('eqn', None),
data_cfg.get('eqn_coeffs', None),
data_cfg.get('axes', None))

return




2 changes: 1 addition & 1 deletion test_string_to_function.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

import numpy as np


expression = 'a + b / (variable1_range/10000.0) + c * np.log10(variable2_range/10000)'
Expand Down

0 comments on commit 44ead6d

Please sign in to comment.