Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
christinahedges committed Mar 15, 2024
1 parent 9a10c46 commit 5a310e9
Show file tree
Hide file tree
Showing 9 changed files with 379 additions and 151 deletions.
52 changes: 39 additions & 13 deletions src/lamatrix/__init__.py
@@ -1,9 +1,27 @@
# Standard library
import os # noqa
import platform
from datetime import datetime

PACKAGEDIR = os.path.abspath(os.path.dirname(__file__))

version = "0.1.0"
__version__ = "0.1.0"


def _META_DATA():
"""
Returns metadata information to a dictionary.
"""
metadata = {
"creation_date": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"tool_name": "lamatrix",
"tool_version": f"{__version__}",
"operating_system": platform.system(),
"os_version": platform.version(),
"python_version": platform.python_version(),
}
return metadata


# Standard library
import logging # noqa: E402
Expand All @@ -14,24 +32,27 @@
log = logging.getLogger("tesswcs")
log.addHandler(RichHandler(markup=True))

import json

import numpy as np

from .combine import * # noqa: E402, F401
from .models.astrophysical import * # noqa: E402, F401
from .models.gaussian import * # noqa: E402, F401
from .models.simple import * # noqa: E402, F401
from .models.spline import * # noqa: E402, F401

import json
import numpy as np

def _load_from_dict(dict):
new = globals()[dict['object_type']](**dict['initializing_kwargs'])
_ = [setattr(new, key, value) for key, value in dict['fit_results'].items()]
new = globals()[dict["object_type"]](**dict["initializing_kwargs"])
_ = [setattr(new, key, value) for key, value in dict["fit_results"].items()]
return new


def load(filename):
def process(arg):
if isinstance(arg, dict):
return {key:process(item) for key, item in arg.items()}
return {key: process(item) for key, item in arg.items()}
if arg is None:
return None
elif isinstance(arg, str):
Expand All @@ -44,12 +65,17 @@ def process(arg):
return np.asarray(arg)

"""Load a Generator object"""
with open(filename, 'r') as json_file:
with open(filename, "r") as json_file:
data_loaded = json.load(json_file)
data_loaded = {key:process(item) for key, item in data_loaded.items()}
if 'generators' in data_loaded.keys():
generators = [_load_from_dict(item) for _, item in data_loaded['generators'].items()]
new = globals()[data_loaded['object_type']](*generators)
_ = [setattr(new, key, value) for key, value in data_loaded['fit_results'].items()]
data_loaded = {key: process(item) for key, item in data_loaded.items()}
if "generators" in data_loaded.keys():
generators = [
_load_from_dict(item) for _, item in data_loaded["generators"].items()
]
new = globals()[data_loaded["object_type"]](*generators)
_ = [
setattr(new, key, value)
for key, value in data_loaded["fit_results"].items()
]
return new
return _load_from_dict(data_loaded)
return _load_from_dict(data_loaded)
67 changes: 36 additions & 31 deletions src/lamatrix/combine.py
@@ -1,5 +1,8 @@
import numpy as np
import json

import numpy as np

from . import _META_DATA
from .generator import Generator

__all__ = ["StackedIndependentGenerator", "StackedDependentGenerator"]
Expand Down Expand Up @@ -65,6 +68,14 @@ def __init__(self, *args, **kwargs):
self.fit_mu = None
self.fit_sigma = None

def __repr__(self):
str1 = (
f"{type(self).__name__}({', '.join(list(self.arg_names))})[n, {self.width}]"
)
str2 = [f"\t{g.__repr__()}" for g in self.generators]

return "\n".join([str1, *str2])

def __getitem__(self, key):
return self.generators[key]

Expand All @@ -77,6 +88,10 @@ def __getitem__(self, key):
def design_matrix(self, *args, **kwargs):
return np.hstack([g.design_matrix(*args, **kwargs) for g in self.generators])

@property
def gradient(self):
return StackedIndependentGenerator(*[g.gradient for g in self.generators])

@property
def width(self):
return np.sum([g.width for g in self.generators])
Expand Down Expand Up @@ -146,10 +161,6 @@ def fit(self, *args, **kwargs):
def __len__(self):
return len(self.generators)

# @property
# def _equation(self):
# return combine_equations(*[g._equation for g in self])

@property
def _equation(self):
return np.hstack([g._equation for g in self.generators])
Expand All @@ -169,21 +180,15 @@ def save(self, filename: str):
# Write to a JSON file
with open(filename, "w") as json_file:
data_to_store = self._create_save_data()
generators_to_store = {f"generator{idx+1}":g._create_save_data() for idx, g in enumerate(self.generators)}
generators_to_store = {
f"generator{idx+1}": g._create_save_data()
for idx, g in enumerate(self.generators)
}
data_to_store["generators"] = generators_to_store
data_to_store["metadata"] = _META_DATA()
json.dump(data_to_store, json_file, indent=4)

class StackedDependentGenerator(StackedIndependentGenerator):
# def __init__(self, *args, **kwargs):
# if (
# not len(np.unique([a.data_shape for a in args if a.data_shape is not None]))
# <= 1
# ):
# raise ValueError("Can not have different `data_shape`.")
# self.generators = [a.copy() for a in args]
# self.data_shape = self.generators[0].data_shape
# self.fit_mu = None
# self.fit_sigma = None

@property
def width(self):
Expand Down Expand Up @@ -221,18 +226,18 @@ def prior_mu(self):
def fit(self, *args, **kwargs):
self.fit_mu, self.fit_sigma = self._fit(*args, **kwargs)

# @property
# def _INIT_ATTRS(self):
# return []

# def save(self, filename: str):
# if not filename.endswith(".json"):
# filename = filename + ".json"

# # Write to a JSON file
# with open(filename, "w") as json_file:
# data_to_store = self._create_save_data()
# json.dump(data_to_store, json_file, indent=4)
# for g in self.generators:
# data_to_store = g._create_save_data()
# json.dump(data_to_store, json_file, indent=4)
@property
def mu(self):
return self.prior_mu if self.fit_mu is None else self.fit_mu

@property
def sigma(self):
return self.prior_sigma if self.fit_sigma is None else self.fit_sigma

def __getitem__(self, key):
raise AttributeError(
"Can not extract individual generators from a dependent stacked generator."
)
@property
def gradient(self):
raise AttributeError("Can not create a gradient for a dependent stacked generator.")
27 changes: 15 additions & 12 deletions src/lamatrix/generator.py
@@ -1,15 +1,15 @@
"""Abstract base class for a Generator object"""

import json
import math
from abc import ABC, abstractmethod
from copy import deepcopy
import json

import numpy as np

__all__ = [
"Generator"
]
from . import _META_DATA

__all__ = ["Generator"]


class Generator(ABC):
Expand Down Expand Up @@ -40,7 +40,7 @@ def _validate_priors(self, prior_mu, prior_sigma, offset_prior=None):
self.prior_sigma = prior_sigma
else:
raise ValueError("Can not parse `prior_sigma`.")

self.offset_prior = offset_prior
if self.offset_prior is not None:
if not hasattr(self.offset_prior, "__iter__"):
Expand Down Expand Up @@ -71,23 +71,25 @@ def process(arg):
arg = arg.tolist()
arg = [a if a != np.inf else "Infinity" for a in arg]
return arg

results = {attr:process(getattr(self, attr)) for attr in ["fit_mu", "fit_sigma"]}
kwargs = {attr:process(getattr(self, attr)) for attr in self._INIT_ATTRS}

results = {
attr: process(getattr(self, attr)) for attr in ["fit_mu", "fit_sigma"]
}
kwargs = {attr: process(getattr(self, attr)) for attr in self._INIT_ATTRS}
type_name = type(self).__name__

data_to_store = {
"object_type": type_name,
"initializing_kwargs": kwargs,
"fit_results": results,
"equation": self.equation,
"latex": self.to_latex(),
}
return data_to_store

def save(self, filename: str):
data_to_store = self._create_save_data()
data_to_store["metadata"] = _META_DATA()
if not filename.endswith(".json"):
filename = filename + ".json"

Expand All @@ -99,8 +101,9 @@ def copy(self):
return deepcopy(self)

def __repr__(self):
fit = "<fit>" if self.fit_mu is not None else ""
return (
f"{type(self).__name__}({', '.join(list(self.arg_names))})[n, {self.width}]"
f"{type(self).__name__}({', '.join(list(self.arg_names))})[n, {self.width}] {fit}"
)

# def __add__(self, other):
Expand Down Expand Up @@ -269,4 +272,4 @@ def fit(self):
@abstractmethod
def _INIT_ATTRS(self):
"""Defines the variables needed to initialize self, so that they can be stored when saved."""
pass
pass
2 changes: 1 addition & 1 deletion src/lamatrix/math.py
@@ -1,4 +1,4 @@
from .combine import StackedIndependentGenerator, StackedDependentGenerator
from .combine import StackedDependentGenerator, StackedIndependentGenerator
from .generator import Generator

__all__ = ["MathMixins"]
Expand Down
39 changes: 25 additions & 14 deletions src/lamatrix/models/gaussian.py
Expand Up @@ -10,6 +10,7 @@
"dlnGaussian2DGenerator",
]


class lnGaussian2DGenerator(MathMixins, Generator):
def __init__(
self,
Expand Down Expand Up @@ -66,7 +67,17 @@ def arg_names(self):

@property
def _INIT_ATTRS(self):
return ["x_name", "y_name", "stddev_x_prior", "stddev_y_prior", "prior_mu", "prior_sigma", "offset_prior", "data_shape", "nterms"]
return [
"x_name",
"y_name",
"stddev_x_prior",
"stddev_y_prior",
"prior_mu",
"prior_sigma",
"offset_prior",
"data_shape",
"nterms",
]

def design_matrix(self, *args, **kwargs):
"""Build a 1D polynomial in x
Expand Down Expand Up @@ -177,6 +188,7 @@ def to_latex(self):
[eq1, eq2, eq3, eq4, eq5, eq6, eq7, eq8, self._to_latex_table()]
)

@property
def derivative(self):
return dlnGaussian2DGenerator(
stddev_x=self.stddev_x[0],
Expand All @@ -187,18 +199,6 @@ def derivative(self):
data_shape=self.data_shape,
)

# @property
# def equation(self):
# eq1 = "$\\ln(G(x, y)) = a + bx^2 + cy^2 + 2dxy$"
# eq2 = "$ a = -\\ln(2\\pi\\sigma_x\\sigma_y\\sqrt{1-\\rho^2}) $"
# eq3 = "$ b = \\frac{1}{2(1-\\rho^2)\\sigma_x^2}$"
# eq4 = "$ c = \\frac{1}{2(1-\\rho^2)\\sigma_y^2}$"
# eq5 = "$ d = \\frac{\\rho}{2(1-\\rho^2)\\sigma_x\\sigma_y}$"
# eq6 = "$\\sigma_x = \\sqrt{-\\frac{1}{2b(1-\\rho^2)}}$"
# eq7 = "$\\sigma_y = \\sqrt{-\\frac{1}{2c(1-\\rho^2)}}$"
# eq8 = "$\\rho = \\sqrt{\\frac{d^2}{bc}}$"
# return [eq1, eq2, eq3, eq4, eq5, eq6, eq7, eq8]


class dlnGaussian2DGenerator(MathMixins, Generator):
def __init__(
Expand Down Expand Up @@ -238,7 +238,18 @@ def arg_names(self):

@property
def _INIT_ATTRS(self):
return ["x_name", "y_name", "stddev_x", "stddev_y", "prior_mu", "rho", "prior_sigma", "offset_prior", "data_shape", "nterms"]
return [
"x_name",
"y_name",
"stddev_x",
"stddev_y",
"prior_mu",
"rho",
"prior_sigma",
"offset_prior",
"data_shape",
"nterms",
]

def design_matrix(self, *args, **kwargs):
"""Build a 1D polynomial in x
Expand Down

0 comments on commit 5a310e9

Please sign in to comment.