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(list(self._components.values())) self._add_child(spectrum_node) type(self).__call__ = type(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 = old_div(1, current_units.energy) # Now set the units of the components for component in list(self._components.values()): component.shape.set_units(x_unit, y_unit)
def test_call(): # Multi-component po1 = Powerlaw() po2 = Powerlaw() c1 = SpectralComponent("component1", po1) c2 = SpectralComponent("component2", po2) point_source = PointSource("test_source", 125.4, -22.3, components=[c1, c2]) assert np.all(point_source.spectrum.component1([1, 2, 3]) == po1([1, 2, 3])) assert np.all(point_source.spectrum.component2([1, 2, 3]) == po2([1, 2, 3])) one = point_source.spectrum.component1([1, 2, 3]) two = point_source.spectrum.component2([1, 2, 3]) assert np.all( np.abs(one + two - point_source([1,2,3])) == 0 )
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: str, ra: Optional[float] = None, dec: Optional[float] = None, spectral_shape: Optional[Function1D] = None, l: Optional[float] = None, b: Optional[float] = None, components=None, sky_position: Optional[SkyDirection] = 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 if not ((ra is not None and dec is not None) ^ (l is not None and b is not None) ^ (sky_position is not None)): log.error( "You have to provide one and only one specification for the position" ) raise AssertionError() # 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): log.error( "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." ) raise AssertionError() sky_position = SkyDirection(ra=ra, dec=dec) else: sky_position = SkyDirection(l=l, b=b) self._sky_position: SkyDirection = sky_position # Now gather the component(s) # We need either a single component, or a list of components, but not both # (that's the ^ symbol) if not (spectral_shape is not None) ^ (components is not None): log.error( "You have to provide either a single component, or a list of components (but not both)." ) raise AssertionError() # 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, src_type=SourceType.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(list(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 list(self._components.values()): component.shape.set_units(x_unit, y_unit)
def test_constructor(): # RA, Dec and L,B of the same point in the sky ra, dec = (125.6, -75.3) l, b = (288.44190139183564, -20.717313145391525) # This should throw as we are using Powerlaw instead of Powerlaw() with pytest.raises(TypeError): _ = PointSource("my_source", ra, dec, Powerlaw) # Init with RA, Dec point_source1 = PointSource('my_source',ra, dec, Powerlaw()) assert point_source1.position.get_ra() == ra assert point_source1.position.get_dec() == dec assert abs(point_source1.position.get_l() - l) < 1e-7 assert abs(point_source1.position.get_b() - b) < 1e-7 assert point_source1.position.ra.value == ra assert point_source1.position.dec.value == dec # Verify that the position is fixed by default assert point_source1.position.ra.fix assert point_source1.position.dec.fix # Init with l,b point_source2 = PointSource('my_source', l=l, b=b, spectral_shape=Powerlaw()) assert point_source2.position.get_l() == l assert point_source2.position.get_b() == b assert abs(point_source2.position.get_ra() - ra) < 1e-7 assert abs(point_source2.position.get_dec() - dec) < 1e-7 assert point_source2.position.l.value == l assert point_source2.position.b.value == b # Verify that the position is fixed by default assert point_source2.position.l.fix assert point_source2.position.b.fix # Multi-component po1 = Powerlaw() po2 = Powerlaw() c1 = SpectralComponent("component1", po1) c2 = SpectralComponent("component2", po2) point_source3 = PointSource("test_source", ra, dec, components=[c1, c2]) assert np.all(point_source3.spectrum.component1([1,2,3]) == po1([1,2,3])) assert np.all(point_source3.spectrum.component2([1,2,3]) == po2([1,2,3])) with pytest.raises(AssertionError): # Illegal RA _ = PointSource("test",720.0, -15.0, components=[c1,c2]) with pytest.raises(AssertionError): # Illegal Dec _ = PointSource("test", 120.0, 180.0, components=[c1, c2]) with pytest.raises(AssertionError): # Illegal l _ = PointSource("test", l=-195, b=-15.0, components=[c1, c2]) with pytest.raises(AssertionError): # Illegal b _ = PointSource("test", l=120.0, b=-180.0, components=[c1, c2])
def test_call(): # Multi-component po1 = Powerlaw() po2 = Powerlaw() c1 = SpectralComponent("component1", po1) c2 = SpectralComponent("component2", po2) ra, dec = (125.6, -75.3) def test_one(class_type, name): print("testing %s ..." % name) shape = class_type() source = ExtendedSource('test_source_%s' % name, shape, components=[c1, c2]) if name != "SpatialTemplate_2D": shape.lon0 = ra * u.degree shape.lat0 = dec * u.degree else: make_test_template(ra, dec, "__test.fits") shape.load_file("__test.fits") shape.K = 1.0 assert np.all(source.spectrum.component1([1, 2, 3]) == po1([1, 2, 3])) assert np.all(source.spectrum.component2([1, 2, 3]) == po2([1, 2, 3])) one = source.spectrum.component1([1, 2, 3]) two = source.spectrum.component2([1, 2, 3]) #check spectral components assert np.all( np.abs(one + two - source.get_spatially_integrated_flux([1, 2, 3])) == 0) #check spectral and spatial components total = source([ra, ra, ra], [dec, dec, dec], [1, 2, 3]) spectrum = one + two spatial = source.spatial_shape([ra, ra, ra], [dec, dec, dec]) assert np.all(np.abs(total - spectrum * spatial) == 0) total = source([ra * 1.01] * 3, [dec * 1.01] * 3, [1, 2, 3]) spectrum = one + two spatial = source.spatial_shape([ra * 1.01] * 3, [dec * 1.01] * 3) assert np.all(np.abs(total - spectrum * spatial) == 0) for key in _known_functions: if key in ["Latitude_galactic_diffuse"]: #not testing latitude galactic diffuse for now. continue this_function = _known_functions[key] if this_function._n_dim == 2 and not this_function().is_prior: test_one(this_function, key) with pytest.raises(AssertionError): #this will fail because the Latitude_galactic_diffuse function isn't normalized. test_one(_known_functions["Latitude_galactic_diffuse"], "Latitude_galactic_diffuse")