Skip to content

Commit

Permalink
Add factory methods to enable gain jones matrix.
Browse files Browse the repository at this point in the history
  • Loading branch information
jrhosk committed Feb 6, 2025
1 parent 9b4dc32 commit 8ddde25
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 140 deletions.
11 changes: 11 additions & 0 deletions src/calviper/config/jones.param.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"CalibrationMatrix.create_jones": {
"factory": {
"nullable": false,
"required": true,
"type": [
"string"
]
}
}
}
3 changes: 3 additions & 0 deletions src/calviper/config/subclasses.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"GainMatrixDataset": "calviper.factory.gain"
}
103 changes: 0 additions & 103 deletions src/calviper/factory/_jones.py

This file was deleted.

21 changes: 17 additions & 4 deletions src/calviper/factory/accessor.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
import pathlib
import json
import importlib

import toolviper.utils.logger as logger

def register_subclass(cls):
"""
There will be a lot more added here bt for testing .....
"""
import importlib

if cls.__name__ == "GainMatrixDataSet":
importlib.import_module("calviper.factory.gain")
config_path = str(pathlib.Path(__file__).parent.parent.joinpath("config").joinpath("subclasses.config.json").resolve())

with open(config_path, "r") as file:
object_ = json.load(file)
if cls.__name__ in object_:
importlib.import_module(object_[cls.__name__])

else:
logger.error(f"No subclass named {cls.__name__}")


return cls

return cls
29 changes: 8 additions & 21 deletions src/calviper/factory/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ def __init__(self):
self.type: Union[str, None] = None

#self.dtype: Union[type, None] = None
self.n_times: Union[int, None] = None
self.n_antennas: Union[int, None] = None
self.n_channels: Union[int, None] = None
self.n_polarizations: Union[int, None] = None
#self.n_times: Union[int, None] = None
#self.n_antennas: Union[int, None] = None
#self.n_channels: Union[int, None] = None
#self.n_polarizations: Union[int, None] = None

#self.n_channel_matrices: Union[int, None] = None
self.n_parameters: Union[int, None] = None
#self.n_parameters: Union[int, None] = None
self.caltable_name: Union[str, None] = None

#self.channel_dependent_parameters: bool = False
Expand All @@ -51,16 +51,6 @@ def shape(self) -> tuple:
def shape(self, shape: tuple):
return NotImplementedError

@property
@abstractmethod
def parameters(self) -> np.ndarray:
raise NotImplementedError

@parameters.setter
@abstractmethod
def parameters(self, array: np.array) -> None:
raise NotImplementedError

@property
@abstractmethod
def matrix(self) -> np.ndarray:
Expand All @@ -71,13 +61,10 @@ def matrix(self) -> np.ndarray:
def matrix(self, array: np.array) -> np.ndarray:
raise NotImplementedError

@abstractmethod
def calculate(self) -> None:
raise NotImplementedError

# Inherited method properties
@classmethod
def from_parameters(cls: Type[T], parameters: dict) -> T:
# This is deprecated at the moment, I'll add it back in when I figure out what is needed.
import inspect

obj = cls()
Expand Down Expand Up @@ -105,15 +92,15 @@ def from_parameters(cls: Type[T], parameters: dict) -> T:
vars(obj).update(updated_params)

return obj

'''
@classmethod
def from_visibility(cls: Type[T], data: xr.Dataset, time_dependence: bool = False) -> T:
return cls
# Commenting all these out for the moment. They were written in line with George's original code
# but that was based on a different workflow than I am foreseeing at the moment. These will be
# added back, if needed, as work progresses.
'''
def initialize_parameters(self, dtype: np.dtype, shape: tuple = None):
# Set data type
self.type = dtype
Expand Down
34 changes: 32 additions & 2 deletions src/calviper/factory/gain.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,41 @@
from abc import ABC

import numpy as np
import xarray as xr

import calviper.math.tools as tools
import toolviper.utils.logger as logger

from calviper.factory.base import JonesMatrix
from typing import TypeVar, Type, Union

T = TypeVar('T', bound='Parent')


@xr.register_dataset_accessor("gain")
class GainMatrix:
class GainMatrix(JonesMatrix, ABC):
def __init__(self, dataset: xr.Dataset):
super(GainMatrix, self).__init__()
self._object = dataset

self.type: str = "G"
self.dtype: Type = np.complex64
self.channel_dependent_parameters: bool = False

self._matrix: Union[None, np.ndarray] = None

@property
def data(self):
return self._object
return self._object

@property
def matrix(self) -> np.ndarray:
return self._matrix

@matrix.setter
def matrix(self, array: np.ndarray) -> None:
# (self.n_times, self.n_baselines, self.n_channels, _, _) = array.shape

# There should be a check on the shape here. I don't think we want to allow, for instance,
# an axis to be averaged while also having the dimensions stored in the object not change.
self._matrix = array
12 changes: 6 additions & 6 deletions src/calviper/factory/jones.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,22 @@

class BaseJonesMatrix(ABC):

# Base calibration table abstract class
# Base calibration matrix abstract class
@abstractmethod
def generate(self, coords: dict) -> Union[xr.Dataset, None]:
pass


class JonesFactory(ABC):
# Base factory class for table factory
# Base factory class for matrix factory
@abstractmethod
def create_jones(self, factory: Union[None, str]):
pass

@accessor.register_subclass
class GainMatrixDataSet(BaseJonesMatrix):
class GainMatrixDataset(BaseJonesMatrix):

# This is intended to be an implementation of a gain table simulator. It is
# This is intended to be an implementation of a gain jones simulator. It is
# currently very rough and filled with random numbers. Generally based on the
# original cal.py
def generate(self, coords: dict) -> None:
Expand Down Expand Up @@ -107,10 +107,10 @@ class CalibrationMatrix(JonesFactory, ABC):

def __init__(self):
self.factory_list = {
"gain": GainMatrixDataSet,
"gain": GainMatrixDataset,
}

#@toolviper.utils.parameter.validate()
@toolviper.utils.parameter.validate()
def create_jones(self, factory: str) -> Union[BaseJonesMatrix, None]:
try:
return self.factory_list[factory]()
Expand Down
11 changes: 7 additions & 4 deletions src/calviper/jones.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from abc import ABC

import numpy as np
import xarray as xr

Expand All @@ -10,7 +12,7 @@
T = TypeVar('T', bound='Parent')


class GainJones(JonesMatrix):
class GainJones(JonesMatrix, ABC):
def __init__(self):
super(GainJones, self).__init__()

Expand All @@ -31,7 +33,7 @@ def __init__(self):
self._antenna_map = None

self.name: str = "GainJonesMatrix"

'''
# This is just an example of how this would be done. There should certainly be checks and customization
# but for now just set the values simply as the original code doesn't do anything more complicated for now.
@property
Expand All @@ -41,7 +43,7 @@ def parameters(self) -> np.ndarray:
@parameters.setter
def parameters(self, array: np.ndarray) -> None:
self._parameters = array

'''
@property
def matrix(self) -> np.ndarray:
return self._matrix
Expand All @@ -53,7 +55,7 @@ def matrix(self, array: np.ndarray) -> None:
# There should be a check on the shape here. I don't think we want to allow, for instance,
# an axis to be averaged while also having the dimensions stored in the object not change.
self._matrix = array

'''
def calculate(self) -> None:
#self.initialize_jones()
Expand Down Expand Up @@ -101,3 +103,4 @@ def from_visibility(cls: Type[T], dataset: xr.Dataset, time_dependence: bool = F
instance.matrix = np.tile(identity, reps=[instance.n_times, instance.n_baselines, instance.n_channels, 1, 1])
return instance
'''

0 comments on commit 8ddde25

Please sign in to comment.