def assign_orientation(self, **kwargs): r""" """ if 'table' in kwargs.keys(): table = kwargs['table'] N = len(table) else: N = kwargs['size'] # assign random orientations major_v = random_unit_vectors_3d(N) inter_v = random_perpendicular_directions(major_v) minor_v = normalized_vectors(np.cross(major_v, inter_v)) if 'table' in kwargs.keys(): try: mask = (table['gal_type'] == self.gal_type) except KeyError: mask = np.array([True] * N) msg = ( "Because `gal_type` not indicated in `table`.", "The orientation is being assigned for all galaxies in the `table`." ) print(msg) # check to see if the columns exist for key in list(self._galprop_dtypes_to_allocate.names): if key not in table.keys(): table[key] = 0.0 table['galaxy_axisA_x'][mask] = major_v[mask, 0] table['galaxy_axisA_y'][mask] = major_v[mask, 1] table['galaxy_axisA_z'][mask] = major_v[mask, 2] table['galaxy_axisB_x'][mask] = inter_v[mask, 0] table['galaxy_axisB_y'][mask] = inter_v[mask, 1] table['galaxy_axisB_z'][mask] = inter_v[mask, 2] table['galaxy_axisC_x'][mask] = minor_v[mask, 0] table['galaxy_axisC_y'][mask] = minor_v[mask, 1] table['galaxy_axisC_z'][mask] = minor_v[mask, 2] return table else: return major_v, inter_v, minor_v
def mc_unit_sphere(self, Npts, **kwargs): r""" Returns Npts anisotropically distributed points on the unit sphere. Parameters ---------- Npts : int Number of 3d points to generate seed : int, optional Random number seed used in the Monte Carlo realization. Default is None, which will produce stochastic results. Returns ------- x, y, z : array_like Length-Npts arrays of the coordinate positions. """ seed = kwargs.get('seed', None) if 'table' in kwargs: table = kwargs['table'] try: b_to_a = table['halo_b_to_a'] except KeyError: b_to_a = 1.0 try: c_to_a = table['halo_c_to_a'] except KeyError: c_to_a = 1.0 try: halo_axisA_x = table['halo_axisA_x'] halo_axisA_y = table['halo_axisA_y'] halo_axisA_z = table['halo_axisA_z'] except KeyError: with NumpyRNGContext(seed): v = random_unit_vectors_3d(len(table)) halo_axisA_x = v[:, 0] halo_axisA_y = v[:, 1] halo_axisA_z = v[:, 2] try: halo_axisC_x = table['halo_axisC_x'] halo_axisC_y = table['halo_axisC_y'] halo_axisC_z = table['halo_axisC_z'] except KeyError: with NumpyRNGContext(seed): v = random_unit_vectors_3d(len(table)) halo_axisC_x = v[:, 0] halo_axisC_y = v[:, 1] halo_axisC_z = v[:, 2] else: try: b_to_a = np.atleast_1d(kwargs['b_to_a']) except KeyError: b_to_a = 1.0 try: c_to_a = np.atleast_1d(kwargs['c_to_a']) except KeyError: c_to_a = 1.0 try: halo_axisA_x = np.atleast_1d(kwargs['halo_axisA_x']) halo_axisA_y = np.atleast_1d(kwargs['halo_axisA_y']) halo_axisA_z = np.atleast_1d(kwargs['halo_axisA_z']) except KeyError: with NumpyRNGContext(seed): v = random_unit_vectors_3d(1) halo_axisC_x = v[:, 0] halo_axisC_y = v[:, 1] halo_axisC_z = v[:, 2] try: halo_axisC_x = np.atleast_1d(kwargs['halo_axisC_x']) halo_axisC_y = np.atleast_1d(kwargs['halo_axisC_y']) halo_axisC_z = np.atleast_1d(kwargs['halo_axisC_z']) except KeyError: with NumpyRNGContext(seed): v = random_unit_vectors_3d(len(halo_axisA_x)) halo_axisC_x = v[:, 0] halo_axisC_y = v[:, 1] halo_axisC_z = v[:, 2] v1 = np.vstack((halo_axisA_x, halo_axisA_y, halo_axisA_z)).T v3 = np.vstack((halo_axisC_x, halo_axisC_y, halo_axisC_z)).T v2 = np.cross(v1, v3) with NumpyRNGContext(seed): phi = np.random.uniform(0, 2 * np.pi, Npts) uran = np.random.rand(Npts) * 2 - 1 cos_t = uran sin_t = np.sqrt((1. - cos_t * cos_t)) b_to_a, c_to_a = self.anisotropy_bias_response(b_to_a, c_to_a) c_to_b = c_to_a / b_to_a # temporarily use x-axis as the major axis x = 1.0 / c_to_a * sin_t * np.cos(phi) y = 1.0 / c_to_b * sin_t * np.sin(phi) z = cos_t x_correlated_axes = np.vstack((x, y, z)).T x_axes = np.tile((1, 0, 0), Npts).reshape((Npts, 3)) major_axes = v1 matrices = rotation_matrices_from_basis(v1, v2, v3) # rotate x-axis into the major axis #angles = angles_between_list_of_vectors(x_axes, major_axes) #rotation_axes = vectors_normal_to_planes(x_axes, major_axes) #matrices = rotation_matrices_from_angles(angles, rotation_axes) correlated_axes = rotate_vector_collection(matrices, x_correlated_axes) #correlated_axes = x_correlated_axes return correlated_axes[:, 0], correlated_axes[:, 1], correlated_axes[:, 2]
def assign_satellite_orientation(self, **kwargs): r""" assign a a set of three orthoganl unit vectors indicating the orientation of the galaxies' major, intermediate, and minor axis Returns ======= major_aixs, intermediate_axis, minor_axis : numpy nd.arrays arrays of galaxies' axies """ if 'table' in kwargs.keys(): table = kwargs['table'] try: Lbox = kwargs['Lbox'] except KeyError: Lbox = self._Lbox else: try: Lbox = kwargs['Lbox'] except KeyError: Lbox = self._Lbox # calculate the radial vector between satellites and centrals major_input_vectors, r = self.get_radial_vector(Lbox=Lbox, **kwargs) # check for length 0 radial vectors mask = (r <= 0.0) | (~np.isfinite(r)) if np.sum(mask) > 0: major_input_vectors[mask, 0] = np.random.random((np.sum(mask))) major_input_vectors[mask, 1] = np.random.random((np.sum(mask))) major_input_vectors[mask, 2] = np.random.random((np.sum(mask))) msg = ( '{0} galaxies have a radial distance equal to zero (or infinity) from their host. ' 'These galaxies will be re-assigned random alignment vectors.'. format(int(np.sum(mask)))) warn(msg) # set prim_gal_axis orientation theta_ma = self.misalignment_rvs(size=N) # rotate alignment vector by theta_ma ran_vecs = random_unit_vectors_3d(N) mrot = rotation_matrices_from_angles(theta_ma, ran_vecs) A_v = rotate_vector_collection(rotm, major_input_vectors) # check for nan vectors mask = (~np.isfinite(np.sum(np.prod(A_v, axis=-1)))) if np.sum(mask) > 0: A_v[mask, 0] = np.random.random((np.sum(mask))) A_v[mask, 1] = np.random.random((np.sum(mask))) A_v[mask, 2] = np.random.random((np.sum(mask))) msg = ( '{0} correlated alignment axis(axes) were not found to be not finite. ' 'These will be re-assigned random vectors.'.format( int(np.sum(mask)))) warn(msg) # randomly set secondary axis orientation B_v = random_perpendicular_directions(A_v) # the tertiary axis is determined C_v = vectors_normal_to_planes(A_v, B_v) # use galaxy major axis as orientation axis major_v = A_v inter_v = B_v minor_v = C_v if 'table' in kwargs.keys(): try: mask = (table['gal_type'] == self.gal_type) except KeyError: mask = np.array([True] * len(table)) msg = ( "`gal_type` not indicated in `table`.", "The orientation is being assigned for all galaxies in the `table`." ) print(msg) # check to see if the columns exist for key in list(self._galprop_dtypes_to_allocate.names): if key not in table.keys(): table[key] = 0.0 # add orientations to the galaxy table table['galaxy_axisA_x'][mask] = major_v[mask, 0] table['galaxy_axisA_y'][mask] = major_v[mask, 1] table['galaxy_axisA_z'][mask] = major_v[mask, 2] table['galaxy_axisB_x'][mask] = inter_v[mask, 0] table['galaxy_axisB_y'][mask] = inter_v[mask, 1] table['galaxy_axisB_z'][mask] = inter_v[mask, 2] table['galaxy_axisC_x'][mask] = minor_v[mask, 0] table['galaxy_axisC_y'][mask] = minor_v[mask, 1] table['galaxy_axisC_z'][mask] = minor_v[mask, 2] return table else: return major_v, inter_v, minor_v
def assign_central_orientation(self, **kwargs): r""" Assign a set of three orthoganl unit vectors indicating the orientation of the galaxies' major, intermediate, and minor axis Parameters ========== halo_axisA_x, halo_axisA_y, halo_axisA_z : array_like x,y,z components of halo alignment axis Returns ======= major_aixs, intermediate_axis, minor_axis : numpy nd.arrays arrays of galaxies' axes """ if 'table' in kwargs.keys(): table = kwargs['table'] Ax = table[self.list_of_haloprops_needed[0]] Ay = table[self.list_of_haloprops_needed[1]] Az = table[self.list_of_haloprops_needed[2]] else: Ax = kwargs[self.list_of_haloprops_needed[0]] Ay = kwargs[self.list_of_haloprops_needed[1]] Az = kwargs[self.list_of_haloprops_needed[2]] # number of haloes N = len(Ax) # set prim_gal_axis orientation major_input_vectors = np.vstack((Ax, Ay, Az)).T theta_ma = self.misalignment_rvs(size=N) # rotate alignment vector by theta_ma ran_vecs = random_unit_vectors_3d(N) mrot = rotation_matrices_from_angles(theta_ma, ran_vecs) A_v = rotate_vector_collection(rotm, major_input_vectors) # randomly set secondary axis orientation B_v = random_perpendicular_directions(A_v) # the tertiary axis is determined C_v = vectors_normal_to_planes(A_v, B_v) # depending on the prim_gal_axis, assign correlated axes if self.prim_gal_axis == 'A': major_v = A_v inter_v = B_v minor_v = C_v elif self.prim_gal_axis == 'B': major_v = B_v inter_v = A_v minor_v = C_v elif self.prim_gal_axis == 'C': major_v = B_v inter_v = C_v minor_v = A_v else: msg = ('primary galaxy axis {0} is not recognized.'.format( self.prim_gal_axis)) raise ValueError(msg) if 'table' in kwargs.keys(): try: mask = (table['gal_type'] == self.gal_type) except KeyError: mask = np.array([True] * len(table)) msg = ( "Because `gal_type` not indicated in `table`.", "The orientation is being assigned for all galaxies in the `table`." ) print(msg) # check to see if the columns exist for key in list(self._galprop_dtypes_to_allocate.names): if key not in table.keys(): table[key] = 0.0 # add orientations to the galaxy table table['galaxy_axisA_x'][mask] = major_v[mask, 0] table['galaxy_axisA_y'][mask] = major_v[mask, 1] table['galaxy_axisA_z'][mask] = major_v[mask, 2] table['galaxy_axisB_x'][mask] = inter_v[mask, 0] table['galaxy_axisB_y'][mask] = inter_v[mask, 1] table['galaxy_axisB_z'][mask] = inter_v[mask, 2] table['galaxy_axisC_x'][mask] = minor_v[mask, 0] table['galaxy_axisC_y'][mask] = minor_v[mask, 1] table['galaxy_axisC_z'][mask] = minor_v[mask, 2] return table else: return major_v, inter_v, minor_v
def assign_satellite_orientation(self, **kwargs): r""" assign a a set of three orthoganl unit vectors indicating the orientation of the galaxies' major, intermediate, and minor axis Returns ------- major_aixs, intermediate_axis, minor_axis : numpy nd.arrays arrays of galaxies' axies """ if 'table' in kwargs.keys(): table = kwargs['table'] try: Lbox = kwargs['Lbox'] except KeyError: Lbox = self._Lbox else: try: Lbox = kwargs['Lbox'] except KeyError: Lbox = self._Lbox # calculate the radial vector between satellites and centrals major_input_vectors, r = self.get_radial_vector(Lbox=Lbox, **kwargs) # check for length 0 radial vectors mask = (r <= 0.0) | (~np.isfinite(r)) N_bad_axes = np.sum(mask) if N_bad_axes > 0: major_input_vectors[mask, :] = random_unit_vectors_3d(N_bad_axes) msg = ( '{0} galaxies have a radial distance equal to zero (or infinity) from their host. ' 'These galaxies will be re-assigned random alignment vectors.'. format(int(N_bad_axes))) warn(msg) # get alignment strength for each galaxy if 'table' in kwargs.keys(): try: p = table['satellite_alignment_strength'] except KeyError: msg = ( '`satellite_alignment_strength` key not detected in `table`.' 'The value set in self.param_dict of this class will be used instead.' ) warn(msg) p = np.ones(len( table)) * self.param_dict['satellite_alignment_strength'] else: N = len(self.param_dict['x']) p = np.ones(N * self.param_dict['satellite_alignment_strength']) # set prim_gal_axis orientation A_v = axes_correlated_with_input_vector(major_input_vectors, p=p) # check for nan vectors mask = (~np.isfinite(np.sum(np.prod(A_v, axis=-1)))) N_bad_axes = np.sum(mask) if N_bad_axes > 0: A_v[mask, :] = random_unit_vectors_3d(N_bad_axes) msg = ( '{0} correlated alignment axis(axes) were found to be not finite. ' 'These will be re-assigned random vectors.'.format( int(N_bad_axes))) warn(msg) # randomly set secondary axis orientation B_v = random_perpendicular_directions(A_v) # the tertiary axis is determined C_v = vectors_normal_to_planes(A_v, B_v) # depending on the prim_gal_axis, assign correlated axes if self.prim_gal_axis == 'A': major_v = A_v inter_v = B_v minor_v = C_v elif self.prim_gal_axis == 'B': major_v = B_v inter_v = A_v minor_v = C_v elif self.prim_gal_axis == 'C': major_v = B_v inter_v = C_v minor_v = A_v if 'table' in kwargs.keys(): try: mask = (table['gal_type'] == self.gal_type) except KeyError: mask = np.array([True] * len(table)) msg = ( "`gal_type` not indicated in `table`.", "The orientation is being assigned for all galaxies in the `table`." ) print(msg) # check to see if the columns exist for key in list(self._galprop_dtypes_to_allocate.names): if key not in table.keys(): table[key] = 0.0 # add orientations to the galaxy table table['galaxy_axisA_x'][mask] = major_v[mask, 0] table['galaxy_axisA_y'][mask] = major_v[mask, 1] table['galaxy_axisA_z'][mask] = major_v[mask, 2] table['galaxy_axisB_x'][mask] = inter_v[mask, 0] table['galaxy_axisB_y'][mask] = inter_v[mask, 1] table['galaxy_axisB_z'][mask] = inter_v[mask, 2] table['galaxy_axisC_x'][mask] = minor_v[mask, 0] table['galaxy_axisC_y'][mask] = minor_v[mask, 1] table['galaxy_axisC_z'][mask] = minor_v[mask, 2] return table else: return major_v, inter_v, minor_v