2017-09-03 11 views
3

私は、3次元の他のオブジェクトに含まれる3次元のオブジェクトの数を数えることができるメソッドを作成しようとしています。あなたは、あまりにも半径を持っているので、私は球の中のオブジェクトの数を数えようとしている値を持っているこのオブジェクトを言うことができる。x、y、z座標のセットに含まれる値の数を数えよう

私は現在のスクリプトを掲載しませんが、私は例を試してみます:銀河の3D座標がgal_posで、半径がgal_radです。

import numpy as np 
gal_pos = np.array(
    [[ 528.1373291 , 432.18615723, 443.8348999 ], 
    [ 540.12231445, 450.08154297, 442.07891846], 
    [ 590.73675537, 234.6769104 , 296.02798462], 
    [ 529.98809814, 161.75544739, 567.58203125], 
    [ 552.45446777, 312.1973877 , 375.42492676], 
    [ 700.94335938, 65.46828461, 172.71842957], 
    [ 463.43258667, 73.57706451, 285.4147644 ], 
    [ 547.74414062, 330.9855957 , 401.49771118], 
    [ 591.89801025, 196.19670105, 274.60073853], 
    [ 581.28320312, 376.70013428, 359.81851196], 
    [ 520.09820557, 302.17849731, 371.68771362], 
    [ 812.84539795, 97.41672516, 150.87428284], 
    [ 541.6552124 , 17.40070724, 373.07562256], 
    [ 523.34509277, 302.18151855, 503.6333313 ]]) 

gal_rad = np.array(
    [ 1.14752779, 1.02471195, 0.79648002, 0.6085083 , 0.78725676, 
    1.07809084, 0.57744866, 0.93733404, 0.76053329, 0.68979678, 
    0.61188519, 1.07989271, 0.83872035, 0.59899661]) 

私はまた、3D位置で星を持っていますstar_pos

star_pos = np.array(
    [[ 517.0300293 , 264.54165649, 547.87835693], 
    [ 530.37280273, 358.40835571, 455.68734741], 
    [ 530.42211914, 358.20803833, 455.80908203], 
    [ 530.86737061, 324.91717529, 407.96405029], 
    [ 547.05175781, 333.9262085 , 403.82403564], 
    [ 530.61053467, 325.91259766, 407.04153442], 
    [ 533.9979248 , 331.18804932, 451.3795166 ], 
    [ 531.20678711, 326.75308228, 406.44711304], 
    [ 550.81237793, 340.88101196, 408.75830078], 
    [ 519.52880859, 299.91259766, 516.25140381], 
    [ 525.82739258, 301.46209717, 501.66738892], 
    [ 524.87988281, 268.88357544, 510.], 
    [ 524.43371582, 299.99725342, 512.36077881], 
    [ 524.40429688, 299.8979187 , 512.57452393], 
    [ 524.40765381, 299.89120483, 512.5032959 ], 
    [ 545.57440186, 331.59066772, 401.20291138], 
    [ 532.29016113, 306.27557373, 491.26434326], 
    [ 530.77410889, 326.18057251, 407.06216431], 
    [ 524.14819336, 306.60586548, 509.55993652]]) 

以上は、私が持っている値のほんの一例です。

xmax_rad = gal_pos[:,0]+gal_rad 
xmin_rad = gal_pos[:,0]-gal_rad 

ymax_rad = gal_pos[:,1]+gal_rad 
ymin_rad = gal_pos[:,1]-gal_rad 

zmax_rad = gal_pos[:,2]+gal_rad 
zmin_rad = gal_pos[:,2]-gal_rad 

tot_pop = [] # Total population found each galaxy 

Nind = [(x,y,z) for x,y,z in enumerate(star_pos) 
     if any(xmin_rad <=x<= xmax_rad) and 
     any(ymin_rad<=y<=ymax_rad) 
     and any(zmin_rad<=x<=zmax_rad)] 
tot_pop.append(Nind) 

print tot_pop 

私がしようとしています。この方法では、すべてを破壊することにより、私にはほとんど意味がありますが、これはサイズ〜300の配列のために使用されているが、戻りNindためValueError: need more than 2 values to unpackです。私の繰り返しは3つのオブジェクトをアンパックできないという事実のためでしょうか?

私は位置のそれぞれの大きさを取る他の方法を試しましたが、ヒストグラムで値を数えて間違った結果を返しますが、再び不正な結果を返します(2dヒストグラム)。

tot_pop = [] 
for k in np.arange(len(gal_pos)): 
    Nind = [(x,y) for x,y in enumerate(star_pos) 
     if xmin_rad[k] <=x<= xmax_rad[k]) and 
     ymin_rad[k]<=y<=ymax_rad[k]] 

    tot_pop.append(Nind) 
+0

関連する入力の形状は何ですか? – Divakar

+0

@MSeifert @Divakarこんにちは、申し訳ありませんが、私はそれらを含めるべきでした。私の分析(128,3)の 'star_pos'の形は、実際にはNumPyの配列です。同様に 'gal_pos'は形状(14,3)であり、NumPy配列でもあります。私は私のポストにいくつかの値を瞬間的に含めるつもりです! – DarthLazar

答えて

3

あなたは銀河+半径を反復して、マッチを見つけるために、放送とブールインデックスを使用するようにzipを使用することができます:

result = [] 
for galaxy, galaxy_radius in zip(gal_pos, gal_rad): 
    # With broadcasting you can simply subtract the positions from the galaxy center 
    # and using abs avoids checking lower and upper bound. 
    rel_star_pos = abs(star_pos - galaxy) 
    # Check which distances are below the radius and keep these which are 
    # within the radius for x, y and z 
    matches = (rel_star_pos <= galaxy_radius).all(axis=1) 
    # use boolean indexing to append the stars which satisfy the above condition 
    result.append(star_pos[matches]) 
print(result) 
各銀河のためのインデックスiは、それぞれの銀河にnullの配列を返します。この方法あなたはインデックスを追加したい場合は

(実際の星の座標ではない)あなたがappendラインを変更することができます。

result.append(np.where(matches)[0]) 

それとも、あなたの場合私は与えられたデータと一致するものを見つけることができませんでししかし

result.append(np.sum(matches)) 

[array([], shape=(0, 3), dtype=float64), 
array([], shape=(0, 3), dtype=float64), 
array([], shape=(0, 3), dtype=float64), 
array([], shape=(0, 3), dtype=float64), 
array([], shape=(0, 3), dtype=float64), 
array([], shape=(0, 3), dtype=float64), 
array([], shape=(0, 3), dtype=float64), 
array([], shape=(0, 3), dtype=float64), 
array([], shape=(0, 3), dtype=float64), 
array([], shape=(0, 3), dtype=float64), 
array([], shape=(0, 3), dtype=float64), 
array([], shape=(0, 3), dtype=float64), 
array([], shape=(0, 3), dtype=float64), 
array([], shape=(0, 3), dtype=float64)] 
+0

私が与えた値は結果をもたらさなかったが、私が持っていた他の100の値は数回現れた!どうもありがとうございました。 – DarthLazar

3

ここに1つの、ほとんどのベクトル化のアプローチは、効率的なNumPy broadcastingslicingの使用が同様に手助けすることだ一致の数をしたいです -

# Define low and high limits 
l = gal_pos - gal_rad[:,None] 
h = gal_pos + gal_rad[:,None] 

# Get mask of valid ones for each row of star_pos 
mask = np.ones(star_pos.shape[0], dtype=bool) 
for i in range(star_pos.shape[1]): 
    mask &= ((l[:,i,None] <= star_pos[:,i]) & (h[:,i,None] >= star_pos[:,i])).any(0) 

# Finally use the mask to select valid rows off star_pos 
out = star_pos[mask] 

我々はまだstar_posの列数を反復処理しているため、ほぼベクトル化、それを呼び出します。しかし、X,Y,Zデータを処理しているので、3となります。そのため、ほぼベクトル化されていると呼ぶのは安全です。

In [302]: out 
Out[302]: array([], shape=(0, 3), dtype=float64) 

だから、 star_posからのポイントは制限を満たしていない - 与えられたサンプルについては

は、ここで私は何を得るのです。

+0

hm、面白いです。私は 'any'と' | 'で少し苦労しています。私はそれが正しいとは思わない。私はそれが3つのすべての座標の "範囲"内にあるべきだと思った。 – MSeifert

+0

@MSeifert私は 'any(xmin_rad <= x <= xmax_rad)'が私を混乱させたと思います。一定。 – Divakar

+0

今はるかに良い:)私は、メモリを使い切るのが簡単すぎるため、**このような問題のために**完全にベクトル化されたソリューションではありません。データセットがかなりの大きさであればRAMが多いコンピュータ。この場合、それは長さ約300の配列なので、ここでは問題ありません。+1: – MSeifert

関連する問題