Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mb/ifu missing #72

Draft
wants to merge 16 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions metisp/pymetis/src/UNKNOWN.egg-info/PKG-INFO

This file was deleted.

43 changes: 0 additions & 43 deletions metisp/pymetis/src/UNKNOWN.egg-info/SOURCES.txt

This file was deleted.

1 change: 0 additions & 1 deletion metisp/pymetis/src/UNKNOWN.egg-info/dependency_links.txt

This file was deleted.

1 change: 0 additions & 1 deletion metisp/pymetis/src/UNKNOWN.egg-info/top_level.txt

This file was deleted.

53 changes: 32 additions & 21 deletions metisp/pymetis/src/pymetis/base/impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@

class MetisRecipeImpl(ABC):
"""
An abstract base class for all METIS recipe implementations.
Contains central flow control and provides abstract methods to be overridden
by particular pipeline recipe implementations.
An abstract base class for all METIS recipe implementations.
Contains central data flow control and also provides abstract methods to be overridden
by particular pipeline recipe implementations.
"""
InputSet = PipelineInputSet
Product = PipelineProduct
InputSet: PipelineInputSet = None
Product: PipelineProduct = None

# Available parameters are a class variable. This must be present, even if empty.
parameters = cpl.ui.ParameterList([])
Expand All @@ -48,15 +48,18 @@ def __init__(self, recipe: 'MetisRecipe') -> None:
self.inputset = None
self.frameset = None
self.header = None
self.products: Dict[str, PipelineProduct] = {}
self.product_frames = cpl.ui.FrameSet()
self.products = {}

def run(self, frameset: cpl.ui.FrameSet, settings: Dict[str, Any]) -> cpl.ui.FrameSet:
"""
The main function of the recipe implementation. Mirrors the signature of Recipe.run.
All recipe implementations follow this schema (and hence it does not have to be repeated).
"""
The main function of the recipe implementation. It mirrors the signature of `Recipe.run`
and is meant to be called directly by the owner recipe.
All recipe implementations should follow this schema (and hence it does not have to be repeated
or overridden anywhere). ToDo: at least Martin thinks so now.

If this structure does not cover the needs of your particular recipe, we should discuss and adapt.
"""

try:
self.frameset = frameset
Expand Down Expand Up @@ -90,31 +93,39 @@ def process_images(self) -> Dict[str, PipelineProduct]:
The core method of the recipe implementation. It should contain all the processing logic.
At its entry point the Input class must be already loaded and verified.

All pixel manipulation should happen inside this function (or something it calls from within).
That means, no pixel manipulation before entering `process_images`
and no pixel manipulation after exiting `process_images`.

The basic workflow inside should be as follows:

1. Load the actual CPL Images associated with Input frames.
2. Do the preprocessing (dark, bias, flat, ...) as needed
2. Do the preprocessing (dark, bias, flat, ...) as needed.
- Use provided functions if possible. Much of the functionality is common to many recipes.
- Use HDRL functions, if available.
- Use CPL functions, if available.
- Implement what you need yourself.
3. Build the output images as specified in the DRLD.
Each product should be an instance of the associated Product class.
4. Return a dictionary in the form {tag: Product(...)}
Each product should be an instance of the associated `Product` class.
There should be exactly one `Product` for every file produced (at least for now).
4. Return a dictionary in the form {tag: ProductTag(...)}

The resulting products are passed to `save_products()`.
The resulting products dict is then be passed to `save_products()`.
"""
return {}

def save_products(self, products: Dict[str, PipelineProduct]) -> None:
""" Save and register the created products """
"""
Save and register the created products.
"""
for name, product in products.items():
Msg.debug(self.__class__.__qualname__,
f"Saving {name}")
product.save()

def build_product_frameset(self, products: Dict[str, PipelineProduct]) -> cpl.ui.FrameSet:
""" Gather all the products and build a FrameSet from their frames. """
"""
Gather all the products and build a FrameSet from their frames so that is can be returned.
"""
Msg.debug(self.__class__.__qualname__, f"Building the product frameset")
product_frames = cpl.ui.FrameSet()

for name, product in products.items():
product_frames.append(product.as_frame())

return product_frames
return cpl.ui.FrameSet([product.as_frame() for product in products.values()])
37 changes: 34 additions & 3 deletions metisp/pymetis/src/pymetis/base/product.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ def as_frame(self):
def save(self):
""" Save this Product to a file """
Msg.info(self.__class__.__qualname__, f"Saving product file as {self.output_file_name!r}.")

Msg.warning(self.__class__.__qualname__, str(self.recipe.frameset))
# At least one frame must be tagged as RAW, otherwise it *will not* save (rite of passage!)
cpl.dfs.save_image(
self.recipe.frameset, # All frames for the recipe
self.recipe.parameters, # The list of input parameters
Expand All @@ -116,13 +119,41 @@ def output_file_name(self) -> str:
return f"{self.category}.fits"


class DetectorProduct(PipelineProduct, ABC):
class DetectorSpecificProduct(PipelineProduct, ABC):
detector = None

def __init__(self,
recipe: 'MetisRecipe',
header: cpl.core.PropertyList,
image: cpl.core.Image,
*,
detector: str = None,
**kwargs):

if detector is not None:
self.detector = detector

if self.detector is None:
raise NotImplementedError("Products specific to a detector must define 'detector'")

super().__init__(recipe, header, image, **kwargs)


class TargetSpecificProduct(PipelineProduct, ABC):
target = None

def __init__(self,
recipe: 'MetisRecipe',
header: cpl.core.PropertyList,
image: cpl.core.Image,
*,
detector: str,
target: str = None,
**kwargs):
self.detector = detector

if target is not None:
self.target = target

if self.target is None:
raise NotImplementedError("Products specific to a target must define 'target'")

super().__init__(recipe, header, image, **kwargs)
4 changes: 3 additions & 1 deletion metisp/pymetis/src/pymetis/inputs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@

from .inputset import PipelineInputSet

from .base import PipelineInput, SinglePipelineInput, MultiplePipelineInput
from .base import PipelineInput
from .single import SinglePipelineInput
from .multiple import MultiplePipelineInput

from .common import (RawInput,
MasterDarkInput,
Expand Down
Loading