# Path: emirdrp/core/recipe.py
# class EmirRecipe(recipes.BaseRecipe):
#     """Base clase for all EMIR Recipes
# 
# 
#     Attributes
#     ----------
#     logger :
#          recipe logger
# 
#     datamodel : EmirDataModel
# 
#     """
#     logger = logging.getLogger(__name__)
#     datamodel = emirdrp.datamodel.EmirDataModel()
# 
#     def types_getter(self):
#         imgtypes = [prods.MasterBadPixelMask,
#                     prods.MasterBias,
#                     prods.MasterDark,
#                     prods.MasterIntensityFlat,
#                     prods.MasterSpectralFlat,
#                     prods.MasterSky
#                     ]
#         getters = [cor.get_corrector_p, cor.get_corrector_b, cor.get_corrector_d,
#                    [cor.get_corrector_f, cor.get_checker], cor.get_corrector_sf, cor.get_corrector_s]
# 
#         return imgtypes, getters
# 
#     def get_filters(self):
#         import collections
#         imgtypes, getters = self.types_getter()
#         used_getters = []
#         for rtype, getter in zip(imgtypes, getters):
#             self.logger.debug('get_filters, %s  %s', rtype, getter)
#             if rtype is None:
#                 # Unconditional
#                 if isinstance(getter, collections.Iterable):
#                     used_getters.extend(getter)
#                 else:
#                     used_getters.append(getter)
#             else:
#                 # Search
#                 for key, val in self.RecipeInput.stored().items():
#                     if isinstance(val.type, rtype):
#                         if isinstance(getter, collections.Iterable):
#                             used_getters.extend(getter)
#                         else:
#                             used_getters.append(getter)
#                         break
#                 else:
#                     pass
#         return used_getters
# 
#     def init_filters_generic(self, rinput, getters, ins):
#         # with BPM, bias, dark, flat and sky
#         if numina.ext.gtc.check_gtc():
#             self.logger.debug('running in GTC environment')
#         else:
#             self.logger.debug('running outside of GTC environment')
# 
#         meta = emirdrp.processing.info.gather_info(rinput)
#         self.logger.debug('obresult info')
#         for entry in meta['obresult']:
#             self.logger.debug('frame info is %s', entry)
#         correctors = [getter(rinput, meta, ins, self.datamodel) for getter in getters]
#         flow = flowmod.SerialFlow(correctors)
#         return flow
# 
#     def init_filters(self, rinput, ins='EMIR'):
#         getters = self.get_filters()
#         return self.init_filters_generic(rinput, getters, ins)
# 
#     def aggregate_result(self, result, rinput):
#         return result
# 
# Path: emirdrp/core/utils.py
# def create_rot2d(angle):
#     """Create 2D rotation matrix"""
#     ca = math.cos(angle)
#     sa = math.sin(angle)
#     return numpy.array([[ca, -sa], [sa, ca]])
# 
# Path: emirdrp/instrument/csuconf.py
# class TargetType(enum.Enum):
#     """Possible targets in a slit"""
#     UNASSIGNED = 0
#     SOURCE = 1
#     REFERENCE = 2
#     SKY = 3
#     UNKNOWN = 4


import sys
import math
import logging
import itertools
import numpy as np
import matplotlib.pyplot as plt
import sep
import astropy.units as u
import astropy.wcs
import skimage.filters as filt
import skimage.feature as feat
import numina.types.array as tarray
import numina.core.query as qmod
import emirdrp.instrument.constants as cons
import emirdrp.requirements as reqs
import emirdrp.products as prods
import emirdrp.instrument.distortions as dist
import emirdrp.instrument.csuconf as csuconf
from scipy import ndimage as ndi
from numina.array.utils import coor_to_pix_1d
from numina.array.bbox import BoundingBox
from numina.array.offrot import fit_offset_and_rotation
from numina.array.peaks.peakdet import refine_peaks
from numina.core import Requirement, Result
from numina.types.qc import QC
from numina.core.requirements import ObservationResultRequirement
from emirdrp.core.recipe import EmirRecipe
from emirdrp.core.utils import create_rot2d
from emirdrp.processing.combine import basic_processing_, combine_images
from emirdrp.processing.combine import process_ab, process_abba
from emirdrp.instrument.csuconf import TargetType
    from matplotlib.patches import Ellipse
        from emirdrp.instrument.dtuconf import DtuConf

            y1_virt = ref_y_l_v - slit_h_virt - slit_h_tol
            y2_virt = ref_y_r_v + slit_h_virt + slit_h_tol
            _, y1 = dist.wcs_exvp(wcs, xpos1_virt + 1, y1_virt)
            _, y2 = dist.wcs_exvp(wcs, xpos2_virt + 1, y2_virt)
            # print(comp2_l, comp2_r, y1 - 1, y2 - 1)
            cbb = BoundingBox.from_coordinates(comp2_l, comp2_r, y1 - 1, y2 - 1)
            slits_bb[lbarid] = cbb
            mask1[cbb.slice] = lbarid

        self.save_intermediate_array(mask1, 'mask_slit_computed.fits')
        return slits_bb


def compute_off_rotation(data, wcsa, csu_conf, slits_bb=None, rotaxis=(0, 0),
                         logger=None, debug_plot=False,
                         intermediate_results=True
                         ):
    # We can use a dictionary of slits_bb created by measuring the slits
    # in the image or we can use the slits given by the model of the CSU
    # which is correct around ~ 1.5 pix

    if logger is None:
        logger = logging.getLogger(__name__)

    swapped_code = (sys.byteorder == 'little') and '>' or '<'
    if data.dtype.byteorder == swapped_code:
        data = data.byteswap().newbyteorder()

    logger.info('we have %s slits', len(csu_conf.slits))

# Path: emirdrp/core/recipe.py
# class EmirRecipe(recipes.BaseRecipe):
#     """Base clase for all EMIR Recipes
# 
# 
#     Attributes
#     ----------
#     logger :
#          recipe logger
# 
#     datamodel : EmirDataModel
# 
#     """
#     logger = logging.getLogger(__name__)
#     datamodel = emirdrp.datamodel.EmirDataModel()
# 
#     def types_getter(self):
#         imgtypes = [prods.MasterBadPixelMask,
#                     prods.MasterBias,
#                     prods.MasterDark,
#                     prods.MasterIntensityFlat,
#                     prods.MasterSpectralFlat,
#                     prods.MasterSky
#                     ]
#         getters = [cor.get_corrector_p, cor.get_corrector_b, cor.get_corrector_d,
#                    [cor.get_corrector_f, cor.get_checker], cor.get_corrector_sf, cor.get_corrector_s]
# 
#         return imgtypes, getters
# 
#     def get_filters(self):
#         import collections
#         imgtypes, getters = self.types_getter()
#         used_getters = []
#         for rtype, getter in zip(imgtypes, getters):
#             self.logger.debug('get_filters, %s  %s', rtype, getter)
#             if rtype is None:
#                 # Unconditional
#                 if isinstance(getter, collections.Iterable):
#                     used_getters.extend(getter)
#                 else:
#                     used_getters.append(getter)
#             else:
#                 # Search
#                 for key, val in self.RecipeInput.stored().items():
#                     if isinstance(val.type, rtype):
#                         if isinstance(getter, collections.Iterable):
#                             used_getters.extend(getter)
#                         else:
#                             used_getters.append(getter)
#                         break
#                 else:
#                     pass
#         return used_getters
# 
#     def init_filters_generic(self, rinput, getters, ins):
#         # with BPM, bias, dark, flat and sky
#         if numina.ext.gtc.check_gtc():
#             self.logger.debug('running in GTC environment')
#         else:
#             self.logger.debug('running outside of GTC environment')
# 
#         meta = emirdrp.processing.info.gather_info(rinput)
#         self.logger.debug('obresult info')
#         for entry in meta['obresult']:
#             self.logger.debug('frame info is %s', entry)
#         correctors = [getter(rinput, meta, ins, self.datamodel) for getter in getters]
#         flow = flowmod.SerialFlow(correctors)
#         return flow
# 
#     def init_filters(self, rinput, ins='EMIR'):
#         getters = self.get_filters()
#         return self.init_filters_generic(rinput, getters, ins)
# 
#     def aggregate_result(self, result, rinput):
#         return result
# 
# Path: emirdrp/core/utils.py
# def create_rot2d(angle):
#     """Create 2D rotation matrix"""
#     ca = math.cos(angle)
#     sa = math.sin(angle)
#     return numpy.array([[ca, -sa], [sa, ca]])
# 
# Path: emirdrp/instrument/csuconf.py
# class TargetType(enum.Enum):
#     """Possible targets in a slit"""
#     UNASSIGNED = 0
#     SOURCE = 1
#     REFERENCE = 2
#     SKY = 3
#     UNKNOWN = 4


# Path: emirdrp/recipes/acquisition/maskcheck.py
import sys
import math
import logging
import itertools
import numpy as np
import matplotlib.pyplot as plt
import sep
import astropy.units as u
import astropy.wcs
import skimage.filters as filt
import skimage.feature as feat
import numina.types.array as tarray
import numina.core.query as qmod
import emirdrp.instrument.constants as cons
import emirdrp.requirements as reqs
import emirdrp.products as prods
import emirdrp.instrument.distortions as dist
import emirdrp.instrument.csuconf as csuconf
from scipy import ndimage as ndi
from numina.array.utils import coor_to_pix_1d
from numina.array.bbox import BoundingBox
from numina.array.offrot import fit_offset_and_rotation
from numina.array.peaks.peakdet import refine_peaks
from numina.core import Requirement, Result
from numina.types.qc import QC
from numina.core.requirements import ObservationResultRequirement
from emirdrp.core.recipe import EmirRecipe
from emirdrp.core.utils import create_rot2d
from emirdrp.processing.combine import basic_processing_, combine_images
from emirdrp.processing.combine import process_ab, process_abba
from emirdrp.instrument.csuconf import TargetType
    from matplotlib.patches import Ellipse
        from emirdrp.instrument.dtuconf import DtuConf


            y1_virt = ref_y_l_v - slit_h_virt - slit_h_tol
            y2_virt = ref_y_r_v + slit_h_virt + slit_h_tol
            _, y1 = dist.wcs_exvp(wcs, xpos1_virt + 1, y1_virt)
            _, y2 = dist.wcs_exvp(wcs, xpos2_virt + 1, y2_virt)
            # print(comp2_l, comp2_r, y1 - 1, y2 - 1)
            cbb = BoundingBox.from_coordinates(comp2_l, comp2_r, y1 - 1, y2 - 1)
            slits_bb[lbarid] = cbb
            mask1[cbb.slice] = lbarid

        self.save_intermediate_array(mask1, 'mask_slit_computed.fits')
        return slits_bb


def compute_off_rotation(data, wcsa, csu_conf, slits_bb=None, rotaxis=(0, 0),
                         logger=None, debug_plot=False,
                         intermediate_results=True
                         ):
    # We can use a dictionary of slits_bb created by measuring the slits
    # in the image or we can use the slits given by the model of the CSU
    # which is correct around ~ 1.5 pix

    if logger is None:
        logger = logging.getLogger(__name__)

    swapped_code = (sys.byteorder == 'little') and '>' or '<'
    if data.dtype.byteorder == swapped_code:
        data = data.byteswap().newbyteorder()

    logger.info('we have %s slits', len(csu_conf.slits))

    refslits = [slit for slit in csu_conf.slits.values() if slit.target_type is TargetType.REFERENCE]