如何以 pythonic 方式在大球体中洗牌小球体?

How to shuffle tiny spheres inside a big sphere in a pythonic way?

我有一个具有一些已知特征(ids、半径、质量和位置)的球体列表,其中 idsradiimasses1D arrays with shape (511, ) and positions being 3D array with shape (511, 3) inside some big spherical volume with known center, (0, 0, 0) and radius, distance_max.

hal_ids_data = np.array([19895, 19896, ..., 24249])                   
hal_radiuss_data = np.array([1.047, 1.078, ..., 3.263])                 
hal_masss_data = np.array([2.427e+06, 8.268e+06, ..., 8.954e+07]     
hal_positions_data = np.array([np.array([-33.78, 10.4, 33.83]), np.array([-33.61, 6.34, 35.64]), ..., np.array([-0.4014, 4.121, 33.05])])

我想将这些小球体随机放置在大球体的整个体积内,同时保持它们各自的特征完好无损,这意味着只需要调整它们的位置受下面所示的两个约束.

for hal_id, hal_position, hal_radius, hal_mass in zip(hal_ids_data, hal_positions_data, hal_radiuss_data, hal_masss_data):

    # check if 1) any one of the small spheres are above some mass threshold AND 2) inside the big sphere
    if ((np.sqrt(pow(hal_position[0], 2)+pow(hal_position[1], 2)+pow(hal_position[2], 2)) < distance_max) and (log10(hal_mass)>=1e8)):

        # if so, then do the following stuff down here but to the shuffled populations of small spheres meeting the conditions above rather than to the original population

在对球体做一些事情之前,将我的球体洗牌到最后一个if statement下的最快和最短的方法是什么? (虽然我确实需要我的原始人口信息以备后用,所以我不能忽视它)

最好的方法是以向量化格式(这在 numpy 中非常有效)而不是使用 for 循环来计算约束。然后生成一个与您的约束相匹配的索引数组,然后将这些索引打乱。

所以使用上面的示例数据:

import numpy as np

distance_max = 49 #I chose this so that we have some matching items

hal_ids_data = np.array([19895, 19896, 24249])                   
hal_radius_data = np.array([1.047, 1.078, 3.263])                 
hal_mass_data = np.array([2.427e+06, 8.268e+06, 8.954e+07])     
hal_positions_data = np.array([np.array([-33.78, 10.4, 33.83]), np.array([-33.61, 6.34, 35.64]), np.array([-0.4014, 4.121, 33.05])])

# Compute the conditions for every sphere at the same time instead of for loop
within_max = np.sqrt(pow(hal_positions_data[:,0],2) + pow(hal_positions_data[:,1],2) + pow(hal_positions_data[:,2],2)) < distance_max
mass_contraint = np.log10(hal_mass_data) >= 1 #I chose this so that we have some matching items
matched_spheres = within_max & mass_contraint

# Get indexes of matching spheres
idx = np.where(matched_spheres)[0] # create array of indexes
np.random.shuffle(idx) #shuffle array of indexes in place

# Generate shuffled data by applying the idx to the original arrays and saving to new 's_' arrays
s_hal_ids_data = hal_ids_data[idx]
s_hal_radius_data = hal_radius_data[idx]
s_hal_mass_data = hal_mass_data[idx]
s_hal_positions_data = hal_positions_data[idx]

# Do stuff with shuffled population of small spheres