# Path: sedfitter/utils/validator.py
# def validate_scalar(name, value, domain=None, physical_type=None):
# 
#     validate_physical_type(name, value, physical_type)
# 
#     if not physical_type:
#         if np.isscalar(value) or not np.isreal(value):
#             raise TypeError("{0} should be a scalar floating point value".format(name))
# 
#     if domain == 'positive':
#         if value < 0.:
#             raise ValueError("{0} should be positive".format(name))
#     elif domain == 'strictly-positive':
#         if value <= 0.:
#             raise ValueError("{0} should be strictly positive".format(name))
#     elif domain == 'negative':
#         if value > 0.:
#             raise ValueError("{0} should be negative".format(name))
#     elif domain == 'strictly-negative':
#         if value >= 0.:
#             raise ValueError("{0} should be strictly negative".format(name))
#     elif type(domain) in [tuple, list] and len(domain) == 2:
#         if value < domain[0] or value > domain[-1]:
#             raise ValueError("{0} should be in the range [{1}:{2}]".format(name, domain[0], domain[-1]))
# 
#     return value
# 
# def validate_array(name, value, domain=None, ndim=1, shape=None, physical_type=None):
# 
#     validate_physical_type(name, value, physical_type)
# 
#     # First convert to a Numpy array:
#     if type(value) in [list, tuple]:
#         value = np.array(value)
# 
#     # Check the value is an array with the right number of dimensions
#     if not isinstance(value, np.ndarray) or value.ndim != ndim:
#         if ndim == 1:
#             raise TypeError("{0} should be a 1-d sequence".format(name))
#         else:
#             raise TypeError("{0} should be a {1:d}-d array".format(name, ndim))
# 
#     # Check that the shape matches that expected
#     if shape is not None and value.shape != shape:
#         if ndim == 1:
#             raise ValueError("{0} has incorrect length (expected {1} but found {2})".format(name, shape[0], value.shape[0]))
#         else:
#             # On Windows, shapes can contain long integers, so we fix this to
#             # have consistent error messages across platforms.
#             expected_shape = tuple(int(x) for x in shape)
#             actual_shape = tuple(int(x) for x in value.shape)
#             raise ValueError("{0} has incorrect shape (expected {1} but found {2})".format(name, expected_shape, actual_shape))
# 
#     return value
# 
# Path: sedfitter/sed/helpers.py
# def parse_unit_safe(unit_string):
#     if unit_string in UNIT_MAPPING:
#         return UNIT_MAPPING[unit_string]
#     else:
#         return u.Unit(unit_string, parse_strict=False)
# 
# def table_to_hdu(table):
#     hdu = fits.BinTableHDU(np.array(table))
#     for i in range(len(table.columns)):
#         if table.columns[i].unit is not None:
#             hdu.columns[i].unit = table.columns[i].unit.to_string(format='fits')
#     return hdu
# 
# def assert_allclose_quantity(q1, q2):
#     if q1 is None and q2 is None:
#         return True
#     if q1 is None or q2 is None:
#         raise AssertionError()
#     else:
#         np.testing.assert_allclose(q1.value, q2.to(q1.unit).value)


import abc
import numpy as np
import six
from astropy import units as u
from astropy.io import fits
from astropy.table import Table
from ..utils.validator import validate_scalar, validate_array
from .helpers import parse_unit_safe, table_to_hdu, assert_allclose_quantity
        from .sed import SED

        # Create empty first HDU and add distance
        hdu0 = fits.PrimaryHDU(data=self.valid.astype(int))
        hdu0.header['distance'] = (self.distance.to(u.cm).value, 'Distance assumed for the values, in cm')
        hdu0.header['NWAV'] = (self.n_wav, "Number of wavelengths")
        if self.apertures is not None:
            hdu0.header['NAP'] = (self.n_ap, "Number of apertures")
        for key in meta:
            hdu0.header[key] = meta[key]
        hdulist.append(hdu0)

        # Create names table
        t1 = Table()
        t1['MODEL_NAME'] = np.array(self.names, 'S')
        hdu1 = table_to_hdu(t1)
        hdu1.name = "MODEL_NAMES"
        hdulist.append(hdu1)

        # Create wavelength table
        t2 = Table()
        t2['WAVELENGTH'] = self.wav
        t2['FREQUENCY'] = self.nu
        hdu2 = table_to_hdu(t2)
        hdu2.name = "SPECTRAL_INFO"
        hdulist.append(hdu2)

        # Create aperture table
        if self.apertures is not None:
            t3 = Table()
            t3['APERTURE'] = self.apertures

# Path: sedfitter/utils/validator.py
# def validate_scalar(name, value, domain=None, physical_type=None):
# 
#     validate_physical_type(name, value, physical_type)
# 
#     if not physical_type:
#         if np.isscalar(value) or not np.isreal(value):
#             raise TypeError("{0} should be a scalar floating point value".format(name))
# 
#     if domain == 'positive':
#         if value < 0.:
#             raise ValueError("{0} should be positive".format(name))
#     elif domain == 'strictly-positive':
#         if value <= 0.:
#             raise ValueError("{0} should be strictly positive".format(name))
#     elif domain == 'negative':
#         if value > 0.:
#             raise ValueError("{0} should be negative".format(name))
#     elif domain == 'strictly-negative':
#         if value >= 0.:
#             raise ValueError("{0} should be strictly negative".format(name))
#     elif type(domain) in [tuple, list] and len(domain) == 2:
#         if value < domain[0] or value > domain[-1]:
#             raise ValueError("{0} should be in the range [{1}:{2}]".format(name, domain[0], domain[-1]))
# 
#     return value
# 
# def validate_array(name, value, domain=None, ndim=1, shape=None, physical_type=None):
# 
#     validate_physical_type(name, value, physical_type)
# 
#     # First convert to a Numpy array:
#     if type(value) in [list, tuple]:
#         value = np.array(value)
# 
#     # Check the value is an array with the right number of dimensions
#     if not isinstance(value, np.ndarray) or value.ndim != ndim:
#         if ndim == 1:
#             raise TypeError("{0} should be a 1-d sequence".format(name))
#         else:
#             raise TypeError("{0} should be a {1:d}-d array".format(name, ndim))
# 
#     # Check that the shape matches that expected
#     if shape is not None and value.shape != shape:
#         if ndim == 1:
#             raise ValueError("{0} has incorrect length (expected {1} but found {2})".format(name, shape[0], value.shape[0]))
#         else:
#             # On Windows, shapes can contain long integers, so we fix this to
#             # have consistent error messages across platforms.
#             expected_shape = tuple(int(x) for x in shape)
#             actual_shape = tuple(int(x) for x in value.shape)
#             raise ValueError("{0} has incorrect shape (expected {1} but found {2})".format(name, expected_shape, actual_shape))
# 
#     return value
# 
# Path: sedfitter/sed/helpers.py
# def parse_unit_safe(unit_string):
#     if unit_string in UNIT_MAPPING:
#         return UNIT_MAPPING[unit_string]
#     else:
#         return u.Unit(unit_string, parse_strict=False)
# 
# def table_to_hdu(table):
#     hdu = fits.BinTableHDU(np.array(table))
#     for i in range(len(table.columns)):
#         if table.columns[i].unit is not None:
#             hdu.columns[i].unit = table.columns[i].unit.to_string(format='fits')
#     return hdu
# 
# def assert_allclose_quantity(q1, q2):
#     if q1 is None and q2 is None:
#         return True
#     if q1 is None or q2 is None:
#         raise AssertionError()
#     else:
#         np.testing.assert_allclose(q1.value, q2.to(q1.unit).value)


# Path: sedfitter/sed/cube.py
import abc
import numpy as np
import six
from astropy import units as u
from astropy.io import fits
from astropy.table import Table
from ..utils.validator import validate_scalar, validate_array
from .helpers import parse_unit_safe, table_to_hdu, assert_allclose_quantity
        from .sed import SED


        # Create empty first HDU and add distance
        hdu0 = fits.PrimaryHDU(data=self.valid.astype(int))
        hdu0.header['distance'] = (self.distance.to(u.cm).value, 'Distance assumed for the values, in cm')
        hdu0.header['NWAV'] = (self.n_wav, "Number of wavelengths")
        if self.apertures is not None:
            hdu0.header['NAP'] = (self.n_ap, "Number of apertures")
        for key in meta:
            hdu0.header[key] = meta[key]
        hdulist.append(hdu0)

        # Create names table
        t1 = Table()
        t1['MODEL_NAME'] = np.array(self.names, 'S')
        hdu1 = table_to_hdu(t1)
        hdu1.name = "MODEL_NAMES"
        hdulist.append(hdu1)

        # Create wavelength table
        t2 = Table()
        t2['WAVELENGTH'] = self.wav
        t2['FREQUENCY'] = self.nu
        hdu2 = table_to_hdu(t2)
        hdu2.name = "SPECTRAL_INFO"
        hdulist.append(hdu2)

        # Create aperture table
        if self.apertures is not None:
            t3 = Table()
            t3['APERTURE'] = self.apertures

            hdu3 = table_to_hdu(t3)