Package: cQuadTree
Infinite jest with your favorite space-dividing trees. Fork from this
C++-codebase:https://github.com/benmaier/BarnesHutTree/repository:https://github.com/benmaier/cQuadTree/>>>fromcQuadTreeimportQuadTree>>>points=[...(1.0,2.0),...(0.1,10.0),...(0.5,7.4),...(6.0,0.7),...]>>>T=QuadTree(points)>>>TQuadTree(geom=Extent(left=0.1,bottom=0.7,width=9.3,height=9.3),current_data_quadrant=-1,is_leaf=False,number_of_contained_points=4,center_of_mass=Point(x=1.9,y=5.025),total_mass=4,total_mass_position=Point(x=7.6,y=20.1),number_of_occupied_subtrees=3)>>>print(T)+-CM=1.9,5.025;M=4;n=4|+-(nw)CM=0.3,8.7;M=2;n=2||+-(nw)1(0.1,10)||+-(sw)2(0.5,7.4)|+-(se)3(6,0.7)|+-(sw)0(1,2)InstallYour machine needs to have a C++11-compatible compiler installed.pipinstallcQuadTreeSo far, the package’s functionality was tested on Mac OS X and CentOS
only.DependenciescQuadTreedirectly depends on the following packages which will be
installed bypipduring the installation processnumpy>=1.20DocumentationBuild the treeimportnumpyasnpfromcQuadTreeimportQuadTreepoints=np.random.rand(100,2).tolist()T=QuadTree(points)Explore the tree recursivelyAs an example, here’s a recursive function that collects all internal
node boxes and leaf’s pointsdefget_points_and_boxes(quadtree):points=[]boxes=[]ifquadtree.is_leaf():points.append(quadtree.this_pos)boxes.append(quadtree.geom)fortreeinquadtree.get_subtrees():_points,_boxes=get_points_and_boxes(tree)points.extend(_points)boxes.extend(_boxes)returnpoints,boxesCompute the force on a point>>>T.compute_force(point=(0.,0.001),theta=1.0)# default is theta=0.5(0.117681690892212,0.20856460584929215)Get all distances to a pointNote that per default, distances of value zero will be disregarded. If
you want to include those, setignore_zero_distance=Falsein the
function call.>>>T.get_distances_to((0.,0),theta=1)# default is theta=0.2[(8.705170877128145,2),(6.040695324215583,1),(2.23606797749979,1)]The first number is the distance to the query point, the second is the
number of points that lie at this approximate distance to the query
point.Get all distances between pairs of points in a list and points in the tree>>>T.get_distances_to_points(points,theta=1)[(6.7364679172397155,2),(5.166236541235796,1),(2.630589287593181,1),(11.013627921806693,1),(8.050465825031493,1),(2.630589287593181,1),(8.668333173107735,1),(5.4230987451825,1),(9.822932352408825,2),(5.166236541235796,1)]Get all pairwise distances between points in the tree>>>T.get_pairwise_distances(theta=1.0)[(2.630589287593181,1),(11.013627921806693,1),(8.050465825031493,1),(2.630589287593181,1),(8.668333173107735,1),(5.4230987451825,1),(9.822932352408825,2),(5.166236541235796,1),(6.7364679172397155,2),(5.166236541235796,1)]Build a distance histogram from distance countsfromcQuadTreeimporthistogramdists,counts=zip(*T.get_pairwise_distances(theta=1.0))bin_edges=np.logspace(-4,1/2,101,base=2)pdf,_=histogram(dists,counts,bin_edges)Plot tree as boxes and pointsfromcQuadTreeimportget_points_and_boxesfromcQuadTree.plotimportplot_box_treeplot_box_tree(*get_points_and_boxes(T))DocstringsQuadTreeHelponclassQuadTreeinmodule_cQuadTree:classQuadTree(pybind11_builtins.pybind11_object)|AQuadTree.||Methodresolutionorder:|QuadTree|pybind11_builtins.pybind11_object|builtins.object||Methodsdefinedhere:||__init__(...)|__init__(*args,**kwargs)|Overloadedfunction.||1.__init__(self:_cQuadTree.QuadTree)->None||Initializeanemptytree.||2.__init__(self:_cQuadTree.QuadTree,position_pairs:List[Tuple[float,float]],force_square:bool=True)->None||Initializeatreegivenalistofpositions.||3.__init__(self:_cQuadTree.QuadTree,position_pairs:List[Tuple[float,float]],masses:List[float],force_square:bool=True)->None||Initializeatreegivenalistofpositionsandalistofcorrespondingmasses.||__repr__(...)|__repr__(self:_cQuadTree.QuadTree)->str||Getstringrepresentationofobject||__str__(...)|__str__(self:_cQuadTree.QuadTree)->str||Getastringrepresentationofthefulltree||compute_force(...)|compute_force(self:_cQuadTree.QuadTree,point:Tuple[float,float],theta:float=0.5)->Tuple[float,float]|||ComputetheforceonasinglepointusingtheBarnes-Hut-Algorithm|withcutoffparameter:math:`\theta`.||Parameters|----------|point:2-tupleoffloat|Pointinplaneonwhichtocomputethetotalforce|theta:float,default=0.5|Ifthedistancebetweenthepointandthecurrentinternalnode's|centerofmassissmallerthan:math:`\theta`timesthediameter|oftheinternalnode's extent (box), the algorithm will treat|allchildrenofthisnodeasagiantpointmasslocatedatthe|centerofmassofthisinternalnode.||Returns|-------|force:2-tupleoffloat|Evaluatedforcevector||get_distances_to(...)|get_distances_to(self:_cQuadTree.QuadTree,point:Tuple[float,float],theta:float=0.2,ignore_zero_distance:bool=True,tree:_cQuadTree.QuadTree=None)->List[Tuple[float,int]]|||Computedistancesofpointmassesandmassclusterstoasinglepoint|usingtheBarnes-Hut-Algorithmwithcutoffparameter:math:`\theta`.||Parameters|----------|point:2-tupleoffloat|Pointsintheplanetowhichtomeasurethedistances|theta:float,default=0.2|Ifthedistancebetweenthepointandthecurrentinternalnode's|centerofmassissmallerthan:math:`\theta`timesthediameter|oftheinternalnode's extent (box), the algorithm will treat|allchildrenofthisnodeasagiantpointmasslocatedatthe|centerofmassofthisinternalnode.|ignore_zero_distance:bool,default=True|Ifthedistanceiszero,doordonotincludethisresultin|the``distance_counts``-list.||Returns|-------|distance_counts:listof2-tupleofdouble,int|Anitemofthislistisadistance-countpair,|thefirstentryofthetuplecontainingadistance|tothequerypointandthesecondentrybeingthe|numberofpointsthatlieatthatapproximatedistance|tothequerypoint,suchthatitwilllooklikethis||..code::python||[|(0.2,1),|(0.1,1),|(1.5,32),|...|]||get_distances_to_points(...)|get_distances_to_points(self:_cQuadTree.QuadTree,points:List[Tuple[float,float]],theta:float=0.2,ignore_zero_distance:bool=True,tree:_cQuadTree.QuadTree=None)->List[Tuple[float,int]]|||Computedistancesofpointmassesandmassclusterstoalistofpoints|usingtheBarnes-Hut-Algorithmwithcutoffparameter:math:`\theta`.||Parameters|----------|points:2-tupleoffloat|Listofpointsintheplanetowhichtomeasurethedistances|theta:float,default=0.2|Ifthedistancebetweenthepointandthecurrentinternalnode's|centerofmassissmallerthan:math:`\theta`timesthediameter|oftheinternalnode's extent (box), the algorithm will treat|allchildrenofthisnodeasagiantpointmasslocatedatthe|centerofmassofthisinternalnode.|ignore_zero_distance:bool,default=True|Ifthedistanceiszero,doordonotincludethisresultin|the``distance_counts``-list.||Returns|-------|distance_counts:listof2-tupleofdouble,int|Anitemofthislistisadistance-countpair,|thefirstentryofthetuplecontainingadistance|tothequerypointandthesecondentrybeingthe|numberofpointsthatlieatthatapproximatedistance|tothequerypoint,suchthatitwilllooklikethis||..code::python||[|(0.2,1),|(0.1,1),|(1.5,32),|...|]||get_pairwise_distances(...)|get_pairwise_distances(self:_cQuadTree.QuadTree,theta:float=0.2,ignore_zero_distance:bool=True)->List[Tuple[float,int]]|||Computedistancesbetweenpairsofpointsandpointclusters|ofatreeusingtheBarnes-Hut-Algorithmwithcutoffparameter|:math:`\theta`.||Iteratesoverpointsbyqueryingthetreerecursively,which|mighttakelongerthansimplyexternallyiteratingoveralistofpoints|ifthey're known.||Parameters|----------|theta:float,default=0.2|Ifthedistancebetweenthepointandthecurrentinternalnode's|centerofmassissmallerthan:math:`\theta`timesthediameter|oftheinternalnode's extent (box), the algorithm will treat|allchildrenofthisnodeasagiantpointmasslocatedatthe|centerofmassofthisinternalnode.|ignore_zero_distance:bool,default=True|Ifthedistanceiszero,doordonotincludethisresultin|the``distance_counts``-list.||Returns|-------|distance_counts:listof2-tupleofdouble,int|Anitemofthislistisadistance-countpair,|thefirstentryofthetuplecontainingadistance|tothequerypointandthesecondentrybeingthe|numberofpointsthatlieatthatapproximatedistance|tothequerypoint,suchthatitwilllooklikethis||..code::python||[|(0.2,1),|(0.1,1),|(1.5,32),|...|]||get_subtree(...)|get_subtree(self:_cQuadTree.QuadTree,arg0:int)->_cQuadTree.QuadTree||Getsubtree0<=i<=3.||get_subtrees(...)|get_subtrees(self:_cQuadTree.QuadTree)->List[_cQuadTree.QuadTree]||Getalistofallofthisnode's children that contain data.||is_leaf(...)|is_leaf(self:_cQuadTree.QuadTree)->bool||Whetherornotthisnodeisaleaf.||----------------------------------------------------------------------|Datadescriptorsdefinedhere:||center_of_mass|Mass-weightedmeanpositionofallpointscontainedinthisinternalnode.||current_data_quadrant|Quadrantoftheparentgeometrythedataofthistreeresidesin.||geom|Extentofboxthistreerepresents.||number_of_contained_points|Numberofpointscontainedinthisinternalnode.||parent|Theparentofthisinternalnode.||this_id|Dataindexofthepointcontainedinthisleaf.||this_mass|Massthepointcontainedinthisleaf.||this_pos|Positionofthepointcontainedinthisleaf.||total_mass|Totalmassofallpointscontainedinthisinternalnode.||total_mass_position|Sumofproductofmassandpositionofallpointscontainedinthisinternalnode.|ExtentclassExtent(pybind11_builtins.pybind11_object)|Arectangulargeometry.||Methodresolutionorder:|Extent|pybind11_builtins.pybind11_object|builtins.object||Methodsdefinedhere:||__init__(...)|__init__(*args,**kwargs)|Overloadedfunction.||1.__init__(self:_cQuadTree.Extent)->None||Initializesazero-dimensionalbox.||2.__init__(self:_cQuadTree.Extent,left:float,bottom:float,width:float,height:float)->None||Initializewithpositionofbottomleftcorner,aswellaswidthandheight.||__repr__(...)|__repr__(self:_cQuadTree.Extent)->str||Getstringrepresentationofobject||b(...)|b(self:_cQuadTree.Extent)->float||bottom(...)|bottom(self:_cQuadTree.Extent)->float||h(...)|h(self:_cQuadTree.Extent)->float||height(...)|height(self:_cQuadTree.Extent)->float||l(...)|l(self:_cQuadTree.Extent)->float||left(...)|left(self:_cQuadTree.Extent)->float||w(...)|w(self:_cQuadTree.Extent)->float||width(...)|width(self:_cQuadTree.Extent)->floatPointclassPoint(pybind11_builtins.pybind11_object)|Minimal2D-vectorimplementationbasedoncodebyopenFrameworks||Methodresolutionorder:|Point|pybind11_builtins.pybind11_object|builtins.object||Methodsdefinedhere:||__init__(...)|__init__(*args,**kwargs)|Overloadedfunction.||1.__init__(self:_cQuadTree.Point)->None||2.__init__(self:_cQuadTree.Point,x:float,y:float)->None||Initializewithcoordinates||__repr__(...)|__repr__(self:_cQuadTree.Point)->str||Getstringrepresentationofobject||length(...)|length(self:_cQuadTree.Point)->float||Getthelengthofthevector||----------------------------------------------------------------------|Datadescriptorsdefinedhere:||x||yHistogram>>>fromcQuadTreeimporthistogram>>>help(histogram)histogram(data,counts,bin_edges,density=True)Returnsahistogramfromdistancecountdatareceivedfromatree.Parameters==========data:numpy.ndarrayoffloatDistancescounts:numpy.ndarrayofintCorrespondingcountsofdistancesin``data``.bin_edges:numpy.ndarrayEdgesofbinsforwhichthehistogramshouldbecomputeddensity:boolean,default=TrueWhetherornottomakethehistogramaprobabilitydensityReturns=======hist:numpy.ndarrayEithercountofdatainbins,orpdf,willhavelength``len(bin_edges)-1``.bin_edges:numpy.ndarrayTheusedbinedgesGet points and boxes>>>fromcQuadTree.utilsimportget_points_and_boxes>>>help(get_points_and_boxes)get_points_and_boxes(quadtree)Returnstwolists,onefilledwith"Extent"objectsrepresentingtheboxesofthetreethatareoccupied,theotheronecontainsthepointsthatarelocatedattheleafnodesParameters==========quadtree::class:`_cQuadTree.QuadTree`Self-explanatory,no?Returns=======points:listof:class:`_cQuadTree.Point`Pointslocatedattheleavesotthetreeboxes:listof:class:`_cQuadTree.Extent`TheboxesthatinternaltreenodesrepresentPlot boxes>>>fromcQuadTree.plotimportplot_box_tree>>>help(plot_box_tree)plot_box_tree(list_of_points,list_of_boxes,ax=None,box_kwargs={},point_kwargs={})Plotagraphicalrepresentationofthetreeasboxesandpointsonamatplotlib.Axes.Usewithdataobtainedfrom:func:`cQuadTree.utils.get_points_and_boxes`.ChangelogChanges are logged in aseparate
file.LicenseThis project is licensed under theMIT
License.
Note that this excludes any images/pictures/figures shown here or in the
documentation.ContributingIf you want to contribute to this project, please make sure to read thecode of
conductand thecontributing
guidelines.
In case you’re wondering about what to contribute, we’re always
collecting ideas of what we want to implement next in theoutlook
notes.Dev notesFork this repository, clone it, and install it in dev mode.gitclonegit@github.com:YOURUSERNAME/cQuadTree.gitmakeIf you want to upload to PyPI, first convert the newREADME.mdtoREADME.rstmakereadmeIt will give you warnings about bad.rst-syntax. Fix those errors inREADME.rst. Then wrap the whole thingmakepypiIt will probably give you more warnings about.rst-syntax. Fix those
until the warnings disappear. Then domakeupload