test_kdtree.py 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361
  1. # Copyright Anne M. Archibald 2008
  2. # Released under the scipy license
  3. from __future__ import division, print_function, absolute_import
  4. from numpy.testing import (assert_equal, assert_array_equal, assert_,
  5. assert_almost_equal, assert_array_almost_equal)
  6. from pytest import raises as assert_raises
  7. import pytest
  8. from platform import python_implementation
  9. import numpy as np
  10. from scipy.spatial import KDTree, Rectangle, distance_matrix, cKDTree
  11. from scipy.spatial.ckdtree import cKDTreeNode
  12. from scipy.spatial import minkowski_distance
  13. import itertools
  14. def distance_box(a, b, p, boxsize):
  15. diff = a - b
  16. diff[diff > 0.5 * boxsize] -= boxsize
  17. diff[diff < -0.5 * boxsize] += boxsize
  18. d = minkowski_distance(diff, 0, p)
  19. return d
  20. class ConsistencyTests:
  21. def distance(self, a, b, p):
  22. return minkowski_distance(a, b, p)
  23. def test_nearest(self):
  24. x = self.x
  25. d, i = self.kdtree.query(x, 1)
  26. assert_almost_equal(d**2,np.sum((x-self.data[i])**2))
  27. eps = 1e-8
  28. assert_(np.all(np.sum((self.data-x[np.newaxis,:])**2,axis=1) > d**2-eps))
  29. def test_m_nearest(self):
  30. x = self.x
  31. m = self.m
  32. dd, ii = self.kdtree.query(x, m)
  33. d = np.amax(dd)
  34. i = ii[np.argmax(dd)]
  35. assert_almost_equal(d**2,np.sum((x-self.data[i])**2))
  36. eps = 1e-8
  37. assert_equal(np.sum(np.sum((self.data-x[np.newaxis,:])**2,axis=1) < d**2+eps),m)
  38. def test_points_near(self):
  39. x = self.x
  40. d = self.d
  41. dd, ii = self.kdtree.query(x, k=self.kdtree.n, distance_upper_bound=d)
  42. eps = 1e-8
  43. hits = 0
  44. for near_d, near_i in zip(dd,ii):
  45. if near_d == np.inf:
  46. continue
  47. hits += 1
  48. assert_almost_equal(near_d**2,np.sum((x-self.data[near_i])**2))
  49. assert_(near_d < d+eps, "near_d=%g should be less than %g" % (near_d,d))
  50. assert_equal(np.sum(self.distance(self.data,x,2) < d**2+eps),hits)
  51. def test_points_near_l1(self):
  52. x = self.x
  53. d = self.d
  54. dd, ii = self.kdtree.query(x, k=self.kdtree.n, p=1, distance_upper_bound=d)
  55. eps = 1e-8
  56. hits = 0
  57. for near_d, near_i in zip(dd,ii):
  58. if near_d == np.inf:
  59. continue
  60. hits += 1
  61. assert_almost_equal(near_d,self.distance(x,self.data[near_i],1))
  62. assert_(near_d < d+eps, "near_d=%g should be less than %g" % (near_d,d))
  63. assert_equal(np.sum(self.distance(self.data,x,1) < d+eps),hits)
  64. def test_points_near_linf(self):
  65. x = self.x
  66. d = self.d
  67. dd, ii = self.kdtree.query(x, k=self.kdtree.n, p=np.inf, distance_upper_bound=d)
  68. eps = 1e-8
  69. hits = 0
  70. for near_d, near_i in zip(dd,ii):
  71. if near_d == np.inf:
  72. continue
  73. hits += 1
  74. assert_almost_equal(near_d,self.distance(x,self.data[near_i],np.inf))
  75. assert_(near_d < d+eps, "near_d=%g should be less than %g" % (near_d,d))
  76. assert_equal(np.sum(self.distance(self.data,x,np.inf) < d+eps),hits)
  77. def test_approx(self):
  78. x = self.x
  79. k = self.k
  80. eps = 0.1
  81. d_real, i_real = self.kdtree.query(x, k)
  82. d, i = self.kdtree.query(x, k, eps=eps)
  83. assert_(np.all(d <= d_real*(1+eps)))
  84. class Test_random(ConsistencyTests):
  85. def setup_method(self):
  86. self.n = 100
  87. self.m = 4
  88. np.random.seed(1234)
  89. self.data = np.random.randn(self.n, self.m)
  90. self.kdtree = KDTree(self.data,leafsize=2)
  91. self.x = np.random.randn(self.m)
  92. self.d = 0.2
  93. self.k = 10
  94. class Test_random_far(Test_random):
  95. def setup_method(self):
  96. Test_random.setup_method(self)
  97. self.x = np.random.randn(self.m)+10
  98. class Test_small(ConsistencyTests):
  99. def setup_method(self):
  100. self.data = np.array([[0,0,0],
  101. [0,0,1],
  102. [0,1,0],
  103. [0,1,1],
  104. [1,0,0],
  105. [1,0,1],
  106. [1,1,0],
  107. [1,1,1]])
  108. self.kdtree = KDTree(self.data)
  109. self.n = self.kdtree.n
  110. self.m = self.kdtree.m
  111. np.random.seed(1234)
  112. self.x = np.random.randn(3)
  113. self.d = 0.5
  114. self.k = 4
  115. def test_nearest(self):
  116. assert_array_equal(
  117. self.kdtree.query((0,0,0.1), 1),
  118. (0.1,0))
  119. def test_nearest_two(self):
  120. assert_array_equal(
  121. self.kdtree.query((0,0,0.1), 2),
  122. ([0.1,0.9],[0,1]))
  123. class Test_small_nonleaf(Test_small):
  124. def setup_method(self):
  125. Test_small.setup_method(self)
  126. self.kdtree = KDTree(self.data,leafsize=1)
  127. class Test_small_compiled(Test_small):
  128. def setup_method(self):
  129. Test_small.setup_method(self)
  130. self.kdtree = cKDTree(self.data)
  131. class Test_small_nonleaf_compiled(Test_small):
  132. def setup_method(self):
  133. Test_small.setup_method(self)
  134. self.kdtree = cKDTree(self.data,leafsize=1)
  135. class Test_random_compiled(Test_random):
  136. def setup_method(self):
  137. Test_random.setup_method(self)
  138. self.kdtree = cKDTree(self.data)
  139. class Test_random_far_compiled(Test_random_far):
  140. def setup_method(self):
  141. Test_random_far.setup_method(self)
  142. self.kdtree = cKDTree(self.data)
  143. class Test_vectorization:
  144. def setup_method(self):
  145. self.data = np.array([[0,0,0],
  146. [0,0,1],
  147. [0,1,0],
  148. [0,1,1],
  149. [1,0,0],
  150. [1,0,1],
  151. [1,1,0],
  152. [1,1,1]])
  153. self.kdtree = KDTree(self.data)
  154. def test_single_query(self):
  155. d, i = self.kdtree.query(np.array([0,0,0]))
  156. assert_(isinstance(d,float))
  157. assert_(np.issubdtype(i, np.signedinteger))
  158. def test_vectorized_query(self):
  159. d, i = self.kdtree.query(np.zeros((2,4,3)))
  160. assert_equal(np.shape(d),(2,4))
  161. assert_equal(np.shape(i),(2,4))
  162. def test_single_query_multiple_neighbors(self):
  163. s = 23
  164. kk = self.kdtree.n+s
  165. d, i = self.kdtree.query(np.array([0,0,0]),k=kk)
  166. assert_equal(np.shape(d),(kk,))
  167. assert_equal(np.shape(i),(kk,))
  168. assert_(np.all(~np.isfinite(d[-s:])))
  169. assert_(np.all(i[-s:] == self.kdtree.n))
  170. def test_vectorized_query_multiple_neighbors(self):
  171. s = 23
  172. kk = self.kdtree.n+s
  173. d, i = self.kdtree.query(np.zeros((2,4,3)),k=kk)
  174. assert_equal(np.shape(d),(2,4,kk))
  175. assert_equal(np.shape(i),(2,4,kk))
  176. assert_(np.all(~np.isfinite(d[:,:,-s:])))
  177. assert_(np.all(i[:,:,-s:] == self.kdtree.n))
  178. def test_single_query_all_neighbors(self):
  179. d, i = self.kdtree.query([0,0,0],k=None,distance_upper_bound=1.1)
  180. assert_(isinstance(d,list))
  181. assert_(isinstance(i,list))
  182. def test_vectorized_query_all_neighbors(self):
  183. d, i = self.kdtree.query(np.zeros((2,4,3)),k=None,distance_upper_bound=1.1)
  184. assert_equal(np.shape(d),(2,4))
  185. assert_equal(np.shape(i),(2,4))
  186. assert_(isinstance(d[0,0],list))
  187. assert_(isinstance(i[0,0],list))
  188. class Test_vectorization_compiled:
  189. def setup_method(self):
  190. self.data = np.array([[0,0,0],
  191. [0,0,1],
  192. [0,1,0],
  193. [0,1,1],
  194. [1,0,0],
  195. [1,0,1],
  196. [1,1,0],
  197. [1,1,1]])
  198. self.kdtree = cKDTree(self.data)
  199. def test_single_query(self):
  200. d, i = self.kdtree.query([0,0,0])
  201. assert_(isinstance(d,float))
  202. assert_(isinstance(i,int))
  203. def test_vectorized_query(self):
  204. d, i = self.kdtree.query(np.zeros((2,4,3)))
  205. assert_equal(np.shape(d),(2,4))
  206. assert_equal(np.shape(i),(2,4))
  207. def test_vectorized_query_noncontiguous_values(self):
  208. np.random.seed(1234)
  209. qs = np.random.randn(3,1000).T
  210. ds, i_s = self.kdtree.query(qs)
  211. for q, d, i in zip(qs,ds,i_s):
  212. assert_equal(self.kdtree.query(q),(d,i))
  213. def test_single_query_multiple_neighbors(self):
  214. s = 23
  215. kk = self.kdtree.n+s
  216. d, i = self.kdtree.query([0,0,0],k=kk)
  217. assert_equal(np.shape(d),(kk,))
  218. assert_equal(np.shape(i),(kk,))
  219. assert_(np.all(~np.isfinite(d[-s:])))
  220. assert_(np.all(i[-s:] == self.kdtree.n))
  221. def test_vectorized_query_multiple_neighbors(self):
  222. s = 23
  223. kk = self.kdtree.n+s
  224. d, i = self.kdtree.query(np.zeros((2,4,3)),k=kk)
  225. assert_equal(np.shape(d),(2,4,kk))
  226. assert_equal(np.shape(i),(2,4,kk))
  227. assert_(np.all(~np.isfinite(d[:,:,-s:])))
  228. assert_(np.all(i[:,:,-s:] == self.kdtree.n))
  229. class ball_consistency:
  230. def distance(self, a, b, p):
  231. return minkowski_distance(a, b, p)
  232. def test_in_ball(self):
  233. l = self.T.query_ball_point(self.x, self.d, p=self.p, eps=self.eps)
  234. for i in l:
  235. assert_(self.distance(self.data[i],self.x,self.p) <= self.d*(1.+self.eps))
  236. def test_found_all(self):
  237. c = np.ones(self.T.n,dtype=bool)
  238. l = self.T.query_ball_point(self.x, self.d, p=self.p, eps=self.eps)
  239. c[l] = False
  240. assert_(np.all(self.distance(self.data[c],self.x,self.p) >= self.d/(1.+self.eps)))
  241. class Test_random_ball(ball_consistency):
  242. def setup_method(self):
  243. n = 100
  244. m = 4
  245. np.random.seed(1234)
  246. self.data = np.random.randn(n,m)
  247. self.T = KDTree(self.data,leafsize=2)
  248. self.x = np.random.randn(m)
  249. self.p = 2.
  250. self.eps = 0
  251. self.d = 0.2
  252. class Test_random_ball_compiled(ball_consistency):
  253. def setup_method(self):
  254. n = 100
  255. m = 4
  256. np.random.seed(1234)
  257. self.data = np.random.randn(n,m)
  258. self.T = cKDTree(self.data,leafsize=2)
  259. self.x = np.random.randn(m)
  260. self.p = 2.
  261. self.eps = 0
  262. self.d = 0.2
  263. class Test_random_ball_compiled_periodic(ball_consistency):
  264. def distance(self, a, b, p):
  265. return distance_box(a, b, p, 1.0)
  266. def setup_method(self):
  267. n = 10000
  268. m = 4
  269. np.random.seed(1234)
  270. self.data = np.random.uniform(size=(n,m))
  271. self.T = cKDTree(self.data,leafsize=2, boxsize=1)
  272. self.x = np.ones(m) * 0.1
  273. self.p = 2.
  274. self.eps = 0
  275. self.d = 0.2
  276. def test_in_ball_outside(self):
  277. l = self.T.query_ball_point(self.x + 1.0, self.d, p=self.p, eps=self.eps)
  278. for i in l:
  279. assert_(self.distance(self.data[i],self.x,self.p) <= self.d*(1.+self.eps))
  280. l = self.T.query_ball_point(self.x - 1.0, self.d, p=self.p, eps=self.eps)
  281. for i in l:
  282. assert_(self.distance(self.data[i],self.x,self.p) <= self.d*(1.+self.eps))
  283. def test_found_all_outside(self):
  284. c = np.ones(self.T.n,dtype=bool)
  285. l = self.T.query_ball_point(self.x + 1.0, self.d, p=self.p, eps=self.eps)
  286. c[l] = False
  287. assert_(np.all(self.distance(self.data[c],self.x,self.p) >= self.d/(1.+self.eps)))
  288. l = self.T.query_ball_point(self.x - 1.0, self.d, p=self.p, eps=self.eps)
  289. c[l] = False
  290. assert_(np.all(self.distance(self.data[c],self.x,self.p) >= self.d/(1.+self.eps)))
  291. class Test_random_ball_approx(Test_random_ball):
  292. def setup_method(self):
  293. Test_random_ball.setup_method(self)
  294. self.eps = 0.1
  295. class Test_random_ball_approx_compiled(Test_random_ball_compiled):
  296. def setup_method(self):
  297. Test_random_ball_compiled.setup_method(self)
  298. self.eps = 0.1
  299. class Test_random_ball_approx_compiled_periodic(Test_random_ball_compiled_periodic):
  300. def setup_method(self):
  301. Test_random_ball_compiled_periodic.setup_method(self)
  302. self.eps = 0.1
  303. class Test_random_ball_far(Test_random_ball):
  304. def setup_method(self):
  305. Test_random_ball.setup_method(self)
  306. self.d = 2.
  307. class Test_random_ball_far_compiled(Test_random_ball_compiled):
  308. def setup_method(self):
  309. Test_random_ball_compiled.setup_method(self)
  310. self.d = 2.
  311. class Test_random_ball_far_compiled_periodic(Test_random_ball_compiled_periodic):
  312. def setup_method(self):
  313. Test_random_ball_compiled_periodic.setup_method(self)
  314. self.d = 2.
  315. class Test_random_ball_l1(Test_random_ball):
  316. def setup_method(self):
  317. Test_random_ball.setup_method(self)
  318. self.p = 1
  319. class Test_random_ball_l1_compiled(Test_random_ball_compiled):
  320. def setup_method(self):
  321. Test_random_ball_compiled.setup_method(self)
  322. self.p = 1
  323. class Test_random_ball_l1_compiled_periodic(Test_random_ball_compiled_periodic):
  324. def setup_method(self):
  325. Test_random_ball_compiled_periodic.setup_method(self)
  326. self.p = 1
  327. class Test_random_ball_linf(Test_random_ball):
  328. def setup_method(self):
  329. Test_random_ball.setup_method(self)
  330. self.p = np.inf
  331. class Test_random_ball_linf_compiled_periodic(Test_random_ball_compiled_periodic):
  332. def setup_method(self):
  333. Test_random_ball_compiled_periodic.setup_method(self)
  334. self.p = np.inf
  335. def test_random_ball_vectorized():
  336. n = 20
  337. m = 5
  338. T = KDTree(np.random.randn(n,m))
  339. r = T.query_ball_point(np.random.randn(2,3,m),1)
  340. assert_equal(r.shape,(2,3))
  341. assert_(isinstance(r[0,0],list))
  342. def test_random_ball_vectorized_compiled():
  343. n = 20
  344. m = 5
  345. np.random.seed(1234)
  346. T = cKDTree(np.random.randn(n,m))
  347. r = T.query_ball_point(np.random.randn(2,3,m),1)
  348. assert_equal(r.shape,(2,3))
  349. assert_(isinstance(r[0,0],list))
  350. def test_query_ball_point_multithreading():
  351. np.random.seed(0)
  352. n = 5000
  353. k = 2
  354. points = np.random.randn(n,k)
  355. T = cKDTree(points)
  356. l1 = T.query_ball_point(points,0.003,n_jobs=1)
  357. l2 = T.query_ball_point(points,0.003,n_jobs=64)
  358. l3 = T.query_ball_point(points,0.003,n_jobs=-1)
  359. for i in range(n):
  360. if l1[i] or l2[i]:
  361. assert_array_equal(l1[i],l2[i])
  362. for i in range(n):
  363. if l1[i] or l3[i]:
  364. assert_array_equal(l1[i],l3[i])
  365. class two_trees_consistency:
  366. def distance(self, a, b, p):
  367. return minkowski_distance(a, b, p)
  368. def test_all_in_ball(self):
  369. r = self.T1.query_ball_tree(self.T2, self.d, p=self.p, eps=self.eps)
  370. for i, l in enumerate(r):
  371. for j in l:
  372. assert_(self.distance(self.data1[i],self.data2[j],self.p) <= self.d*(1.+self.eps))
  373. def test_found_all(self):
  374. r = self.T1.query_ball_tree(self.T2, self.d, p=self.p, eps=self.eps)
  375. for i, l in enumerate(r):
  376. c = np.ones(self.T2.n,dtype=bool)
  377. c[l] = False
  378. assert_(np.all(self.distance(self.data2[c],self.data1[i],self.p) >= self.d/(1.+self.eps)))
  379. class Test_two_random_trees(two_trees_consistency):
  380. def setup_method(self):
  381. n = 50
  382. m = 4
  383. np.random.seed(1234)
  384. self.data1 = np.random.randn(n,m)
  385. self.T1 = KDTree(self.data1,leafsize=2)
  386. self.data2 = np.random.randn(n,m)
  387. self.T2 = KDTree(self.data2,leafsize=2)
  388. self.p = 2.
  389. self.eps = 0
  390. self.d = 0.2
  391. class Test_two_random_trees_compiled(two_trees_consistency):
  392. def setup_method(self):
  393. n = 50
  394. m = 4
  395. np.random.seed(1234)
  396. self.data1 = np.random.randn(n,m)
  397. self.T1 = cKDTree(self.data1,leafsize=2)
  398. self.data2 = np.random.randn(n,m)
  399. self.T2 = cKDTree(self.data2,leafsize=2)
  400. self.p = 2.
  401. self.eps = 0
  402. self.d = 0.2
  403. class Test_two_random_trees_compiled_periodic(two_trees_consistency):
  404. def distance(self, a, b, p):
  405. return distance_box(a, b, p, 1.0)
  406. def setup_method(self):
  407. n = 50
  408. m = 4
  409. np.random.seed(1234)
  410. self.data1 = np.random.uniform(size=(n,m))
  411. self.T1 = cKDTree(self.data1,leafsize=2, boxsize=1.0)
  412. self.data2 = np.random.uniform(size=(n,m))
  413. self.T2 = cKDTree(self.data2,leafsize=2, boxsize=1.0)
  414. self.p = 2.
  415. self.eps = 0
  416. self.d = 0.2
  417. class Test_two_random_trees_far(Test_two_random_trees):
  418. def setup_method(self):
  419. Test_two_random_trees.setup_method(self)
  420. self.d = 2
  421. class Test_two_random_trees_far_compiled(Test_two_random_trees_compiled):
  422. def setup_method(self):
  423. Test_two_random_trees_compiled.setup_method(self)
  424. self.d = 2
  425. class Test_two_random_trees_far_compiled_periodic(Test_two_random_trees_compiled_periodic):
  426. def setup_method(self):
  427. Test_two_random_trees_compiled_periodic.setup_method(self)
  428. self.d = 2
  429. class Test_two_random_trees_linf(Test_two_random_trees):
  430. def setup_method(self):
  431. Test_two_random_trees.setup_method(self)
  432. self.p = np.inf
  433. class Test_two_random_trees_linf_compiled(Test_two_random_trees_compiled):
  434. def setup_method(self):
  435. Test_two_random_trees_compiled.setup_method(self)
  436. self.p = np.inf
  437. class Test_two_random_trees_linf_compiled_periodic(Test_two_random_trees_compiled_periodic):
  438. def setup_method(self):
  439. Test_two_random_trees_compiled_periodic.setup_method(self)
  440. self.p = np.inf
  441. class Test_rectangle:
  442. def setup_method(self):
  443. self.rect = Rectangle([0,0],[1,1])
  444. def test_min_inside(self):
  445. assert_almost_equal(self.rect.min_distance_point([0.5,0.5]),0)
  446. def test_min_one_side(self):
  447. assert_almost_equal(self.rect.min_distance_point([0.5,1.5]),0.5)
  448. def test_min_two_sides(self):
  449. assert_almost_equal(self.rect.min_distance_point([2,2]),np.sqrt(2))
  450. def test_max_inside(self):
  451. assert_almost_equal(self.rect.max_distance_point([0.5,0.5]),1/np.sqrt(2))
  452. def test_max_one_side(self):
  453. assert_almost_equal(self.rect.max_distance_point([0.5,1.5]),np.hypot(0.5,1.5))
  454. def test_max_two_sides(self):
  455. assert_almost_equal(self.rect.max_distance_point([2,2]),2*np.sqrt(2))
  456. def test_split(self):
  457. less, greater = self.rect.split(0,0.1)
  458. assert_array_equal(less.maxes,[0.1,1])
  459. assert_array_equal(less.mins,[0,0])
  460. assert_array_equal(greater.maxes,[1,1])
  461. assert_array_equal(greater.mins,[0.1,0])
  462. def test_distance_l2():
  463. assert_almost_equal(minkowski_distance([0,0],[1,1],2),np.sqrt(2))
  464. def test_distance_l1():
  465. assert_almost_equal(minkowski_distance([0,0],[1,1],1),2)
  466. def test_distance_linf():
  467. assert_almost_equal(minkowski_distance([0,0],[1,1],np.inf),1)
  468. def test_distance_vectorization():
  469. np.random.seed(1234)
  470. x = np.random.randn(10,1,3)
  471. y = np.random.randn(1,7,3)
  472. assert_equal(minkowski_distance(x,y).shape,(10,7))
  473. class count_neighbors_consistency:
  474. def test_one_radius(self):
  475. r = 0.2
  476. assert_equal(self.T1.count_neighbors(self.T2, r),
  477. np.sum([len(l) for l in self.T1.query_ball_tree(self.T2,r)]))
  478. def test_large_radius(self):
  479. r = 1000
  480. assert_equal(self.T1.count_neighbors(self.T2, r),
  481. np.sum([len(l) for l in self.T1.query_ball_tree(self.T2,r)]))
  482. def test_multiple_radius(self):
  483. rs = np.exp(np.linspace(np.log(0.01),np.log(10),3))
  484. results = self.T1.count_neighbors(self.T2, rs)
  485. assert_(np.all(np.diff(results) >= 0))
  486. for r,result in zip(rs, results):
  487. assert_equal(self.T1.count_neighbors(self.T2, r), result)
  488. class Test_count_neighbors(count_neighbors_consistency):
  489. def setup_method(self):
  490. n = 50
  491. m = 2
  492. np.random.seed(1234)
  493. self.T1 = KDTree(np.random.randn(n,m),leafsize=2)
  494. self.T2 = KDTree(np.random.randn(n,m),leafsize=2)
  495. class Test_count_neighbors_compiled(count_neighbors_consistency):
  496. def setup_method(self):
  497. n = 50
  498. m = 2
  499. np.random.seed(1234)
  500. self.T1 = cKDTree(np.random.randn(n,m),leafsize=2)
  501. self.T2 = cKDTree(np.random.randn(n,m),leafsize=2)
  502. class sparse_distance_matrix_consistency:
  503. def distance(self, a, b, p):
  504. return minkowski_distance(a, b, p)
  505. def test_consistency_with_neighbors(self):
  506. M = self.T1.sparse_distance_matrix(self.T2, self.r)
  507. r = self.T1.query_ball_tree(self.T2, self.r)
  508. for i,l in enumerate(r):
  509. for j in l:
  510. assert_almost_equal(M[i,j],
  511. self.distance(self.T1.data[i], self.T2.data[j], self.p),
  512. decimal=14)
  513. for ((i,j),d) in M.items():
  514. assert_(j in r[i])
  515. def test_zero_distance(self):
  516. # raises an exception for bug 870 (FIXME: Does it?)
  517. self.T1.sparse_distance_matrix(self.T1, self.r)
  518. class Test_sparse_distance_matrix(sparse_distance_matrix_consistency):
  519. def setup_method(self):
  520. n = 50
  521. m = 4
  522. np.random.seed(1234)
  523. data1 = np.random.randn(n,m)
  524. data2 = np.random.randn(n,m)
  525. self.T1 = cKDTree(data1,leafsize=2)
  526. self.T2 = cKDTree(data2,leafsize=2)
  527. self.r = 0.5
  528. self.p = 2
  529. self.data1 = data1
  530. self.data2 = data2
  531. self.n = n
  532. self.m = m
  533. class Test_sparse_distance_matrix_compiled(sparse_distance_matrix_consistency):
  534. def setup_method(self):
  535. n = 50
  536. m = 4
  537. np.random.seed(0)
  538. data1 = np.random.randn(n,m)
  539. data2 = np.random.randn(n,m)
  540. self.T1 = cKDTree(data1,leafsize=2)
  541. self.T2 = cKDTree(data2,leafsize=2)
  542. self.ref_T1 = KDTree(data1, leafsize=2)
  543. self.ref_T2 = KDTree(data2, leafsize=2)
  544. self.r = 0.5
  545. self.n = n
  546. self.m = m
  547. self.data1 = data1
  548. self.data2 = data2
  549. self.p = 2
  550. def test_consistency_with_python(self):
  551. M1 = self.T1.sparse_distance_matrix(self.T2, self.r)
  552. M2 = self.ref_T1.sparse_distance_matrix(self.ref_T2, self.r)
  553. assert_array_almost_equal(M1.todense(), M2.todense(), decimal=14)
  554. def test_against_logic_error_regression(self):
  555. # regression test for gh-5077 logic error
  556. np.random.seed(0)
  557. too_many = np.array(np.random.randn(18, 2), dtype=int)
  558. tree = cKDTree(too_many, balanced_tree=False, compact_nodes=False)
  559. d = tree.sparse_distance_matrix(tree, 3).todense()
  560. assert_array_almost_equal(d, d.T, decimal=14)
  561. def test_ckdtree_return_types(self):
  562. # brute-force reference
  563. ref = np.zeros((self.n,self.n))
  564. for i in range(self.n):
  565. for j in range(self.n):
  566. v = self.data1[i,:] - self.data2[j,:]
  567. ref[i,j] = np.dot(v,v)
  568. ref = np.sqrt(ref)
  569. ref[ref > self.r] = 0.
  570. # test return type 'dict'
  571. dist = np.zeros((self.n,self.n))
  572. r = self.T1.sparse_distance_matrix(self.T2, self.r, output_type='dict')
  573. for i,j in r.keys():
  574. dist[i,j] = r[(i,j)]
  575. assert_array_almost_equal(ref, dist, decimal=14)
  576. # test return type 'ndarray'
  577. dist = np.zeros((self.n,self.n))
  578. r = self.T1.sparse_distance_matrix(self.T2, self.r,
  579. output_type='ndarray')
  580. for k in range(r.shape[0]):
  581. i = r['i'][k]
  582. j = r['j'][k]
  583. v = r['v'][k]
  584. dist[i,j] = v
  585. assert_array_almost_equal(ref, dist, decimal=14)
  586. # test return type 'dok_matrix'
  587. r = self.T1.sparse_distance_matrix(self.T2, self.r,
  588. output_type='dok_matrix')
  589. assert_array_almost_equal(ref, r.todense(), decimal=14)
  590. # test return type 'coo_matrix'
  591. r = self.T1.sparse_distance_matrix(self.T2, self.r,
  592. output_type='coo_matrix')
  593. assert_array_almost_equal(ref, r.todense(), decimal=14)
  594. def test_distance_matrix():
  595. m = 10
  596. n = 11
  597. k = 4
  598. np.random.seed(1234)
  599. xs = np.random.randn(m,k)
  600. ys = np.random.randn(n,k)
  601. ds = distance_matrix(xs,ys)
  602. assert_equal(ds.shape, (m,n))
  603. for i in range(m):
  604. for j in range(n):
  605. assert_almost_equal(minkowski_distance(xs[i],ys[j]),ds[i,j])
  606. def test_distance_matrix_looping():
  607. m = 10
  608. n = 11
  609. k = 4
  610. np.random.seed(1234)
  611. xs = np.random.randn(m,k)
  612. ys = np.random.randn(n,k)
  613. ds = distance_matrix(xs,ys)
  614. dsl = distance_matrix(xs,ys,threshold=1)
  615. assert_equal(ds,dsl)
  616. def check_onetree_query(T,d):
  617. r = T.query_ball_tree(T, d)
  618. s = set()
  619. for i, l in enumerate(r):
  620. for j in l:
  621. if i < j:
  622. s.add((i,j))
  623. assert_(s == T.query_pairs(d))
  624. def test_onetree_query():
  625. np.random.seed(0)
  626. n = 50
  627. k = 4
  628. points = np.random.randn(n,k)
  629. T = KDTree(points)
  630. check_onetree_query(T, 0.1)
  631. points = np.random.randn(3*n,k)
  632. points[:n] *= 0.001
  633. points[n:2*n] += 2
  634. T = KDTree(points)
  635. check_onetree_query(T, 0.1)
  636. check_onetree_query(T, 0.001)
  637. check_onetree_query(T, 0.00001)
  638. check_onetree_query(T, 1e-6)
  639. def test_onetree_query_compiled():
  640. np.random.seed(0)
  641. n = 100
  642. k = 4
  643. points = np.random.randn(n,k)
  644. T = cKDTree(points)
  645. check_onetree_query(T, 0.1)
  646. points = np.random.randn(3*n,k)
  647. points[:n] *= 0.001
  648. points[n:2*n] += 2
  649. T = cKDTree(points)
  650. check_onetree_query(T, 0.1)
  651. check_onetree_query(T, 0.001)
  652. check_onetree_query(T, 0.00001)
  653. check_onetree_query(T, 1e-6)
  654. def test_query_pairs_single_node():
  655. tree = KDTree([[0, 1]])
  656. assert_equal(tree.query_pairs(0.5), set())
  657. def test_query_pairs_single_node_compiled():
  658. tree = cKDTree([[0, 1]])
  659. assert_equal(tree.query_pairs(0.5), set())
  660. def test_ckdtree_query_pairs():
  661. np.random.seed(0)
  662. n = 50
  663. k = 2
  664. r = 0.1
  665. r2 = r**2
  666. points = np.random.randn(n,k)
  667. T = cKDTree(points)
  668. # brute force reference
  669. brute = set()
  670. for i in range(n):
  671. for j in range(i+1,n):
  672. v = points[i,:] - points[j,:]
  673. if np.dot(v,v) <= r2:
  674. brute.add((i,j))
  675. l0 = sorted(brute)
  676. # test default return type
  677. s = T.query_pairs(r)
  678. l1 = sorted(s)
  679. assert_array_equal(l0,l1)
  680. # test return type 'set'
  681. s = T.query_pairs(r, output_type='set')
  682. l1 = sorted(s)
  683. assert_array_equal(l0,l1)
  684. # test return type 'ndarray'
  685. s = set()
  686. arr = T.query_pairs(r, output_type='ndarray')
  687. for i in range(arr.shape[0]):
  688. s.add((int(arr[i,0]),int(arr[i,1])))
  689. l2 = sorted(s)
  690. assert_array_equal(l0,l2)
  691. def test_ball_point_ints():
  692. # Regression test for #1373.
  693. x, y = np.mgrid[0:4, 0:4]
  694. points = list(zip(x.ravel(), y.ravel()))
  695. tree = KDTree(points)
  696. assert_equal(sorted([4, 8, 9, 12]),
  697. sorted(tree.query_ball_point((2, 0), 1)))
  698. points = np.asarray(points, dtype=float)
  699. tree = KDTree(points)
  700. assert_equal(sorted([4, 8, 9, 12]),
  701. sorted(tree.query_ball_point((2, 0), 1)))
  702. def test_kdtree_comparisons():
  703. # Regression test: node comparisons were done wrong in 0.12 w/Py3.
  704. nodes = [KDTree.node() for _ in range(3)]
  705. assert_equal(sorted(nodes), sorted(nodes[::-1]))
  706. def test_ckdtree_build_modes():
  707. # check if different build modes for cKDTree give
  708. # similar query results
  709. np.random.seed(0)
  710. n = 5000
  711. k = 4
  712. points = np.random.randn(n, k)
  713. T1 = cKDTree(points).query(points, k=5)[-1]
  714. T2 = cKDTree(points, compact_nodes=False).query(points, k=5)[-1]
  715. T3 = cKDTree(points, balanced_tree=False).query(points, k=5)[-1]
  716. T4 = cKDTree(points, compact_nodes=False, balanced_tree=False).query(points, k=5)[-1]
  717. assert_array_equal(T1, T2)
  718. assert_array_equal(T1, T3)
  719. assert_array_equal(T1, T4)
  720. def test_ckdtree_pickle():
  721. # test if it is possible to pickle
  722. # a cKDTree
  723. try:
  724. import cPickle as pickle
  725. except ImportError:
  726. import pickle
  727. np.random.seed(0)
  728. n = 50
  729. k = 4
  730. points = np.random.randn(n, k)
  731. T1 = cKDTree(points)
  732. tmp = pickle.dumps(T1)
  733. T2 = pickle.loads(tmp)
  734. T1 = T1.query(points, k=5)[-1]
  735. T2 = T2.query(points, k=5)[-1]
  736. assert_array_equal(T1, T2)
  737. def test_ckdtree_pickle_boxsize():
  738. # test if it is possible to pickle a periodic
  739. # cKDTree
  740. try:
  741. import cPickle as pickle
  742. except ImportError:
  743. import pickle
  744. np.random.seed(0)
  745. n = 50
  746. k = 4
  747. points = np.random.uniform(size=(n, k))
  748. T1 = cKDTree(points, boxsize=1.0)
  749. tmp = pickle.dumps(T1)
  750. T2 = pickle.loads(tmp)
  751. T1 = T1.query(points, k=5)[-1]
  752. T2 = T2.query(points, k=5)[-1]
  753. assert_array_equal(T1, T2)
  754. def test_ckdtree_copy_data():
  755. # check if copy_data=True makes the kd-tree
  756. # impervious to data corruption by modification of
  757. # the data arrray
  758. np.random.seed(0)
  759. n = 5000
  760. k = 4
  761. points = np.random.randn(n, k)
  762. T = cKDTree(points, copy_data=True)
  763. q = points.copy()
  764. T1 = T.query(q, k=5)[-1]
  765. points[...] = np.random.randn(n, k)
  766. T2 = T.query(q, k=5)[-1]
  767. assert_array_equal(T1, T2)
  768. def test_ckdtree_parallel():
  769. # check if parallel=True also generates correct
  770. # query results
  771. np.random.seed(0)
  772. n = 5000
  773. k = 4
  774. points = np.random.randn(n, k)
  775. T = cKDTree(points)
  776. T1 = T.query(points, k=5, n_jobs=64)[-1]
  777. T2 = T.query(points, k=5, n_jobs=-1)[-1]
  778. T3 = T.query(points, k=5)[-1]
  779. assert_array_equal(T1, T2)
  780. assert_array_equal(T1, T3)
  781. def test_ckdtree_view():
  782. # Check that the nodes can be correctly viewed from Python.
  783. # This test also sanity checks each node in the cKDTree, and
  784. # thus verifies the internal structure of the kd-tree.
  785. np.random.seed(0)
  786. n = 100
  787. k = 4
  788. points = np.random.randn(n, k)
  789. kdtree = cKDTree(points)
  790. # walk the whole kd-tree and sanity check each node
  791. def recurse_tree(n):
  792. assert_(isinstance(n, cKDTreeNode))
  793. if n.split_dim == -1:
  794. assert_(n.lesser is None)
  795. assert_(n.greater is None)
  796. assert_(n.indices.shape[0] <= kdtree.leafsize)
  797. else:
  798. recurse_tree(n.lesser)
  799. recurse_tree(n.greater)
  800. x = n.lesser.data_points[:, n.split_dim]
  801. y = n.greater.data_points[:, n.split_dim]
  802. assert_(x.max() < y.min())
  803. recurse_tree(kdtree.tree)
  804. # check that indices are correctly retrieved
  805. n = kdtree.tree
  806. assert_array_equal(np.sort(n.indices), range(100))
  807. # check that data_points are correctly retrieved
  808. assert_array_equal(kdtree.data[n.indices, :], n.data_points)
  809. # cKDTree is specialized to type double points, so no need to make
  810. # a unit test corresponding to test_ball_point_ints()
  811. def test_ckdtree_list_k():
  812. # check ckdtree periodic boundary
  813. n = 200
  814. m = 2
  815. klist = [1, 2, 3]
  816. kint = 3
  817. np.random.seed(1234)
  818. data = np.random.uniform(size=(n, m))
  819. kdtree = cKDTree(data, leafsize=1)
  820. # check agreement between arange(1,k+1) and k
  821. dd, ii = kdtree.query(data, klist)
  822. dd1, ii1 = kdtree.query(data, kint)
  823. assert_equal(dd, dd1)
  824. assert_equal(ii, ii1)
  825. # now check skipping one element
  826. klist = np.array([1, 3])
  827. kint = 3
  828. dd, ii = kdtree.query(data, kint)
  829. dd1, ii1 = kdtree.query(data, klist)
  830. assert_equal(dd1, dd[..., klist - 1])
  831. assert_equal(ii1, ii[..., klist - 1])
  832. # check k == 1 special case
  833. # and k == [1] non-special case
  834. dd, ii = kdtree.query(data, 1)
  835. dd1, ii1 = kdtree.query(data, [1])
  836. assert_equal(len(dd.shape), 1)
  837. assert_equal(len(dd1.shape), 2)
  838. assert_equal(dd, np.ravel(dd1))
  839. assert_equal(ii, np.ravel(ii1))
  840. def test_ckdtree_box():
  841. # check ckdtree periodic boundary
  842. n = 2000
  843. m = 3
  844. k = 3
  845. np.random.seed(1234)
  846. data = np.random.uniform(size=(n, m))
  847. kdtree = cKDTree(data, leafsize=1, boxsize=1.0)
  848. # use the standard python KDTree for the simulated periodic box
  849. kdtree2 = cKDTree(data, leafsize=1)
  850. for p in [1, 2, 3.0, np.inf]:
  851. dd, ii = kdtree.query(data, k, p=p)
  852. dd1, ii1 = kdtree.query(data + 1.0, k, p=p)
  853. assert_almost_equal(dd, dd1)
  854. assert_equal(ii, ii1)
  855. dd1, ii1 = kdtree.query(data - 1.0, k, p=p)
  856. assert_almost_equal(dd, dd1)
  857. assert_equal(ii, ii1)
  858. dd2, ii2 = simulate_periodic_box(kdtree2, data, k, boxsize=1.0, p=p)
  859. assert_almost_equal(dd, dd2)
  860. assert_equal(ii, ii2)
  861. def test_ckdtree_box_0boxsize():
  862. # check ckdtree periodic boundary that mimics non-periodic
  863. n = 2000
  864. m = 2
  865. k = 3
  866. np.random.seed(1234)
  867. data = np.random.uniform(size=(n, m))
  868. kdtree = cKDTree(data, leafsize=1, boxsize=0.0)
  869. # use the standard python KDTree for the simulated periodic box
  870. kdtree2 = cKDTree(data, leafsize=1)
  871. for p in [1, 2, np.inf]:
  872. dd, ii = kdtree.query(data, k, p=p)
  873. dd1, ii1 = kdtree2.query(data, k, p=p)
  874. assert_almost_equal(dd, dd1)
  875. assert_equal(ii, ii1)
  876. def test_ckdtree_box_upper_bounds():
  877. data = np.linspace(0, 2, 10).reshape(-1, 2)
  878. data[:, 1] += 10
  879. assert_raises(ValueError, cKDTree, data, leafsize=1, boxsize=1.0)
  880. assert_raises(ValueError, cKDTree, data, leafsize=1, boxsize=(0.0, 2.0))
  881. # skip a dimension.
  882. cKDTree(data, leafsize=1, boxsize=(2.0, 0.0))
  883. def test_ckdtree_box_lower_bounds():
  884. data = np.linspace(-1, 1, 10)
  885. assert_raises(ValueError, cKDTree, data, leafsize=1, boxsize=1.0)
  886. def simulate_periodic_box(kdtree, data, k, boxsize, p):
  887. dd = []
  888. ii = []
  889. x = np.arange(3 ** data.shape[1])
  890. nn = np.array(np.unravel_index(x, [3] * data.shape[1])).T
  891. nn = nn - 1.0
  892. for n in nn:
  893. image = data + n * 1.0 * boxsize
  894. dd2, ii2 = kdtree.query(image, k, p=p)
  895. dd2 = dd2.reshape(-1, k)
  896. ii2 = ii2.reshape(-1, k)
  897. dd.append(dd2)
  898. ii.append(ii2)
  899. dd = np.concatenate(dd, axis=-1)
  900. ii = np.concatenate(ii, axis=-1)
  901. result = np.empty([len(data), len(nn) * k], dtype=[
  902. ('ii', 'i8'),
  903. ('dd', 'f8')])
  904. result['ii'][:] = ii
  905. result['dd'][:] = dd
  906. result.sort(order='dd')
  907. return result['dd'][:, :k], result['ii'][:,:k]
  908. @pytest.mark.skipif(python_implementation() == 'PyPy',
  909. reason="Fails on PyPy CI runs. See #9507")
  910. def test_ckdtree_memuse():
  911. # unit test adaptation of gh-5630
  912. # NOTE: this will fail when run via valgrind,
  913. # because rss is no longer a reliable memory usage indicator.
  914. try:
  915. import resource
  916. except ImportError:
  917. # resource is not available on Windows with Python 2.6
  918. return
  919. # Make some data
  920. dx, dy = 0.05, 0.05
  921. y, x = np.mgrid[slice(1, 5 + dy, dy),
  922. slice(1, 5 + dx, dx)]
  923. z = np.sin(x)**10 + np.cos(10 + y*x) * np.cos(x)
  924. z_copy = np.empty_like(z)
  925. z_copy[:] = z
  926. # Place FILLVAL in z_copy at random number of random locations
  927. FILLVAL = 99.
  928. mask = np.random.randint(0, z.size, np.random.randint(50) + 5)
  929. z_copy.flat[mask] = FILLVAL
  930. igood = np.vstack(np.nonzero(x != FILLVAL)).T
  931. ibad = np.vstack(np.nonzero(x == FILLVAL)).T
  932. mem_use = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
  933. # burn-in
  934. for i in range(10):
  935. tree = cKDTree(igood)
  936. # count memleaks while constructing and querying cKDTree
  937. num_leaks = 0
  938. for i in range(100):
  939. mem_use = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
  940. tree = cKDTree(igood)
  941. dist, iquery = tree.query(ibad, k=4, p=2)
  942. new_mem_use = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
  943. if new_mem_use > mem_use:
  944. num_leaks += 1
  945. # ideally zero leaks, but errors might accidentally happen
  946. # outside cKDTree
  947. assert_(num_leaks < 10)
  948. def test_ckdtree_weights():
  949. data = np.linspace(0, 1, 4).reshape(-1, 1)
  950. tree1 = cKDTree(data, leafsize=1)
  951. weights = np.ones(len(data), dtype='f4')
  952. nw = tree1._build_weights(weights)
  953. assert_array_equal(nw, [4, 2, 1, 1, 2, 1, 1])
  954. assert_raises(ValueError, tree1._build_weights, weights[:-1])
  955. for i in range(10):
  956. # since weights are uniform, these shall agree:
  957. c1 = tree1.count_neighbors(tree1, np.linspace(0, 10, i))
  958. c2 = tree1.count_neighbors(tree1, np.linspace(0, 10, i),
  959. weights=(weights, weights))
  960. c3 = tree1.count_neighbors(tree1, np.linspace(0, 10, i),
  961. weights=(weights, None))
  962. c4 = tree1.count_neighbors(tree1, np.linspace(0, 10, i),
  963. weights=(None, weights))
  964. c5 = tree1.count_neighbors(tree1, np.linspace(0, 10, i),
  965. weights=weights)
  966. assert_array_equal(c1, c2)
  967. assert_array_equal(c1, c3)
  968. assert_array_equal(c1, c4)
  969. for i in range(len(data)):
  970. # this tests removal of one data point by setting weight to 0
  971. w1 = weights.copy()
  972. w1[i] = 0
  973. data2 = data[w1 != 0]
  974. w2 = weights[w1 != 0]
  975. tree2 = cKDTree(data2)
  976. c1 = tree1.count_neighbors(tree1, np.linspace(0, 10, 100),
  977. weights=(w1, w1))
  978. # "c2 is correct"
  979. c2 = tree2.count_neighbors(tree2, np.linspace(0, 10, 100))
  980. assert_array_equal(c1, c2)
  981. #this asserts for two different trees, singular weights
  982. # crashes
  983. assert_raises(ValueError, tree1.count_neighbors,
  984. tree2, np.linspace(0, 10, 100), weights=w1)
  985. def test_ckdtree_count_neighbous_multiple_r():
  986. n = 2000
  987. m = 2
  988. np.random.seed(1234)
  989. data = np.random.normal(size=(n, m))
  990. kdtree = cKDTree(data, leafsize=1)
  991. r0 = [0, 0.01, 0.01, 0.02, 0.05]
  992. i0 = np.arange(len(r0))
  993. n0 = kdtree.count_neighbors(kdtree, r0)
  994. nnc = kdtree.count_neighbors(kdtree, r0, cumulative=False)
  995. assert_equal(n0, nnc.cumsum())
  996. for i, r in zip(itertools.permutations(i0),
  997. itertools.permutations(r0)):
  998. # permute n0 by i and it shall agree
  999. n = kdtree.count_neighbors(kdtree, r)
  1000. assert_array_equal(n, n0[list(i)])
  1001. def test_len0_arrays():
  1002. # make sure len-0 arrays are handled correctly
  1003. # in range queries (gh-5639)
  1004. np.random.seed(1234)
  1005. X = np.random.rand(10,2)
  1006. Y = np.random.rand(10,2)
  1007. tree = cKDTree(X)
  1008. # query_ball_point (single)
  1009. d,i = tree.query([.5, .5], k=1)
  1010. z = tree.query_ball_point([.5, .5], 0.1*d)
  1011. assert_array_equal(z, [])
  1012. # query_ball_point (multiple)
  1013. d,i = tree.query(Y, k=1)
  1014. mind = d.min()
  1015. z = tree.query_ball_point(Y, 0.1*mind)
  1016. y = np.empty(shape=(10,), dtype=object)
  1017. y.fill([])
  1018. assert_array_equal(y, z)
  1019. # query_ball_tree
  1020. other = cKDTree(Y)
  1021. y = tree.query_ball_tree(other, 0.1*mind)
  1022. assert_array_equal(10*[[]], y)
  1023. # count_neighbors
  1024. y = tree.count_neighbors(other, 0.1*mind)
  1025. assert_(y == 0)
  1026. # sparse_distance_matrix
  1027. y = tree.sparse_distance_matrix(other, 0.1*mind, output_type='dok_matrix')
  1028. assert_array_equal(y == np.zeros((10,10)), True)
  1029. y = tree.sparse_distance_matrix(other, 0.1*mind, output_type='coo_matrix')
  1030. assert_array_equal(y == np.zeros((10,10)), True)
  1031. y = tree.sparse_distance_matrix(other, 0.1*mind, output_type='dict')
  1032. assert_equal(y, {})
  1033. y = tree.sparse_distance_matrix(other,0.1*mind, output_type='ndarray')
  1034. _dtype = [('i',np.intp), ('j',np.intp), ('v',np.float64)]
  1035. res_dtype = np.dtype(_dtype, align=True)
  1036. z = np.empty(shape=(0,), dtype=res_dtype)
  1037. assert_array_equal(y, z)
  1038. # query_pairs
  1039. d,i = tree.query(X, k=2)
  1040. mind = d[:,-1].min()
  1041. y = tree.query_pairs(0.1*mind, output_type='set')
  1042. assert_equal(y, set())
  1043. y = tree.query_pairs(0.1*mind, output_type='ndarray')
  1044. z = np.empty(shape=(0,2), dtype=np.intp)
  1045. assert_array_equal(y, z)
  1046. def test_ckdtree_duplicated_inputs():
  1047. # check ckdtree with duplicated inputs
  1048. n = 1024
  1049. for m in range(1, 8):
  1050. data = np.concatenate([
  1051. np.ones((n // 2, m)) * 1,
  1052. np.ones((n // 2, m)) * 2], axis=0)
  1053. # it shall not divide more than 3 nodes.
  1054. # root left (1), and right (2)
  1055. kdtree = cKDTree(data, leafsize=1)
  1056. assert_equal(kdtree.size, 3)
  1057. kdtree = cKDTree(data)
  1058. assert_equal(kdtree.size, 3)
  1059. # if compact_nodes are disabled, the number
  1060. # of nodes is n (per leaf) + (m - 1)* 2 (splits per dimension) + 1
  1061. # and the root
  1062. kdtree = cKDTree(data, compact_nodes=False, leafsize=1)
  1063. assert_equal(kdtree.size, n + m * 2 - 1)
  1064. def test_ckdtree_noncumulative_nondecreasing():
  1065. # check ckdtree with duplicated inputs
  1066. # it shall not divide more than 3 nodes.
  1067. # root left (1), and right (2)
  1068. kdtree = cKDTree([[0]], leafsize=1)
  1069. assert_raises(ValueError, kdtree.count_neighbors,
  1070. kdtree, [0.1, 0], cumulative=False)
  1071. def test_short_knn():
  1072. # The test case is based on github: #6425 by @SteveDoyle2
  1073. xyz = np.array([
  1074. [0., 0., 0.],
  1075. [1.01, 0., 0.],
  1076. [0., 1., 0.],
  1077. [0., 1.01, 0.],
  1078. [1., 0., 0.],
  1079. [1., 1., 0.],],
  1080. dtype='float64')
  1081. ckdt = cKDTree(xyz)
  1082. deq, ieq = ckdt.query(xyz, k=4, distance_upper_bound=0.2)
  1083. assert_array_almost_equal(deq,
  1084. [[0., np.inf, np.inf, np.inf],
  1085. [0., 0.01, np.inf, np.inf],
  1086. [0., 0.01, np.inf, np.inf],
  1087. [0., 0.01, np.inf, np.inf],
  1088. [0., 0.01, np.inf, np.inf],
  1089. [0., np.inf, np.inf, np.inf]])
  1090. class Test_sorted_query_ball_point(object):
  1091. def setup_method(self):
  1092. np.random.seed(1234)
  1093. self.x = np.random.randn(100, 1)
  1094. self.ckdt = cKDTree(self.x)
  1095. def test_return_sorted_True(self):
  1096. idxs_list = self.ckdt.query_ball_point(self.x, 1., return_sorted=True)
  1097. for idxs in idxs_list:
  1098. assert_array_equal(idxs, sorted(idxs))
  1099. def test_return_sorted_None(self):
  1100. """Previous behavior was to sort the returned indices if there were
  1101. multiple points per query but not sort them if there was a single point
  1102. per query."""
  1103. idxs_list = self.ckdt.query_ball_point(self.x, 1.)
  1104. for idxs in idxs_list:
  1105. assert_array_equal(idxs, sorted(idxs))
  1106. idxs_list_single = [self.ckdt.query_ball_point(xi, 1.) for xi in self.x]
  1107. idxs_list_False = self.ckdt.query_ball_point(self.x, 1., return_sorted=False)
  1108. for idxs0, idxs1 in zip(idxs_list_False, idxs_list_single):
  1109. assert_array_equal(idxs0, idxs1)