def __init__(self, name, shape, polarization=None): # Check that we can call the shape (i.e., it is a function) assert hasattr(shape, '__call__'), "The shape must be callable (i.e., behave like a function)" self._spectral_shape = shape # Store the polarization if polarization is None: self._polarization = Polarization() else: self._polarization = polarization # Add shape and polarization as children Node.__init__(self, name) try: self._add_children([self._spectral_shape, self._polarization]) except TypeError: raise TypeError("Couldn't instance the spectral component. Please verify that you are using an " "*instance* of a function, and not a class. For example, you need to use " "'%s()', and not '%s'." % (shape.__name__, shape.__name__))
def __init__(self, polarization_type='linear'): assert polarization_type in ['linear', 'stokes' ], 'polarization must be linear or stokes' self._polarization_type = polarization_type Node.__init__(self, 'polarization')
def __init__(self, ra=None, dec=None, l=None, b=None, equinox='J2000'): """ :param ra: Right Ascension in degrees :param dec: Declination in degrees :param l: Galactic latitude in degrees :param b: Galactic longitude in degrees :param equinox: string :return: """ self._equinox = equinox # Create the node Node.__init__(self, 'position') # Check that we have the right pairs of coordinates if ra is not None and dec is not None: # This goes against duck typing, but it is needed to provide a means of initiating this class # with either Parameter instances or just floats # Try to transform it to float, if it works than we transform it to a parameter ra = self._get_parameter_from_input(ra, 0, 360, 'ra', 'Right Ascension') dec = self._get_parameter_from_input(dec, -90, 90, 'dec', 'Declination') self._coord_type = 'equatorial' self._add_child(ra) self._add_child(dec) elif l is not None and b is not None: # This goes against duck typing, but it is needed to provide a means of initiating this class # with either Parameter instances or just floats # Try to transform it to float, if it works than we transform it to a parameter l = self._get_parameter_from_input(l, 0, 360, 'l', 'Galactic longitude') b = self._get_parameter_from_input(b, -90, 90, 'b', 'Galactic latitude') self._coord_type = 'galactic' self._add_child(l) self._add_child(b) else: raise WrongCoordinatePair( "You have to specify either (ra, dec) or (l, b).")
def test_constructor(): n = Node(name='node1') assert n.name == 'node1' with pytest.raises(TypeError): n2 = Node() clean()
def test_get_child_from_path(): # Make a small tree node1 = Node('node1') node2 = Node('node2') node3 = Node('node3') node1._add_child(node2) node2._add_child(node3) assert node1._get_child_from_path("node2.node3") == node3 clean()
def test_add_child(): t = _SimpleInheritance('test_add_child') with pytest.raises(TypeError): t._add_child("clara") clara = Node("clara") clara_ref_count = node_ctype._get_reference_counts(clara) t._add_child(clara) # We expect 2 more references: one for the map, one for the vector assert node_ctype._get_reference_counts(clara) == clara_ref_count + 1 assert t.clara == clara with pytest.raises(AttributeError): t.clara = 'argh' assert t.clara == clara clean()
def test_get_path(): # Make a small tree node1 = Node('node1') node2 = Node('node2') node3 = Node('node3') node1._add_child(node2) node2._add_child(node3) print node3.path assert node3.path == "node1.node2.node3" clean()
def test_pickle(): print("\n\n\n\n") import pickle root = Node("root") node = Node("node") root._add_child(node) d = pickle.dumps(root) root2 = pickle.loads(d) assert root2.node.path == 'root.node' assert root2.node.name == 'node' # Now test pickling a subclass of Node root = _SimpleInheritance("root") root._placeholder = 5.3 node = _SimpleInheritance("node") root._add_child(node) d = pickle.dumps(root) root2 = pickle.loads(d) assert root2.node.path == 'root.node' assert root2.node.name == 'node' print root.placeholder assert root2.placeholder == root.placeholder rootc = _ComplexInheritance("root", -1.0, 1.0) nodec = _ComplexInheritance("node", -5.0, 5.0) rootc._add_child(nodec) d = pickle.dumps(rootc) root2c = pickle.loads(d) print root2c.min_value clean()
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_get_child(): t = _SimpleInheritance("test") n = Node("node") t._add_child(n) assert t._get_child("node") == n with pytest.raises(AttributeError): t._get_child("not existing") clean()
def test_remove_child(): t = _SimpleInheritance("test") n = Node("node") for i in range(1000): t._add_child(n) assert t._get_child("node") == n t._remove_child("node") with pytest.raises(AttributeError): print t.node with pytest.raises(AttributeError): t._get_child("node") clean()
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_add_children(): t = _SimpleInheritance("children") t._add_children([Node("node1"), Node("node2")]) clean()
def __init__(self, name, value, min_value=None, max_value=None, desc=None, unit=u.dimensionless_unscaled, transformation=None): # Make this a node Node.__init__(self, name) # Make a static name which will never change (not even after a _change_name call) self._static_name = str(name) # Callbacks are executed any time the value for the parameter changes (i.e., its value changes) # We start from a empty list of callbacks. self._callbacks = [] # Assign to members # Store the units as an astropy.units.Unit instance self._unit = u.Unit(unit) # A ParameterBase instance cannot have auxiliary variables self._aux_variable = {} # Set min and max to None first so that the .value setter will work, # we will override them later if needed self._external_min_value = None self._external_max_value = None # Store the transformation. This allows to disentangle the value of the parameter which the user interact # width with the value of the parameter the fitting engine (or the Bayesian sampler) interact with self._transformation = transformation # Let's store the init value # If the value is a Quantity, deal with that if isinstance(value, u.Quantity): # If the user did not specify an ad-hoc unit, use the unit # of the Quantity if self._unit == u.dimensionless_unscaled: self._unit = value.unit # Convert the value to the provided unit (if necessary) self.value = value.to(self._unit).value else: self.value = value # Set minimum if provided, otherwise use default # (use the property so the checks that are there are performed also on construction) self.min_value = min_value # Set maximum if provided, otherwise use default # this will be overwritten immediately in the next line self.max_value = max_value # Store description self._desc = desc # Make the description the documentation as well self.__doc__ = desc # Now perform a very lazy check that we can perform math operations on value, minimum and maximum # (i.e., they are numbers) if not _behaves_like_a_number(self.value): raise TypeError("The provided initial value is not a number")
def test_memory_leaks_destructors(): print("\n\n\n\n\n") for i in range(1000): print("\n\nRound %i" % (i + 1)) # Test destructors root = Node("root") node1 = Node("node1") node2 = Node("node2") node3 = Node("node3") refc_before_link_root = node_ctype._get_reference_counts(root) refc_before_link1 = node_ctype._get_reference_counts(node1) refc_before_link2 = node_ctype._get_reference_counts(node2) refc_before_link3 = node_ctype._get_reference_counts(node3) # root._add_children([node1, node2, node3]) # node1 +1, node2 + 1, node3 + 1, root +3 root._add_child(node1) root._add_child(node2) root._add_child(node3) assert node_ctype._get_reference_counts( root) == refc_before_link_root + 3 assert node_ctype._get_reference_counts(node1) == refc_before_link1 + 1 assert node_ctype._get_reference_counts(node2) == refc_before_link2 + 1 assert node_ctype._get_reference_counts(node3) == refc_before_link3 + 1 # # Let's destroy the tree root._remove_child("node1") root._remove_child("node2") root._remove_child("node3")
def test_memory_leaks_getters(): # Now test the getters root = Node("root") node1 = Node("node1") node2 = Node("node2") node3 = Node("node3") refc_before_link_root = node_ctype._get_reference_counts(root) refc_before_link1 = node_ctype._get_reference_counts(node1) refc_before_link2 = node_ctype._get_reference_counts(node2) refc_before_link3 = node_ctype._get_reference_counts(node3) None_counts_before = node_ctype._get_reference_counts(None) # Add 3 nodes to root root._add_children([node1, node2, node3]) # node1 +1, node2 +1, node3 + 1, root +3 node_again = root._get_child("node1") # node1 +1 assert node_ctype._get_reference_counts(node1) == refc_before_link1 + 2 del node_again # node1 -1 assert node_ctype._get_reference_counts(node1) == refc_before_link1 + 1 children = root._get_children() #node1 +1, node2 +1, node3 +1 assert len(children) == 3 assert node_ctype._get_reference_counts(node1) == refc_before_link1 + 2 assert node_ctype._get_reference_counts(node2) == refc_before_link2 + 2 assert node_ctype._get_reference_counts(node3) == refc_before_link3 + 2 assert node_ctype._get_reference_counts(root) == refc_before_link_root + 3 # test get_parent root_again = node1._get_parent() # root +1 assert node_ctype._get_reference_counts(root) == refc_before_link_root + 4 del root_again # root -1 assert node_ctype._get_reference_counts(root) == refc_before_link_root + 3 # test _get_path path = node2._get_path() # this shouldn't change any ref count assert node_ctype._get_reference_counts(node1) == refc_before_link1 + 2 assert node_ctype._get_reference_counts(node2) == refc_before_link2 + 2 assert node_ctype._get_reference_counts(node3) == refc_before_link3 + 2 assert node_ctype._get_reference_counts(root) == refc_before_link_root + 3 # test _get_child_from_path node4 = Node("node4") refc_before_link4 = node_ctype._get_reference_counts(node4) node3._add_child(node4) # node3 +1, node4 + 1 node4_again = root._get_child_from_path("node3.node4") # node4 +1 assert node_ctype._get_reference_counts(node4) == refc_before_link4 + 2 assert node_ctype._get_reference_counts(node3) == refc_before_link3 + 3 del node4_again # node4 -1 assert node_ctype._get_reference_counts(node4) == refc_before_link4 + 1
def test_memory_leaks_setters(): root = Node("root") node = Node("node") refc_before_link = node_ctype._get_reference_counts(node) root._add_child(node) # Adding a node adds 1 reference assert node_ctype._get_reference_counts(node) == refc_before_link + 1 # Remove the node and verify that the reference counts goes back to what it was root._remove_child("node") # Now we should go back to the original assert node_ctype._get_reference_counts(node) == refc_before_link # Now add a second node nested under the first one (root.node.node2) node2 = Node("node2") refc_before_link2 = node_ctype._get_reference_counts(node2) root._add_child(node) # +1 for node assert node_ctype._get_reference_counts(node) == refc_before_link + 1 node._add_child(node2) # +1 for node2 and +1 for node assert node_ctype._get_reference_counts(node2) == refc_before_link2 + 1 # "node" is now also parent of node2, so its reference are now 2 more than the original assert node_ctype._get_reference_counts(node) == refc_before_link + 2 # Clean up and verify that we go back to the original number of references node._remove_child("node2") # -1 for node2, -1 for node assert node_ctype._get_reference_counts(node2) == refc_before_link2 assert node_ctype._get_reference_counts(node) == refc_before_link + 1 root._remove_child("node") # -1 for node assert node_ctype._get_reference_counts(node) == refc_before_link # Now test add_children node3 = Node("node3") node4 = Node("node4") refc_before_link3 = node_ctype._get_reference_counts(node3) refc_before_link4 = node_ctype._get_reference_counts(node4) root._add_children([node3, node4]) # +1 for both nodes assert node_ctype._get_reference_counts(node3) == refc_before_link3 + 1 assert node_ctype._get_reference_counts(node3) == refc_before_link4 + 1
def __init__(self): Node.__init__(self, 'polarization')
def test_get_children(): node1 = Node('node1') node2 = Node('node2') node22 = Node('node22') node3 = Node('node3') node1._add_child(node2) node1._add_child(node22) node2._add_child(node3) assert node1._get_children() == (node2, node22) assert node2._get_children() == (node3, ) clean()