files: # Licensed under a 3-clause BSD style license - see LICENSE.rst
  import logging
  import numpy as np
  import astropy.units as u
  from astropy.io import fits
  from astropy.nddata.utils import NoOverlapError
  from astropy.table import Table
  from astropy.utils import lazyproperty
  from regions import CircleSkyRegion
  from gammapy.cube.edisp_map import EDispMap
  from gammapy.cube.psf_kernel import PSFKernel
  from gammapy.cube.psf_map import PSFMap
  from gammapy.data import GTI
  from gammapy.irf import EDispKernel, EffectiveAreaTable
  from gammapy.maps import Map, MapAxis
  from gammapy.modeling import Dataset, Parameters
  from gammapy.modeling.models import BackgroundModel, SkyModel, SkyModels
  from gammapy.modeling.parameter import _get_parameters_str
  from gammapy.spectrum import SpectrumDataset, SpectrumDatasetOnOff
  from gammapy.stats import cash, cash_sum_cython, wstat
  from gammapy.utils.random import get_random_state
  from gammapy.utils.scripts import make_name, make_path
  from .exposure import _map_spectrum_weight
  
  __all__ = ["MapDataset", "MapDatasetOnOff"]
  
  log = logging.getLogger(__name__)
  
  CUTOUT_MARGIN = 0.1 * u.deg
  RAD_MAX = 0.66
  RAD_AXIS_DEFAULT = MapAxis.from_bounds(
      0, RAD_MAX, nbin=66, node_type="edges", name="theta", unit="deg"
  )
  MIGRA_AXIS_DEFAULT = MapAxis.from_bounds(
      0.2, 5, nbin=48, node_type="edges", name="migra"
  )
  
  BINSZ_IRF_DEFAULT = 0.2
  
  
  class MapDataset(Dataset):
      """Perform sky model likelihood fit on maps.
  
      Parameters
      ----------
      models : `~gammapy.modeling.models.SkyModels`
          Source sky models.
      counts : `~gammapy.maps.WcsNDMap`
          Counts cube
      exposure : `~gammapy.maps
  
  [... the rest is omitted ...]
files: gammapy/cube/fit.py
files: # Licensed under a 3-clause BSD style license - see LICENSE.rst
  import logging
  import numpy as np
  import astropy.units as u
  from astropy.io import fits
  from astropy.nddata.utils import NoOverlapError
  from astropy.table import Table
  from astropy.utils import lazyproperty
  from regions import CircleSkyRegion
  from gammapy.cube.edisp_map import EDispMap
  from gammapy.cube.psf_kernel import PSFKernel
  from gammapy.cube.psf_map import PSFMap
  from gammapy.data import GTI
  from gammapy.irf import EffectiveAreaTable, EDispKernel
  from gammapy.maps import Map, MapAxis
  from gammapy.modeling import Dataset, Parameters
  from gammapy.modeling.models import BackgroundModel, SkyModel, SkyModels
  from gammapy.modeling.parameter import _get_parameters_str
  from gammapy.spectrum import SpectrumDataset, SpectrumDatasetOnOff
  from gammapy.stats import cash, cash_sum_cython, wstat
  from gammapy.utils.random import get_random_state
  from gammapy.utils.scripts import make_path
  from .exposure import _map_spectrum_weight
  
  __all__ = ["MapDataset", "MapDatasetOnOff"]
  
  log = logging.getLogger(__name__)
  
  CUTOUT_MARGIN = 0.1 * u.deg
  RAD_MAX = 0.66
  RAD_AXIS_DEFAULT = MapAxis.from_bounds(
      0, RAD_MAX, nbin=66, node_type="edges", name="theta", unit="deg"
  )
  MIGRA_AXIS_DEFAULT = MapAxis.from_bounds(
      0.2, 5, nbin=48, node_type="edges", name="migra"
  )
  
  BINSZ_IRF_DEFAULT = 0.2
  
  
  class MapDataset(Dataset):
      """Perform sky model likelihood fit on maps.
  
      Parameters
      ----------
      models : `~gammapy.modeling.models.SkyModels`
          Source sky models.
      counts : `~gammapy.maps.WcsNDMap`
          Counts cube
      exposure : `~gammapy.maps.WcsND
  
  [... the rest is omitted ...]
files: gammapy/cube/fit.py
files: # Licensed under a 3-clause BSD style license - see LICENSE.rst
  import abc
  import collections.abc
  import copy
  from warnings import warn
  import numpy as np
  from gammapy.utils.scripts import make_name, make_path, read_yaml, write_yaml
  from gammapy.utils.table import table_from_row_data
  from ..maps import WcsNDMap
  from .parameter import Parameters
  
  __all__ = ["Dataset", "Datasets"]
  
  
  class Dataset(abc.ABC):
      """Dataset abstract base class.
  
      TODO: add tutorial how to create your own dataset types.
  
      For now, see existing examples in Gammapy how this works:
  
      - `gammapy.cube.MapDataset`
      - `gammapy.spectrum.SpectrumDataset`
      - `gammapy.spectrum.FluxPointsDataset`
      """
  
      _residuals_labels = {
          "diff": "data - model",
          "diff/model": "(data - model) / model",
          "diff/sqrt(model)": "(data - model) / sqrt(model)",
      }
  
      @property
      def mask(self):
          """Combined fit and safe mask"""
          mask_safe = (
              self.mask_safe.data
              if isinstance(self.mask_safe, WcsNDMap)
              else self.mask_safe
          )
          mask_fit = (
              self.mask_fit.data if isinstance(self.mask_fit, WcsNDMap) else self.mask_fit
          )
          if mask_safe is not None and mask_fit is not None:
              mask = mask_safe & mask_fit
          elif mask_fit is not None:
              mask = mask_fit
          elif mask_safe is not None:
              mask = mask_safe
          else:
              mask = None
          return mask
  
      def stat_sum(self):
          """Total statistic given the current model parameters."""
          stat = self.stat_array()
  
          if self.mask is not None:
              stat = stat[self.mask]
  
          return np.sum(stat, dtype=np.float64)
  
      @abc.abstractmethod
      def stat_array(self):
          """Statistic array, one value per data point."""
  
      def copy(self, name=None):
          """A deep copy."""
          new = copy.deepcopy(self)
  
  
  [... the rest is omitted ...]
files: gammapy/modeling/datasets.py
files: # Licensed under a 3-clause BSD style license - see LICENSE.rst
  import abc
  import collections.abc
  import copy
  import numpy as np
  from gammapy.utils.scripts import make_path, read_yaml, write_yaml
  from gammapy.utils.table import table_from_row_data
  from ..maps import WcsNDMap
  from .parameter import Parameters
  
  __all__ = ["Dataset", "Datasets"]
  
  
  class Dataset(abc.ABC):
      """Dataset abstract base class.
  
      TODO: add tutorial how to create your own dataset types.
  
      For now, see existing examples in Gammapy how this works:
  
      - `gammapy.cube.MapDataset`
      - `gammapy.spectrum.SpectrumDataset`
      - `gammapy.spectrum.FluxPointsDataset`
      """
  
      _residuals_labels = {
          "diff": "data - model",
          "diff/model": "(data - model) / model",
          "diff/sqrt(model)": "(data - model) / sqrt(model)",
      }
  
      @property
      def mask(self):
          """Combined fit and safe mask"""
          mask_safe = (
              self.mask_safe.data
              if isinstance(self.mask_safe, WcsNDMap)
              else self.mask_safe
          )
          mask_fit = (
              self.mask_fit.data if isinstance(self.mask_fit, WcsNDMap) else self.mask_fit
          )
          if mask_safe is not None and mask_fit is not None:
              mask = mask_safe & mask_fit
          elif mask_fit is not None:
              mask = mask_fit
          elif mask_safe is not None:
              mask = mask_safe
          else:
              mask = None
          return mask
  
      def stat_sum(self):
          """Total statistic given the current model parameters."""
          stat = self.stat_array()
  
          if self.mask is not None:
              stat = stat[self.mask]
  
          return np.sum(stat, dtype=np.float64)
  
      @abc.abstractmethod
      def stat_array(self):
          """Statistic array, one value per data point."""
  
      def copy(self):
          """A deep copy."""
          return copy.deepcopy(self)
  
      @staticmethod
      def _compute_residuals(data
  
  [... the rest is omitted ...]
files: gammapy/modeling/datasets.py
files: # Licensed under a 3-clause BSD style license - see LICENSE.rst
  import copy
  import astropy.units as u
  from gammapy.utils.scripts import make_name
  from .parameter import Parameter, Parameters
  
  __all__ = ["Model"]
  
  
  class Model:
      """Model base class."""
  
      def __init__(self, **kwargs):
          # Copy default parameters from the class to the instance
          self._parameters = self.__class__.default_parameters.copy()
          for parameter in self._parameters:
              if parameter.name in self.__dict__:
                  raise ValueError(
                      f"Invalid parameter name: {parameter.name!r}."
                      f"Attribute exists already: {getattr(self, parameter.name)!r}"
                  )
  
              setattr(self, parameter.name, parameter)
  
          # Update parameter information from kwargs
          for name, value in kwargs.items():
              if name not in self.parameters.names:
                  raise ValueError(
                      f"Invalid argument: {name!r}. Parameter names are: {self.parameters.names}"
                  )
  
              self._parameters[name].quantity = u.Quantity(value)
  
      def __init_subclass__(cls, **kwargs):
          # Add parameters list on the model sub-class (not instances)
          cls.default_parameters = Parameters(
              [_ for _ in cls.__dict__.values() if isinstance(_, Parameter)]
          )
  
      def _init_from_parameters(self, parameters):
          """Create model from list of parameters.
  
          This should be called for models that generate
          the parameters dynamically in ``__init__``,
          like the ``NaimaSpectralModel``
          """
          # TODO: should we pass through `Parameters` here? Why?
          parameters = Parameters(parameters)
          self._parameters = parameters
          for parameter in parameters:
              setattr(self, parameter.name, parameter)
  
      @property
      def parameters(self):
          """Parameters (`~gammapy.modeling.Parameters`)"""
          return self._parameters
  
      def copy(self, name=None):
          """A deep copy."""
          new = copy.deepcopy(self)
          if name is None:
              new.name = make_name()
          else:
              new.name = name
          return new
  
      def __str__(self):
          return f"{self.__class__.__name__}\n\n{self.parameters.to_table()}"
  
      def to_dict(self
  
  [... the rest is omitted ...]
files: gammapy/modeling/model.py
files: # Licensed under a 3-clause BSD style license - see LICENSE.rst
  import copy
  import astropy.units as u
  from .parameter import Parameter, Parameters
  
  __all__ = ["Model"]
  
  
  class Model:
      """Model base class."""
  
      def __init__(self, **kwargs):
          # Copy default parameters from the class to the instance
          self._parameters = self.__class__.default_parameters.copy()
          for parameter in self._parameters:
              if parameter.name in self.__dict__:
                  raise ValueError(
                      f"Invalid parameter name: {parameter.name!r}."
                      f"Attribute exists already: {getattr(self, parameter.name)!r}"
                  )
  
              setattr(self, parameter.name, parameter)
  
          # Update parameter information from kwargs
          for name, value in kwargs.items():
              if name not in self.parameters.names:
                  raise ValueError(
                      f"Invalid argument: {name!r}. Parameter names are: {self.parameters.names}"
                  )
  
              self._parameters[name].quantity = u.Quantity(value)
  
      def __init_subclass__(cls, **kwargs):
          # Add parameters list on the model sub-class (not instances)
          cls.default_parameters = Parameters(
              [_ for _ in cls.__dict__.values() if isinstance(_, Parameter)]
          )
  
      def _init_from_parameters(self, parameters):
          """Create model from list of parameters.
  
          This should be called for models that generate
          the parameters dynamically in ``__init__``,
          like the ``NaimaSpectralModel``
          """
          # TODO: should we pass through `Parameters` here? Why?
          parameters = Parameters(parameters)
          self._parameters = parameters
          for parameter in parameters:
              setattr(self, parameter.name, parameter)
  
      @property
      def parameters(self):
          """Parameters (`~gammapy.modeling.Parameters`)"""
          return self._parameters
  
      def copy(self):
          """A deep copy."""
          return copy.deepcopy(self)
  
      def __str__(self):
          return f"{self.__class__.__name__}\n\n{self.parameters.to_table()}"
  
      def to_dict(self):
          """Create dict for YAML serialisation"""
          return {"type": self.tag, "parameters": self.parameters.to_dict()["parameters"]}
  
      @classmethod
      def from_dict(cls
  
  [... the rest is omitted ...]
files: gammapy/modeling/model.py
files: # Licensed under a 3-clause BSD style license - see LICENSE.rst
  """Cube models (axes: lon, lat, energy)."""
  import collections.abc
  import copy
  from pathlib import Path
  from warnings import warn
  import numpy as np
  import astropy.units as u
  import yaml
  from gammapy.maps import Map
  from gammapy.modeling import Model, Parameter, Parameters
  from gammapy.utils.scripts import make_name, make_path
  
  
  class SkyModelBase(Model):
      """Sky model base class"""
  
      def __add__(self, other):
          if isinstance(other, (SkyModels, list)):
              return SkyModels([self, *other])
          elif isinstance(other, (SkyModel, SkyDiffuseCube)):
              return SkyModels([self, other])
          else:
              raise TypeError(f"Invalid type: {other!r}")
  
      def __radd__(self, model):
          return self.__add__(model)
  
      def __call__(self, lon, lat, energy):
          return self.evaluate(lon, lat, energy)
  
      def evaluate_geom(self, geom):
          coords = geom.get_coord(frame=self.frame)
          return self(coords.lon, coords.lat, coords["energy"])
  
  
  class SkyModels(collections.abc.Sequence):
      """Sky model collection.
  
      Parameters
      ----------
      skymodels : `SkyModel`, list of `SkyModel` or `SkyModels`
          Sky models
      """
  
      def __init__(self, skymodels):
          if isinstance(skymodels, SkyModels):
              models = skymodels._skymodels
          elif isinstance(skymodels, SkyModel):
              models = [skymodels]
          elif isinstance(skymodels, list):
              models = skymodels
          else:
              raise TypeError(f"Invalid type: {skymodels!r}")
  
          unique_names = []
          for model in models:
              while model.name in unique_names:
                  model.name = make_name()  # replace duplicate
                  warn("SkyModel names must be unique, auto-replaced duplicates")
              unique_names.append(model.name)
  
          self._skymodels = models
  
      @property
      def parameters(self):
          return Parameters.from_stack([_.parameters for _ in self._skymodels])
  
      @class
  
  [... the rest is omitted ...]
files: gammapy/modeling/models/cube.py
files: # Licensed under a 3-clause BSD style license - see LICENSE.rst
  """Cube models (axes: lon, lat, energy)."""
  import collections.abc
  import copy
  from pathlib import Path
  import numpy as np
  import astropy.units as u
  import yaml
  from gammapy.maps import Map
  from gammapy.modeling import Model, Parameter, Parameters
  from gammapy.utils.scripts import make_path
  
  
  class SkyModelBase(Model):
      """Sky model base class"""
  
      def __add__(self, other):
          if isinstance(other, (SkyModels, list)):
              return SkyModels([self, *other])
          elif isinstance(other, (SkyModel, SkyDiffuseCube)):
              return SkyModels([self, other])
          else:
              raise TypeError(f"Invalid type: {other!r}")
  
      def __radd__(self, model):
          return self.__add__(model)
  
      def __call__(self, lon, lat, energy):
          return self.evaluate(lon, lat, energy)
  
      def evaluate_geom(self, geom):
          coords = geom.get_coord(frame=self.frame)
          return self(coords.lon, coords.lat, coords["energy"])
  
  
  class SkyModels(collections.abc.Sequence):
      """Sky model collection.
  
      Parameters
      ----------
      skymodels : `SkyModel`, list of `SkyModel` or `SkyModels`
          Sky models
      """
  
      def __init__(self, skymodels):
          if isinstance(skymodels, SkyModels):
              models = skymodels._skymodels
          elif isinstance(skymodels, SkyModel):
              models = [skymodels]
          elif isinstance(skymodels, list):
              models = skymodels
          else:
              raise TypeError(f"Invalid type: {skymodels!r}")
  
          self._skymodels = models
  
      @property
      def parameters(self):
          return Parameters.from_stack([_.parameters for _ in self._skymodels])
  
      @classmethod
      def read(cls, filename):
          """Read from YAML file."""
          yaml_str = Path(filename).read_text()
          return cls.from_yaml(yaml_str)
  
      @classmethod
      def from_yaml(cls, yaml_str):
          """Create from YAML string
  
  [... the rest is omitted ...]
files: gammapy/modeling/models/cube.py
files: """Create example model YAML files programmatically.
  
  (some will be also written manually)
  """
  from pathlib import Path
  import numpy as np
  import astropy.units as u
  from gammapy.cube import MapDataset, MapDatasetMaker
  from gammapy.data import DataStore
  from gammapy.maps import MapAxis, WcsGeom
  from gammapy.modeling import Datasets
  from gammapy.modeling.models import (
      ExpCutoffPowerLawSpectralModel,
      GaussianSpatialModel,
      PointSpatialModel,
      PowerLawSpectralModel,
      SkyDiffuseCube,
      SkyModel,
      SkyModels,
  )
  
  DATA_PATH = Path("./")
  
  
  def make_example_2():
      spatial = GaussianSpatialModel(lon_0="0 deg", lat_0="0 deg", sigma="1 deg")
      model = SkyModel(PowerLawSpectralModel(), spatial)
      models = SkyModels([model])
      models.write(DATA_PATH / "example2.yaml")
  
  
  def make_datasets_example():
      # Define which data to use and print some information
  
      energy_axis = MapAxis.from_edges(
          np.logspace(-1.0, 1.0, 4), unit="TeV", name="energy", interp="log"
      )
      geom0 = WcsGeom.create(
          skydir=(0, 0),
          binsz=0.1,
          width=(1, 1),
          frame="galactic",
          proj="CAR",
          axes=[energy_axis],
      )
      geom1 = WcsGeom.create(
          skydir=(1, 0),
          binsz=0.1,
          width=(1, 1),
          frame="galactic",
          proj="CAR",
          axes=[energy_axis],
      )
      geoms = [geom0, geom1]
  
      sources_coords = [(0, 0), (0.9, 0.1)]
      names = ["gc", "g09"]
      models = []
  
      for idx, (lon, lat) in enumerate(sources_coords):
          spatial_model = PointSpatialModel(
              lon_0=lon * u.deg, lat_0=lat * u.deg, frame="galactic"
          )
         
  
  [... the rest is omitted ...]
files: gammapy/modeling/tests/data/make.py
files: """Create example model YAML files programmatically.
  
  (some will be also written manually)
  """
  from pathlib import Path
  import numpy as np
  import astropy.units as u
  from gammapy.cube import MapDataset, MapDatasetMaker
  from gammapy.data import DataStore
  from gammapy.maps import MapAxis, WcsGeom
  from gammapy.modeling import Datasets
  from gammapy.modeling.models import (
      ExpCutoffPowerLawSpectralModel,
      GaussianSpatialModel,
      PointSpatialModel,
      PowerLawSpectralModel,
      SkyDiffuseCube,
      SkyModel,
      SkyModels,
  )
  
  DATA_PATH = Path("./")
  
  
  def make_example_2():
      spatial = GaussianSpatialModel(lon_0="0 deg", lat_0="0 deg", sigma="1 deg")
      model = SkyModel(spatial, PowerLawSpectralModel())
      models = SkyModels([model])
      models.write(DATA_PATH / "example2.yaml")
  
  
  def make_datasets_example():
      # Define which data to use and print some information
  
      energy_axis = MapAxis.from_edges(
          np.logspace(-1.0, 1.0, 4), unit="TeV", name="energy", interp="log"
      )
      geom0 = WcsGeom.create(
          skydir=(0, 0),
          binsz=0.1,
          width=(1, 1),
          frame="galactic",
          proj="CAR",
          axes=[energy_axis],
      )
      geom1 = WcsGeom.create(
          skydir=(1, 0),
          binsz=0.1,
          width=(1, 1),
          frame="galactic",
          proj="CAR",
          axes=[energy_axis],
      )
      geoms = [geom0, geom1]
  
      sources_coords = [(0, 0), (0.9, 0.1)]
      names = ["gc", "g09"]
      models = []
  
      for idx, (lon, lat) in enumerate(sources_coords):
          spatial_model = PointSpatialModel(
              lon_0=lon * u.deg, lat_0=lat * u.deg, frame="galactic"
          )
         
  
  [... the rest is omitted ...]
files: gammapy/modeling/tests/data/make.py
files: # Licensed under a 3-clause BSD style license - see LICENSE.rst
  from pathlib import Path
  import numpy as np
  from astropy import units as u
  from astropy.io import fits
  from astropy.table import Table
  from gammapy.data import GTI
  from gammapy.irf import EDispKernel, EffectiveAreaTable, IRFStacker
  from gammapy.modeling import Dataset, Parameters
  from gammapy.modeling.models import SkyModel, SkyModels
  from gammapy.stats import cash, significance_on_off, significance, wstat
  from gammapy.utils.fits import energy_axis_to_ebounds
  from gammapy.utils.random import get_random_state
  from gammapy.utils.scripts import make_name, make_path
  from .core import CountsSpectrum, SpectrumEvaluator
  
  __all__ = [
      "SpectrumDatasetOnOff",
      "SpectrumDataset",
      "plot_spectrum_datasets_off_regions",
  ]
  
  
  class SpectrumDataset(Dataset):
      """Spectrum dataset for likelihood fitting.
  
      The spectrum dataset bundles reduced counts data, with a spectral model,
      background model and instrument response function to compute the fit-statistic
      given the current model and data.
  
      Parameters
      ----------
      models : `~gammapy.modeling.models.SkyModels`
          Fit model
      counts : `~gammapy.spectrum.CountsSpectrum`
          Counts spectrum
      livetime : `~astropy.units.Quantity`
          Livetime
      aeff : `~gammapy.irf.EffectiveAreaTable`
          Effective area
      edisp : `~gammapy.irf.EDispKernel`
          Energy dispersion
      background : `~gammapy.spectrum.CountsSpectrum`
          Background to use for the fit.
      mask_safe : `~numpy.ndarray`
          Mask defining the safe data range.
      mask_fit : `~numpy.ndarray`
          Mask to apply to the likelihood for fitting.
      name : str
          Dataset name.
      gti : `~gammapy.data.GTI`
          GTI of the observation or union of GTI if it is a stacked observation
  
      See Also
      --------
      Spectrum
  
  [... the rest is omitted ...]
files: gammapy/spectrum/dataset.py
files: # Licensed under a 3-clause BSD style license - see LICENSE.rst
  from pathlib import Path
  import numpy as np
  from astropy import units as u
  from astropy.io import fits
  from astropy.table import Table
  from gammapy.data import GTI
  from gammapy.irf import EffectiveAreaTable, EDispKernel, IRFStacker
  from gammapy.modeling import Dataset, Parameters
  from gammapy.modeling.models import SkyModel, SkyModels
  from gammapy.stats import cash, significance_on_off, significance, wstat
  from gammapy.utils.fits import energy_axis_to_ebounds
  from gammapy.utils.random import get_random_state
  from gammapy.utils.scripts import make_path
  from .core import CountsSpectrum, SpectrumEvaluator
  
  __all__ = [
      "SpectrumDatasetOnOff",
      "SpectrumDataset",
      "plot_spectrum_datasets_off_regions",
  ]
  
  
  class SpectrumDataset(Dataset):
      """Spectrum dataset for likelihood fitting.
  
      The spectrum dataset bundles reduced counts data, with a spectral model,
      background model and instrument response function to compute the fit-statistic
      given the current model and data.
  
      Parameters
      ----------
      models : `~gammapy.modeling.models.SkyModels`
          Fit model
      counts : `~gammapy.spectrum.CountsSpectrum`
          Counts spectrum
      livetime : `~astropy.units.Quantity`
          Livetime
      aeff : `~gammapy.irf.EffectiveAreaTable`
          Effective area
      edisp : `~gammapy.irf.EDispKernel`
          Energy dispersion
      background : `~gammapy.spectrum.CountsSpectrum`
          Background to use for the fit.
      mask_safe : `~numpy.ndarray`
          Mask defining the safe data range.
      mask_fit : `~numpy.ndarray`
          Mask to apply to the likelihood for fitting.
      name : str
          Dataset name.
      gti : `~gammapy.data.GTI`
          GTI of the observation or union of GTI if it is a stacked observation
  
      See Also
      --------
      SpectrumDatasetOnOff
  
  [... the rest is omitted ...]
files: gammapy/spectrum/dataset.py
files: # Licensed under a 3-clause BSD style license - see LICENSE.rst
  import logging
  import numpy as np
  from astropy import units as u
  from astropy.io.registry import IORegistryError
  from astropy.table import Table, vstack
  from gammapy.modeling import Dataset, Datasets, Fit, Parameters
  from gammapy.modeling.models import (
      PowerLawSpectralModel,
      ScaleSpectralModel,
      SkyModel,
      SkyModels,
  )
  from gammapy.utils.interpolation import interpolate_profile
  from gammapy.utils.scripts import make_name, make_path
  from gammapy.utils.table import table_from_row_data, table_standardise_units_copy
  from .dataset import SpectrumDatasetOnOff
  
  __all__ = ["FluxPoints", "FluxPointsEstimator", "FluxPointsDataset"]
  
  log = logging.getLogger(__name__)
  
  REQUIRED_COLUMNS = {
      "dnde": ["e_ref", "dnde"],
      "e2dnde": ["e_ref", "e2dnde"],
      "flux": ["e_min", "e_max", "flux"],
      "eflux": ["e_min", "e_max", "eflux"],
      # TODO: extend required columns
      "likelihood": [
          "e_min",
          "e_max",
          "e_ref",
          "ref_dnde",
          "norm",
          "norm_scan",
          "stat_scan",
      ],
  }
  
  OPTIONAL_COLUMNS = {
      "dnde": ["dnde_err", "dnde_errp", "dnde_errn", "dnde_ul", "is_ul"],
      "e2dnde": ["e2dnde_err", "e2dnde_errp", "e2dnde_errn", "e2dnde_ul", "is_ul"],
      "flux": ["flux_err", "flux_errp", "flux_errn", "flux_ul", "is_ul"],
      "eflux": ["eflux_err", "eflux_errp", "eflux_errn", "eflux_ul", "is_ul"],
  }
  
  DEFAULT_UNIT = {
      "dnde": u.Unit("cm-2 s-1 TeV-1"),
      "e2dnde": u.
  
  [... the rest is omitted ...]
files: gammapy/spectrum/flux_point.py
files: # Licensed under a 3-clause BSD style license - see LICENSE.rst
  import logging
  import numpy as np
  from astropy import units as u
  from astropy.io.registry import IORegistryError
  from astropy.table import Table, vstack
  from gammapy.modeling import Dataset, Datasets, Fit, Parameters
  from gammapy.modeling.models import (
      PowerLawSpectralModel,
      ScaleSpectralModel,
      SkyModel,
      SkyModels,
  )
  from gammapy.utils.interpolation import interpolate_profile
  from gammapy.utils.scripts import make_path
  from gammapy.utils.table import table_from_row_data, table_standardise_units_copy
  from .dataset import SpectrumDatasetOnOff
  
  __all__ = ["FluxPoints", "FluxPointsEstimator", "FluxPointsDataset"]
  
  log = logging.getLogger(__name__)
  
  REQUIRED_COLUMNS = {
      "dnde": ["e_ref", "dnde"],
      "e2dnde": ["e_ref", "e2dnde"],
      "flux": ["e_min", "e_max", "flux"],
      "eflux": ["e_min", "e_max", "eflux"],
      # TODO: extend required columns
      "likelihood": [
          "e_min",
          "e_max",
          "e_ref",
          "ref_dnde",
          "norm",
          "norm_scan",
          "stat_scan",
      ],
  }
  
  OPTIONAL_COLUMNS = {
      "dnde": ["dnde_err", "dnde_errp", "dnde_errn", "dnde_ul", "is_ul"],
      "e2dnde": ["e2dnde_err", "e2dnde_errp", "e2dnde_errn", "e2dnde_ul", "is_ul"],
      "flux": ["flux_err", "flux_errp", "flux_errn", "flux_ul", "is_ul"],
      "eflux": ["eflux_err", "eflux_errp", "eflux_errn", "eflux_ul", "is_ul"],
  }
  
  DEFAULT_UNIT = {
      "dnde": u.Unit("cm-2 s-1 TeV-1"),
      "e2dnde": u.Unit("erg
  
  [... the rest is omitted ...]
files: gammapy/spectrum/flux_point.py
files: # Licensed under a 3-clause BSD style license - see LICENSE.rst
  """Utils to create scripts and command-line tools"""
  import os.path
  from pathlib import Path
  from uuid import uuid4
  import yaml
  
  __all__ = ["read_yaml", "write_yaml", "make_path", "recursive_merge_dicts"]
  
  
  def read_yaml(filename, logger=None):
      """Read YAML file.
  
      Parameters
      ----------
      filename : `~pathlib.Path`
          Filename
      logger : `~logging.Logger`
          Logger
  
      Returns
      -------
      data : dict
          YAML file content as a dict
      """
      path = make_path(filename)
      if logger is not None:
          logger.info(f"Reading {path}")
  
      text = path.read_text()
      return yaml.safe_load(text)
  
  
  def write_yaml(dictionary, filename, logger=None, sort_keys=True):
      """Write YAML file.
  
      Parameters
      ----------
      dictionary : dict
          Python dictionary
      filename : `~pathlib.Path`
          Filename
      logger : `~logging.Logger`
          Logger
      sort_keys : bool
          Whether to sort keys.
      """
      text = yaml.safe_dump(dictionary, default_flow_style=False, sort_keys=sort_keys)
  
      path = make_path(filename)
      path.parent.mkdir(exist_ok=True)
      if logger is not None:
          logger.info(f"Writing {path}")
      path.write_text(text)
  
  
  def make_name():
      return uuid4().hex[:8]
  
  
  def make_path(path):
      """Expand environment variables on `~pathlib.Path` construction.
  
      Parameters
      ----------
      path : str, `pathlib.Path`
          path to expand
      """
      # TODO: raise error or warning if environment variables that don't resolve are used
      # e.g. "spam/$DAMN/ham" where `$DAMN` is not defined
      # Otherwise this can result in cryptic errors later on
      return Path(os.path.expandvars(path))
  
  
  def recursive_merge_dicts(a, b):
      """Recursively merge two dictionaries.
  
      Entries in b override entries in a. The built-in update function cannot be
      used for hierarchical dicts, see:
      http://stackoverflow.com/questions/
  
  [... the rest is omitted ...]
files: gammapy/utils/scripts.py
files: # Licensed under a 3-clause BSD style license - see LICENSE.rst
  """Utils to create scripts and command-line tools"""
  import os.path
  from pathlib import Path
  import yaml
  
  __all__ = ["read_yaml", "write_yaml", "make_path", "recursive_merge_dicts"]
  
  
  def read_yaml(filename, logger=None):
      """Read YAML file.
  
      Parameters
      ----------
      filename : `~pathlib.Path`
          Filename
      logger : `~logging.Logger`
          Logger
  
      Returns
      -------
      data : dict
          YAML file content as a dict
      """
      path = make_path(filename)
      if logger is not None:
          logger.info(f"Reading {path}")
  
      text = path.read_text()
      return yaml.safe_load(text)
  
  
  def write_yaml(dictionary, filename, logger=None, sort_keys=True):
      """Write YAML file.
  
      Parameters
      ----------
      dictionary : dict
          Python dictionary
      filename : `~pathlib.Path`
          Filename
      logger : `~logging.Logger`
          Logger
      sort_keys : bool
          Whether to sort keys.
      """
      text = yaml.safe_dump(dictionary, default_flow_style=False, sort_keys=sort_keys)
  
      path = make_path(filename)
      path.parent.mkdir(exist_ok=True)
      if logger is not None:
          logger.info(f"Writing {path}")
      path.write_text(text)
  
  
  def make_path(path):
      """Expand environment variables on `~pathlib.Path` construction.
  
      Parameters
      ----------
      path : str, `pathlib.Path`
          path to expand
      """
      # TODO: raise error or warning if environment variables that don't resolve are used
      # e.g. "spam/$DAMN/ham" where `$DAMN` is not defined
      # Otherwise this can result in cryptic errors later on
      return Path(os.path.expandvars(path))
  
  
  def recursive_merge_dicts(a, b):
      """Recursively merge two dictionaries.
  
      Entries in b override entries in a. The built-in update function cannot be
      used for hierarchical dicts, see:
      http://stackoverflow.com/questions/3232943/update-value-of-a-nested-dictionary-of-varying-depth/3233356
  
  [... the rest is omitted ...]
files: gammapy/utils/scripts.py