From 30a0a3c6e3731b450b18d1bf8d620d353999ead5 Mon Sep 17 00:00:00 2001 From: josidd <joseph.siddons@noc.ac.uk> Date: Wed, 5 Mar 2025 08:19:29 +0000 Subject: [PATCH] chore: fix spell following codespell output --- GeoSpatialTools/kdtree.py | 4 +- GeoSpatialTools/octtree.py | 4 +- GeoSpatialTools/quadtree.py | 2 +- GeoSpatialTools/utils.py | 2 +- README.md | 16 ++-- docs/Documentation.pdf | Bin 207480 -> 207486 bytes docs/Documentation.tex | 12 +-- notebooks/kdtree.ipynb | 45 ++++++----- notebooks/octtree.ipynb | 150 ++++++++++++++++++------------------ pyproject.toml | 11 ++- test/test_octtree.py | 8 +- test/test_quadtree.py | 8 +- 12 files changed, 138 insertions(+), 124 deletions(-) diff --git a/GeoSpatialTools/kdtree.py b/GeoSpatialTools/kdtree.py index 7151bc6..96ad241 100644 --- a/GeoSpatialTools/kdtree.py +++ b/GeoSpatialTools/kdtree.py @@ -20,7 +20,7 @@ class KDTree: This implementation is a _balanced_ KDTree, each leaf node should have the same number of points (or differ by 1 depending on the number of points - the KDTree is intialised with). + the KDTree is initialised with). The KDTree partitions in each of the lon and lat dimensions alternatively in sequence by splitting at the median of the dimension of the points @@ -34,7 +34,7 @@ class KDTree: The current depth of the KDTree, you should set this to 0, it is used internally. max_depth : int - The maximium depth of the KDTree. The leaf nodes will have depth no + The maximum depth of the KDTree. The leaf nodes will have depth no larger than this value. Leaf nodes will not be created if there is only 1 point in the branch. """ diff --git a/GeoSpatialTools/octtree.py b/GeoSpatialTools/octtree.py index ea48d4d..57c0d44 100644 --- a/GeoSpatialTools/octtree.py +++ b/GeoSpatialTools/octtree.py @@ -1,7 +1,7 @@ """ OctTree ------- -Constuctors for OctTree classes that can decrease the number of comparisons +Constructors for OctTree classes that can decrease the number of comparisons for detecting nearby records for example. This is an implementation that uses Haversine distances for comparisons between records for identification of neighbours. @@ -25,7 +25,7 @@ class SpaceTimeRecord: The temporal component was designed to use `datetime` values, however all methods will work with numeric datetime information - for example a pentad, - timestamp, julian day, etc. Note that any uses within an OctTree and + time-stamp, julian day, etc. Note that any uses within an OctTree and SpaceTimeRectangle must also have timedelta values replaced with numeric ranges in this case. diff --git a/GeoSpatialTools/quadtree.py b/GeoSpatialTools/quadtree.py index 1ef4e31..074364c 100644 --- a/GeoSpatialTools/quadtree.py +++ b/GeoSpatialTools/quadtree.py @@ -1,7 +1,7 @@ """ QuadTree -------- -Constuctors for QuadTree classes that can decrease the number of comparisons +Constructors for QuadTree classes that can decrease the number of comparisons for detecting nearby records for example. This is an implementation that uses Haversine distances for comparisons between records for identification of neighbours. diff --git a/GeoSpatialTools/utils.py b/GeoSpatialTools/utils.py index 4f83cfe..c524f1f 100644 --- a/GeoSpatialTools/utils.py +++ b/GeoSpatialTools/utils.py @@ -8,6 +8,6 @@ class LatitudeError(ValueError): class DateWarning(Warning): - """Warnning for Datetime Value""" + """Warning for Datetime Value""" pass diff --git a/README.md b/README.md index 20d6a9c..cd30003 100644 --- a/README.md +++ b/README.md @@ -81,11 +81,11 @@ N_samples = 1000 records: list[Record] = [Record(choice(lon_range), choice(lat_range)) for _ in range(N_samples)] # Construct Tree -kt = KDTree(records) +kdtree = KDTree(records) test_value: Record = Record(lon=47.6, lat=-31.1) neighbours: list[Record] = [] -neighbours, dist = kt.query(test_value) +neighbours, dist = kdtree.query(test_value) ``` ### Points within distance (2d \& 3d) @@ -126,16 +126,16 @@ N_samples = 1000 # Construct Tree boundary = Rectangle(-180, 180, -90, 90) # Full domain -qt = QuadTree(boundary) +quadtree = QuadTree(boundary) records: list[Record] = [Record(choice(lon_range), choice(lat_range)) for _ in range(N_samples)] for record in records: - qt.insert(record) + quadtree.insert(record) test_value: Record = Record(lon=47.6, lat=-31.1) dist: float = 340 # km -neighbours: list[Record] = qt.nearby_points(test_value, dist) +neighbours: list[Record] = quadtree.nearby_points(test_value, dist) ``` #### OctTree - 3d QuadTree @@ -190,16 +190,16 @@ N_samples = 1000 # Construct Tree boundary = SpaceTimeRectangle(-180, 180, -90, 90, datetime(2009, 1, 1, 0), datetime(2009, 1, 2, 23)) # Full domain -ot = OctTree(boundary) +octtree = OctTree(boundary) records: list[SpaceTimeRecord] = [ SpaceTimeRecord(choice(lon_range), choice(lat_range), choice(dates)) for _ in range(N_samples)] for record in records: - ot.insert(record) + octtree.insert(record) test_value: SpaceTimeRecord = SpaceTimeRecord(lon=47.6, lat=-31.1, datetime=datetime(2009, 1, 23, 17, 41)) dist: float = 340 # km t_dist = timedelta(hours=4) -neighbours: list[Record] = ot.nearby_points(test_value, dist, t_dist) +neighbours: list[Record] = octtree.nearby_points(test_value, dist, t_dist) ``` diff --git a/docs/Documentation.pdf b/docs/Documentation.pdf index 9ed18c58ea3d86c693a459472a60918d3c388e7c..ed9e5795decae77ab20393ef66962c3e782bd904 100644 GIT binary patch delta 9224 zcmajDQ*fpY7pxuI$wU*|wr$(CHF0vs_7fWuPi%AIiEWz`CzIrVzx`M3(_Pm|S9Mpd z!>-jYi%6e~NcCJ8;OwA&NLs)$>5tuz2vXS1I~L!%3Vlj<S7RNcBgyQ}CF7w<t|Bc@ zdyD?to8f3g`Y}gnrZcX@EdrFi_}9abiy8#XHx(+6(#R(ZPrnfHPUoQdT0#E;b?W+F zx%Gi%0b>tC*rv`VBr{cdOE_to8tFTfZX7HvIM`Loi&f{HoSC*V#15eI*G(7ePNbrl zyon;OHMN!?h98YYgB;@Ysr;oG`-lKxbzBmjrRXcOo=qNZcu3yR`t+r^5sPIaH+%O7 zeoE2hYP0;-!fcx>!NJSMm<~U+I(e+LG+#|+JwpcX^PhSJSM4Tr4DLIenGWP**aakQ zIs{863wIAUOH;@HRFerN3L5BCn--Kojtx!^swKw*`VYjFTA#vAYxDE3>k@4*{XOg5 zxrWL<_{e9?B6&!Eh=r*3w}YIlwO3ZhP5z~YsuH-Lbm_JH@Fx=0=fP=uZW2y!vMv{L zHN$eB$U9oUGY=tCARtngaM@*GKbZ(%eTH~Gy7!v={rb=MRnC!A$V{l*O*v{XiHFFN zhDzcF;K>8^2l!Q{&tOlof&_vHr-akT2cmnG(cmE>F(do~_K$w=|1-OuV{w~d`g(IO zQo6PXLl3?%mEa9!J{Ybv-Cy2)U7NbYP5kDV$d2XaPE4H4I&c7Q>;pb>{oMq;i|ngg zSMyzOq6H5<&~u_Vn2#kYt(fP*uffdAxXjTANJCaZsPD>uU#+p*dX365w(@z^^^#9s zEKaVn=>m7JU+Z>$YpL!=k73Hb#e^{rl!-DM;Sk=Jrt@?IML?fE)pHaUG7)=Lq*)ht zu2MSYV@+1k;d|^tW%Uf1!<}Z#JKacXwvp*CavCgDL3LdU43b0Xgc1|~?nU1di=L<f z_>)T|=T{|siU0$i4lG6Y0u=#-2iKRc=worU47Fro#$42UxGvcm7QLrg@8YOaak96p z*t&bR_n&uLdK6Q%t4_>&i9G#Q=)_gvs#2YtJI5}dpEeJj$-iWR$Xwv8_M*cv44BS! z?Mnw_n}(e1OODAeBT-c^Ugb`Zy1o|y*~|s_v~H3*`N<!>xza(FoXt4cykP|4VaSIf z2@vo@xRU6^p%Sm2XnioEUFcps-^u5CvS#GBs5)u??ycJiu9*+z$f$K#nxnK5mlZC& z)7piIFQ8v;<%S0~VM63mi@dhM{)9^SAfc2axmGOva8fEIrPMDnAvqtBLvKC;P-(;A zM(;A`rR8n|rm4mFwCvC}z>$*ih`|KvBV6jENTqzm3JK8|5I5;xq^@&5v=)63%*d`= zj=*jy?*>w_rc5eP0ghRq4)r`DUya*C`aHr_nfr>08`7{^6-Jo<7R$G;Y;UL7RfX20 z*ZD6Idn0|#m<mMmc|mbiFYXO+=It7U`y>ioxY++wSWt4LBCO6q$|eJH<L44JDct$4 zWX3s)+i{S`+WY%oF*EZ@Kl-AL<6XI<PnO;zgC#b_lnzVFiZk*7ez0-ozvPXWmE0!v z=I!R<(JD^YuV+Y>E=%adn2X5C=eDbYgq4mrZRIkL@E?{kj}YyX!kuS;6$23-!>aWi zR4-kg+HH8>ik9=EW~sT@=wyyQ(WTI9auE6SU_p`zf}J)vxQ8XX>{-JaYl?yFLSsc( zkR+7)MuP7K%2pfQjBJdU(TCJbLU3ioy5hViAa)a$2{!5J$G$ykvb4}jtmF`?dYn() z;d#oElj_@od;G)gdHoW=#y>T}Dhax0-Q19)cjS#s)H27Z{W;9mpha*MtF`?uF=OG= zM2~SM>vZVAj$psD6k!XK_Pt-m%Hx&|wqQD|vmsM&gJuw{JNOx1XF9E;`nIu7k;mTI zbHA4(PGlN3(3c`~vQb%W)c52T={(>qjj{u`=;VhJw~hD8+^9M*KDnG9bk|Pp7GPF{ zL5e>rt=gfz8>SL=762hERJhO;pSxpuI0HM5alNUmm*$v4Ji9c}p;%yLxj(w97=LWJ ztETEA(;y%q6Ir?5Po!BpJkpV=pio}9%^Zd2g-~K{pJ_r)xUjwal}5ANHp9VgKBUcT zE9`=3Dlb!@!jcIr3v|O7#RnPR2JNodYG)Mol`-7~7FbOBRCJRVXb`BTdXw6tv+>}= zX1AtQF%J(JFjyVKo!NxXE}WavPU&G19oGLnt0%{_WlWLsK%7$U*r`qJN>rqRmtU~! zVt3+p_HecE??qkI%X*`)4klE4r@#8W<iR*!HSO>{++!XP?pEy`e%u0G)uLg9nwqc) zO(-rS)O5mHJ27cHLhCSgFB;sx1-ZIg>U6A_1@&dnHTr|32dlx2$bEU(;bqjywk9AG zXB#$&rL>EeXzOSm`}b1RA$(x|9W@4}QV~YVb*D49{#5}i8e}ri8Nk6X;)X7K^srtK zDr~`7ms0?+AsQs#wmzB||CQDJ0i+bhK_XR@(<V84nXp1Mwx`o_zhs>uG>KuBK#t^L zF*1?NTj>>YEo_7ma-zec`)q_D?7I})@Gyan2@%K`f4Nc3h?6}1wAPX@{*S8ZSpFEb zXm|{>_IAJP=if0_b&irJUX{4g(bJ_jT*disH{=X<;13mg{mpVjLC%r6&T16at`B2! zf&Kn)`NMa#Ar4Ya7zs)dm|xH)y?bs=wsfxFz&StzkTf7j5dwgr)U95fHY$u`^C$^Z z=$DN>@XxaZ9A$iOECur>+5*z%;r;?<tVci5&zb4d^~c@6A6VXallv@BwNBj>4=FU3 zs#M+8gMK%CbAOIRA4{uhxuPF(%Fgp0TTN5mZahjg%g;iaNKE#Q+p61ec8m=FxuS#l zT|*BunZYY}`vbt;C-?O?5#Yj=s&TQ4z3IsatNiv?_hf7VbNjb=Wl4oYiD3pSyjyvQ z>2?{JsmALc8)w}&Dlj@|O4wsb@JvBDS#QDePSn2_WErr6a~2#R&Yp9E-ubs`U64fA z90plfvY92lW=`rP`E<L}e)e-k>0nC^AKHQBjJ=v~xKe>lX6Mt&^D=4LsnIS)xP`w) zOKoXXYVIG*B&(d#?3p)#+Mf1^#OYkvn6{y*zfCe7lj;@1C>U4{dZq3k#Pv67u2J24 z5kb&}%~8S1{cL!c1@>^|NBF!=8iU0g+0KDBIiXJP?|-yH<kHUjwjCgED*<)RDj<fu zKUTN?b_kF+e6DF>xMg}Ta`EhS<ytCWJ5!5yCD#zoRXupd#y#uP%mSvdL_VbszaoW@ z!z2#@-W86=E1X+JZ>bFCy_^mh<7M6!t*gfmgrw-8XbyiUj!xQ07?z0RDb2&e^|8}6 z1e{qxLhx2F1F;t!bojVbnb+4{x-6MtGB-~?X<+Q_nLt+-hfFt<BVrxydPjKuQ+Yu7 zj(e|MAhbXw!j#LJGzyH83#A(yMk(rMTV)OQdo&G7{FWL`3f>s4*n!Ltam0#dzysIz zd(GkI7wb(?KoCu2+}}sFnJh?N36`iNo)u2cZ;}i_o5X*6ZRfNbZk@T%Ddgmdtzf6f zYk=q^?W&9By!9Im=W&E9Lg~Pw`{gHQtB`=o$d8s*0Y!}cY%4&e8CWY4DBr;8jNGLm zjf|e;h}-R2@>#$xM<kDeApH<##aaxE^%R9vus<xCNBWiS`Za;&PHMIzsETvn6RGPL zB;Ef$GB0BZz6om%^E04ar7W?XvKij;zxxg;=nB8iH~$b=4kxOABww{$-z4QNdycA( zW5QU1H>MG{NBxZsGuf`}ofp;g>FRQdXf;P2ASkd-y?dg*bDW<tBcIIfj*KbJGUPcT z4oev~PmJ7KQrl(niqa*Bq9&m^)xxn+!Xzq}p;M!3QU*V(P^(3uV}5^kK18UN0UC8; zr0?k-_Ew(*hgK{w8RF-qOa2*syuRn2p~96Y_E?RD<^1|G*u;??RO_H=WQNmcRt%Ya zC!pC47aQ#+V#gE;>;$6OzS^TZzV??WzlZ*qr|Is8Ds<vU@wdz`syl6hoH=zgzUEBE zLHqWis0fMeZ}MA2*E3Wr<Tr-`3xM^qlT84new~l*Sy5%jl5xXu9j0yr|4&%upD5<! zyX!PT4n$Q*o_^wYOnjS3n4sZ_wSftOQO_|4O0RD)KX!MJG$ozuH0q4n>=Mzi2f$Ax zr61%u{(RFCtxsUA!R9y7FwL+wiV?$kSm%D~XfnsN58;&{(Ta>xNhJmkVF0{lm;cJ0 znQB(WER*0-OLzX!B3U~kz~}n8985k!zyA|40)i5YP*RoburkIfZ-u}I?~g0~rGY-i zT0h!%GSzM{Qzl-NtpVA)u|c0K{uwQ;m@W*Zh(}&0``Wy9toFc`=%3C_R!|&B?A;WZ z<uQ_{uvnwwPSD5n4huhAf&+mv93j~~dq>EfKu{mz<htq}!Bs>#qoj}EgHvt8tw(iu z_(_geb>=O-0`bh9n4Xc!&9T|g*fbc-vMay(4XUC&*>5dFk%`Vx2OL_g_YjzChm>qi zwB;kmnyaK_V);O0ElcZXMvXc~gn?OieoVOVTHh{CL$b_j!emoS3sazEY6WAL9D2cI zy_%x2cwo{yh81$&Q=i49<_x|E&PsZ?)X~~ydA9QI64L!?$fkFEf&d@&g4=MTfqav4 zdb-^VJJB7S7IOC}*oC9}G{_6Wg(*EBtr!kQjOT~qFa6aK!xg%jMIy{&SclsfYfoyl z4Nu4S(9#~lDz!BhMl665U<lx^df$vG=Hs?TLK>%5vQ*~X`IT1yh;`8o2e^*}8@Z>E zbAZjIst<an|4}^<$GweQ?@yiE+G}pov#%<S3Lj{c4Ru!-Qy2JUvNKT3QRY6C@^XF1 zLWR5AWiDM5X6kY5F9f29)j^|d;u`(=3`->EFHfSzksK$a(FO!}V>cWKl1y=#Lfred z{W}r;M!w77z|->1mE__X%D!`=ANVV(IvrK3^WZR-bEOVv_hGUmd~R?Uk1?)hE{KD6 z+EhUbysG+-#GfCUcom4JOkh;2S}kqt3bha&3xenlqA)3q?>3N>EEWmrMeG7-LE0U} zPcR~_4JOI9^3(v!J{QE!<<em*I7_W|>7U&Xo#_#jKO}LJx90I~_+9gU%X5cKGhXcD zJ#Md{M(;;#+q0vGGb0%2nheS|BdI*t!5yux@43;6%CooumJK)Wox}IWvf7ZKlrQ2f zuKSCkBA6Rt2NgW_@vj)kMANnu-mH#s-(pQss_U-|Cnf;ERn}u4VG9GP`3vQwm~(Zg zaJdQ|OS2to-cTtGz$hYj0Ra1Pl5FejM?yc623L*(WivO%q3St5!g=@IVA{A%vT%73 zpeHeRQoH*U>&;_#1Q99t$sOjxok?7iRM4#!@K={B6fOB4bV<MNR6D90X8ainQu*AM z{tD6m;GoA1XMl4EC<l9nsz**i?=ZezG!11;ezZ(^Lk|-pu>54s<I)BQlXsAoJ=BB0 zU_H2qC_w|(m`&O;U9f<>*8vCC_OrJ4S-*r#qr*5N_N)&J!8Fp8#VQLy0)BP;Ktt%2 zLODU8fHo?BYxPfCbr=)}JN@*!TA{7?E$NuhYA{&l>0YDUfV<pe5=mPzkclgv3%&~# zntX{#GPH0wv&N$*`Gx^@EMDSJ6<s!U6Ymk3e+dHRcS~XxGALkfZ6?-vCZBOSP?(&A z2zEHeJj$GiVZ~bbBQ6waqz{=TMh)E{NB1I#5~5b}_UST`{ZeB{{F{$}3ag?D!e5>N zIO)wQ-Rd8YqGyk$Y=jC4a4}HOvR3PU1m@hdcnUG-@tw3ebj<pRBr&QJ5g}1)R~lQ_ zZ@=$lkb3i_S>*tcHC|Ja2whTVD-IOVJ6)_u;s;`6t2l96=Ad^qMk}nySG~24$*Sqg z$;nQ=jV{k4A-^669QO9*3FO0!>-A3igW97{=H%^fmnKR)a^!p(&0EVXgps9~=EAJv z8{;uOhoOF_50%om7N;mCAR90S^dNfIbE%$A+<J<_(N^I4$+t<ByaRMVX`-PD;RYvn zusYEJW?vA<&N19kXfgu&oe}Pk&5!K5tF>OL(&Dgz@-a>qHbPTo`&=rCHS4d1^;&kf z)*Yonmg2YSubSpLGG+xYDR6!wa5n~~kNp#eOuqol<$FF6qlB--FdXQR30|-fhX}re z@_MmoDII`>QP{74JQG(NhUe8Q8o@1wlAhBp5D4Z`OiVAIm~ubP)-Hb7d%$v~n1>e* zurw?mU&$GKb+`67-rLOVEG@wsGS%e&bQ3C%09DhTaU>`)anc7VcG+f-qd0KUYgYTQ zLO`QZ`Cq2)*h?j~80c%M{5VL1%WN#7NN~wcs03~WDPPd2MNT;eE|ZMmB`TRI?nn&_ z;kfpW4Y1QzI&4DB6r>`ZRQwWc9d3Fn8OC0THP<EvQJ6I0E!ao8gt1#n(gND2%zJ8a z#r=g%4vC~m_A$Zl4-`axvBG?Bef`T?H23b$!yz=XCxUheXE4m#P9S!~uW8g$Ex6&l z$OjbEm3poi`)Pk=a>L%4zz=2?1daagBS`G_$Hhk7!_-;-o=ig_%J9aKaIfj3S@Etn zMqz3Asw123C}fPiq~`wUyyAny)9KKXuFEtz1V^3pd+q_s-kwCIEiuG}N`FZ#JEHS@ zqDC^A7;5o{R;XzT>>qVc1;kBvu$crC8Zkf}t4UqtoIOeZGH)ILBdeK)492s(rwArQ z<B~mT2|q4nF0qD!uT%8jpI2L$;P|1RdApoR;AxQEF+6e3MmMynl_q}A=d9gECrO+z zs$tW1KE8m^d^iTdcpL@KWz?<F*xUYEswKap+mGWqeC=BC$Pm)wZHZp-dJtJqtprf2 zxz4yRZKUwWTu*B`ukRTMUMGLn*<EwD`nmd1*24cymUHs;pnajC<gPE{qSn88ljSi} z2_ddq=9=mCF9iivJ;<8ly6_nFJ@c3m1K{1g93##br!~qhzv%m3Y&eDAky@Do{HG$J zKR;eqB?c`n+nHxtoV)WWlSBmr?12ySbyRjM0jGXmNaJ5|<Odv=wev=A>jr&vjLc*6 zSPMF<EEUulPkb8t@pBL`_9eki=NL}<;a0a^f<JOrCK%f*v%CLPH-a+Pa<po=H67h} zyyt_8*96Gw(?QLb*mYcQ?z&jME8KY#lV&-Ufs>GAF8)u~M+;1X9yGLDl)%5$<wn#u zH&m-2vEkz27<6;AquojkzL&F%m9qEQ)kp=-*EIMb-!dyX!Op83hw%!;u;f)u+);0I zs1ifrt5DtcRk|(ZL<|(!hV9iBc<Q&jtB7SSSmc}z-D*!w%lM^RzMF`;$HS`6KY~Y{ zHgoI~S9%==ezqdn>N1wL3c!fTGyH1qUnnKZmFa;!y-xEJf!q!Fu9aJp8FBqsk5)L$ z(ttMb+|mX{bUdBoX^EBZ+%FfcWAWkrmkQ^9cBWEzJe)PVpxn*EBI-Q+EA^;*4ab)Q zA$PK!ryz4R%&8y7WAn^LB0gLT27bUCU+AKmpZoI1^)=cUNEqThMgsBvJqHTkYS@>y zlD!&y)%(>#{U@O>_KG^z%e&cPHqUpT$8#J~SCI2{rPC$1w-x>h_Qa+&KBmL(=&n>< z1T3z!e|HgIraVAbmpncU6uR3C5Eke7-ZJ&4eC^}A|Nb1l|Gx0*ZgtSyeIs*ZGeY6H z<~GEd9qp;{);52KV-rx<aS{r>dS#=bba6>o;r6Kfli&VD-`<*(uTTPCXzQ-m<qRTD zPdO4i2j2$9icEl80HKcXVBj6`Nb2$+tZi3v#+&O24K5h!#dEmp&oV|biq2-Z*)<s~ zL!JtDzW7wSlAC&((?qzPW3xsn;p&mPlN1i@D@lKr<izDPvlAex)Xi;y|CcG|Is>ie zsGG+@VP8T&1nWH&d#Z2;+AofD_Y)pR<zJexWg@MdtJ~Po_8ExA{W~534Kq8B#N=%Y zO1GDYSTforlme5xI@JpsvrAY>r&m{P6TNu(FeEgkkc{ArV!oP}u=V3Fex}|NiCyX^ z>}x6h+|PH3DKvh?gwGrJ8(|NY7&zCx_)K6PjtouSdxq+Sz9Z`_b!3hThjgKLbpF<` zM0&rzVTif^@1n+DA6P_<(&qmu@i}c?Sa9C|jR8Q7t}$qX3kBFwE|T_PvZ7VPD9xD^ zuak9O@HoC!+fh$hD{{QnQ`dESEI$i;hlE$dZZW9i9*>nwMuQ9LM+H+Xd5@C1ar*4& zc-=eUh?Y}3W=Q1nN;XNBK}<;(SidYuyyIW`^h^<_y!az$;kvQ>QN5HMP4-!6N9h;N zoC;9Dn^w={7&~n{IeoUv1_{PvSY%*`N;dOv`~OoY5uEzMP#v5kdo!y@P|e1<{Z+E# z^yw#FW8=Y8JZ43f&Py9yAVX7RP?%X>D_H5|ty9CE{`<$quVveR&r5toc=0#qS}0Pj zl<v>}_N<MjJWb$fG0|&4sj0Rx{QrJt7cBtm5aPRlG4jE7Z>!e}0gC7T5JH$rmnheB z%U>>|ipG3TjGu>>@P<zOCO><tx%%GlPm$xMcC<+^#N$)8o<sqdMF*)rn1hHg{zz-o zv(p$y?8R{`*D^|uOGq*Y)iR<j(R0;cII}%61OvV2+VB-PyHHXXx}Kcnd&?(Bm7_wq z<2FL-%s%4{HHcC%{(E7tE&8nZUkRgXYwluAyBdkg=J(&q?}pr^;r;x|AEl71AocKx ztEFr`ZG-ts$v{^o%;4Z4LQ_gY&J%%cf?P_k#_f1ckwSE0su80{#F9^WJD*PjSCFwO z9!Kh^m!aQqayfRJUDMgEDFWm0LEf<|*bse`Ta*KP^zzBHf`CncRn5%Z&)`!JmAv_+ zf-=xAQ)1}+(Rl%O(5&fqaBI+|X(;$2$i<8VIPuRXM@YFJUil}yE@(-eIAH<l5>FyM zhE_R4dldNeHH_g)J2Z&n^Xec31-~F2{TP8Eg=pv(jF$Q{$&hdLVD1pMsWPJiUKwE& zWxyCxIHZ^P7j-0<?abPPDvW^+WN|TxWb#{jK(c7Rc<9qEg`!w^gbocY0kW2^eNd@3 z03N8)4wr9GqmA;7p1x0%QQayG>mU~^q)(!uhah#_{mr`WToh(CT?N{3b~-lVN6I$| zEW}5lQ}2Eq+^!MS2pVv|+fC^K#%64xC0{bXl)B%Ek)Y1Q@S-a;Dx|o$iMleX2gFp( zFYhaI(%z3h#TozP3xf0)%oRB52=?<aks@2|#+<v&_%P8D&p_Gc)PPUOY*Q}BEF>~5 z+~7hk9{o>VT3nrAcC_hEQMvj0Ky7Et00ZmPk(-^<rjYGrZ%8;`4n(pgs%ng2UrgKr z>6Uk_)WR2{Yru81%w^!rGASbvj1{FD8(A%tsk0d5pZ|OJXfyes%fST73YZlRSh|2n zkA4AqI=?fH7n)zN0@Mm+-?X&SBXv(nRn68cEfvd9As=Ivs_lqS;;XJvH#{%jDl<Jv zTR9dPnkj^~`>d8b9G0z||D`f925cyh+0)@<^!LDSe{^K)d0ccpjWQ91%`Tjn$#%jR zYs(KnoWzLrq23~3k*fseIk;*(lGOc<>it1V87b+KrMAh13LM{>qR@|e+R+o`!zpmy zlpag%T&*|YrDF^x8HkmIYkIa^zFWV)uW6?AN|E*5fa5nL7}P5l7FZvpevpLm#ZBJ0 z0ke?^P++MPJ)aPwd9ypDK`3=+n9;n9wN`MI2g}wIHX?fj2poEWkMR)nctx^j2mca- zv9WtD&$zg-fYIp_2LflynzI`7Jk?oL`eV0vR~htOhF?txhYTq%%MHE1&)A(8;)DNT z3?OFMQ{K2NHp4)gEE2CbY?F5lDYzQ^u9&m<Ya{)~dlSD2uDYUdI%`VjJwMvPq`gi^ zby^dR{^TkWnvlnH>9SmFB+DIP%l0BGzP#on>;^~V3^41qqa*ZK3KQ>~Tj+H!3YT{; zFr?cDg(lh6zaU6>x24P|qWtuZOe$dZJzt(DeHkqD^pYSlvybt$OE2xh%?t`$R~1QU z>?!P_9iM3pcLl1dP3ygg$wvNIL5Rj{jGJ(O!tqgq7X&T8>VhF@J;yiQ&oarhsZ<u_ z87(?T0M{CQwL2Cevw!LFllOJOdOFdwbe1|x=8%_1oi7x1oqVMxIafh%V&1X`?jjjJ zBRn{;1vHZ`7U)e+zF;Rf_reNtcAqSy+sKvCW4aw8Ol`x>6!0&{E5vxah!!8agy8Z< zZYF!xFgCR`%s9uzn_01Ju{10#-_b?+97s&y0ZaDSk-$Ym<-u&!3;594<=^8`7MLNB zmUS@CH3I^6%+jXO>(2D@!535CEPcy(4-_4PVgBnz_3`HUwMk~D7|C8#A_ct^jYH<M zvjU+k4_6k0_RwH-A|xb{>~o%Tc{L*i>p{kZA$OOsdkz#sDIY7-CWbhV^ea~z=5W(y zK&Fv}eWT148LjR<1S?mcXPQw?WI0%6fUhmb?!d~&{e{|yE%EyEQ#+Nq1SCLpx73o; zY}%DqtC5yFvAd=y(k4?DxRNZ;OJh?z{O@Szr!K<B+0s`E%vZZ2o-D>ieDqo3fBy+4 zEANCdtdE}USmOv5w8wn)kNosbV-92&l*EOb5xcr{h%aJh#L$J%0qe*CYw)%KYly3E zDs~o579Lg}RyI9a1ZG8N3kg#XOA;ChJ~kFMPL}^`W-L-b9;-=;Nl0->v9PmoiAzba zNb<6Cu(5N9v$9HY^Rh{baY_i02>d@Ih6v0GmQL0lHYBVpoIL-h=_%7El~b*;B4@Ia ztGk1cLN+6U(Iq4_M4;1R$zozcqV}N&<g#nCn{DSMasF&jl^On!?&LeGmBsnM>~vhG z;#6EWT=*Hw)Op%B+kF3TQ-Js8_1Ld((x=ybWa?6w+rBA8cW!e;Sfkm1Wu`5P0IT28 zty)6T1#Xkn3six!2!wLFaYx~ckhjY_g;&6HgpMB8ViLkI?!tFi7DMR`sJpF1t&8w` z$8KsClNUmEQ?yBFK;&^s1aFc}mK4Tr!n+|dbPce&=^q~JJ_Q-Mbsg5$UqXJgSlW?! zWgUUhfG)_rqK`-_lDd?f5{}StVKm$Jxm&ai`V7PuM3K*00HdcUeQC)#SEYrI_+VN$ z>i!CSTVr8f_>lox7I39dSr?dG=#wC>Oc?fEfp##a5Z%I@MfHTG+Pj|GqR5UZ!Z=7n z8D`h*nhWg@i5unL`fe9ODoT$kMHa&``ZL)mG7)|zOEu4eM@|j*c!lp>sLNXu!09QB zH&|=G_${0O0GZ>IX7%BegZxm@WismMtp}U0E=t>ZqP3-V4ZV7Tw5^$hXw3`mZLjL_ zzDrFgawM|*AC(pEIoXS<3@8jJo5-8UasMIkAD2j%NVJqIEUXiS3yx3rSJbR?thdZ) zOm72VZBlo|5HylVos5Cy3rX}z^i{h&xZov#3DU0ouDnW(NZRZ{iQH+C4-kyRy4TuS zl*dY4p>VpNiTOV?gkKaO8O^30Kcw>_cn6-*X}<ZZHo(}WJM{T9=wPgPGi)I$lA=*0 zQJpf29z<{KqV(tLz;5i;Zd?nmBgjLzn_=$C7s?gN34kjP$ltDB<?VRjqx?om0x12! zxWx>Q1a|7cH)Z~s>|AZFOw6gMp%XxGlA}<06hd>f2RxLg#~0!ezz~vj1pKW`Xbs_- zMM(%!a>4Qlc5*>_0Q*spvQfR$BFgOLn_`28)E@9ugHl0`9Birr?UBX-AqD<HIcJ>0 zwTr1-4ptz_hfD=dY|V!_9ZbuD3|IvjEkL`VPlfQhz|RWIe`7(#?kCfM&<02NnPUR2 zu_^SWn^?G3lBW$GPsZwpF+{~`h;cx%1$kitxe1%I3tm`K9=VHNs7gVlWHwA;CFcv{ z+3zmWr|h>2EfO)TAZv%Wsi)O8s~{R22hoAD7z!h@*E9mPG@~JWAf+V23H0qf{mxjg zTZ%1hB%1&wliI_WNJwQHK(r^*8c8L^k>H84g;+q1_c$5%)YZIgex`vsb^?xJB_Xeg z`=TeVfp1vIzI#{NF?2>RrK)pDIG;|c9G8;%DjJVwejqZsyh@K{02~=m^o#d8Pp*_M zBg*o%_@7t~EB&9O;dJ_doE=+<EC2ruPT+qTUE*@9f4w->@5jHB3EzqN#jfBol<6Qz O;n)x;DJ7Mq5dJ@7xs@mY delta 9204 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 diff --git a/docs/Documentation.tex b/docs/Documentation.tex index 828aec6..ccc16a2 100644 --- a/docs/Documentation.tex +++ b/docs/Documentation.tex @@ -64,7 +64,7 @@ \title{GeoSpatialTools} -\date{Feb 27, 2025} +\date{Mar 05, 2025} \release{0.11.2} \author{NOC Surface Processes} \newcommand{\sphinxlogo}{\vbox{}} @@ -248,7 +248,7 @@ to True (default), displays a warning if set to False. \section{QuadTree} \label{\detokenize{users_guide:quadtree}}\label{\detokenize{users_guide:module-GeoSpatialTools.quadtree}} \sphinxAtStartPar -Constuctors for QuadTree classes that can decrease the number of comparisons +Constructors for QuadTree classes that can decrease the number of comparisons for detecting nearby records for example. This is an implementation that uses Haversine distances for comparisons between records for identification of neighbours. @@ -759,7 +759,7 @@ Check if point is nearby the Rectangle \section{OctTree} \label{\detokenize{users_guide:octtree}}\label{\detokenize{users_guide:module-GeoSpatialTools.octtree}} \sphinxAtStartPar -Constuctors for OctTree classes that can decrease the number of comparisons +Constructors for OctTree classes that can decrease the number of comparisons for detecting nearby records for example. This is an implementation that uses Haversine distances for comparisons between records for identification of neighbours. @@ -1131,7 +1131,7 @@ temporal data. It can optionally include a UID and extra data. \sphinxAtStartPar The temporal component was designed to use \sphinxtitleref{datetime} values, however all methods will work with numeric datetime information \sphinxhyphen{} for example a pentad, -timestamp, julian day, etc. Note that any uses within an OctTree and +time\sphinxhyphen{}stamp, julian day, etc. Note that any uses within an OctTree and SpaceTimeRectangle must also have timedelta values replaced with numeric ranges in this case. @@ -1484,7 +1484,7 @@ A Haverine distance implementation of a balanced KDTree. \sphinxAtStartPar This implementation is a \_balanced\_ KDTree, each leaf node should have the same number of points (or differ by 1 depending on the number of points -the KDTree is intialised with). +the KDTree is initialised with). \sphinxAtStartPar The KDTree partitions in each of the lon and lat dimensions alternatively @@ -1503,7 +1503,7 @@ internally. \item {} \sphinxAtStartPar -\sphinxstyleliteralstrong{\sphinxupquote{max\_depth}} (\sphinxstyleliteralemphasis{\sphinxupquote{int}}) \textendash{} The maximium depth of the KDTree. The leaf nodes will have depth no +\sphinxstyleliteralstrong{\sphinxupquote{max\_depth}} (\sphinxstyleliteralemphasis{\sphinxupquote{int}}) \textendash{} The maximum depth of the KDTree. The leaf nodes will have depth no larger than this value. Leaf nodes will not be created if there is only 1 point in the branch. diff --git a/notebooks/kdtree.ipynb b/notebooks/kdtree.ipynb index 8d1e674..9fc6ad2 100644 --- a/notebooks/kdtree.ipynb +++ b/notebooks/kdtree.ipynb @@ -63,7 +63,7 @@ "outputs": [], "source": [ "def generate_uid(n: int) -> str:\n", - " \"\"\"Generates a psuedo uid by randomly selecting from characters\"\"\"\n", + " \"\"\"Generates a pseudo uid by randomly selecting from characters\"\"\"\n", " chars = ascii_letters + digits\n", " return \"\".join(random.choice(chars) for _ in range(n))" ] @@ -73,6 +73,9 @@ "execution_count": 4, "id": "9e647ecd-abdc-46a0-8261-aa081fda2e1d", "metadata": { + "jupyter": { + "source_hidden": true + }, "scrolled": true }, "outputs": [], @@ -90,7 +93,7 @@ " df : polars Frame\n", " Dataframe to check\n", " cols : list[str]\n", - " Requried columns\n", + " Required columns\n", " var_name : str\n", " Name of the Frame - used for displaying in any error.\n", " \"\"\"\n", @@ -253,17 +256,17 @@ "text": [ "(16000, 2)\n", "shape: (5, 2)\n", - "┌──────┬─────â”\n", - "│ lon ┆ lat │\n", - "│ --- ┆ --- │\n", - "│ i64 ┆ i64 │\n", - "╞â•â•â•â•â•â•╪â•â•â•â•â•â•¡\n", - "│ 62 ┆ -29 │\n", - "│ 146 ┆ 1 │\n", - "│ 104 ┆ 60 │\n", - "│ -162 ┆ -66 │\n", - "│ 72 ┆ 69 │\n", - "└──────┴─────┘\n" + "┌─────┬─────â”\n", + "│ lon ┆ lat │\n", + "│ --- ┆ --- │\n", + "│ i64 ┆ i64 │\n", + "╞â•â•â•â•â•╪â•â•â•â•â•â•¡\n", + "│ -26 ┆ -42 │\n", + "│ 109 ┆ -33 │\n", + "│ -87 ┆ -18 │\n", + "│ -94 ┆ -81 │\n", + "│ -94 ┆ 0 │\n", + "└─────┴─────┘\n" ] } ], @@ -303,7 +306,7 @@ "id": "bd83330b-ef2c-478e-9a7b-820454d198bb", "metadata": {}, "source": [ - "## Intialise the `KDTree`\n", + "## Initialise the `KDTree`\n", "\n", "There is an overhead to constructing a `KDTree` object, so performance improvement is only for multiple comparisons." ] @@ -318,8 +321,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 32.7 ms, sys: 1.4 ms, total: 34.1 ms\n", - "Wall time: 33.4 ms\n" + "CPU times: user 35 ms, sys: 1.5 ms, total: 36.5 ms\n", + "Wall time: 32.1 ms\n" ] } ], @@ -359,7 +362,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "130 μs ± 847 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)\n" + "101 μs ± 3.52 μs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)\n" ] } ], @@ -378,7 +381,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "8.34 ms ± 83.4 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" + "8.17 ms ± 38.6 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], @@ -397,7 +400,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "8.28 ms ± 105 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" + "8.22 ms ± 95.3 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], @@ -424,8 +427,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 16.9 s, sys: 144 ms, total: 17 s\n", - "Wall time: 17 s\n" + "CPU times: user 16.3 s, sys: 74.7 ms, total: 16.4 s\n", + "Wall time: 16.4 s\n" ] } ], diff --git a/notebooks/octtree.ipynb b/notebooks/octtree.ipynb index 474cb2f..fac3bbb 100644 --- a/notebooks/octtree.ipynb +++ b/notebooks/octtree.ipynb @@ -44,14 +44,18 @@ "source": [ "## Set-up functions\n", "\n", - "For comparisons using brute-force appraoch" + "For comparisons using brute-force approach" ] }, { "cell_type": "code", "execution_count": 2, "id": "972d4a16-39fd-4f80-8592-1c5d5cabf5be", - "metadata": {}, + "metadata": { + "jupyter": { + "source_hidden": true + } + }, "outputs": [], "source": [ "def check_cols(\n", @@ -67,7 +71,7 @@ " df : polars Frame\n", " Dataframe to check\n", " cols : list[str]\n", - " Requried columns\n", + " Required columns\n", " var_name : str\n", " Name of the Frame - used for displaying in any error.\n", " \"\"\"\n", @@ -271,7 +275,7 @@ "outputs": [], "source": [ "def generate_uid(n: int) -> str:\n", - " \"\"\"Generates a psuedo uid by randomly selecting from characters\"\"\"\n", + " \"\"\"Generates a pseudo uid by randomly selecting from characters\"\"\"\n", " chars = ascii_letters + digits\n", " return \"\".join(random.choice(chars) for _ in range(n))" ] @@ -327,7 +331,7 @@ " white-space: pre-wrap;\n", "}\n", "</style>\n", - "<small>shape: (1_616_000, 4)</small><table border=\"1\" class=\"dataframe\"><thead><tr><th>lon</th><th>lat</th><th>datetime</th><th>uid</th></tr><tr><td>i64</td><td>i64</td><td>datetime[μs]</td><td>str</td></tr></thead><tbody><tr><td>-161</td><td>6</td><td>1900-01-22 17:00:00</td><td>"qCulqvN6"</td></tr><tr><td>-1</td><td>25</td><td>1900-01-23 17:00:00</td><td>"krL2tTTH"</td></tr><tr><td>146</td><td>-20</td><td>1900-01-08 22:00:00</td><td>"QCASMObF"</td></tr><tr><td>-16</td><td>-38</td><td>1900-01-05 05:00:00</td><td>"Wh9pptMZ"</td></tr><tr><td>-127</td><td>-33</td><td>1900-01-10 20:00:00</td><td>"PPIxvkbU"</td></tr><tr><td>…</td><td>…</td><td>…</td><td>…</td></tr><tr><td>62</td><td>0</td><td>1900-01-22 11:00:00</td><td>"6PxQzuHv099"</td></tr><tr><td>90</td><td>-34</td><td>1900-01-16 00:00:00</td><td>"pyjCOpgo099"</td></tr><tr><td>-132</td><td>-20</td><td>1900-01-23 05:00:00</td><td>"vZLzl0aX099"</td></tr><tr><td>-104</td><td>39</td><td>1900-01-06 15:00:00</td><td>"8kavFVpP099"</td></tr><tr><td>-131</td><td>-81</td><td>1900-01-24 19:00:00</td><td>"LFTv3XZ1099"</td></tr></tbody></table></div>" + "<small>shape: (1_616_000, 4)</small><table border=\"1\" class=\"dataframe\"><thead><tr><th>lon</th><th>lat</th><th>datetime</th><th>uid</th></tr><tr><td>i64</td><td>i64</td><td>datetime[μs]</td><td>str</td></tr></thead><tbody><tr><td>-152</td><td>-90</td><td>1900-01-16 16:00:00</td><td>"OIcjzfs5"</td></tr><tr><td>-177</td><td>8</td><td>1900-01-29 01:00:00</td><td>"xt99511W"</td></tr><tr><td>0</td><td>35</td><td>1900-01-17 06:00:00</td><td>"2E2Zp4SU"</td></tr><tr><td>-54</td><td>-75</td><td>1900-01-08 12:00:00</td><td>"wceONvH7"</td></tr><tr><td>50</td><td>83</td><td>1900-01-27 10:00:00</td><td>"nwuthgEW"</td></tr><tr><td>…</td><td>…</td><td>…</td><td>…</td></tr><tr><td>-29</td><td>-89</td><td>1900-01-03 23:00:00</td><td>"q8Ue8Uzx099"</td></tr><tr><td>11</td><td>45</td><td>1900-01-31 05:00:00</td><td>"6wKA4HVs099"</td></tr><tr><td>-172</td><td>51</td><td>1900-01-06 17:00:00</td><td>"MuIp2NeA099"</td></tr><tr><td>33</td><td>70</td><td>1900-01-23 10:00:00</td><td>"7dNMyTOj099"</td></tr><tr><td>124</td><td>2</td><td>1900-01-15 20:00:00</td><td>"CoQtomTB099"</td></tr></tbody></table></div>" ], "text/plain": [ "shape: (1_616_000, 4)\n", @@ -336,17 +340,17 @@ "│ --- ┆ --- ┆ --- ┆ --- │\n", "│ i64 ┆ i64 ┆ datetime[μs] ┆ str │\n", "╞â•â•â•â•â•â•╪â•â•â•â•â•╪â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•╪â•â•â•â•â•â•â•â•â•â•â•â•â•â•¡\n", - "│ -161 ┆ 6 ┆ 1900-01-22 17:00:00 ┆ qCulqvN6 │\n", - "│ -1 ┆ 25 ┆ 1900-01-23 17:00:00 ┆ krL2tTTH │\n", - "│ 146 ┆ -20 ┆ 1900-01-08 22:00:00 ┆ QCASMObF │\n", - "│ -16 ┆ -38 ┆ 1900-01-05 05:00:00 ┆ Wh9pptMZ │\n", - "│ -127 ┆ -33 ┆ 1900-01-10 20:00:00 ┆ PPIxvkbU │\n", + "│ -152 ┆ -90 ┆ 1900-01-16 16:00:00 ┆ OIcjzfs5 │\n", + "│ -177 ┆ 8 ┆ 1900-01-29 01:00:00 ┆ xt99511W │\n", + "│ 0 ┆ 35 ┆ 1900-01-17 06:00:00 ┆ 2E2Zp4SU │\n", + "│ -54 ┆ -75 ┆ 1900-01-08 12:00:00 ┆ wceONvH7 │\n", + "│ 50 ┆ 83 ┆ 1900-01-27 10:00:00 ┆ nwuthgEW │\n", "│ … ┆ … ┆ … ┆ … │\n", - "│ 62 ┆ 0 ┆ 1900-01-22 11:00:00 ┆ 6PxQzuHv099 │\n", - "│ 90 ┆ -34 ┆ 1900-01-16 00:00:00 ┆ pyjCOpgo099 │\n", - "│ -132 ┆ -20 ┆ 1900-01-23 05:00:00 ┆ vZLzl0aX099 │\n", - "│ -104 ┆ 39 ┆ 1900-01-06 15:00:00 ┆ 8kavFVpP099 │\n", - "│ -131 ┆ -81 ┆ 1900-01-24 19:00:00 ┆ LFTv3XZ1099 │\n", + "│ -29 ┆ -89 ┆ 1900-01-03 23:00:00 ┆ q8Ue8Uzx099 │\n", + "│ 11 ┆ 45 ┆ 1900-01-31 05:00:00 ┆ 6wKA4HVs099 │\n", + "│ -172 ┆ 51 ┆ 1900-01-06 17:00:00 ┆ MuIp2NeA099 │\n", + "│ 33 ┆ 70 ┆ 1900-01-23 10:00:00 ┆ 7dNMyTOj099 │\n", + "│ 124 ┆ 2 ┆ 1900-01-15 20:00:00 ┆ CoQtomTB099 │\n", "└──────┴─────┴─────────────────────┴─────────────┘" ] }, @@ -376,7 +380,7 @@ "id": "c7bd16e0-96a6-426b-b00a-7c3b8a2aaddd", "metadata": {}, "source": [ - "## Intialise the OctTree Object\n", + "## Initialise the OctTree Object\n", "\n", "There is an overhead in constructing the `OctTree` class. The performance benefits appear if multiple neighbourhood searches are performed." ] @@ -409,8 +413,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 16.3 s, sys: 163 ms, total: 16.4 s\n", - "Wall time: 16.5 s\n" + "CPU times: user 16.3 s, sys: 253 ms, total: 16.6 s\n", + "Wall time: 16.6 s\n" ] } ], @@ -449,16 +453,16 @@ "- max_depth: 25\n", "- contents:\n", "- number of elements: 10\n", - " * SpaceTimeRecord(x = -161, y = 6, datetime = 1900-01-22 17:00:00, uid = qCulqvN6)\n", - " * SpaceTimeRecord(x = -1, y = 25, datetime = 1900-01-23 17:00:00, uid = krL2tTTH)\n", - " * SpaceTimeRecord(x = 146, y = -20, datetime = 1900-01-08 22:00:00, uid = QCASMObF)\n", - " * SpaceTimeRecord(x = -16, y = -38, datetime = 1900-01-05 05:00:00, uid = Wh9pptMZ)\n", - " * SpaceTimeRecord(x = -127, y = -33, datetime = 1900-01-10 20:00:00, uid = PPIxvkbU)\n", - " * SpaceTimeRecord(x = 88, y = 37, datetime = 1900-01-18 12:00:00, uid = gYAwqD2R)\n", - " * SpaceTimeRecord(x = -122, y = 57, datetime = 1900-01-14 13:00:00, uid = L77bWRL1)\n", - " * SpaceTimeRecord(x = -179, y = 23, datetime = 1900-01-29 23:00:00, uid = 3jSwN6aK)\n", - " * SpaceTimeRecord(x = -156, y = 79, datetime = 1900-01-25 16:00:00, uid = OYEzYral)\n", - " * SpaceTimeRecord(x = 140, y = 15, datetime = 1900-01-07 20:00:00, uid = dNqilTiD)\n", + " * SpaceTimeRecord(x = -152, y = -90, datetime = 1900-01-16 16:00:00, uid = OIcjzfs5)\n", + " * SpaceTimeRecord(x = -177, y = 8, datetime = 1900-01-29 01:00:00, uid = xt99511W)\n", + " * SpaceTimeRecord(x = 0, y = 35, datetime = 1900-01-17 06:00:00, uid = 2E2Zp4SU)\n", + " * SpaceTimeRecord(x = -54, y = -75, datetime = 1900-01-08 12:00:00, uid = wceONvH7)\n", + " * SpaceTimeRecord(x = 50, y = 83, datetime = 1900-01-27 10:00:00, uid = nwuthgEW)\n", + " * SpaceTimeRecord(x = -158, y = 56, datetime = 1900-01-05 09:00:00, uid = svHopi53)\n", + " * SpaceTimeRecord(x = 61, y = -31, datetime = 1900-01-30 06:00:00, uid = wQSNr6C4)\n", + " * SpaceTimeRecord(x = 20, y = 54, datetime = 1900-01-19 23:00:00, uid = X0tJnSvA)\n", + " * SpaceTimeRecord(x = -6, y = 20, datetime = 1900-01-22 19:00:00, uid = 0K8N7iN6)\n", + " * SpaceTimeRecord(x = -129, y = -9, datetime = 1900-01-14 11:00:00, uid = 7yXQTGb0)\n", "- with children:\n", " OctTree:\n", " - boundary: SpaceTimeRectangle(west=-180, east=0.0, south=0.0, north=90, start=datetime.datetime(1900, 1, 1, 0, 0), end=datetime.datetime(1900, 1, 16, 11, 30))\n", @@ -467,16 +471,16 @@ " - max_depth: 25\n", " - contents:\n", " - number of elements: 10\n", - " * SpaceTimeRecord(x = -107, y = 89, datetime = 1900-01-10 01:00:00, uid = dB4jDgBL)\n", - " * SpaceTimeRecord(x = -132, y = 50, datetime = 1900-01-11 18:00:00, uid = ZOzYoDbB)\n", - " * SpaceTimeRecord(x = -28, y = 5, datetime = 1900-01-13 17:00:00, uid = YwB5kPdG)\n", - " * SpaceTimeRecord(x = -153, y = 25, datetime = 1900-01-10 22:00:00, uid = vzNI6J3z)\n", - " * SpaceTimeRecord(x = -45, y = 12, datetime = 1900-01-13 18:00:00, uid = kwHmr9mE)\n", - " * SpaceTimeRecord(x = -31, y = 16, datetime = 1900-01-06 17:00:00, uid = h3JQR5Ab)\n", - " * SpaceTimeRecord(x = -153, y = 25, datetime = 1900-01-14 03:00:00, uid = ZgZwvzHY)\n", - " * SpaceTimeRecord(x = -142, y = 43, datetime = 1900-01-15 14:00:00, uid = jd0JycvC)\n", - " * SpaceTimeRecord(x = -25, y = 81, datetime = 1900-01-07 09:00:00, uid = cQFUsvMk)\n", - " * SpaceTimeRecord(x = -116, y = 43, datetime = 1900-01-09 01:00:00, uid = MDpcWsK8)\n", + " * SpaceTimeRecord(x = -166, y = 34, datetime = 1900-01-11 04:00:00, uid = vXHJHSW5)\n", + " * SpaceTimeRecord(x = -13, y = 21, datetime = 1900-01-05 20:00:00, uid = KgAn9Jbx)\n", + " * SpaceTimeRecord(x = -84, y = 88, datetime = 1900-01-06 06:00:00, uid = ViZnTg8Z)\n", + " * SpaceTimeRecord(x = -165, y = 37, datetime = 1900-01-08 23:00:00, uid = LAjiwrGC)\n", + " * SpaceTimeRecord(x = -132, y = 57, datetime = 1900-01-01 03:00:00, uid = dOI2LWaC)\n", + " * SpaceTimeRecord(x = -156, y = 22, datetime = 1900-01-11 01:00:00, uid = RK8e20dA)\n", + " * SpaceTimeRecord(x = -154, y = 56, datetime = 1900-01-09 08:00:00, uid = KqJoV8UA)\n", + " * SpaceTimeRecord(x = -119, y = 52, datetime = 1900-01-02 10:00:00, uid = UtEIgcof)\n", + " * SpaceTimeRecord(x = -161, y = 63, datetime = 1900-01-10 10:00:00, uid = QjifGPIx)\n", + " * SpaceTimeRecord(x = -133, y = 87, datetime = 1900-01-05 07:00:00, uid = qtolX8oT)\n", " - with children:\n", " OctTree:\n", " - boundary: SpaceTimeRectangle(west=-180, east=-90.0, south=45.0, north=90, start=datetime.datetime(1900, 1, 1, 0, 0), end=datetime.datetime(1900, 1, 8, 17, 45))\n", @@ -485,16 +489,16 @@ " - max_depth: 25\n", " - contents:\n", " - number of elements: 10\n", - " * SpaceTimeRecord(x = -130, y = 80, datetime = 1900-01-01 03:00:00, uid = sd0nBvvS)\n", - " * SpaceTimeRecord(x = -148, y = 78, datetime = 1900-01-06 03:00:00, uid = FgJRfXD9)\n", - " * SpaceTimeRecord(x = -153, y = 58, datetime = 1900-01-03 12:00:00, uid = AHWomxBm)\n", - " * SpaceTimeRecord(x = -160, y = 47, datetime = 1900-01-06 18:00:00, uid = 3p50Ejkq)\n", - " * SpaceTimeRecord(x = -91, y = 60, datetime = 1900-01-07 06:00:00, uid = 1Psbg1Vk)\n", - " * SpaceTimeRecord(x = -138, y = 54, datetime = 1900-01-08 10:00:00, uid = kDwksPIp)\n", - " * SpaceTimeRecord(x = -99, y = 86, datetime = 1900-01-05 12:00:00, uid = gfhX01rL)\n", - " * SpaceTimeRecord(x = -96, y = 54, datetime = 1900-01-04 23:00:00, uid = o7lz8pja)\n", - " * SpaceTimeRecord(x = -163, y = 79, datetime = 1900-01-07 22:00:00, uid = 2Fw915S3)\n", - " * SpaceTimeRecord(x = -155, y = 74, datetime = 1900-01-08 09:00:00, uid = 9pL97BD0)\n", + " * SpaceTimeRecord(x = -129, y = 54, datetime = 1900-01-05 04:00:00, uid = dZ2BgU6A)\n", + " * SpaceTimeRecord(x = -96, y = 67, datetime = 1900-01-07 11:00:00, uid = KK38iUxT)\n", + " * SpaceTimeRecord(x = -137, y = 50, datetime = 1900-01-04 15:00:00, uid = Mlj2MvCb)\n", + " * SpaceTimeRecord(x = -134, y = 74, datetime = 1900-01-02 04:00:00, uid = wCj1pLL6)\n", + " * SpaceTimeRecord(x = -158, y = 86, datetime = 1900-01-06 04:00:00, uid = sIPv5QW4)\n", + " * SpaceTimeRecord(x = -113, y = 56, datetime = 1900-01-08 02:00:00, uid = 5hnlO6ce)\n", + " * SpaceTimeRecord(x = -166, y = 54, datetime = 1900-01-08 12:00:00, uid = PXj9tTWn)\n", + " * SpaceTimeRecord(x = -97, y = 83, datetime = 1900-01-06 11:00:00, uid = bizLnSZk)\n", + " * SpaceTimeRecord(x = -126, y = 53, datetime = 1900-01-05 13:00:00, uid = guzXcRwq)\n", + " * SpaceTimeRecord(x = -148, y = 55, datetime = 1900-01-02 05:00:00, uid = CizwDlIJ)\n", " - with children:\n", " OctTree:\n", " - boundary: SpaceTimeRectangle(west=-180, east=-135.0, south=67.5, north=90, start=datetime.datetime(1900, 1, 1, 0, 0), end=datetime.datetime(1900, 1, 4, 20, 52, 30))\n", @@ -503,16 +507,16 @@ " - max_depth: 25\n", " - contents:\n", " - number of elements: 10\n", - " * SpaceTimeRecord(x = -173, y = 71, datetime = 1900-01-04 03:00:00, uid = ThLEI8lF)\n", - " * SpaceTimeRecord(x = -167, y = 83, datetime = 1900-01-04 03:00:00, uid = Q5FzwxD5)\n", - " * SpaceTimeRecord(x = -167, y = 88, datetime = 1900-01-01 16:00:00, uid = DoCBI1YI)\n", - " * SpaceTimeRecord(x = -141, y = 80, datetime = 1900-01-03 16:00:00, uid = 01SVlWsE)\n", - " * SpaceTimeRecord(x = -135, y = 68, datetime = 1900-01-03 22:00:00, uid = Jx2uI4Op)\n", - " * SpaceTimeRecord(x = -163, y = 77, datetime = 1900-01-03 21:00:00, uid = DoOKHLix)\n", - " * SpaceTimeRecord(x = -157, y = 84, datetime = 1900-01-02 11:00:00, uid = lXiFUOBn)\n", - " * SpaceTimeRecord(x = -145, y = 78, datetime = 1900-01-02 05:00:00, uid = 3ngKJmcS)\n", - " * SpaceTimeRecord(x = -179, y = 89, datetime = 1900-01-04 01:00:00, uid = KQXXjSTT)\n", - " * SpaceTimeRecord(x = -171, y = 80, datetime = 1900-01-04 19:00:00, uid = znugCZWi)\n", + " * SpaceTimeRecord(x = -144, y = 83, datetime = 1900-01-03 20:00:00, uid = L5hq9qlG)\n", + " * SpaceTimeRecord(x = -138, y = 84, datetime = 1900-01-03 11:00:00, uid = DnDQBPlt)\n", + " * SpaceTimeRecord(x = -140, y = 78, datetime = 1900-01-01 11:00:00, uid = VVKqwc7O)\n", + " * SpaceTimeRecord(x = -179, y = 85, datetime = 1900-01-02 01:00:00, uid = fd5NWtYa)\n", + " * SpaceTimeRecord(x = -179, y = 86, datetime = 1900-01-04 11:00:00, uid = KJp276Fa)\n", + " * SpaceTimeRecord(x = -176, y = 68, datetime = 1900-01-02 06:00:00, uid = nWy0gnK4)\n", + " * SpaceTimeRecord(x = -136, y = 77, datetime = 1900-01-01 06:00:00, uid = 21nlHCJg)\n", + " * SpaceTimeRecord(x = -171, y = 82, datetime = 1900-01-04 11:00:00, uid = 5uBXalIT)\n", + " * SpaceTimeRecord(x = -145, y = 85, datetime = 1900-01-03 16:00:00, uid = fjG42lVI)\n", + " * SpaceTimeRecord(x = -155, y = 70, datetime = 1900-01-01 13:00:00, uid = lev3XeV1)\n", " - with children:\n", " OctTree:\n", " - boundary: SpaceTimeRectangle(west=-180, east=-157.5, south=78.75, north=90, start=datetime.datetime(1900, 1, 1, 0, 0), end=datetime.datetime(1900, 1, 2, 22, 26, 15))\n", @@ -521,16 +525,16 @@ " - max_depth: 25\n", " - contents:\n", " - number of elements: 10\n", - " * SpaceTimeRecord(x = -164, y = 79, datetime = 1900-01-01 18:00:00, uid = L0scr6Dw)\n", - " * SpaceTimeRecord(x = -165, y = 87, datetime = 1900-01-02 12:00:00, uid = P2JSVMig)\n", - " * SpaceTimeRecord(x = -158, y = 80, datetime = 1900-01-01 07:00:00, uid = rrfLnl9a000)\n", - " * SpaceTimeRecord(x = -179, y = 88, datetime = 1900-01-01 18:00:00, uid = piKfH7lZ000)\n", - " * SpaceTimeRecord(x = -162, y = 85, datetime = 1900-01-01 00:00:00, uid = TzzMqFl4000)\n", - " * SpaceTimeRecord(x = -170, y = 85, datetime = 1900-01-01 02:00:00, uid = v6BVfkmP000)\n", - " * SpaceTimeRecord(x = -177, y = 87, datetime = 1900-01-01 08:00:00, uid = sAxKIWXJ001)\n", - " * SpaceTimeRecord(x = -164, y = 79, datetime = 1900-01-01 02:00:00, uid = 55vXE5De001)\n", - " * SpaceTimeRecord(x = -167, y = 87, datetime = 1900-01-02 00:00:00, uid = RzUJ5Q7h001)\n", - " * SpaceTimeRecord(x = -170, y = 89, datetime = 1900-01-01 20:00:00, uid = ipKiaytp002)\n", + " * SpaceTimeRecord(x = -169, y = 85, datetime = 1900-01-02 17:00:00, uid = xdVWmHGw)\n", + " * SpaceTimeRecord(x = -176, y = 87, datetime = 1900-01-01 03:00:00, uid = M6ActtYJ)\n", + " * SpaceTimeRecord(x = -171, y = 89, datetime = 1900-01-02 22:00:00, uid = Xw7p5CU0)\n", + " * SpaceTimeRecord(x = -166, y = 86, datetime = 1900-01-01 13:00:00, uid = Ini19LT9)\n", + " * SpaceTimeRecord(x = -166, y = 87, datetime = 1900-01-02 07:00:00, uid = 77vJfw2i000)\n", + " * SpaceTimeRecord(x = -164, y = 83, datetime = 1900-01-01 15:00:00, uid = tSjaLRdX000)\n", + " * SpaceTimeRecord(x = -171, y = 81, datetime = 1900-01-01 04:00:00, uid = xNRbwxLR000)\n", + " * SpaceTimeRecord(x = -177, y = 87, datetime = 1900-01-02 14:00:00, uid = 26OOsEav000)\n", + " * SpaceTimeRecord(x = -163, y = 80, datetime = 1900-01-02 08:00:00, uid = 80kZku0r000)\n", + " * SpaceTimeRecord(x = -174, y = 83, datetime = 1900-01-02 06:00:00, uid = TORItCvU001)\n", " - with children:\n", " OctTree:\n", " - boundary: SpaceTimeRectangle(west=-180, east=-168.75, south=84.375, north=90, start=datetime.datetime(1900, 1, 1, 0, 0), end=datetime.datetime(1900, 1, 1, 23, 13, 7, 500000))\n", @@ -539,9 +543,9 @@ " - max_depth: 25\n", " - contents:\n", " - number of elements: 10\n", - " * SpaceTimeRecord(x = -178, y = 87, datetime = 1900-01-01 11:00:00, uid = 9i3tUAKH003)\n", - " * SpaceTimeRecord(x = -169, y = 88, datetime = 1900-01-01 23:00:00, uid = ib1mXyZJ003)\n", - " * SpaceTimeRecord(x = -174, y = 88, datetime = 1900-01-01 03:00:00, uid = vYJ8DamM004)\n" + " * SpaceTimeRecord(x = -178, y = 86, datetime = 1900-01-01 19:00:00, uid = iuABumaA002)\n", + " * SpaceTimeRecord(x = -172, y = 88, datetime = 1900-01-01 09:00:00, uid = 7H12EJwT002)\n", + " * SpaceTimeRecord(x = -176, y = 85, datetime = 1900-01-01 13:00:00, uid = A2rVtlYK006)\n" ] } ], @@ -593,7 +597,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "1.32 ms ± 20.8 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)\n" + "1.28 ms ± 28.2 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)\n" ] } ], @@ -614,7 +618,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "12.1 ms ± 81.4 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" + "11.8 ms ± 198 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], diff --git a/pyproject.toml b/pyproject.toml index e9bf58c..d79967d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,7 +14,7 @@ packages = ["GeoSpatialTools"] name = "GeoSpatialTools" version = "0.11.2" dependencies = ["numpy"] -requires-python = ">=3.9" +requires-python = ">=3.11" authors = [ { name = "Joseph Siddons", email = "josidd@noc.ac.uk" }, { name = "Richard Cornes", email = "rcornes@noc.ac.uk" }, @@ -93,8 +93,15 @@ polars = "pl" scipy = "sp" xarray = "xr" +[tool.codespell] +skip = "./docs/_build" +count = true +quiet-level = 3 + [project.urls] Repository = "https://git.noc.ac.uk/nocsurfaceprocesses/geospatialtools" [dependency-groups] -dev = ["bpython>=0.25"] +dev = [ + "bpython>=0.25", +] diff --git a/test/test_octtree.py b/test/test_octtree.py index 7a3d979..de6f335 100644 --- a/test/test_octtree.py +++ b/test/test_octtree.py @@ -294,7 +294,7 @@ class TestOctTree(unittest.TestCase): start = d - dt end = d + dt boundary = Rectangle(-180, 180, -90, 90, start, end) - ot = OctTree(boundary, capacity=3) + octree = OctTree(boundary, capacity=3) quert_rect = Rectangle(140, -160, 40, 50, d, d + timedelta(days=8)) points_want: list[Record] = [ @@ -311,9 +311,9 @@ class TestOctTree(unittest.TestCase): ] points.extend(points_want) for p in points: - ot.insert(p) + octree.insert(p) - res = ot.query(quert_rect) + res = octree.query(quert_rect) assert len(res) == len(points_want) assert all([p in res for p in points_want]) @@ -339,7 +339,7 @@ class TestOctTree(unittest.TestCase): test_datetime - test_timedelta / 2, test_datetime + test_timedelta / 2, ) - # TEST: distint locii + # TEST: distinct locii assert (ellipse.p1_lon, ellipse.p1_lat) != ( ellipse.p2_lon, ellipse.p2_lat, diff --git a/test/test_quadtree.py b/test/test_quadtree.py index 482f9c5..9388620 100644 --- a/test/test_quadtree.py +++ b/test/test_quadtree.py @@ -155,7 +155,7 @@ class TestQuadTree(unittest.TestCase): assert qt_boundary.lat == 0 assert qt_boundary.lat_range == 180 - qt = QuadTree(qt_boundary, capacity=3) + quadtree = QuadTree(qt_boundary, capacity=3) quert_rect = Rectangle(140, -160, 40, 50) assert quert_rect.lon == 170 @@ -176,9 +176,9 @@ class TestQuadTree(unittest.TestCase): ] points.extend(points_want) for p in points: - qt.insert(p) + quadtree.insert(p) - res = qt.query(quert_rect) + res = quadtree.query(quert_rect) assert len(res) == len(points_want) assert all([p in res for p in points_want]) @@ -188,7 +188,7 @@ class TestQuadTree(unittest.TestCase): theta = 0 ellipse = Ellipse(12.5, 2.5, d1, d2, theta) - # TEST: distint locii + # TEST: distinct locii assert (ellipse.p1_lon, ellipse.p1_lat) != ( ellipse.p2_lon, ellipse.p2_lat, -- GitLab