def _set_units(self, x_unit, y_unit): # This function can only be used as a spectrum, # so let's check that x_unit is a energy and y_unit is # differential flux if hasattr(x_unit, "physical_type") and x_unit.physical_type == 'energy': # Now check that y is a differential flux current_units = get_units() should_be_unitless = y_unit * (current_units.energy * current_units.time * current_units.area) if not hasattr(should_be_unitless, 'physical_type') or \ should_be_unitless.decompose().physical_type != 'dimensionless': # y is not a differential flux raise InvalidUsageForFunction( "Unit for y is not differential flux. The function synchrotron " "can only be used as a spectrum.") else: raise InvalidUsageForFunction( "Unit for x is not an energy. The function synchrotron can only be used " "as a spectrum")
def __init__(self, name, distribution_shape=None, components=None): Node.__init__(self, name) if components is None: assert distribution_shape is not None, "You have to either provied a list of components, or a " \ "distribution shape" components = [SpectralComponent("main", distribution_shape)] Source.__init__(self, components, PARTICLE_SOURCE) # Add a node called 'spectrum' spectrum_node = Node('spectrum') spectrum_node._add_children(self._components.values()) self._add_child(spectrum_node) self.__call__ = self.get_flux # Set the units # Now sets the units of the parameters for the energy domain current_units = get_units() # energy as x and particle flux as y x_unit = current_units.energy y_unit = 1 / current_units.energy # Now set the units of the components for component in self._components.values(): component.shape.set_units(x_unit, y_unit)
def evaluate(self, x, B, distance, emin, emax, need): _synch = naima.models.Synchrotron(self._particle_distribution_wrapper, B * astropy_units.Gauss, Eemin=emin * astropy_units.GeV, Eemax=emax * astropy_units.GeV, nEed=need) return _synch.flux(x * get_units().energy, distance=distance * astropy_units.kpc).value
def evaluate(self, x, B, distance, emin, emax, need): _synch = naima.models.Synchrotron( self._particle_distribution_wrapper, B * astropy_units.Gauss, Eemin=emin * astropy_units.GeV, Eemax=emax * astropy_units.GeV, nEed=need) return _synch.flux(x * get_units().energy, distance=distance * astropy_units.kpc).value
def set_particle_distribution(self, function): self._particle_distribution = function # Now set the units for the function current_units = get_units() self._particle_distribution.set_units(current_units.energy, current_units.energy ** (-1)) # Naima wants a function which accepts a quantity as x (in units of eV) and returns an astropy quantity, # so we need to create a wrapper which will remove the unit from x and add the unit to the return # value self._particle_distribution_wrapper = lambda x: function(x.value) / current_units.energy
def set_particle_distribution(self, function): self._particle_distribution = function # Now set the units for the function current_units = get_units() self._particle_distribution.set_units(current_units.energy, current_units.energy**(-1)) # Naima wants a function which accepts a quantity as x (in units of eV) and returns an astropy quantity, # so we need to create a wrapper which will remove the unit from x and add the unit to the return # value self._particle_distribution_wrapper = lambda x: function( x.value) / current_units.energy
def _set_units(self, x_unit, y_unit): # This function can only be used as a spectrum, # so let's check that x_unit is a energy and y_unit is # differential flux if hasattr(x_unit, "physical_type") and x_unit.physical_type == 'energy': # Now check that y is a differential flux current_units = get_units() should_be_unitless = y_unit * (current_units.energy * current_units.time * current_units.area) if not hasattr(should_be_unitless, 'physical_type') or \ should_be_unitless.decompose().physical_type != 'dimensionless': # y is not a differential flux raise InvalidUsageForFunction("Unit for y is not differential flux. The function synchrotron " "can only be used as a spectrum.") else: raise InvalidUsageForFunction("Unit for x is not an energy. The function synchrotron can only be used " "as a spectrum")
def __init__(self, source_name, ra=None, dec=None, spectral_shape=None, l=None, b=None, components=None, sky_position=None): # Check that we have all the required information # (the '^' operator acts as XOR on booleans) # Check that we have one and only one specification of the position assert ((ra is not None and dec is not None) ^ (l is not None and b is not None) ^ (sky_position is not None)), "You have to provide one and only one specification for the position" # Gather the position if not isinstance(sky_position, SkyDirection): if (ra is not None) and (dec is not None): # Check that ra and dec are actually numbers try: ra = float(ra) dec = float(dec) except (TypeError, ValueError): raise AssertionError("RA and Dec must be numbers. If you are confused by this message, you " "are likely using the constructor in the wrong way. Check the documentation.") sky_position = SkyDirection(ra=ra, dec=dec) else: sky_position = SkyDirection(l=l, b=b) self._sky_position = sky_position # Fix the position by default self._sky_position.fix() # Now gather the component(s) # We need either a single component, or a list of components, but not both # (that's the ^ symbol) assert (spectral_shape is not None) ^ (components is not None), "You have to provide either a single " \ "component, or a list of components " \ "(but not both)." # If the user specified only one component, make a list of one element with a default name ("main") if spectral_shape is not None: components = [SpectralComponent("main", spectral_shape)] Source.__init__(self, components, POINT_SOURCE) # A source is also a Node in the tree Node.__init__(self, source_name) # Add the position as a child node, with an explicit name self._add_child(self._sky_position) # Add a node called 'spectrum' spectrum_node = Node('spectrum') spectrum_node._add_children(self._components.values()) self._add_child(spectrum_node) # Now set the units # Now sets the units of the parameters for the energy domain current_units = get_units() # Components in this case have energy as x and differential flux as y x_unit = current_units.energy y_unit = (current_units.energy * current_units.area * current_units.time) ** (-1) # Now set the units of the components for component in self._components.values(): component.shape.set_units(x_unit, y_unit)
def __init__(self, source_name, ra=None, dec=None, spectral_shape=None, l=None, b=None, components=None, sky_position=None): # Check that we have all the required information # (the '^' operator acts as XOR on booleans) # Check that we have one and only one specification of the position assert ( (ra is not None and dec is not None) ^ (l is not None and b is not None) ^ (sky_position is not None) ), "You have to provide one and only one specification for the position" # Gather the position if not isinstance(sky_position, SkyDirection): if (ra is not None) and (dec is not None): # Check that ra and dec are actually numbers try: ra = float(ra) dec = float(dec) except (TypeError, ValueError): raise AssertionError( "RA and Dec must be numbers. If you are confused by this message, you " "are likely using the constructor in the wrong way. Check the documentation." ) sky_position = SkyDirection(ra=ra, dec=dec) else: sky_position = SkyDirection(l=l, b=b) self._sky_position = sky_position # Fix the position by default self._sky_position.fix() # Now gather the component(s) # We need either a single component, or a list of components, but not both # (that's the ^ symbol) assert (spectral_shape is not None) ^ (components is not None), "You have to provide either a single " \ "component, or a list of components " \ "(but not both)." # If the user specified only one component, make a list of one element with a default name ("main") if spectral_shape is not None: components = [SpectralComponent("main", spectral_shape)] Source.__init__(self, components, POINT_SOURCE) # A source is also a Node in the tree Node.__init__(self, source_name) # Add the position as a child node, with an explicit name self._add_child(self._sky_position) # Add a node called 'spectrum' spectrum_node = Node('spectrum') spectrum_node._add_children(self._components.values()) self._add_child(spectrum_node) # Now set the units # Now sets the units of the parameters for the energy domain current_units = get_units() # Components in this case have energy as x and differential flux as y x_unit = current_units.energy y_unit = (current_units.energy * current_units.area * current_units.time)**(-1) # Now set the units of the components for component in self._components.values(): component.shape.set_units(x_unit, y_unit)
def __init__(self, source_name, spatial_shape, spectral_shape=None, components=None): # Check that we have all the required information # and set the units current_u = get_units() if spatial_shape.n_dim == 2: # Now gather the component(s) # We need either a single component, or a list of components, but not both # (that's the ^ symbol) assert (spectral_shape is not None) ^ (components is not None), "You have to provide either a single " \ "component, or a list of components " \ "(but not both)." # If the user specified only one component, make a list of one element with a default name ("main") if spectral_shape is not None: components = [SpectralComponent("main", spectral_shape)] # Components in this case have energy as x and differential flux as y diff_flux_units = (current_u.energy * current_u.area * current_u.time) ** (-1) # Now set the units of the components for component in components: component.shape.set_units(current_u.energy, diff_flux_units) # Set the units of the brightness spatial_shape.set_units(current_u.angle, current_u.angle, current_u.angle**(-2)) elif spatial_shape.n_dim == 3: # If there is no spectral component then assume that the input is a template, which will provide the # spectrum by itself. We just use a renormalization (a bias) if spectral_shape is None and components is None: # This is a template. Add a component which is just a renormalization spectral_shape = Constant() components = [SpectralComponent("main", spectral_shape)] # set the units diff_flux_units = (current_u.energy * current_u.area * current_u.time * current_u.angle**2) ** (-1) spatial_shape.set_units(current_u.angle, current_u.angle, current_u.energy, diff_flux_units) else: # the spectral shape has been given, so this is a case where the spatial template gives an # energy-dependent shape and the spectral components give the spectrum assert (spectral_shape is not None) ^ (components is not None), "You can provide either a single " \ "component, or a list of components " \ "(but not both)." if spectral_shape is not None: components = [SpectralComponent("main", spectral_shape)] # Assign units diff_flux_units = (current_u.energy * current_u.area * current_u.time) ** (-1) # Now set the units of the components for component in components: component.shape.set_units(current_u.energy, diff_flux_units) # Set the unit of the spatial template spatial_shape.set_units(current_u.angle, current_u.angle, current_u.energy, current_u.angle**(-2)) else: raise RuntimeError("The spatial shape must have either 2 or 3 dimensions.") # Here we have a list of components Source.__init__(self, components, EXTENDED_SOURCE) # A source is also a Node in the tree Node.__init__(self, source_name) # Add the spatial shape as a child node, with an explicit name self._spatial_shape = spatial_shape self._add_child(self._spatial_shape) # Add the same node also with the name of the function #self._add_child(self._shape, self._shape.__name__) # Add a node called 'spectrum' spectrum_node = Node('spectrum') spectrum_node._add_children(self._components.values()) self._add_child(spectrum_node)
def __init__(self, source_name, spatial_shape, spectral_shape=None, components=None): # Check that we have all the required information # and set the units current_u = get_units() if spatial_shape.n_dim == 2: # Now gather the component(s) # We need either a single component, or a list of components, but not both # (that's the ^ symbol) assert (spectral_shape is not None) ^ (components is not None), "You have to provide either a single " \ "component, or a list of components " \ "(but not both)." # If the user specified only one component, make a list of one element with a default name ("main") if spectral_shape is not None: components = [SpectralComponent("main", spectral_shape)] # Components in this case have energy as x and differential flux as y diff_flux_units = (current_u.energy * current_u.area * current_u.time)**(-1) # Now set the units of the components for component in components: component.shape.set_units(current_u.energy, diff_flux_units) # Set the units of the brightness spatial_shape.set_units(current_u.angle, current_u.angle, current_u.angle**(-2)) elif spatial_shape.n_dim == 3: # If there is no spectral component then assume that the input is a template, which will provide the # spectrum by itself. We just use a renormalization (a bias) if spectral_shape is None and components is None: # This is a template. Add a component which is just a renormalization spectral_shape = Constant() components = [SpectralComponent("main", spectral_shape)] # set the units diff_flux_units = (current_u.energy * current_u.area * current_u.time * current_u.angle**2)**(-1) spatial_shape.set_units(current_u.angle, current_u.angle, current_u.energy, diff_flux_units) else: # the spectral shape has been given, so this is a case where the spatial template gives an # energy-dependent shape and the spectral components give the spectrum assert (spectral_shape is not None) ^ (components is not None), "You can provide either a single " \ "component, or a list of components " \ "(but not both)." if spectral_shape is not None: components = [SpectralComponent("main", spectral_shape)] # Assign units diff_flux_units = (current_u.energy * current_u.area * current_u.time)**(-1) # Now set the units of the components for component in components: component.shape.set_units(current_u.energy, diff_flux_units) # Set the unit of the spatial template spatial_shape.set_units(current_u.angle, current_u.angle, current_u.energy, current_u.angle**(-2)) else: raise RuntimeError( "The spatial shape must have either 2 or 3 dimensions.") # Here we have a list of components Source.__init__(self, components, EXTENDED_SOURCE) # A source is also a Node in the tree Node.__init__(self, source_name) # Add the spatial shape as a child node, with an explicit name self._spatial_shape = spatial_shape self._add_child(self._spatial_shape) # Add the same node also with the name of the function #self._add_child(self._shape, self._shape.__name__) # Add a node called 'spectrum' spectrum_node = Node('spectrum') spectrum_node._add_children(self._components.values()) self._add_child(spectrum_node)