function_base.py 158 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932
  1. import collections.abc
  2. import functools
  3. import re
  4. import sys
  5. import warnings
  6. import numpy as np
  7. import numpy.core.numeric as _nx
  8. from numpy.core import transpose
  9. from numpy.core.numeric import (
  10. ones, zeros_like, arange, concatenate, array, asarray, asanyarray, empty,
  11. ndarray, around, floor, ceil, take, dot, where, intp,
  12. integer, isscalar, absolute
  13. )
  14. from numpy.core.umath import (
  15. pi, add, arctan2, frompyfunc, cos, less_equal, sqrt, sin,
  16. mod, exp, not_equal, subtract
  17. )
  18. from numpy.core.fromnumeric import (
  19. ravel, nonzero, partition, mean, any, sum
  20. )
  21. from numpy.core.numerictypes import typecodes
  22. from numpy.core.overrides import set_module
  23. from numpy.core import overrides
  24. from numpy.core.function_base import add_newdoc
  25. from numpy.lib.twodim_base import diag
  26. from numpy.core.multiarray import (
  27. _insert, add_docstring, bincount, normalize_axis_index, _monotonicity,
  28. interp as compiled_interp, interp_complex as compiled_interp_complex
  29. )
  30. from numpy.core.umath import _add_newdoc_ufunc as add_newdoc_ufunc
  31. import builtins
  32. # needed in this module for compatibility
  33. from numpy.lib.histograms import histogram, histogramdd
  34. array_function_dispatch = functools.partial(
  35. overrides.array_function_dispatch, module='numpy')
  36. __all__ = [
  37. 'select', 'piecewise', 'trim_zeros', 'copy', 'iterable', 'percentile',
  38. 'diff', 'gradient', 'angle', 'unwrap', 'sort_complex', 'disp', 'flip',
  39. 'rot90', 'extract', 'place', 'vectorize', 'asarray_chkfinite', 'average',
  40. 'bincount', 'digitize', 'cov', 'corrcoef',
  41. 'msort', 'median', 'sinc', 'hamming', 'hanning', 'bartlett',
  42. 'blackman', 'kaiser', 'trapz', 'i0', 'add_newdoc', 'add_docstring',
  43. 'meshgrid', 'delete', 'insert', 'append', 'interp', 'add_newdoc_ufunc',
  44. 'quantile'
  45. ]
  46. def _rot90_dispatcher(m, k=None, axes=None):
  47. return (m,)
  48. @array_function_dispatch(_rot90_dispatcher)
  49. def rot90(m, k=1, axes=(0, 1)):
  50. """
  51. Rotate an array by 90 degrees in the plane specified by axes.
  52. Rotation direction is from the first towards the second axis.
  53. Parameters
  54. ----------
  55. m : array_like
  56. Array of two or more dimensions.
  57. k : integer
  58. Number of times the array is rotated by 90 degrees.
  59. axes: (2,) array_like
  60. The array is rotated in the plane defined by the axes.
  61. Axes must be different.
  62. .. versionadded:: 1.12.0
  63. Returns
  64. -------
  65. y : ndarray
  66. A rotated view of `m`.
  67. See Also
  68. --------
  69. flip : Reverse the order of elements in an array along the given axis.
  70. fliplr : Flip an array horizontally.
  71. flipud : Flip an array vertically.
  72. Notes
  73. -----
  74. rot90(m, k=1, axes=(1,0)) is the reverse of rot90(m, k=1, axes=(0,1))
  75. rot90(m, k=1, axes=(1,0)) is equivalent to rot90(m, k=-1, axes=(0,1))
  76. Examples
  77. --------
  78. >>> m = np.array([[1,2],[3,4]], int)
  79. >>> m
  80. array([[1, 2],
  81. [3, 4]])
  82. >>> np.rot90(m)
  83. array([[2, 4],
  84. [1, 3]])
  85. >>> np.rot90(m, 2)
  86. array([[4, 3],
  87. [2, 1]])
  88. >>> m = np.arange(8).reshape((2,2,2))
  89. >>> np.rot90(m, 1, (1,2))
  90. array([[[1, 3],
  91. [0, 2]],
  92. [[5, 7],
  93. [4, 6]]])
  94. """
  95. axes = tuple(axes)
  96. if len(axes) != 2:
  97. raise ValueError("len(axes) must be 2.")
  98. m = asanyarray(m)
  99. if axes[0] == axes[1] or absolute(axes[0] - axes[1]) == m.ndim:
  100. raise ValueError("Axes must be different.")
  101. if (axes[0] >= m.ndim or axes[0] < -m.ndim
  102. or axes[1] >= m.ndim or axes[1] < -m.ndim):
  103. raise ValueError("Axes={} out of range for array of ndim={}."
  104. .format(axes, m.ndim))
  105. k %= 4
  106. if k == 0:
  107. return m[:]
  108. if k == 2:
  109. return flip(flip(m, axes[0]), axes[1])
  110. axes_list = arange(0, m.ndim)
  111. (axes_list[axes[0]], axes_list[axes[1]]) = (axes_list[axes[1]],
  112. axes_list[axes[0]])
  113. if k == 1:
  114. return transpose(flip(m, axes[1]), axes_list)
  115. else:
  116. # k == 3
  117. return flip(transpose(m, axes_list), axes[1])
  118. def _flip_dispatcher(m, axis=None):
  119. return (m,)
  120. @array_function_dispatch(_flip_dispatcher)
  121. def flip(m, axis=None):
  122. """
  123. Reverse the order of elements in an array along the given axis.
  124. The shape of the array is preserved, but the elements are reordered.
  125. .. versionadded:: 1.12.0
  126. Parameters
  127. ----------
  128. m : array_like
  129. Input array.
  130. axis : None or int or tuple of ints, optional
  131. Axis or axes along which to flip over. The default,
  132. axis=None, will flip over all of the axes of the input array.
  133. If axis is negative it counts from the last to the first axis.
  134. If axis is a tuple of ints, flipping is performed on all of the axes
  135. specified in the tuple.
  136. .. versionchanged:: 1.15.0
  137. None and tuples of axes are supported
  138. Returns
  139. -------
  140. out : array_like
  141. A view of `m` with the entries of axis reversed. Since a view is
  142. returned, this operation is done in constant time.
  143. See Also
  144. --------
  145. flipud : Flip an array vertically (axis=0).
  146. fliplr : Flip an array horizontally (axis=1).
  147. Notes
  148. -----
  149. flip(m, 0) is equivalent to flipud(m).
  150. flip(m, 1) is equivalent to fliplr(m).
  151. flip(m, n) corresponds to ``m[...,::-1,...]`` with ``::-1`` at position n.
  152. flip(m) corresponds to ``m[::-1,::-1,...,::-1]`` with ``::-1`` at all
  153. positions.
  154. flip(m, (0, 1)) corresponds to ``m[::-1,::-1,...]`` with ``::-1`` at
  155. position 0 and position 1.
  156. Examples
  157. --------
  158. >>> A = np.arange(8).reshape((2,2,2))
  159. >>> A
  160. array([[[0, 1],
  161. [2, 3]],
  162. [[4, 5],
  163. [6, 7]]])
  164. >>> np.flip(A, 0)
  165. array([[[4, 5],
  166. [6, 7]],
  167. [[0, 1],
  168. [2, 3]]])
  169. >>> np.flip(A, 1)
  170. array([[[2, 3],
  171. [0, 1]],
  172. [[6, 7],
  173. [4, 5]]])
  174. >>> np.flip(A)
  175. array([[[7, 6],
  176. [5, 4]],
  177. [[3, 2],
  178. [1, 0]]])
  179. >>> np.flip(A, (0, 2))
  180. array([[[5, 4],
  181. [7, 6]],
  182. [[1, 0],
  183. [3, 2]]])
  184. >>> A = np.random.randn(3,4,5)
  185. >>> np.all(np.flip(A,2) == A[:,:,::-1,...])
  186. True
  187. """
  188. if not hasattr(m, 'ndim'):
  189. m = asarray(m)
  190. if axis is None:
  191. indexer = (np.s_[::-1],) * m.ndim
  192. else:
  193. axis = _nx.normalize_axis_tuple(axis, m.ndim)
  194. indexer = [np.s_[:]] * m.ndim
  195. for ax in axis:
  196. indexer[ax] = np.s_[::-1]
  197. indexer = tuple(indexer)
  198. return m[indexer]
  199. @set_module('numpy')
  200. def iterable(y):
  201. """
  202. Check whether or not an object can be iterated over.
  203. Parameters
  204. ----------
  205. y : object
  206. Input object.
  207. Returns
  208. -------
  209. b : bool
  210. Return ``True`` if the object has an iterator method or is a
  211. sequence and ``False`` otherwise.
  212. Examples
  213. --------
  214. >>> np.iterable([1, 2, 3])
  215. True
  216. >>> np.iterable(2)
  217. False
  218. """
  219. try:
  220. iter(y)
  221. except TypeError:
  222. return False
  223. return True
  224. def _average_dispatcher(a, axis=None, weights=None, returned=None):
  225. return (a, weights)
  226. @array_function_dispatch(_average_dispatcher)
  227. def average(a, axis=None, weights=None, returned=False):
  228. """
  229. Compute the weighted average along the specified axis.
  230. Parameters
  231. ----------
  232. a : array_like
  233. Array containing data to be averaged. If `a` is not an array, a
  234. conversion is attempted.
  235. axis : None or int or tuple of ints, optional
  236. Axis or axes along which to average `a`. The default,
  237. axis=None, will average over all of the elements of the input array.
  238. If axis is negative it counts from the last to the first axis.
  239. .. versionadded:: 1.7.0
  240. If axis is a tuple of ints, averaging is performed on all of the axes
  241. specified in the tuple instead of a single axis or all the axes as
  242. before.
  243. weights : array_like, optional
  244. An array of weights associated with the values in `a`. Each value in
  245. `a` contributes to the average according to its associated weight.
  246. The weights array can either be 1-D (in which case its length must be
  247. the size of `a` along the given axis) or of the same shape as `a`.
  248. If `weights=None`, then all data in `a` are assumed to have a
  249. weight equal to one. The 1-D calculation is::
  250. avg = sum(a * weights) / sum(weights)
  251. The only constraint on `weights` is that `sum(weights)` must not be 0.
  252. returned : bool, optional
  253. Default is `False`. If `True`, the tuple (`average`, `sum_of_weights`)
  254. is returned, otherwise only the average is returned.
  255. If `weights=None`, `sum_of_weights` is equivalent to the number of
  256. elements over which the average is taken.
  257. Returns
  258. -------
  259. retval, [sum_of_weights] : array_type or double
  260. Return the average along the specified axis. When `returned` is `True`,
  261. return a tuple with the average as the first element and the sum
  262. of the weights as the second element. `sum_of_weights` is of the
  263. same type as `retval`. The result dtype follows a genereal pattern.
  264. If `weights` is None, the result dtype will be that of `a` , or ``float64``
  265. if `a` is integral. Otherwise, if `weights` is not None and `a` is non-
  266. integral, the result type will be the type of lowest precision capable of
  267. representing values of both `a` and `weights`. If `a` happens to be
  268. integral, the previous rules still applies but the result dtype will
  269. at least be ``float64``.
  270. Raises
  271. ------
  272. ZeroDivisionError
  273. When all weights along axis are zero. See `numpy.ma.average` for a
  274. version robust to this type of error.
  275. TypeError
  276. When the length of 1D `weights` is not the same as the shape of `a`
  277. along axis.
  278. See Also
  279. --------
  280. mean
  281. ma.average : average for masked arrays -- useful if your data contains
  282. "missing" values
  283. numpy.result_type : Returns the type that results from applying the
  284. numpy type promotion rules to the arguments.
  285. Examples
  286. --------
  287. >>> data = np.arange(1, 5)
  288. >>> data
  289. array([1, 2, 3, 4])
  290. >>> np.average(data)
  291. 2.5
  292. >>> np.average(np.arange(1, 11), weights=np.arange(10, 0, -1))
  293. 4.0
  294. >>> data = np.arange(6).reshape((3,2))
  295. >>> data
  296. array([[0, 1],
  297. [2, 3],
  298. [4, 5]])
  299. >>> np.average(data, axis=1, weights=[1./4, 3./4])
  300. array([0.75, 2.75, 4.75])
  301. >>> np.average(data, weights=[1./4, 3./4])
  302. Traceback (most recent call last):
  303. ...
  304. TypeError: Axis must be specified when shapes of a and weights differ.
  305. >>> a = np.ones(5, dtype=np.float128)
  306. >>> w = np.ones(5, dtype=np.complex64)
  307. >>> avg = np.average(a, weights=w)
  308. >>> print(avg.dtype)
  309. complex256
  310. """
  311. a = np.asanyarray(a)
  312. if weights is None:
  313. avg = a.mean(axis)
  314. scl = avg.dtype.type(a.size/avg.size)
  315. else:
  316. wgt = np.asanyarray(weights)
  317. if issubclass(a.dtype.type, (np.integer, np.bool_)):
  318. result_dtype = np.result_type(a.dtype, wgt.dtype, 'f8')
  319. else:
  320. result_dtype = np.result_type(a.dtype, wgt.dtype)
  321. # Sanity checks
  322. if a.shape != wgt.shape:
  323. if axis is None:
  324. raise TypeError(
  325. "Axis must be specified when shapes of a and weights "
  326. "differ.")
  327. if wgt.ndim != 1:
  328. raise TypeError(
  329. "1D weights expected when shapes of a and weights differ.")
  330. if wgt.shape[0] != a.shape[axis]:
  331. raise ValueError(
  332. "Length of weights not compatible with specified axis.")
  333. # setup wgt to broadcast along axis
  334. wgt = np.broadcast_to(wgt, (a.ndim-1)*(1,) + wgt.shape)
  335. wgt = wgt.swapaxes(-1, axis)
  336. scl = wgt.sum(axis=axis, dtype=result_dtype)
  337. if np.any(scl == 0.0):
  338. raise ZeroDivisionError(
  339. "Weights sum to zero, can't be normalized")
  340. avg = np.multiply(a, wgt, dtype=result_dtype).sum(axis)/scl
  341. if returned:
  342. if scl.shape != avg.shape:
  343. scl = np.broadcast_to(scl, avg.shape).copy()
  344. return avg, scl
  345. else:
  346. return avg
  347. @set_module('numpy')
  348. def asarray_chkfinite(a, dtype=None, order=None):
  349. """Convert the input to an array, checking for NaNs or Infs.
  350. Parameters
  351. ----------
  352. a : array_like
  353. Input data, in any form that can be converted to an array. This
  354. includes lists, lists of tuples, tuples, tuples of tuples, tuples
  355. of lists and ndarrays. Success requires no NaNs or Infs.
  356. dtype : data-type, optional
  357. By default, the data-type is inferred from the input data.
  358. order : {'C', 'F', 'A', 'K'}, optional
  359. Memory layout. 'A' and 'K' depend on the order of input array a.
  360. 'C' row-major (C-style),
  361. 'F' column-major (Fortran-style) memory representation.
  362. 'A' (any) means 'F' if `a` is Fortran contiguous, 'C' otherwise
  363. 'K' (keep) preserve input order
  364. Defaults to 'C'.
  365. Returns
  366. -------
  367. out : ndarray
  368. Array interpretation of `a`. No copy is performed if the input
  369. is already an ndarray. If `a` is a subclass of ndarray, a base
  370. class ndarray is returned.
  371. Raises
  372. ------
  373. ValueError
  374. Raises ValueError if `a` contains NaN (Not a Number) or Inf (Infinity).
  375. See Also
  376. --------
  377. asarray : Create and array.
  378. asanyarray : Similar function which passes through subclasses.
  379. ascontiguousarray : Convert input to a contiguous array.
  380. asfarray : Convert input to a floating point ndarray.
  381. asfortranarray : Convert input to an ndarray with column-major
  382. memory order.
  383. fromiter : Create an array from an iterator.
  384. fromfunction : Construct an array by executing a function on grid
  385. positions.
  386. Examples
  387. --------
  388. Convert a list into an array. If all elements are finite
  389. ``asarray_chkfinite`` is identical to ``asarray``.
  390. >>> a = [1, 2]
  391. >>> np.asarray_chkfinite(a, dtype=float)
  392. array([1., 2.])
  393. Raises ValueError if array_like contains Nans or Infs.
  394. >>> a = [1, 2, np.inf]
  395. >>> try:
  396. ... np.asarray_chkfinite(a)
  397. ... except ValueError:
  398. ... print('ValueError')
  399. ...
  400. ValueError
  401. """
  402. a = asarray(a, dtype=dtype, order=order)
  403. if a.dtype.char in typecodes['AllFloat'] and not np.isfinite(a).all():
  404. raise ValueError(
  405. "array must not contain infs or NaNs")
  406. return a
  407. def _piecewise_dispatcher(x, condlist, funclist, *args, **kw):
  408. yield x
  409. # support the undocumented behavior of allowing scalars
  410. if np.iterable(condlist):
  411. yield from condlist
  412. @array_function_dispatch(_piecewise_dispatcher)
  413. def piecewise(x, condlist, funclist, *args, **kw):
  414. """
  415. Evaluate a piecewise-defined function.
  416. Given a set of conditions and corresponding functions, evaluate each
  417. function on the input data wherever its condition is true.
  418. Parameters
  419. ----------
  420. x : ndarray or scalar
  421. The input domain.
  422. condlist : list of bool arrays or bool scalars
  423. Each boolean array corresponds to a function in `funclist`. Wherever
  424. `condlist[i]` is True, `funclist[i](x)` is used as the output value.
  425. Each boolean array in `condlist` selects a piece of `x`,
  426. and should therefore be of the same shape as `x`.
  427. The length of `condlist` must correspond to that of `funclist`.
  428. If one extra function is given, i.e. if
  429. ``len(funclist) == len(condlist) + 1``, then that extra function
  430. is the default value, used wherever all conditions are false.
  431. funclist : list of callables, f(x,*args,**kw), or scalars
  432. Each function is evaluated over `x` wherever its corresponding
  433. condition is True. It should take a 1d array as input and give an 1d
  434. array or a scalar value as output. If, instead of a callable,
  435. a scalar is provided then a constant function (``lambda x: scalar``) is
  436. assumed.
  437. args : tuple, optional
  438. Any further arguments given to `piecewise` are passed to the functions
  439. upon execution, i.e., if called ``piecewise(..., ..., 1, 'a')``, then
  440. each function is called as ``f(x, 1, 'a')``.
  441. kw : dict, optional
  442. Keyword arguments used in calling `piecewise` are passed to the
  443. functions upon execution, i.e., if called
  444. ``piecewise(..., ..., alpha=1)``, then each function is called as
  445. ``f(x, alpha=1)``.
  446. Returns
  447. -------
  448. out : ndarray
  449. The output is the same shape and type as x and is found by
  450. calling the functions in `funclist` on the appropriate portions of `x`,
  451. as defined by the boolean arrays in `condlist`. Portions not covered
  452. by any condition have a default value of 0.
  453. See Also
  454. --------
  455. choose, select, where
  456. Notes
  457. -----
  458. This is similar to choose or select, except that functions are
  459. evaluated on elements of `x` that satisfy the corresponding condition from
  460. `condlist`.
  461. The result is::
  462. |--
  463. |funclist[0](x[condlist[0]])
  464. out = |funclist[1](x[condlist[1]])
  465. |...
  466. |funclist[n2](x[condlist[n2]])
  467. |--
  468. Examples
  469. --------
  470. Define the sigma function, which is -1 for ``x < 0`` and +1 for ``x >= 0``.
  471. >>> x = np.linspace(-2.5, 2.5, 6)
  472. >>> np.piecewise(x, [x < 0, x >= 0], [-1, 1])
  473. array([-1., -1., -1., 1., 1., 1.])
  474. Define the absolute value, which is ``-x`` for ``x <0`` and ``x`` for
  475. ``x >= 0``.
  476. >>> np.piecewise(x, [x < 0, x >= 0], [lambda x: -x, lambda x: x])
  477. array([2.5, 1.5, 0.5, 0.5, 1.5, 2.5])
  478. Apply the same function to a scalar value.
  479. >>> y = -2
  480. >>> np.piecewise(y, [y < 0, y >= 0], [lambda x: -x, lambda x: x])
  481. array(2)
  482. """
  483. x = asanyarray(x)
  484. n2 = len(funclist)
  485. # undocumented: single condition is promoted to a list of one condition
  486. if isscalar(condlist) or (
  487. not isinstance(condlist[0], (list, ndarray)) and x.ndim != 0):
  488. condlist = [condlist]
  489. condlist = asarray(condlist, dtype=bool)
  490. n = len(condlist)
  491. if n == n2 - 1: # compute the "otherwise" condition.
  492. condelse = ~np.any(condlist, axis=0, keepdims=True)
  493. condlist = np.concatenate([condlist, condelse], axis=0)
  494. n += 1
  495. elif n != n2:
  496. raise ValueError(
  497. "with {} condition(s), either {} or {} functions are expected"
  498. .format(n, n, n+1)
  499. )
  500. y = zeros_like(x)
  501. for cond, func in zip(condlist, funclist):
  502. if not isinstance(func, collections.abc.Callable):
  503. y[cond] = func
  504. else:
  505. vals = x[cond]
  506. if vals.size > 0:
  507. y[cond] = func(vals, *args, **kw)
  508. return y
  509. def _select_dispatcher(condlist, choicelist, default=None):
  510. yield from condlist
  511. yield from choicelist
  512. @array_function_dispatch(_select_dispatcher)
  513. def select(condlist, choicelist, default=0):
  514. """
  515. Return an array drawn from elements in choicelist, depending on conditions.
  516. Parameters
  517. ----------
  518. condlist : list of bool ndarrays
  519. The list of conditions which determine from which array in `choicelist`
  520. the output elements are taken. When multiple conditions are satisfied,
  521. the first one encountered in `condlist` is used.
  522. choicelist : list of ndarrays
  523. The list of arrays from which the output elements are taken. It has
  524. to be of the same length as `condlist`.
  525. default : scalar, optional
  526. The element inserted in `output` when all conditions evaluate to False.
  527. Returns
  528. -------
  529. output : ndarray
  530. The output at position m is the m-th element of the array in
  531. `choicelist` where the m-th element of the corresponding array in
  532. `condlist` is True.
  533. See Also
  534. --------
  535. where : Return elements from one of two arrays depending on condition.
  536. take, choose, compress, diag, diagonal
  537. Examples
  538. --------
  539. >>> x = np.arange(10)
  540. >>> condlist = [x<3, x>5]
  541. >>> choicelist = [x, x**2]
  542. >>> np.select(condlist, choicelist)
  543. array([ 0, 1, 2, ..., 49, 64, 81])
  544. """
  545. # Check the size of condlist and choicelist are the same, or abort.
  546. if len(condlist) != len(choicelist):
  547. raise ValueError(
  548. 'list of cases must be same length as list of conditions')
  549. # Now that the dtype is known, handle the deprecated select([], []) case
  550. if len(condlist) == 0:
  551. raise ValueError("select with an empty condition list is not possible")
  552. choicelist = [np.asarray(choice) for choice in choicelist]
  553. try:
  554. intermediate_dtype = np.result_type(*choicelist)
  555. except TypeError as e:
  556. msg = f'Choicelist elements do not have a common dtype: {e}'
  557. raise TypeError(msg) from None
  558. default_array = np.asarray(default)
  559. choicelist.append(default_array)
  560. # need to get the result type before broadcasting for correct scalar
  561. # behaviour
  562. try:
  563. dtype = np.result_type(intermediate_dtype, default_array)
  564. except TypeError as e:
  565. msg = f'Choicelists and default value do not have a common dtype: {e}'
  566. raise TypeError(msg) from None
  567. # Convert conditions to arrays and broadcast conditions and choices
  568. # as the shape is needed for the result. Doing it separately optimizes
  569. # for example when all choices are scalars.
  570. condlist = np.broadcast_arrays(*condlist)
  571. choicelist = np.broadcast_arrays(*choicelist)
  572. # If cond array is not an ndarray in boolean format or scalar bool, abort.
  573. for i, cond in enumerate(condlist):
  574. if cond.dtype.type is not np.bool_:
  575. raise TypeError(
  576. 'invalid entry {} in condlist: should be boolean ndarray'.format(i))
  577. if choicelist[0].ndim == 0:
  578. # This may be common, so avoid the call.
  579. result_shape = condlist[0].shape
  580. else:
  581. result_shape = np.broadcast_arrays(condlist[0], choicelist[0])[0].shape
  582. result = np.full(result_shape, choicelist[-1], dtype)
  583. # Use np.copyto to burn each choicelist array onto result, using the
  584. # corresponding condlist as a boolean mask. This is done in reverse
  585. # order since the first choice should take precedence.
  586. choicelist = choicelist[-2::-1]
  587. condlist = condlist[::-1]
  588. for choice, cond in zip(choicelist, condlist):
  589. np.copyto(result, choice, where=cond)
  590. return result
  591. def _copy_dispatcher(a, order=None, subok=None):
  592. return (a,)
  593. @array_function_dispatch(_copy_dispatcher)
  594. def copy(a, order='K', subok=False):
  595. """
  596. Return an array copy of the given object.
  597. Parameters
  598. ----------
  599. a : array_like
  600. Input data.
  601. order : {'C', 'F', 'A', 'K'}, optional
  602. Controls the memory layout of the copy. 'C' means C-order,
  603. 'F' means F-order, 'A' means 'F' if `a` is Fortran contiguous,
  604. 'C' otherwise. 'K' means match the layout of `a` as closely
  605. as possible. (Note that this function and :meth:`ndarray.copy` are very
  606. similar, but have different default values for their order=
  607. arguments.)
  608. subok : bool, optional
  609. If True, then sub-classes will be passed-through, otherwise the
  610. returned array will be forced to be a base-class array (defaults to False).
  611. .. versionadded:: 1.19.0
  612. Returns
  613. -------
  614. arr : ndarray
  615. Array interpretation of `a`.
  616. See Also
  617. --------
  618. ndarray.copy : Preferred method for creating an array copy
  619. Notes
  620. -----
  621. This is equivalent to:
  622. >>> np.array(a, copy=True) #doctest: +SKIP
  623. Examples
  624. --------
  625. Create an array x, with a reference y and a copy z:
  626. >>> x = np.array([1, 2, 3])
  627. >>> y = x
  628. >>> z = np.copy(x)
  629. Note that, when we modify x, y changes, but not z:
  630. >>> x[0] = 10
  631. >>> x[0] == y[0]
  632. True
  633. >>> x[0] == z[0]
  634. False
  635. Note that np.copy is a shallow copy and will not copy object
  636. elements within arrays. This is mainly important for arrays
  637. containing Python objects. The new array will contain the
  638. same object which may lead to surprises if that object can
  639. be modified (is mutable):
  640. >>> a = np.array([1, 'm', [2, 3, 4]], dtype=object)
  641. >>> b = np.copy(a)
  642. >>> b[2][0] = 10
  643. >>> a
  644. array([1, 'm', list([10, 3, 4])], dtype=object)
  645. To ensure all elements within an ``object`` array are copied,
  646. use `copy.deepcopy`:
  647. >>> import copy
  648. >>> a = np.array([1, 'm', [2, 3, 4]], dtype=object)
  649. >>> c = copy.deepcopy(a)
  650. >>> c[2][0] = 10
  651. >>> c
  652. array([1, 'm', list([10, 3, 4])], dtype=object)
  653. >>> a
  654. array([1, 'm', list([2, 3, 4])], dtype=object)
  655. """
  656. return array(a, order=order, subok=subok, copy=True)
  657. # Basic operations
  658. def _gradient_dispatcher(f, *varargs, axis=None, edge_order=None):
  659. yield f
  660. yield from varargs
  661. @array_function_dispatch(_gradient_dispatcher)
  662. def gradient(f, *varargs, axis=None, edge_order=1):
  663. """
  664. Return the gradient of an N-dimensional array.
  665. The gradient is computed using second order accurate central differences
  666. in the interior points and either first or second order accurate one-sides
  667. (forward or backwards) differences at the boundaries.
  668. The returned gradient hence has the same shape as the input array.
  669. Parameters
  670. ----------
  671. f : array_like
  672. An N-dimensional array containing samples of a scalar function.
  673. varargs : list of scalar or array, optional
  674. Spacing between f values. Default unitary spacing for all dimensions.
  675. Spacing can be specified using:
  676. 1. single scalar to specify a sample distance for all dimensions.
  677. 2. N scalars to specify a constant sample distance for each dimension.
  678. i.e. `dx`, `dy`, `dz`, ...
  679. 3. N arrays to specify the coordinates of the values along each
  680. dimension of F. The length of the array must match the size of
  681. the corresponding dimension
  682. 4. Any combination of N scalars/arrays with the meaning of 2. and 3.
  683. If `axis` is given, the number of varargs must equal the number of axes.
  684. Default: 1.
  685. edge_order : {1, 2}, optional
  686. Gradient is calculated using N-th order accurate differences
  687. at the boundaries. Default: 1.
  688. .. versionadded:: 1.9.1
  689. axis : None or int or tuple of ints, optional
  690. Gradient is calculated only along the given axis or axes
  691. The default (axis = None) is to calculate the gradient for all the axes
  692. of the input array. axis may be negative, in which case it counts from
  693. the last to the first axis.
  694. .. versionadded:: 1.11.0
  695. Returns
  696. -------
  697. gradient : ndarray or list of ndarray
  698. A list of ndarrays (or a single ndarray if there is only one dimension)
  699. corresponding to the derivatives of f with respect to each dimension.
  700. Each derivative has the same shape as f.
  701. Examples
  702. --------
  703. >>> f = np.array([1, 2, 4, 7, 11, 16], dtype=float)
  704. >>> np.gradient(f)
  705. array([1. , 1.5, 2.5, 3.5, 4.5, 5. ])
  706. >>> np.gradient(f, 2)
  707. array([0.5 , 0.75, 1.25, 1.75, 2.25, 2.5 ])
  708. Spacing can be also specified with an array that represents the coordinates
  709. of the values F along the dimensions.
  710. For instance a uniform spacing:
  711. >>> x = np.arange(f.size)
  712. >>> np.gradient(f, x)
  713. array([1. , 1.5, 2.5, 3.5, 4.5, 5. ])
  714. Or a non uniform one:
  715. >>> x = np.array([0., 1., 1.5, 3.5, 4., 6.], dtype=float)
  716. >>> np.gradient(f, x)
  717. array([1. , 3. , 3.5, 6.7, 6.9, 2.5])
  718. For two dimensional arrays, the return will be two arrays ordered by
  719. axis. In this example the first array stands for the gradient in
  720. rows and the second one in columns direction:
  721. >>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]], dtype=float))
  722. [array([[ 2., 2., -1.],
  723. [ 2., 2., -1.]]), array([[1. , 2.5, 4. ],
  724. [1. , 1. , 1. ]])]
  725. In this example the spacing is also specified:
  726. uniform for axis=0 and non uniform for axis=1
  727. >>> dx = 2.
  728. >>> y = [1., 1.5, 3.5]
  729. >>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]], dtype=float), dx, y)
  730. [array([[ 1. , 1. , -0.5],
  731. [ 1. , 1. , -0.5]]), array([[2. , 2. , 2. ],
  732. [2. , 1.7, 0.5]])]
  733. It is possible to specify how boundaries are treated using `edge_order`
  734. >>> x = np.array([0, 1, 2, 3, 4])
  735. >>> f = x**2
  736. >>> np.gradient(f, edge_order=1)
  737. array([1., 2., 4., 6., 7.])
  738. >>> np.gradient(f, edge_order=2)
  739. array([0., 2., 4., 6., 8.])
  740. The `axis` keyword can be used to specify a subset of axes of which the
  741. gradient is calculated
  742. >>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]], dtype=float), axis=0)
  743. array([[ 2., 2., -1.],
  744. [ 2., 2., -1.]])
  745. Notes
  746. -----
  747. Assuming that :math:`f\\in C^{3}` (i.e., :math:`f` has at least 3 continuous
  748. derivatives) and let :math:`h_{*}` be a non-homogeneous stepsize, we
  749. minimize the "consistency error" :math:`\\eta_{i}` between the true gradient
  750. and its estimate from a linear combination of the neighboring grid-points:
  751. .. math::
  752. \\eta_{i} = f_{i}^{\\left(1\\right)} -
  753. \\left[ \\alpha f\\left(x_{i}\\right) +
  754. \\beta f\\left(x_{i} + h_{d}\\right) +
  755. \\gamma f\\left(x_{i}-h_{s}\\right)
  756. \\right]
  757. By substituting :math:`f(x_{i} + h_{d})` and :math:`f(x_{i} - h_{s})`
  758. with their Taylor series expansion, this translates into solving
  759. the following the linear system:
  760. .. math::
  761. \\left\\{
  762. \\begin{array}{r}
  763. \\alpha+\\beta+\\gamma=0 \\\\
  764. \\beta h_{d}-\\gamma h_{s}=1 \\\\
  765. \\beta h_{d}^{2}+\\gamma h_{s}^{2}=0
  766. \\end{array}
  767. \\right.
  768. The resulting approximation of :math:`f_{i}^{(1)}` is the following:
  769. .. math::
  770. \\hat f_{i}^{(1)} =
  771. \\frac{
  772. h_{s}^{2}f\\left(x_{i} + h_{d}\\right)
  773. + \\left(h_{d}^{2} - h_{s}^{2}\\right)f\\left(x_{i}\\right)
  774. - h_{d}^{2}f\\left(x_{i}-h_{s}\\right)}
  775. { h_{s}h_{d}\\left(h_{d} + h_{s}\\right)}
  776. + \\mathcal{O}\\left(\\frac{h_{d}h_{s}^{2}
  777. + h_{s}h_{d}^{2}}{h_{d}
  778. + h_{s}}\\right)
  779. It is worth noting that if :math:`h_{s}=h_{d}`
  780. (i.e., data are evenly spaced)
  781. we find the standard second order approximation:
  782. .. math::
  783. \\hat f_{i}^{(1)}=
  784. \\frac{f\\left(x_{i+1}\\right) - f\\left(x_{i-1}\\right)}{2h}
  785. + \\mathcal{O}\\left(h^{2}\\right)
  786. With a similar procedure the forward/backward approximations used for
  787. boundaries can be derived.
  788. References
  789. ----------
  790. .. [1] Quarteroni A., Sacco R., Saleri F. (2007) Numerical Mathematics
  791. (Texts in Applied Mathematics). New York: Springer.
  792. .. [2] Durran D. R. (1999) Numerical Methods for Wave Equations
  793. in Geophysical Fluid Dynamics. New York: Springer.
  794. .. [3] Fornberg B. (1988) Generation of Finite Difference Formulas on
  795. Arbitrarily Spaced Grids,
  796. Mathematics of Computation 51, no. 184 : 699-706.
  797. `PDF <http://www.ams.org/journals/mcom/1988-51-184/
  798. S0025-5718-1988-0935077-0/S0025-5718-1988-0935077-0.pdf>`_.
  799. """
  800. f = np.asanyarray(f)
  801. N = f.ndim # number of dimensions
  802. if axis is None:
  803. axes = tuple(range(N))
  804. else:
  805. axes = _nx.normalize_axis_tuple(axis, N)
  806. len_axes = len(axes)
  807. n = len(varargs)
  808. if n == 0:
  809. # no spacing argument - use 1 in all axes
  810. dx = [1.0] * len_axes
  811. elif n == 1 and np.ndim(varargs[0]) == 0:
  812. # single scalar for all axes
  813. dx = varargs * len_axes
  814. elif n == len_axes:
  815. # scalar or 1d array for each axis
  816. dx = list(varargs)
  817. for i, distances in enumerate(dx):
  818. distances = np.asanyarray(distances)
  819. if distances.ndim == 0:
  820. continue
  821. elif distances.ndim != 1:
  822. raise ValueError("distances must be either scalars or 1d")
  823. if len(distances) != f.shape[axes[i]]:
  824. raise ValueError("when 1d, distances must match "
  825. "the length of the corresponding dimension")
  826. if np.issubdtype(distances.dtype, np.integer):
  827. # Convert numpy integer types to float64 to avoid modular
  828. # arithmetic in np.diff(distances).
  829. distances = distances.astype(np.float64)
  830. diffx = np.diff(distances)
  831. # if distances are constant reduce to the scalar case
  832. # since it brings a consistent speedup
  833. if (diffx == diffx[0]).all():
  834. diffx = diffx[0]
  835. dx[i] = diffx
  836. else:
  837. raise TypeError("invalid number of arguments")
  838. if edge_order > 2:
  839. raise ValueError("'edge_order' greater than 2 not supported")
  840. # use central differences on interior and one-sided differences on the
  841. # endpoints. This preserves second order-accuracy over the full domain.
  842. outvals = []
  843. # create slice objects --- initially all are [:, :, ..., :]
  844. slice1 = [slice(None)]*N
  845. slice2 = [slice(None)]*N
  846. slice3 = [slice(None)]*N
  847. slice4 = [slice(None)]*N
  848. otype = f.dtype
  849. if otype.type is np.datetime64:
  850. # the timedelta dtype with the same unit information
  851. otype = np.dtype(otype.name.replace('datetime', 'timedelta'))
  852. # view as timedelta to allow addition
  853. f = f.view(otype)
  854. elif otype.type is np.timedelta64:
  855. pass
  856. elif np.issubdtype(otype, np.inexact):
  857. pass
  858. else:
  859. # All other types convert to floating point.
  860. # First check if f is a numpy integer type; if so, convert f to float64
  861. # to avoid modular arithmetic when computing the changes in f.
  862. if np.issubdtype(otype, np.integer):
  863. f = f.astype(np.float64)
  864. otype = np.float64
  865. for axis, ax_dx in zip(axes, dx):
  866. if f.shape[axis] < edge_order + 1:
  867. raise ValueError(
  868. "Shape of array too small to calculate a numerical gradient, "
  869. "at least (edge_order + 1) elements are required.")
  870. # result allocation
  871. out = np.empty_like(f, dtype=otype)
  872. # spacing for the current axis
  873. uniform_spacing = np.ndim(ax_dx) == 0
  874. # Numerical differentiation: 2nd order interior
  875. slice1[axis] = slice(1, -1)
  876. slice2[axis] = slice(None, -2)
  877. slice3[axis] = slice(1, -1)
  878. slice4[axis] = slice(2, None)
  879. if uniform_spacing:
  880. out[tuple(slice1)] = (f[tuple(slice4)] - f[tuple(slice2)]) / (2. * ax_dx)
  881. else:
  882. dx1 = ax_dx[0:-1]
  883. dx2 = ax_dx[1:]
  884. a = -(dx2)/(dx1 * (dx1 + dx2))
  885. b = (dx2 - dx1) / (dx1 * dx2)
  886. c = dx1 / (dx2 * (dx1 + dx2))
  887. # fix the shape for broadcasting
  888. shape = np.ones(N, dtype=int)
  889. shape[axis] = -1
  890. a.shape = b.shape = c.shape = shape
  891. # 1D equivalent -- out[1:-1] = a * f[:-2] + b * f[1:-1] + c * f[2:]
  892. out[tuple(slice1)] = a * f[tuple(slice2)] + b * f[tuple(slice3)] + c * f[tuple(slice4)]
  893. # Numerical differentiation: 1st order edges
  894. if edge_order == 1:
  895. slice1[axis] = 0
  896. slice2[axis] = 1
  897. slice3[axis] = 0
  898. dx_0 = ax_dx if uniform_spacing else ax_dx[0]
  899. # 1D equivalent -- out[0] = (f[1] - f[0]) / (x[1] - x[0])
  900. out[tuple(slice1)] = (f[tuple(slice2)] - f[tuple(slice3)]) / dx_0
  901. slice1[axis] = -1
  902. slice2[axis] = -1
  903. slice3[axis] = -2
  904. dx_n = ax_dx if uniform_spacing else ax_dx[-1]
  905. # 1D equivalent -- out[-1] = (f[-1] - f[-2]) / (x[-1] - x[-2])
  906. out[tuple(slice1)] = (f[tuple(slice2)] - f[tuple(slice3)]) / dx_n
  907. # Numerical differentiation: 2nd order edges
  908. else:
  909. slice1[axis] = 0
  910. slice2[axis] = 0
  911. slice3[axis] = 1
  912. slice4[axis] = 2
  913. if uniform_spacing:
  914. a = -1.5 / ax_dx
  915. b = 2. / ax_dx
  916. c = -0.5 / ax_dx
  917. else:
  918. dx1 = ax_dx[0]
  919. dx2 = ax_dx[1]
  920. a = -(2. * dx1 + dx2)/(dx1 * (dx1 + dx2))
  921. b = (dx1 + dx2) / (dx1 * dx2)
  922. c = - dx1 / (dx2 * (dx1 + dx2))
  923. # 1D equivalent -- out[0] = a * f[0] + b * f[1] + c * f[2]
  924. out[tuple(slice1)] = a * f[tuple(slice2)] + b * f[tuple(slice3)] + c * f[tuple(slice4)]
  925. slice1[axis] = -1
  926. slice2[axis] = -3
  927. slice3[axis] = -2
  928. slice4[axis] = -1
  929. if uniform_spacing:
  930. a = 0.5 / ax_dx
  931. b = -2. / ax_dx
  932. c = 1.5 / ax_dx
  933. else:
  934. dx1 = ax_dx[-2]
  935. dx2 = ax_dx[-1]
  936. a = (dx2) / (dx1 * (dx1 + dx2))
  937. b = - (dx2 + dx1) / (dx1 * dx2)
  938. c = (2. * dx2 + dx1) / (dx2 * (dx1 + dx2))
  939. # 1D equivalent -- out[-1] = a * f[-3] + b * f[-2] + c * f[-1]
  940. out[tuple(slice1)] = a * f[tuple(slice2)] + b * f[tuple(slice3)] + c * f[tuple(slice4)]
  941. outvals.append(out)
  942. # reset the slice object in this dimension to ":"
  943. slice1[axis] = slice(None)
  944. slice2[axis] = slice(None)
  945. slice3[axis] = slice(None)
  946. slice4[axis] = slice(None)
  947. if len_axes == 1:
  948. return outvals[0]
  949. else:
  950. return outvals
  951. def _diff_dispatcher(a, n=None, axis=None, prepend=None, append=None):
  952. return (a, prepend, append)
  953. @array_function_dispatch(_diff_dispatcher)
  954. def diff(a, n=1, axis=-1, prepend=np._NoValue, append=np._NoValue):
  955. """
  956. Calculate the n-th discrete difference along the given axis.
  957. The first difference is given by ``out[i] = a[i+1] - a[i]`` along
  958. the given axis, higher differences are calculated by using `diff`
  959. recursively.
  960. Parameters
  961. ----------
  962. a : array_like
  963. Input array
  964. n : int, optional
  965. The number of times values are differenced. If zero, the input
  966. is returned as-is.
  967. axis : int, optional
  968. The axis along which the difference is taken, default is the
  969. last axis.
  970. prepend, append : array_like, optional
  971. Values to prepend or append to `a` along axis prior to
  972. performing the difference. Scalar values are expanded to
  973. arrays with length 1 in the direction of axis and the shape
  974. of the input array in along all other axes. Otherwise the
  975. dimension and shape must match `a` except along axis.
  976. .. versionadded:: 1.16.0
  977. Returns
  978. -------
  979. diff : ndarray
  980. The n-th differences. The shape of the output is the same as `a`
  981. except along `axis` where the dimension is smaller by `n`. The
  982. type of the output is the same as the type of the difference
  983. between any two elements of `a`. This is the same as the type of
  984. `a` in most cases. A notable exception is `datetime64`, which
  985. results in a `timedelta64` output array.
  986. See Also
  987. --------
  988. gradient, ediff1d, cumsum
  989. Notes
  990. -----
  991. Type is preserved for boolean arrays, so the result will contain
  992. `False` when consecutive elements are the same and `True` when they
  993. differ.
  994. For unsigned integer arrays, the results will also be unsigned. This
  995. should not be surprising, as the result is consistent with
  996. calculating the difference directly:
  997. >>> u8_arr = np.array([1, 0], dtype=np.uint8)
  998. >>> np.diff(u8_arr)
  999. array([255], dtype=uint8)
  1000. >>> u8_arr[1,...] - u8_arr[0,...]
  1001. 255
  1002. If this is not desirable, then the array should be cast to a larger
  1003. integer type first:
  1004. >>> i16_arr = u8_arr.astype(np.int16)
  1005. >>> np.diff(i16_arr)
  1006. array([-1], dtype=int16)
  1007. Examples
  1008. --------
  1009. >>> x = np.array([1, 2, 4, 7, 0])
  1010. >>> np.diff(x)
  1011. array([ 1, 2, 3, -7])
  1012. >>> np.diff(x, n=2)
  1013. array([ 1, 1, -10])
  1014. >>> x = np.array([[1, 3, 6, 10], [0, 5, 6, 8]])
  1015. >>> np.diff(x)
  1016. array([[2, 3, 4],
  1017. [5, 1, 2]])
  1018. >>> np.diff(x, axis=0)
  1019. array([[-1, 2, 0, -2]])
  1020. >>> x = np.arange('1066-10-13', '1066-10-16', dtype=np.datetime64)
  1021. >>> np.diff(x)
  1022. array([1, 1], dtype='timedelta64[D]')
  1023. """
  1024. if n == 0:
  1025. return a
  1026. if n < 0:
  1027. raise ValueError(
  1028. "order must be non-negative but got " + repr(n))
  1029. a = asanyarray(a)
  1030. nd = a.ndim
  1031. if nd == 0:
  1032. raise ValueError("diff requires input that is at least one dimensional")
  1033. axis = normalize_axis_index(axis, nd)
  1034. combined = []
  1035. if prepend is not np._NoValue:
  1036. prepend = np.asanyarray(prepend)
  1037. if prepend.ndim == 0:
  1038. shape = list(a.shape)
  1039. shape[axis] = 1
  1040. prepend = np.broadcast_to(prepend, tuple(shape))
  1041. combined.append(prepend)
  1042. combined.append(a)
  1043. if append is not np._NoValue:
  1044. append = np.asanyarray(append)
  1045. if append.ndim == 0:
  1046. shape = list(a.shape)
  1047. shape[axis] = 1
  1048. append = np.broadcast_to(append, tuple(shape))
  1049. combined.append(append)
  1050. if len(combined) > 1:
  1051. a = np.concatenate(combined, axis)
  1052. slice1 = [slice(None)] * nd
  1053. slice2 = [slice(None)] * nd
  1054. slice1[axis] = slice(1, None)
  1055. slice2[axis] = slice(None, -1)
  1056. slice1 = tuple(slice1)
  1057. slice2 = tuple(slice2)
  1058. op = not_equal if a.dtype == np.bool_ else subtract
  1059. for _ in range(n):
  1060. a = op(a[slice1], a[slice2])
  1061. return a
  1062. def _interp_dispatcher(x, xp, fp, left=None, right=None, period=None):
  1063. return (x, xp, fp)
  1064. @array_function_dispatch(_interp_dispatcher)
  1065. def interp(x, xp, fp, left=None, right=None, period=None):
  1066. """
  1067. One-dimensional linear interpolation for monotonically increasing sample points.
  1068. Returns the one-dimensional piecewise linear interpolant to a function
  1069. with given discrete data points (`xp`, `fp`), evaluated at `x`.
  1070. Parameters
  1071. ----------
  1072. x : array_like
  1073. The x-coordinates at which to evaluate the interpolated values.
  1074. xp : 1-D sequence of floats
  1075. The x-coordinates of the data points, must be increasing if argument
  1076. `period` is not specified. Otherwise, `xp` is internally sorted after
  1077. normalizing the periodic boundaries with ``xp = xp % period``.
  1078. fp : 1-D sequence of float or complex
  1079. The y-coordinates of the data points, same length as `xp`.
  1080. left : optional float or complex corresponding to fp
  1081. Value to return for `x < xp[0]`, default is `fp[0]`.
  1082. right : optional float or complex corresponding to fp
  1083. Value to return for `x > xp[-1]`, default is `fp[-1]`.
  1084. period : None or float, optional
  1085. A period for the x-coordinates. This parameter allows the proper
  1086. interpolation of angular x-coordinates. Parameters `left` and `right`
  1087. are ignored if `period` is specified.
  1088. .. versionadded:: 1.10.0
  1089. Returns
  1090. -------
  1091. y : float or complex (corresponding to fp) or ndarray
  1092. The interpolated values, same shape as `x`.
  1093. Raises
  1094. ------
  1095. ValueError
  1096. If `xp` and `fp` have different length
  1097. If `xp` or `fp` are not 1-D sequences
  1098. If `period == 0`
  1099. See Also
  1100. --------
  1101. scipy.interpolate
  1102. Warnings
  1103. --------
  1104. The x-coordinate sequence is expected to be increasing, but this is not
  1105. explicitly enforced. However, if the sequence `xp` is non-increasing,
  1106. interpolation results are meaningless.
  1107. Note that, since NaN is unsortable, `xp` also cannot contain NaNs.
  1108. A simple check for `xp` being strictly increasing is::
  1109. np.all(np.diff(xp) > 0)
  1110. Examples
  1111. --------
  1112. >>> xp = [1, 2, 3]
  1113. >>> fp = [3, 2, 0]
  1114. >>> np.interp(2.5, xp, fp)
  1115. 1.0
  1116. >>> np.interp([0, 1, 1.5, 2.72, 3.14], xp, fp)
  1117. array([3. , 3. , 2.5 , 0.56, 0. ])
  1118. >>> UNDEF = -99.0
  1119. >>> np.interp(3.14, xp, fp, right=UNDEF)
  1120. -99.0
  1121. Plot an interpolant to the sine function:
  1122. >>> x = np.linspace(0, 2*np.pi, 10)
  1123. >>> y = np.sin(x)
  1124. >>> xvals = np.linspace(0, 2*np.pi, 50)
  1125. >>> yinterp = np.interp(xvals, x, y)
  1126. >>> import matplotlib.pyplot as plt
  1127. >>> plt.plot(x, y, 'o')
  1128. [<matplotlib.lines.Line2D object at 0x...>]
  1129. >>> plt.plot(xvals, yinterp, '-x')
  1130. [<matplotlib.lines.Line2D object at 0x...>]
  1131. >>> plt.show()
  1132. Interpolation with periodic x-coordinates:
  1133. >>> x = [-180, -170, -185, 185, -10, -5, 0, 365]
  1134. >>> xp = [190, -190, 350, -350]
  1135. >>> fp = [5, 10, 3, 4]
  1136. >>> np.interp(x, xp, fp, period=360)
  1137. array([7.5 , 5. , 8.75, 6.25, 3. , 3.25, 3.5 , 3.75])
  1138. Complex interpolation:
  1139. >>> x = [1.5, 4.0]
  1140. >>> xp = [2,3,5]
  1141. >>> fp = [1.0j, 0, 2+3j]
  1142. >>> np.interp(x, xp, fp)
  1143. array([0.+1.j , 1.+1.5j])
  1144. """
  1145. fp = np.asarray(fp)
  1146. if np.iscomplexobj(fp):
  1147. interp_func = compiled_interp_complex
  1148. input_dtype = np.complex128
  1149. else:
  1150. interp_func = compiled_interp
  1151. input_dtype = np.float64
  1152. if period is not None:
  1153. if period == 0:
  1154. raise ValueError("period must be a non-zero value")
  1155. period = abs(period)
  1156. left = None
  1157. right = None
  1158. x = np.asarray(x, dtype=np.float64)
  1159. xp = np.asarray(xp, dtype=np.float64)
  1160. fp = np.asarray(fp, dtype=input_dtype)
  1161. if xp.ndim != 1 or fp.ndim != 1:
  1162. raise ValueError("Data points must be 1-D sequences")
  1163. if xp.shape[0] != fp.shape[0]:
  1164. raise ValueError("fp and xp are not of the same length")
  1165. # normalizing periodic boundaries
  1166. x = x % period
  1167. xp = xp % period
  1168. asort_xp = np.argsort(xp)
  1169. xp = xp[asort_xp]
  1170. fp = fp[asort_xp]
  1171. xp = np.concatenate((xp[-1:]-period, xp, xp[0:1]+period))
  1172. fp = np.concatenate((fp[-1:], fp, fp[0:1]))
  1173. return interp_func(x, xp, fp, left, right)
  1174. def _angle_dispatcher(z, deg=None):
  1175. return (z,)
  1176. @array_function_dispatch(_angle_dispatcher)
  1177. def angle(z, deg=False):
  1178. """
  1179. Return the angle of the complex argument.
  1180. Parameters
  1181. ----------
  1182. z : array_like
  1183. A complex number or sequence of complex numbers.
  1184. deg : bool, optional
  1185. Return angle in degrees if True, radians if False (default).
  1186. Returns
  1187. -------
  1188. angle : ndarray or scalar
  1189. The counterclockwise angle from the positive real axis on the complex
  1190. plane in the range ``(-pi, pi]``, with dtype as numpy.float64.
  1191. .. versionchanged:: 1.16.0
  1192. This function works on subclasses of ndarray like `ma.array`.
  1193. See Also
  1194. --------
  1195. arctan2
  1196. absolute
  1197. Notes
  1198. -----
  1199. Although the angle of the complex number 0 is undefined, ``numpy.angle(0)``
  1200. returns the value 0.
  1201. Examples
  1202. --------
  1203. >>> np.angle([1.0, 1.0j, 1+1j]) # in radians
  1204. array([ 0. , 1.57079633, 0.78539816]) # may vary
  1205. >>> np.angle(1+1j, deg=True) # in degrees
  1206. 45.0
  1207. """
  1208. z = asanyarray(z)
  1209. if issubclass(z.dtype.type, _nx.complexfloating):
  1210. zimag = z.imag
  1211. zreal = z.real
  1212. else:
  1213. zimag = 0
  1214. zreal = z
  1215. a = arctan2(zimag, zreal)
  1216. if deg:
  1217. a *= 180/pi
  1218. return a
  1219. def _unwrap_dispatcher(p, discont=None, axis=None, *, period=None):
  1220. return (p,)
  1221. @array_function_dispatch(_unwrap_dispatcher)
  1222. def unwrap(p, discont=None, axis=-1, *, period=2*pi):
  1223. r"""
  1224. Unwrap by taking the complement of large deltas with respect to the period.
  1225. This unwraps a signal `p` by changing elements which have an absolute
  1226. difference from their predecessor of more than ``max(discont, period/2)``
  1227. to their `period`-complementary values.
  1228. For the default case where `period` is :math:`2\pi` and is `discont` is
  1229. :math:`\pi`, this unwraps a radian phase `p` such that adjacent differences
  1230. are never greater than :math:`\pi` by adding :math:`2k\pi` for some
  1231. integer :math:`k`.
  1232. Parameters
  1233. ----------
  1234. p : array_like
  1235. Input array.
  1236. discont : float, optional
  1237. Maximum discontinuity between values, default is ``period/2``.
  1238. Values below ``period/2`` are treated as if they were ``period/2``.
  1239. To have an effect different from the default, `discont` should be
  1240. larger than ``period/2``.
  1241. axis : int, optional
  1242. Axis along which unwrap will operate, default is the last axis.
  1243. period: float, optional
  1244. Size of the range over which the input wraps. By default, it is
  1245. ``2 pi``.
  1246. .. versionadded:: 1.21.0
  1247. Returns
  1248. -------
  1249. out : ndarray
  1250. Output array.
  1251. See Also
  1252. --------
  1253. rad2deg, deg2rad
  1254. Notes
  1255. -----
  1256. If the discontinuity in `p` is smaller than ``period/2``,
  1257. but larger than `discont`, no unwrapping is done because taking
  1258. the complement would only make the discontinuity larger.
  1259. Examples
  1260. --------
  1261. >>> phase = np.linspace(0, np.pi, num=5)
  1262. >>> phase[3:] += np.pi
  1263. >>> phase
  1264. array([ 0. , 0.78539816, 1.57079633, 5.49778714, 6.28318531]) # may vary
  1265. >>> np.unwrap(phase)
  1266. array([ 0. , 0.78539816, 1.57079633, -0.78539816, 0. ]) # may vary
  1267. >>> np.unwrap([0, 1, 2, -1, 0], period=4)
  1268. array([0, 1, 2, 3, 4])
  1269. >>> np.unwrap([ 1, 2, 3, 4, 5, 6, 1, 2, 3], period=6)
  1270. array([1, 2, 3, 4, 5, 6, 7, 8, 9])
  1271. >>> np.unwrap([2, 3, 4, 5, 2, 3, 4, 5], period=4)
  1272. array([2, 3, 4, 5, 6, 7, 8, 9])
  1273. >>> phase_deg = np.mod(np.linspace(0 ,720, 19), 360) - 180
  1274. >>> np.unwrap(phase_deg, period=360)
  1275. array([-180., -140., -100., -60., -20., 20., 60., 100., 140.,
  1276. 180., 220., 260., 300., 340., 380., 420., 460., 500.,
  1277. 540.])
  1278. """
  1279. p = asarray(p)
  1280. nd = p.ndim
  1281. dd = diff(p, axis=axis)
  1282. if discont is None:
  1283. discont = period/2
  1284. slice1 = [slice(None, None)]*nd # full slices
  1285. slice1[axis] = slice(1, None)
  1286. slice1 = tuple(slice1)
  1287. dtype = np.result_type(dd, period)
  1288. if _nx.issubdtype(dtype, _nx.integer):
  1289. interval_high, rem = divmod(period, 2)
  1290. boundary_ambiguous = rem == 0
  1291. else:
  1292. interval_high = period / 2
  1293. boundary_ambiguous = True
  1294. interval_low = -interval_high
  1295. ddmod = mod(dd - interval_low, period) + interval_low
  1296. if boundary_ambiguous:
  1297. # for `mask = (abs(dd) == period/2)`, the above line made
  1298. # `ddmod[mask] == -period/2`. correct these such that
  1299. # `ddmod[mask] == sign(dd[mask])*period/2`.
  1300. _nx.copyto(ddmod, interval_high,
  1301. where=(ddmod == interval_low) & (dd > 0))
  1302. ph_correct = ddmod - dd
  1303. _nx.copyto(ph_correct, 0, where=abs(dd) < discont)
  1304. up = array(p, copy=True, dtype=dtype)
  1305. up[slice1] = p[slice1] + ph_correct.cumsum(axis)
  1306. return up
  1307. def _sort_complex(a):
  1308. return (a,)
  1309. @array_function_dispatch(_sort_complex)
  1310. def sort_complex(a):
  1311. """
  1312. Sort a complex array using the real part first, then the imaginary part.
  1313. Parameters
  1314. ----------
  1315. a : array_like
  1316. Input array
  1317. Returns
  1318. -------
  1319. out : complex ndarray
  1320. Always returns a sorted complex array.
  1321. Examples
  1322. --------
  1323. >>> np.sort_complex([5, 3, 6, 2, 1])
  1324. array([1.+0.j, 2.+0.j, 3.+0.j, 5.+0.j, 6.+0.j])
  1325. >>> np.sort_complex([1 + 2j, 2 - 1j, 3 - 2j, 3 - 3j, 3 + 5j])
  1326. array([1.+2.j, 2.-1.j, 3.-3.j, 3.-2.j, 3.+5.j])
  1327. """
  1328. b = array(a, copy=True)
  1329. b.sort()
  1330. if not issubclass(b.dtype.type, _nx.complexfloating):
  1331. if b.dtype.char in 'bhBH':
  1332. return b.astype('F')
  1333. elif b.dtype.char == 'g':
  1334. return b.astype('G')
  1335. else:
  1336. return b.astype('D')
  1337. else:
  1338. return b
  1339. def _trim_zeros(filt, trim=None):
  1340. return (filt,)
  1341. @array_function_dispatch(_trim_zeros)
  1342. def trim_zeros(filt, trim='fb'):
  1343. """
  1344. Trim the leading and/or trailing zeros from a 1-D array or sequence.
  1345. Parameters
  1346. ----------
  1347. filt : 1-D array or sequence
  1348. Input array.
  1349. trim : str, optional
  1350. A string with 'f' representing trim from front and 'b' to trim from
  1351. back. Default is 'fb', trim zeros from both front and back of the
  1352. array.
  1353. Returns
  1354. -------
  1355. trimmed : 1-D array or sequence
  1356. The result of trimming the input. The input data type is preserved.
  1357. Examples
  1358. --------
  1359. >>> a = np.array((0, 0, 0, 1, 2, 3, 0, 2, 1, 0))
  1360. >>> np.trim_zeros(a)
  1361. array([1, 2, 3, 0, 2, 1])
  1362. >>> np.trim_zeros(a, 'b')
  1363. array([0, 0, 0, ..., 0, 2, 1])
  1364. The input data type is preserved, list/tuple in means list/tuple out.
  1365. >>> np.trim_zeros([0, 1, 2, 0])
  1366. [1, 2]
  1367. """
  1368. first = 0
  1369. trim = trim.upper()
  1370. if 'F' in trim:
  1371. for i in filt:
  1372. if i != 0.:
  1373. break
  1374. else:
  1375. first = first + 1
  1376. last = len(filt)
  1377. if 'B' in trim:
  1378. for i in filt[::-1]:
  1379. if i != 0.:
  1380. break
  1381. else:
  1382. last = last - 1
  1383. return filt[first:last]
  1384. def _extract_dispatcher(condition, arr):
  1385. return (condition, arr)
  1386. @array_function_dispatch(_extract_dispatcher)
  1387. def extract(condition, arr):
  1388. """
  1389. Return the elements of an array that satisfy some condition.
  1390. This is equivalent to ``np.compress(ravel(condition), ravel(arr))``. If
  1391. `condition` is boolean ``np.extract`` is equivalent to ``arr[condition]``.
  1392. Note that `place` does the exact opposite of `extract`.
  1393. Parameters
  1394. ----------
  1395. condition : array_like
  1396. An array whose nonzero or True entries indicate the elements of `arr`
  1397. to extract.
  1398. arr : array_like
  1399. Input array of the same size as `condition`.
  1400. Returns
  1401. -------
  1402. extract : ndarray
  1403. Rank 1 array of values from `arr` where `condition` is True.
  1404. See Also
  1405. --------
  1406. take, put, copyto, compress, place
  1407. Examples
  1408. --------
  1409. >>> arr = np.arange(12).reshape((3, 4))
  1410. >>> arr
  1411. array([[ 0, 1, 2, 3],
  1412. [ 4, 5, 6, 7],
  1413. [ 8, 9, 10, 11]])
  1414. >>> condition = np.mod(arr, 3)==0
  1415. >>> condition
  1416. array([[ True, False, False, True],
  1417. [False, False, True, False],
  1418. [False, True, False, False]])
  1419. >>> np.extract(condition, arr)
  1420. array([0, 3, 6, 9])
  1421. If `condition` is boolean:
  1422. >>> arr[condition]
  1423. array([0, 3, 6, 9])
  1424. """
  1425. return _nx.take(ravel(arr), nonzero(ravel(condition))[0])
  1426. def _place_dispatcher(arr, mask, vals):
  1427. return (arr, mask, vals)
  1428. @array_function_dispatch(_place_dispatcher)
  1429. def place(arr, mask, vals):
  1430. """
  1431. Change elements of an array based on conditional and input values.
  1432. Similar to ``np.copyto(arr, vals, where=mask)``, the difference is that
  1433. `place` uses the first N elements of `vals`, where N is the number of
  1434. True values in `mask`, while `copyto` uses the elements where `mask`
  1435. is True.
  1436. Note that `extract` does the exact opposite of `place`.
  1437. Parameters
  1438. ----------
  1439. arr : ndarray
  1440. Array to put data into.
  1441. mask : array_like
  1442. Boolean mask array. Must have the same size as `a`.
  1443. vals : 1-D sequence
  1444. Values to put into `a`. Only the first N elements are used, where
  1445. N is the number of True values in `mask`. If `vals` is smaller
  1446. than N, it will be repeated, and if elements of `a` are to be masked,
  1447. this sequence must be non-empty.
  1448. See Also
  1449. --------
  1450. copyto, put, take, extract
  1451. Examples
  1452. --------
  1453. >>> arr = np.arange(6).reshape(2, 3)
  1454. >>> np.place(arr, arr>2, [44, 55])
  1455. >>> arr
  1456. array([[ 0, 1, 2],
  1457. [44, 55, 44]])
  1458. """
  1459. if not isinstance(arr, np.ndarray):
  1460. raise TypeError("argument 1 must be numpy.ndarray, "
  1461. "not {name}".format(name=type(arr).__name__))
  1462. return _insert(arr, mask, vals)
  1463. def disp(mesg, device=None, linefeed=True):
  1464. """
  1465. Display a message on a device.
  1466. Parameters
  1467. ----------
  1468. mesg : str
  1469. Message to display.
  1470. device : object
  1471. Device to write message. If None, defaults to ``sys.stdout`` which is
  1472. very similar to ``print``. `device` needs to have ``write()`` and
  1473. ``flush()`` methods.
  1474. linefeed : bool, optional
  1475. Option whether to print a line feed or not. Defaults to True.
  1476. Raises
  1477. ------
  1478. AttributeError
  1479. If `device` does not have a ``write()`` or ``flush()`` method.
  1480. Examples
  1481. --------
  1482. Besides ``sys.stdout``, a file-like object can also be used as it has
  1483. both required methods:
  1484. >>> from io import StringIO
  1485. >>> buf = StringIO()
  1486. >>> np.disp(u'"Display" in a file', device=buf)
  1487. >>> buf.getvalue()
  1488. '"Display" in a file\\n'
  1489. """
  1490. if device is None:
  1491. device = sys.stdout
  1492. if linefeed:
  1493. device.write('%s\n' % mesg)
  1494. else:
  1495. device.write('%s' % mesg)
  1496. device.flush()
  1497. return
  1498. # See https://docs.scipy.org/doc/numpy/reference/c-api.generalized-ufuncs.html
  1499. _DIMENSION_NAME = r'\w+'
  1500. _CORE_DIMENSION_LIST = '(?:{0:}(?:,{0:})*)?'.format(_DIMENSION_NAME)
  1501. _ARGUMENT = r'\({}\)'.format(_CORE_DIMENSION_LIST)
  1502. _ARGUMENT_LIST = '{0:}(?:,{0:})*'.format(_ARGUMENT)
  1503. _SIGNATURE = '^{0:}->{0:}$'.format(_ARGUMENT_LIST)
  1504. def _parse_gufunc_signature(signature):
  1505. """
  1506. Parse string signatures for a generalized universal function.
  1507. Arguments
  1508. ---------
  1509. signature : string
  1510. Generalized universal function signature, e.g., ``(m,n),(n,p)->(m,p)``
  1511. for ``np.matmul``.
  1512. Returns
  1513. -------
  1514. Tuple of input and output core dimensions parsed from the signature, each
  1515. of the form List[Tuple[str, ...]].
  1516. """
  1517. if not re.match(_SIGNATURE, signature):
  1518. raise ValueError(
  1519. 'not a valid gufunc signature: {}'.format(signature))
  1520. return tuple([tuple(re.findall(_DIMENSION_NAME, arg))
  1521. for arg in re.findall(_ARGUMENT, arg_list)]
  1522. for arg_list in signature.split('->'))
  1523. def _update_dim_sizes(dim_sizes, arg, core_dims):
  1524. """
  1525. Incrementally check and update core dimension sizes for a single argument.
  1526. Arguments
  1527. ---------
  1528. dim_sizes : Dict[str, int]
  1529. Sizes of existing core dimensions. Will be updated in-place.
  1530. arg : ndarray
  1531. Argument to examine.
  1532. core_dims : Tuple[str, ...]
  1533. Core dimensions for this argument.
  1534. """
  1535. if not core_dims:
  1536. return
  1537. num_core_dims = len(core_dims)
  1538. if arg.ndim < num_core_dims:
  1539. raise ValueError(
  1540. '%d-dimensional argument does not have enough '
  1541. 'dimensions for all core dimensions %r'
  1542. % (arg.ndim, core_dims))
  1543. core_shape = arg.shape[-num_core_dims:]
  1544. for dim, size in zip(core_dims, core_shape):
  1545. if dim in dim_sizes:
  1546. if size != dim_sizes[dim]:
  1547. raise ValueError(
  1548. 'inconsistent size for core dimension %r: %r vs %r'
  1549. % (dim, size, dim_sizes[dim]))
  1550. else:
  1551. dim_sizes[dim] = size
  1552. def _parse_input_dimensions(args, input_core_dims):
  1553. """
  1554. Parse broadcast and core dimensions for vectorize with a signature.
  1555. Arguments
  1556. ---------
  1557. args : Tuple[ndarray, ...]
  1558. Tuple of input arguments to examine.
  1559. input_core_dims : List[Tuple[str, ...]]
  1560. List of core dimensions corresponding to each input.
  1561. Returns
  1562. -------
  1563. broadcast_shape : Tuple[int, ...]
  1564. Common shape to broadcast all non-core dimensions to.
  1565. dim_sizes : Dict[str, int]
  1566. Common sizes for named core dimensions.
  1567. """
  1568. broadcast_args = []
  1569. dim_sizes = {}
  1570. for arg, core_dims in zip(args, input_core_dims):
  1571. _update_dim_sizes(dim_sizes, arg, core_dims)
  1572. ndim = arg.ndim - len(core_dims)
  1573. dummy_array = np.lib.stride_tricks.as_strided(0, arg.shape[:ndim])
  1574. broadcast_args.append(dummy_array)
  1575. broadcast_shape = np.lib.stride_tricks._broadcast_shape(*broadcast_args)
  1576. return broadcast_shape, dim_sizes
  1577. def _calculate_shapes(broadcast_shape, dim_sizes, list_of_core_dims):
  1578. """Helper for calculating broadcast shapes with core dimensions."""
  1579. return [broadcast_shape + tuple(dim_sizes[dim] for dim in core_dims)
  1580. for core_dims in list_of_core_dims]
  1581. def _create_arrays(broadcast_shape, dim_sizes, list_of_core_dims, dtypes):
  1582. """Helper for creating output arrays in vectorize."""
  1583. shapes = _calculate_shapes(broadcast_shape, dim_sizes, list_of_core_dims)
  1584. arrays = tuple(np.empty(shape, dtype=dtype)
  1585. for shape, dtype in zip(shapes, dtypes))
  1586. return arrays
  1587. @set_module('numpy')
  1588. class vectorize:
  1589. """
  1590. vectorize(pyfunc, otypes=None, doc=None, excluded=None, cache=False,
  1591. signature=None)
  1592. Generalized function class.
  1593. Define a vectorized function which takes a nested sequence of objects or
  1594. numpy arrays as inputs and returns a single numpy array or a tuple of numpy
  1595. arrays. The vectorized function evaluates `pyfunc` over successive tuples
  1596. of the input arrays like the python map function, except it uses the
  1597. broadcasting rules of numpy.
  1598. The data type of the output of `vectorized` is determined by calling
  1599. the function with the first element of the input. This can be avoided
  1600. by specifying the `otypes` argument.
  1601. Parameters
  1602. ----------
  1603. pyfunc : callable
  1604. A python function or method.
  1605. otypes : str or list of dtypes, optional
  1606. The output data type. It must be specified as either a string of
  1607. typecode characters or a list of data type specifiers. There should
  1608. be one data type specifier for each output.
  1609. doc : str, optional
  1610. The docstring for the function. If None, the docstring will be the
  1611. ``pyfunc.__doc__``.
  1612. excluded : set, optional
  1613. Set of strings or integers representing the positional or keyword
  1614. arguments for which the function will not be vectorized. These will be
  1615. passed directly to `pyfunc` unmodified.
  1616. .. versionadded:: 1.7.0
  1617. cache : bool, optional
  1618. If `True`, then cache the first function call that determines the number
  1619. of outputs if `otypes` is not provided.
  1620. .. versionadded:: 1.7.0
  1621. signature : string, optional
  1622. Generalized universal function signature, e.g., ``(m,n),(n)->(m)`` for
  1623. vectorized matrix-vector multiplication. If provided, ``pyfunc`` will
  1624. be called with (and expected to return) arrays with shapes given by the
  1625. size of corresponding core dimensions. By default, ``pyfunc`` is
  1626. assumed to take scalars as input and output.
  1627. .. versionadded:: 1.12.0
  1628. Returns
  1629. -------
  1630. vectorized : callable
  1631. Vectorized function.
  1632. See Also
  1633. --------
  1634. frompyfunc : Takes an arbitrary Python function and returns a ufunc
  1635. Notes
  1636. -----
  1637. The `vectorize` function is provided primarily for convenience, not for
  1638. performance. The implementation is essentially a for loop.
  1639. If `otypes` is not specified, then a call to the function with the
  1640. first argument will be used to determine the number of outputs. The
  1641. results of this call will be cached if `cache` is `True` to prevent
  1642. calling the function twice. However, to implement the cache, the
  1643. original function must be wrapped which will slow down subsequent
  1644. calls, so only do this if your function is expensive.
  1645. The new keyword argument interface and `excluded` argument support
  1646. further degrades performance.
  1647. References
  1648. ----------
  1649. .. [1] :doc:`/reference/c-api/generalized-ufuncs`
  1650. Examples
  1651. --------
  1652. >>> def myfunc(a, b):
  1653. ... "Return a-b if a>b, otherwise return a+b"
  1654. ... if a > b:
  1655. ... return a - b
  1656. ... else:
  1657. ... return a + b
  1658. >>> vfunc = np.vectorize(myfunc)
  1659. >>> vfunc([1, 2, 3, 4], 2)
  1660. array([3, 4, 1, 2])
  1661. The docstring is taken from the input function to `vectorize` unless it
  1662. is specified:
  1663. >>> vfunc.__doc__
  1664. 'Return a-b if a>b, otherwise return a+b'
  1665. >>> vfunc = np.vectorize(myfunc, doc='Vectorized `myfunc`')
  1666. >>> vfunc.__doc__
  1667. 'Vectorized `myfunc`'
  1668. The output type is determined by evaluating the first element of the input,
  1669. unless it is specified:
  1670. >>> out = vfunc([1, 2, 3, 4], 2)
  1671. >>> type(out[0])
  1672. <class 'numpy.int64'>
  1673. >>> vfunc = np.vectorize(myfunc, otypes=[float])
  1674. >>> out = vfunc([1, 2, 3, 4], 2)
  1675. >>> type(out[0])
  1676. <class 'numpy.float64'>
  1677. The `excluded` argument can be used to prevent vectorizing over certain
  1678. arguments. This can be useful for array-like arguments of a fixed length
  1679. such as the coefficients for a polynomial as in `polyval`:
  1680. >>> def mypolyval(p, x):
  1681. ... _p = list(p)
  1682. ... res = _p.pop(0)
  1683. ... while _p:
  1684. ... res = res*x + _p.pop(0)
  1685. ... return res
  1686. >>> vpolyval = np.vectorize(mypolyval, excluded=['p'])
  1687. >>> vpolyval(p=[1, 2, 3], x=[0, 1])
  1688. array([3, 6])
  1689. Positional arguments may also be excluded by specifying their position:
  1690. >>> vpolyval.excluded.add(0)
  1691. >>> vpolyval([1, 2, 3], x=[0, 1])
  1692. array([3, 6])
  1693. The `signature` argument allows for vectorizing functions that act on
  1694. non-scalar arrays of fixed length. For example, you can use it for a
  1695. vectorized calculation of Pearson correlation coefficient and its p-value:
  1696. >>> import scipy.stats
  1697. >>> pearsonr = np.vectorize(scipy.stats.pearsonr,
  1698. ... signature='(n),(n)->(),()')
  1699. >>> pearsonr([[0, 1, 2, 3]], [[1, 2, 3, 4], [4, 3, 2, 1]])
  1700. (array([ 1., -1.]), array([ 0., 0.]))
  1701. Or for a vectorized convolution:
  1702. >>> convolve = np.vectorize(np.convolve, signature='(n),(m)->(k)')
  1703. >>> convolve(np.eye(4), [1, 2, 1])
  1704. array([[1., 2., 1., 0., 0., 0.],
  1705. [0., 1., 2., 1., 0., 0.],
  1706. [0., 0., 1., 2., 1., 0.],
  1707. [0., 0., 0., 1., 2., 1.]])
  1708. """
  1709. def __init__(self, pyfunc, otypes=None, doc=None, excluded=None,
  1710. cache=False, signature=None):
  1711. self.pyfunc = pyfunc
  1712. self.cache = cache
  1713. self.signature = signature
  1714. self._ufunc = {} # Caching to improve default performance
  1715. if doc is None:
  1716. self.__doc__ = pyfunc.__doc__
  1717. else:
  1718. self.__doc__ = doc
  1719. if isinstance(otypes, str):
  1720. for char in otypes:
  1721. if char not in typecodes['All']:
  1722. raise ValueError("Invalid otype specified: %s" % (char,))
  1723. elif iterable(otypes):
  1724. otypes = ''.join([_nx.dtype(x).char for x in otypes])
  1725. elif otypes is not None:
  1726. raise ValueError("Invalid otype specification")
  1727. self.otypes = otypes
  1728. # Excluded variable support
  1729. if excluded is None:
  1730. excluded = set()
  1731. self.excluded = set(excluded)
  1732. if signature is not None:
  1733. self._in_and_out_core_dims = _parse_gufunc_signature(signature)
  1734. else:
  1735. self._in_and_out_core_dims = None
  1736. def __call__(self, *args, **kwargs):
  1737. """
  1738. Return arrays with the results of `pyfunc` broadcast (vectorized) over
  1739. `args` and `kwargs` not in `excluded`.
  1740. """
  1741. excluded = self.excluded
  1742. if not kwargs and not excluded:
  1743. func = self.pyfunc
  1744. vargs = args
  1745. else:
  1746. # The wrapper accepts only positional arguments: we use `names` and
  1747. # `inds` to mutate `the_args` and `kwargs` to pass to the original
  1748. # function.
  1749. nargs = len(args)
  1750. names = [_n for _n in kwargs if _n not in excluded]
  1751. inds = [_i for _i in range(nargs) if _i not in excluded]
  1752. the_args = list(args)
  1753. def func(*vargs):
  1754. for _n, _i in enumerate(inds):
  1755. the_args[_i] = vargs[_n]
  1756. kwargs.update(zip(names, vargs[len(inds):]))
  1757. return self.pyfunc(*the_args, **kwargs)
  1758. vargs = [args[_i] for _i in inds]
  1759. vargs.extend([kwargs[_n] for _n in names])
  1760. return self._vectorize_call(func=func, args=vargs)
  1761. def _get_ufunc_and_otypes(self, func, args):
  1762. """Return (ufunc, otypes)."""
  1763. # frompyfunc will fail if args is empty
  1764. if not args:
  1765. raise ValueError('args can not be empty')
  1766. if self.otypes is not None:
  1767. otypes = self.otypes
  1768. # self._ufunc is a dictionary whose keys are the number of
  1769. # arguments (i.e. len(args)) and whose values are ufuncs created
  1770. # by frompyfunc. len(args) can be different for different calls if
  1771. # self.pyfunc has parameters with default values. We only use the
  1772. # cache when func is self.pyfunc, which occurs when the call uses
  1773. # only positional arguments and no arguments are excluded.
  1774. nin = len(args)
  1775. nout = len(self.otypes)
  1776. if func is not self.pyfunc or nin not in self._ufunc:
  1777. ufunc = frompyfunc(func, nin, nout)
  1778. else:
  1779. ufunc = None # We'll get it from self._ufunc
  1780. if func is self.pyfunc:
  1781. ufunc = self._ufunc.setdefault(nin, ufunc)
  1782. else:
  1783. # Get number of outputs and output types by calling the function on
  1784. # the first entries of args. We also cache the result to prevent
  1785. # the subsequent call when the ufunc is evaluated.
  1786. # Assumes that ufunc first evaluates the 0th elements in the input
  1787. # arrays (the input values are not checked to ensure this)
  1788. args = [asarray(arg) for arg in args]
  1789. if builtins.any(arg.size == 0 for arg in args):
  1790. raise ValueError('cannot call `vectorize` on size 0 inputs '
  1791. 'unless `otypes` is set')
  1792. inputs = [arg.flat[0] for arg in args]
  1793. outputs = func(*inputs)
  1794. # Performance note: profiling indicates that -- for simple
  1795. # functions at least -- this wrapping can almost double the
  1796. # execution time.
  1797. # Hence we make it optional.
  1798. if self.cache:
  1799. _cache = [outputs]
  1800. def _func(*vargs):
  1801. if _cache:
  1802. return _cache.pop()
  1803. else:
  1804. return func(*vargs)
  1805. else:
  1806. _func = func
  1807. if isinstance(outputs, tuple):
  1808. nout = len(outputs)
  1809. else:
  1810. nout = 1
  1811. outputs = (outputs,)
  1812. otypes = ''.join([asarray(outputs[_k]).dtype.char
  1813. for _k in range(nout)])
  1814. # Performance note: profiling indicates that creating the ufunc is
  1815. # not a significant cost compared with wrapping so it seems not
  1816. # worth trying to cache this.
  1817. ufunc = frompyfunc(_func, len(args), nout)
  1818. return ufunc, otypes
  1819. def _vectorize_call(self, func, args):
  1820. """Vectorized call to `func` over positional `args`."""
  1821. if self.signature is not None:
  1822. res = self._vectorize_call_with_signature(func, args)
  1823. elif not args:
  1824. res = func()
  1825. else:
  1826. ufunc, otypes = self._get_ufunc_and_otypes(func=func, args=args)
  1827. # Convert args to object arrays first
  1828. inputs = [asanyarray(a, dtype=object) for a in args]
  1829. outputs = ufunc(*inputs)
  1830. if ufunc.nout == 1:
  1831. res = asanyarray(outputs, dtype=otypes[0])
  1832. else:
  1833. res = tuple([asanyarray(x, dtype=t)
  1834. for x, t in zip(outputs, otypes)])
  1835. return res
  1836. def _vectorize_call_with_signature(self, func, args):
  1837. """Vectorized call over positional arguments with a signature."""
  1838. input_core_dims, output_core_dims = self._in_and_out_core_dims
  1839. if len(args) != len(input_core_dims):
  1840. raise TypeError('wrong number of positional arguments: '
  1841. 'expected %r, got %r'
  1842. % (len(input_core_dims), len(args)))
  1843. args = tuple(asanyarray(arg) for arg in args)
  1844. broadcast_shape, dim_sizes = _parse_input_dimensions(
  1845. args, input_core_dims)
  1846. input_shapes = _calculate_shapes(broadcast_shape, dim_sizes,
  1847. input_core_dims)
  1848. args = [np.broadcast_to(arg, shape, subok=True)
  1849. for arg, shape in zip(args, input_shapes)]
  1850. outputs = None
  1851. otypes = self.otypes
  1852. nout = len(output_core_dims)
  1853. for index in np.ndindex(*broadcast_shape):
  1854. results = func(*(arg[index] for arg in args))
  1855. n_results = len(results) if isinstance(results, tuple) else 1
  1856. if nout != n_results:
  1857. raise ValueError(
  1858. 'wrong number of outputs from pyfunc: expected %r, got %r'
  1859. % (nout, n_results))
  1860. if nout == 1:
  1861. results = (results,)
  1862. if outputs is None:
  1863. for result, core_dims in zip(results, output_core_dims):
  1864. _update_dim_sizes(dim_sizes, result, core_dims)
  1865. if otypes is None:
  1866. otypes = [asarray(result).dtype for result in results]
  1867. outputs = _create_arrays(broadcast_shape, dim_sizes,
  1868. output_core_dims, otypes)
  1869. for output, result in zip(outputs, results):
  1870. output[index] = result
  1871. if outputs is None:
  1872. # did not call the function even once
  1873. if otypes is None:
  1874. raise ValueError('cannot call `vectorize` on size 0 inputs '
  1875. 'unless `otypes` is set')
  1876. if builtins.any(dim not in dim_sizes
  1877. for dims in output_core_dims
  1878. for dim in dims):
  1879. raise ValueError('cannot call `vectorize` with a signature '
  1880. 'including new output dimensions on size 0 '
  1881. 'inputs')
  1882. outputs = _create_arrays(broadcast_shape, dim_sizes,
  1883. output_core_dims, otypes)
  1884. return outputs[0] if nout == 1 else outputs
  1885. def _cov_dispatcher(m, y=None, rowvar=None, bias=None, ddof=None,
  1886. fweights=None, aweights=None, *, dtype=None):
  1887. return (m, y, fweights, aweights)
  1888. @array_function_dispatch(_cov_dispatcher)
  1889. def cov(m, y=None, rowvar=True, bias=False, ddof=None, fweights=None,
  1890. aweights=None, *, dtype=None):
  1891. """
  1892. Estimate a covariance matrix, given data and weights.
  1893. Covariance indicates the level to which two variables vary together.
  1894. If we examine N-dimensional samples, :math:`X = [x_1, x_2, ... x_N]^T`,
  1895. then the covariance matrix element :math:`C_{ij}` is the covariance of
  1896. :math:`x_i` and :math:`x_j`. The element :math:`C_{ii}` is the variance
  1897. of :math:`x_i`.
  1898. See the notes for an outline of the algorithm.
  1899. Parameters
  1900. ----------
  1901. m : array_like
  1902. A 1-D or 2-D array containing multiple variables and observations.
  1903. Each row of `m` represents a variable, and each column a single
  1904. observation of all those variables. Also see `rowvar` below.
  1905. y : array_like, optional
  1906. An additional set of variables and observations. `y` has the same form
  1907. as that of `m`.
  1908. rowvar : bool, optional
  1909. If `rowvar` is True (default), then each row represents a
  1910. variable, with observations in the columns. Otherwise, the relationship
  1911. is transposed: each column represents a variable, while the rows
  1912. contain observations.
  1913. bias : bool, optional
  1914. Default normalization (False) is by ``(N - 1)``, where ``N`` is the
  1915. number of observations given (unbiased estimate). If `bias` is True,
  1916. then normalization is by ``N``. These values can be overridden by using
  1917. the keyword ``ddof`` in numpy versions >= 1.5.
  1918. ddof : int, optional
  1919. If not ``None`` the default value implied by `bias` is overridden.
  1920. Note that ``ddof=1`` will return the unbiased estimate, even if both
  1921. `fweights` and `aweights` are specified, and ``ddof=0`` will return
  1922. the simple average. See the notes for the details. The default value
  1923. is ``None``.
  1924. .. versionadded:: 1.5
  1925. fweights : array_like, int, optional
  1926. 1-D array of integer frequency weights; the number of times each
  1927. observation vector should be repeated.
  1928. .. versionadded:: 1.10
  1929. aweights : array_like, optional
  1930. 1-D array of observation vector weights. These relative weights are
  1931. typically large for observations considered "important" and smaller for
  1932. observations considered less "important". If ``ddof=0`` the array of
  1933. weights can be used to assign probabilities to observation vectors.
  1934. .. versionadded:: 1.10
  1935. dtype : data-type, optional
  1936. Data-type of the result. By default, the return data-type will have
  1937. at least `numpy.float64` precision.
  1938. .. versionadded:: 1.20
  1939. Returns
  1940. -------
  1941. out : ndarray
  1942. The covariance matrix of the variables.
  1943. See Also
  1944. --------
  1945. corrcoef : Normalized covariance matrix
  1946. Notes
  1947. -----
  1948. Assume that the observations are in the columns of the observation
  1949. array `m` and let ``f = fweights`` and ``a = aweights`` for brevity. The
  1950. steps to compute the weighted covariance are as follows::
  1951. >>> m = np.arange(10, dtype=np.float64)
  1952. >>> f = np.arange(10) * 2
  1953. >>> a = np.arange(10) ** 2.
  1954. >>> ddof = 1
  1955. >>> w = f * a
  1956. >>> v1 = np.sum(w)
  1957. >>> v2 = np.sum(w * a)
  1958. >>> m -= np.sum(m * w, axis=None, keepdims=True) / v1
  1959. >>> cov = np.dot(m * w, m.T) * v1 / (v1**2 - ddof * v2)
  1960. Note that when ``a == 1``, the normalization factor
  1961. ``v1 / (v1**2 - ddof * v2)`` goes over to ``1 / (np.sum(f) - ddof)``
  1962. as it should.
  1963. Examples
  1964. --------
  1965. Consider two variables, :math:`x_0` and :math:`x_1`, which
  1966. correlate perfectly, but in opposite directions:
  1967. >>> x = np.array([[0, 2], [1, 1], [2, 0]]).T
  1968. >>> x
  1969. array([[0, 1, 2],
  1970. [2, 1, 0]])
  1971. Note how :math:`x_0` increases while :math:`x_1` decreases. The covariance
  1972. matrix shows this clearly:
  1973. >>> np.cov(x)
  1974. array([[ 1., -1.],
  1975. [-1., 1.]])
  1976. Note that element :math:`C_{0,1}`, which shows the correlation between
  1977. :math:`x_0` and :math:`x_1`, is negative.
  1978. Further, note how `x` and `y` are combined:
  1979. >>> x = [-2.1, -1, 4.3]
  1980. >>> y = [3, 1.1, 0.12]
  1981. >>> X = np.stack((x, y), axis=0)
  1982. >>> np.cov(X)
  1983. array([[11.71 , -4.286 ], # may vary
  1984. [-4.286 , 2.144133]])
  1985. >>> np.cov(x, y)
  1986. array([[11.71 , -4.286 ], # may vary
  1987. [-4.286 , 2.144133]])
  1988. >>> np.cov(x)
  1989. array(11.71)
  1990. """
  1991. # Check inputs
  1992. if ddof is not None and ddof != int(ddof):
  1993. raise ValueError(
  1994. "ddof must be integer")
  1995. # Handles complex arrays too
  1996. m = np.asarray(m)
  1997. if m.ndim > 2:
  1998. raise ValueError("m has more than 2 dimensions")
  1999. if y is not None:
  2000. y = np.asarray(y)
  2001. if y.ndim > 2:
  2002. raise ValueError("y has more than 2 dimensions")
  2003. if dtype is None:
  2004. if y is None:
  2005. dtype = np.result_type(m, np.float64)
  2006. else:
  2007. dtype = np.result_type(m, y, np.float64)
  2008. X = array(m, ndmin=2, dtype=dtype)
  2009. if not rowvar and X.shape[0] != 1:
  2010. X = X.T
  2011. if X.shape[0] == 0:
  2012. return np.array([]).reshape(0, 0)
  2013. if y is not None:
  2014. y = array(y, copy=False, ndmin=2, dtype=dtype)
  2015. if not rowvar and y.shape[0] != 1:
  2016. y = y.T
  2017. X = np.concatenate((X, y), axis=0)
  2018. if ddof is None:
  2019. if bias == 0:
  2020. ddof = 1
  2021. else:
  2022. ddof = 0
  2023. # Get the product of frequencies and weights
  2024. w = None
  2025. if fweights is not None:
  2026. fweights = np.asarray(fweights, dtype=float)
  2027. if not np.all(fweights == np.around(fweights)):
  2028. raise TypeError(
  2029. "fweights must be integer")
  2030. if fweights.ndim > 1:
  2031. raise RuntimeError(
  2032. "cannot handle multidimensional fweights")
  2033. if fweights.shape[0] != X.shape[1]:
  2034. raise RuntimeError(
  2035. "incompatible numbers of samples and fweights")
  2036. if any(fweights < 0):
  2037. raise ValueError(
  2038. "fweights cannot be negative")
  2039. w = fweights
  2040. if aweights is not None:
  2041. aweights = np.asarray(aweights, dtype=float)
  2042. if aweights.ndim > 1:
  2043. raise RuntimeError(
  2044. "cannot handle multidimensional aweights")
  2045. if aweights.shape[0] != X.shape[1]:
  2046. raise RuntimeError(
  2047. "incompatible numbers of samples and aweights")
  2048. if any(aweights < 0):
  2049. raise ValueError(
  2050. "aweights cannot be negative")
  2051. if w is None:
  2052. w = aweights
  2053. else:
  2054. w *= aweights
  2055. avg, w_sum = average(X, axis=1, weights=w, returned=True)
  2056. w_sum = w_sum[0]
  2057. # Determine the normalization
  2058. if w is None:
  2059. fact = X.shape[1] - ddof
  2060. elif ddof == 0:
  2061. fact = w_sum
  2062. elif aweights is None:
  2063. fact = w_sum - ddof
  2064. else:
  2065. fact = w_sum - ddof*sum(w*aweights)/w_sum
  2066. if fact <= 0:
  2067. warnings.warn("Degrees of freedom <= 0 for slice",
  2068. RuntimeWarning, stacklevel=3)
  2069. fact = 0.0
  2070. X -= avg[:, None]
  2071. if w is None:
  2072. X_T = X.T
  2073. else:
  2074. X_T = (X*w).T
  2075. c = dot(X, X_T.conj())
  2076. c *= np.true_divide(1, fact)
  2077. return c.squeeze()
  2078. def _corrcoef_dispatcher(x, y=None, rowvar=None, bias=None, ddof=None, *,
  2079. dtype=None):
  2080. return (x, y)
  2081. @array_function_dispatch(_corrcoef_dispatcher)
  2082. def corrcoef(x, y=None, rowvar=True, bias=np._NoValue, ddof=np._NoValue, *,
  2083. dtype=None):
  2084. """
  2085. Return Pearson product-moment correlation coefficients.
  2086. Please refer to the documentation for `cov` for more detail. The
  2087. relationship between the correlation coefficient matrix, `R`, and the
  2088. covariance matrix, `C`, is
  2089. .. math:: R_{ij} = \\frac{ C_{ij} } { \\sqrt{ C_{ii} * C_{jj} } }
  2090. The values of `R` are between -1 and 1, inclusive.
  2091. Parameters
  2092. ----------
  2093. x : array_like
  2094. A 1-D or 2-D array containing multiple variables and observations.
  2095. Each row of `x` represents a variable, and each column a single
  2096. observation of all those variables. Also see `rowvar` below.
  2097. y : array_like, optional
  2098. An additional set of variables and observations. `y` has the same
  2099. shape as `x`.
  2100. rowvar : bool, optional
  2101. If `rowvar` is True (default), then each row represents a
  2102. variable, with observations in the columns. Otherwise, the relationship
  2103. is transposed: each column represents a variable, while the rows
  2104. contain observations.
  2105. bias : _NoValue, optional
  2106. Has no effect, do not use.
  2107. .. deprecated:: 1.10.0
  2108. ddof : _NoValue, optional
  2109. Has no effect, do not use.
  2110. .. deprecated:: 1.10.0
  2111. dtype : data-type, optional
  2112. Data-type of the result. By default, the return data-type will have
  2113. at least `numpy.float64` precision.
  2114. .. versionadded:: 1.20
  2115. Returns
  2116. -------
  2117. R : ndarray
  2118. The correlation coefficient matrix of the variables.
  2119. See Also
  2120. --------
  2121. cov : Covariance matrix
  2122. Notes
  2123. -----
  2124. Due to floating point rounding the resulting array may not be Hermitian,
  2125. the diagonal elements may not be 1, and the elements may not satisfy the
  2126. inequality abs(a) <= 1. The real and imaginary parts are clipped to the
  2127. interval [-1, 1] in an attempt to improve on that situation but is not
  2128. much help in the complex case.
  2129. This function accepts but discards arguments `bias` and `ddof`. This is
  2130. for backwards compatibility with previous versions of this function. These
  2131. arguments had no effect on the return values of the function and can be
  2132. safely ignored in this and previous versions of numpy.
  2133. Examples
  2134. --------
  2135. In this example we generate two random arrays, ``xarr`` and ``yarr``, and
  2136. compute the row-wise and column-wise Pearson correlation coefficients,
  2137. ``R``. Since ``rowvar`` is true by default, we first find the row-wise
  2138. Pearson correlation coefficients between the variables of ``xarr``.
  2139. >>> import numpy as np
  2140. >>> rng = np.random.default_rng(seed=42)
  2141. >>> xarr = rng.random((3, 3))
  2142. >>> xarr
  2143. array([[0.77395605, 0.43887844, 0.85859792],
  2144. [0.69736803, 0.09417735, 0.97562235],
  2145. [0.7611397 , 0.78606431, 0.12811363]])
  2146. >>> R1 = np.corrcoef(xarr)
  2147. >>> R1
  2148. array([[ 1. , 0.99256089, -0.68080986],
  2149. [ 0.99256089, 1. , -0.76492172],
  2150. [-0.68080986, -0.76492172, 1. ]])
  2151. If we add another set of variables and observations ``yarr``, we can
  2152. compute the row-wise Pearson correlation coefficients between the
  2153. variables in ``xarr`` and ``yarr``.
  2154. >>> yarr = rng.random((3, 3))
  2155. >>> yarr
  2156. array([[0.45038594, 0.37079802, 0.92676499],
  2157. [0.64386512, 0.82276161, 0.4434142 ],
  2158. [0.22723872, 0.55458479, 0.06381726]])
  2159. >>> R2 = np.corrcoef(xarr, yarr)
  2160. >>> R2
  2161. array([[ 1. , 0.99256089, -0.68080986, 0.75008178, -0.934284 ,
  2162. -0.99004057],
  2163. [ 0.99256089, 1. , -0.76492172, 0.82502011, -0.97074098,
  2164. -0.99981569],
  2165. [-0.68080986, -0.76492172, 1. , -0.99507202, 0.89721355,
  2166. 0.77714685],
  2167. [ 0.75008178, 0.82502011, -0.99507202, 1. , -0.93657855,
  2168. -0.83571711],
  2169. [-0.934284 , -0.97074098, 0.89721355, -0.93657855, 1. ,
  2170. 0.97517215],
  2171. [-0.99004057, -0.99981569, 0.77714685, -0.83571711, 0.97517215,
  2172. 1. ]])
  2173. Finally if we use the option ``rowvar=False``, the columns are now
  2174. being treated as the variables and we will find the column-wise Pearson
  2175. correlation coefficients between variables in ``xarr`` and ``yarr``.
  2176. >>> R3 = np.corrcoef(xarr, yarr, rowvar=False)
  2177. >>> R3
  2178. array([[ 1. , 0.77598074, -0.47458546, -0.75078643, -0.9665554 ,
  2179. 0.22423734],
  2180. [ 0.77598074, 1. , -0.92346708, -0.99923895, -0.58826587,
  2181. -0.44069024],
  2182. [-0.47458546, -0.92346708, 1. , 0.93773029, 0.23297648,
  2183. 0.75137473],
  2184. [-0.75078643, -0.99923895, 0.93773029, 1. , 0.55627469,
  2185. 0.47536961],
  2186. [-0.9665554 , -0.58826587, 0.23297648, 0.55627469, 1. ,
  2187. -0.46666491],
  2188. [ 0.22423734, -0.44069024, 0.75137473, 0.47536961, -0.46666491,
  2189. 1. ]])
  2190. """
  2191. if bias is not np._NoValue or ddof is not np._NoValue:
  2192. # 2015-03-15, 1.10
  2193. warnings.warn('bias and ddof have no effect and are deprecated',
  2194. DeprecationWarning, stacklevel=3)
  2195. c = cov(x, y, rowvar, dtype=dtype)
  2196. try:
  2197. d = diag(c)
  2198. except ValueError:
  2199. # scalar covariance
  2200. # nan if incorrect value (nan, inf, 0), 1 otherwise
  2201. return c / c
  2202. stddev = sqrt(d.real)
  2203. c /= stddev[:, None]
  2204. c /= stddev[None, :]
  2205. # Clip real and imaginary parts to [-1, 1]. This does not guarantee
  2206. # abs(a[i,j]) <= 1 for complex arrays, but is the best we can do without
  2207. # excessive work.
  2208. np.clip(c.real, -1, 1, out=c.real)
  2209. if np.iscomplexobj(c):
  2210. np.clip(c.imag, -1, 1, out=c.imag)
  2211. return c
  2212. @set_module('numpy')
  2213. def blackman(M):
  2214. """
  2215. Return the Blackman window.
  2216. The Blackman window is a taper formed by using the first three
  2217. terms of a summation of cosines. It was designed to have close to the
  2218. minimal leakage possible. It is close to optimal, only slightly worse
  2219. than a Kaiser window.
  2220. Parameters
  2221. ----------
  2222. M : int
  2223. Number of points in the output window. If zero or less, an empty
  2224. array is returned.
  2225. Returns
  2226. -------
  2227. out : ndarray
  2228. The window, with the maximum value normalized to one (the value one
  2229. appears only if the number of samples is odd).
  2230. See Also
  2231. --------
  2232. bartlett, hamming, hanning, kaiser
  2233. Notes
  2234. -----
  2235. The Blackman window is defined as
  2236. .. math:: w(n) = 0.42 - 0.5 \\cos(2\\pi n/M) + 0.08 \\cos(4\\pi n/M)
  2237. Most references to the Blackman window come from the signal processing
  2238. literature, where it is used as one of many windowing functions for
  2239. smoothing values. It is also known as an apodization (which means
  2240. "removing the foot", i.e. smoothing discontinuities at the beginning
  2241. and end of the sampled signal) or tapering function. It is known as a
  2242. "near optimal" tapering function, almost as good (by some measures)
  2243. as the kaiser window.
  2244. References
  2245. ----------
  2246. Blackman, R.B. and Tukey, J.W., (1958) The measurement of power spectra,
  2247. Dover Publications, New York.
  2248. Oppenheim, A.V., and R.W. Schafer. Discrete-Time Signal Processing.
  2249. Upper Saddle River, NJ: Prentice-Hall, 1999, pp. 468-471.
  2250. Examples
  2251. --------
  2252. >>> import matplotlib.pyplot as plt
  2253. >>> np.blackman(12)
  2254. array([-1.38777878e-17, 3.26064346e-02, 1.59903635e-01, # may vary
  2255. 4.14397981e-01, 7.36045180e-01, 9.67046769e-01,
  2256. 9.67046769e-01, 7.36045180e-01, 4.14397981e-01,
  2257. 1.59903635e-01, 3.26064346e-02, -1.38777878e-17])
  2258. Plot the window and the frequency response:
  2259. >>> from numpy.fft import fft, fftshift
  2260. >>> window = np.blackman(51)
  2261. >>> plt.plot(window)
  2262. [<matplotlib.lines.Line2D object at 0x...>]
  2263. >>> plt.title("Blackman window")
  2264. Text(0.5, 1.0, 'Blackman window')
  2265. >>> plt.ylabel("Amplitude")
  2266. Text(0, 0.5, 'Amplitude')
  2267. >>> plt.xlabel("Sample")
  2268. Text(0.5, 0, 'Sample')
  2269. >>> plt.show()
  2270. >>> plt.figure()
  2271. <Figure size 640x480 with 0 Axes>
  2272. >>> A = fft(window, 2048) / 25.5
  2273. >>> mag = np.abs(fftshift(A))
  2274. >>> freq = np.linspace(-0.5, 0.5, len(A))
  2275. >>> with np.errstate(divide='ignore', invalid='ignore'):
  2276. ... response = 20 * np.log10(mag)
  2277. ...
  2278. >>> response = np.clip(response, -100, 100)
  2279. >>> plt.plot(freq, response)
  2280. [<matplotlib.lines.Line2D object at 0x...>]
  2281. >>> plt.title("Frequency response of Blackman window")
  2282. Text(0.5, 1.0, 'Frequency response of Blackman window')
  2283. >>> plt.ylabel("Magnitude [dB]")
  2284. Text(0, 0.5, 'Magnitude [dB]')
  2285. >>> plt.xlabel("Normalized frequency [cycles per sample]")
  2286. Text(0.5, 0, 'Normalized frequency [cycles per sample]')
  2287. >>> _ = plt.axis('tight')
  2288. >>> plt.show()
  2289. """
  2290. if M < 1:
  2291. return array([])
  2292. if M == 1:
  2293. return ones(1, float)
  2294. n = arange(1-M, M, 2)
  2295. return 0.42 + 0.5*cos(pi*n/(M-1)) + 0.08*cos(2.0*pi*n/(M-1))
  2296. @set_module('numpy')
  2297. def bartlett(M):
  2298. """
  2299. Return the Bartlett window.
  2300. The Bartlett window is very similar to a triangular window, except
  2301. that the end points are at zero. It is often used in signal
  2302. processing for tapering a signal, without generating too much
  2303. ripple in the frequency domain.
  2304. Parameters
  2305. ----------
  2306. M : int
  2307. Number of points in the output window. If zero or less, an
  2308. empty array is returned.
  2309. Returns
  2310. -------
  2311. out : array
  2312. The triangular window, with the maximum value normalized to one
  2313. (the value one appears only if the number of samples is odd), with
  2314. the first and last samples equal to zero.
  2315. See Also
  2316. --------
  2317. blackman, hamming, hanning, kaiser
  2318. Notes
  2319. -----
  2320. The Bartlett window is defined as
  2321. .. math:: w(n) = \\frac{2}{M-1} \\left(
  2322. \\frac{M-1}{2} - \\left|n - \\frac{M-1}{2}\\right|
  2323. \\right)
  2324. Most references to the Bartlett window come from the signal
  2325. processing literature, where it is used as one of many windowing
  2326. functions for smoothing values. Note that convolution with this
  2327. window produces linear interpolation. It is also known as an
  2328. apodization (which means"removing the foot", i.e. smoothing
  2329. discontinuities at the beginning and end of the sampled signal) or
  2330. tapering function. The fourier transform of the Bartlett is the product
  2331. of two sinc functions.
  2332. Note the excellent discussion in Kanasewich.
  2333. References
  2334. ----------
  2335. .. [1] M.S. Bartlett, "Periodogram Analysis and Continuous Spectra",
  2336. Biometrika 37, 1-16, 1950.
  2337. .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics",
  2338. The University of Alberta Press, 1975, pp. 109-110.
  2339. .. [3] A.V. Oppenheim and R.W. Schafer, "Discrete-Time Signal
  2340. Processing", Prentice-Hall, 1999, pp. 468-471.
  2341. .. [4] Wikipedia, "Window function",
  2342. https://en.wikipedia.org/wiki/Window_function
  2343. .. [5] W.H. Press, B.P. Flannery, S.A. Teukolsky, and W.T. Vetterling,
  2344. "Numerical Recipes", Cambridge University Press, 1986, page 429.
  2345. Examples
  2346. --------
  2347. >>> import matplotlib.pyplot as plt
  2348. >>> np.bartlett(12)
  2349. array([ 0. , 0.18181818, 0.36363636, 0.54545455, 0.72727273, # may vary
  2350. 0.90909091, 0.90909091, 0.72727273, 0.54545455, 0.36363636,
  2351. 0.18181818, 0. ])
  2352. Plot the window and its frequency response (requires SciPy and matplotlib):
  2353. >>> from numpy.fft import fft, fftshift
  2354. >>> window = np.bartlett(51)
  2355. >>> plt.plot(window)
  2356. [<matplotlib.lines.Line2D object at 0x...>]
  2357. >>> plt.title("Bartlett window")
  2358. Text(0.5, 1.0, 'Bartlett window')
  2359. >>> plt.ylabel("Amplitude")
  2360. Text(0, 0.5, 'Amplitude')
  2361. >>> plt.xlabel("Sample")
  2362. Text(0.5, 0, 'Sample')
  2363. >>> plt.show()
  2364. >>> plt.figure()
  2365. <Figure size 640x480 with 0 Axes>
  2366. >>> A = fft(window, 2048) / 25.5
  2367. >>> mag = np.abs(fftshift(A))
  2368. >>> freq = np.linspace(-0.5, 0.5, len(A))
  2369. >>> with np.errstate(divide='ignore', invalid='ignore'):
  2370. ... response = 20 * np.log10(mag)
  2371. ...
  2372. >>> response = np.clip(response, -100, 100)
  2373. >>> plt.plot(freq, response)
  2374. [<matplotlib.lines.Line2D object at 0x...>]
  2375. >>> plt.title("Frequency response of Bartlett window")
  2376. Text(0.5, 1.0, 'Frequency response of Bartlett window')
  2377. >>> plt.ylabel("Magnitude [dB]")
  2378. Text(0, 0.5, 'Magnitude [dB]')
  2379. >>> plt.xlabel("Normalized frequency [cycles per sample]")
  2380. Text(0.5, 0, 'Normalized frequency [cycles per sample]')
  2381. >>> _ = plt.axis('tight')
  2382. >>> plt.show()
  2383. """
  2384. if M < 1:
  2385. return array([])
  2386. if M == 1:
  2387. return ones(1, float)
  2388. n = arange(1-M, M, 2)
  2389. return where(less_equal(n, 0), 1 + n/(M-1), 1 - n/(M-1))
  2390. @set_module('numpy')
  2391. def hanning(M):
  2392. """
  2393. Return the Hanning window.
  2394. The Hanning window is a taper formed by using a weighted cosine.
  2395. Parameters
  2396. ----------
  2397. M : int
  2398. Number of points in the output window. If zero or less, an
  2399. empty array is returned.
  2400. Returns
  2401. -------
  2402. out : ndarray, shape(M,)
  2403. The window, with the maximum value normalized to one (the value
  2404. one appears only if `M` is odd).
  2405. See Also
  2406. --------
  2407. bartlett, blackman, hamming, kaiser
  2408. Notes
  2409. -----
  2410. The Hanning window is defined as
  2411. .. math:: w(n) = 0.5 - 0.5cos\\left(\\frac{2\\pi{n}}{M-1}\\right)
  2412. \\qquad 0 \\leq n \\leq M-1
  2413. The Hanning was named for Julius von Hann, an Austrian meteorologist.
  2414. It is also known as the Cosine Bell. Some authors prefer that it be
  2415. called a Hann window, to help avoid confusion with the very similar
  2416. Hamming window.
  2417. Most references to the Hanning window come from the signal processing
  2418. literature, where it is used as one of many windowing functions for
  2419. smoothing values. It is also known as an apodization (which means
  2420. "removing the foot", i.e. smoothing discontinuities at the beginning
  2421. and end of the sampled signal) or tapering function.
  2422. References
  2423. ----------
  2424. .. [1] Blackman, R.B. and Tukey, J.W., (1958) The measurement of power
  2425. spectra, Dover Publications, New York.
  2426. .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics",
  2427. The University of Alberta Press, 1975, pp. 106-108.
  2428. .. [3] Wikipedia, "Window function",
  2429. https://en.wikipedia.org/wiki/Window_function
  2430. .. [4] W.H. Press, B.P. Flannery, S.A. Teukolsky, and W.T. Vetterling,
  2431. "Numerical Recipes", Cambridge University Press, 1986, page 425.
  2432. Examples
  2433. --------
  2434. >>> np.hanning(12)
  2435. array([0. , 0.07937323, 0.29229249, 0.57115742, 0.82743037,
  2436. 0.97974649, 0.97974649, 0.82743037, 0.57115742, 0.29229249,
  2437. 0.07937323, 0. ])
  2438. Plot the window and its frequency response:
  2439. >>> import matplotlib.pyplot as plt
  2440. >>> from numpy.fft import fft, fftshift
  2441. >>> window = np.hanning(51)
  2442. >>> plt.plot(window)
  2443. [<matplotlib.lines.Line2D object at 0x...>]
  2444. >>> plt.title("Hann window")
  2445. Text(0.5, 1.0, 'Hann window')
  2446. >>> plt.ylabel("Amplitude")
  2447. Text(0, 0.5, 'Amplitude')
  2448. >>> plt.xlabel("Sample")
  2449. Text(0.5, 0, 'Sample')
  2450. >>> plt.show()
  2451. >>> plt.figure()
  2452. <Figure size 640x480 with 0 Axes>
  2453. >>> A = fft(window, 2048) / 25.5
  2454. >>> mag = np.abs(fftshift(A))
  2455. >>> freq = np.linspace(-0.5, 0.5, len(A))
  2456. >>> with np.errstate(divide='ignore', invalid='ignore'):
  2457. ... response = 20 * np.log10(mag)
  2458. ...
  2459. >>> response = np.clip(response, -100, 100)
  2460. >>> plt.plot(freq, response)
  2461. [<matplotlib.lines.Line2D object at 0x...>]
  2462. >>> plt.title("Frequency response of the Hann window")
  2463. Text(0.5, 1.0, 'Frequency response of the Hann window')
  2464. >>> plt.ylabel("Magnitude [dB]")
  2465. Text(0, 0.5, 'Magnitude [dB]')
  2466. >>> plt.xlabel("Normalized frequency [cycles per sample]")
  2467. Text(0.5, 0, 'Normalized frequency [cycles per sample]')
  2468. >>> plt.axis('tight')
  2469. ...
  2470. >>> plt.show()
  2471. """
  2472. if M < 1:
  2473. return array([])
  2474. if M == 1:
  2475. return ones(1, float)
  2476. n = arange(1-M, M, 2)
  2477. return 0.5 + 0.5*cos(pi*n/(M-1))
  2478. @set_module('numpy')
  2479. def hamming(M):
  2480. """
  2481. Return the Hamming window.
  2482. The Hamming window is a taper formed by using a weighted cosine.
  2483. Parameters
  2484. ----------
  2485. M : int
  2486. Number of points in the output window. If zero or less, an
  2487. empty array is returned.
  2488. Returns
  2489. -------
  2490. out : ndarray
  2491. The window, with the maximum value normalized to one (the value
  2492. one appears only if the number of samples is odd).
  2493. See Also
  2494. --------
  2495. bartlett, blackman, hanning, kaiser
  2496. Notes
  2497. -----
  2498. The Hamming window is defined as
  2499. .. math:: w(n) = 0.54 - 0.46cos\\left(\\frac{2\\pi{n}}{M-1}\\right)
  2500. \\qquad 0 \\leq n \\leq M-1
  2501. The Hamming was named for R. W. Hamming, an associate of J. W. Tukey
  2502. and is described in Blackman and Tukey. It was recommended for
  2503. smoothing the truncated autocovariance function in the time domain.
  2504. Most references to the Hamming window come from the signal processing
  2505. literature, where it is used as one of many windowing functions for
  2506. smoothing values. It is also known as an apodization (which means
  2507. "removing the foot", i.e. smoothing discontinuities at the beginning
  2508. and end of the sampled signal) or tapering function.
  2509. References
  2510. ----------
  2511. .. [1] Blackman, R.B. and Tukey, J.W., (1958) The measurement of power
  2512. spectra, Dover Publications, New York.
  2513. .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics", The
  2514. University of Alberta Press, 1975, pp. 109-110.
  2515. .. [3] Wikipedia, "Window function",
  2516. https://en.wikipedia.org/wiki/Window_function
  2517. .. [4] W.H. Press, B.P. Flannery, S.A. Teukolsky, and W.T. Vetterling,
  2518. "Numerical Recipes", Cambridge University Press, 1986, page 425.
  2519. Examples
  2520. --------
  2521. >>> np.hamming(12)
  2522. array([ 0.08 , 0.15302337, 0.34890909, 0.60546483, 0.84123594, # may vary
  2523. 0.98136677, 0.98136677, 0.84123594, 0.60546483, 0.34890909,
  2524. 0.15302337, 0.08 ])
  2525. Plot the window and the frequency response:
  2526. >>> import matplotlib.pyplot as plt
  2527. >>> from numpy.fft import fft, fftshift
  2528. >>> window = np.hamming(51)
  2529. >>> plt.plot(window)
  2530. [<matplotlib.lines.Line2D object at 0x...>]
  2531. >>> plt.title("Hamming window")
  2532. Text(0.5, 1.0, 'Hamming window')
  2533. >>> plt.ylabel("Amplitude")
  2534. Text(0, 0.5, 'Amplitude')
  2535. >>> plt.xlabel("Sample")
  2536. Text(0.5, 0, 'Sample')
  2537. >>> plt.show()
  2538. >>> plt.figure()
  2539. <Figure size 640x480 with 0 Axes>
  2540. >>> A = fft(window, 2048) / 25.5
  2541. >>> mag = np.abs(fftshift(A))
  2542. >>> freq = np.linspace(-0.5, 0.5, len(A))
  2543. >>> response = 20 * np.log10(mag)
  2544. >>> response = np.clip(response, -100, 100)
  2545. >>> plt.plot(freq, response)
  2546. [<matplotlib.lines.Line2D object at 0x...>]
  2547. >>> plt.title("Frequency response of Hamming window")
  2548. Text(0.5, 1.0, 'Frequency response of Hamming window')
  2549. >>> plt.ylabel("Magnitude [dB]")
  2550. Text(0, 0.5, 'Magnitude [dB]')
  2551. >>> plt.xlabel("Normalized frequency [cycles per sample]")
  2552. Text(0.5, 0, 'Normalized frequency [cycles per sample]')
  2553. >>> plt.axis('tight')
  2554. ...
  2555. >>> plt.show()
  2556. """
  2557. if M < 1:
  2558. return array([])
  2559. if M == 1:
  2560. return ones(1, float)
  2561. n = arange(1-M, M, 2)
  2562. return 0.54 + 0.46*cos(pi*n/(M-1))
  2563. ## Code from cephes for i0
  2564. _i0A = [
  2565. -4.41534164647933937950E-18,
  2566. 3.33079451882223809783E-17,
  2567. -2.43127984654795469359E-16,
  2568. 1.71539128555513303061E-15,
  2569. -1.16853328779934516808E-14,
  2570. 7.67618549860493561688E-14,
  2571. -4.85644678311192946090E-13,
  2572. 2.95505266312963983461E-12,
  2573. -1.72682629144155570723E-11,
  2574. 9.67580903537323691224E-11,
  2575. -5.18979560163526290666E-10,
  2576. 2.65982372468238665035E-9,
  2577. -1.30002500998624804212E-8,
  2578. 6.04699502254191894932E-8,
  2579. -2.67079385394061173391E-7,
  2580. 1.11738753912010371815E-6,
  2581. -4.41673835845875056359E-6,
  2582. 1.64484480707288970893E-5,
  2583. -5.75419501008210370398E-5,
  2584. 1.88502885095841655729E-4,
  2585. -5.76375574538582365885E-4,
  2586. 1.63947561694133579842E-3,
  2587. -4.32430999505057594430E-3,
  2588. 1.05464603945949983183E-2,
  2589. -2.37374148058994688156E-2,
  2590. 4.93052842396707084878E-2,
  2591. -9.49010970480476444210E-2,
  2592. 1.71620901522208775349E-1,
  2593. -3.04682672343198398683E-1,
  2594. 6.76795274409476084995E-1
  2595. ]
  2596. _i0B = [
  2597. -7.23318048787475395456E-18,
  2598. -4.83050448594418207126E-18,
  2599. 4.46562142029675999901E-17,
  2600. 3.46122286769746109310E-17,
  2601. -2.82762398051658348494E-16,
  2602. -3.42548561967721913462E-16,
  2603. 1.77256013305652638360E-15,
  2604. 3.81168066935262242075E-15,
  2605. -9.55484669882830764870E-15,
  2606. -4.15056934728722208663E-14,
  2607. 1.54008621752140982691E-14,
  2608. 3.85277838274214270114E-13,
  2609. 7.18012445138366623367E-13,
  2610. -1.79417853150680611778E-12,
  2611. -1.32158118404477131188E-11,
  2612. -3.14991652796324136454E-11,
  2613. 1.18891471078464383424E-11,
  2614. 4.94060238822496958910E-10,
  2615. 3.39623202570838634515E-9,
  2616. 2.26666899049817806459E-8,
  2617. 2.04891858946906374183E-7,
  2618. 2.89137052083475648297E-6,
  2619. 6.88975834691682398426E-5,
  2620. 3.36911647825569408990E-3,
  2621. 8.04490411014108831608E-1
  2622. ]
  2623. def _chbevl(x, vals):
  2624. b0 = vals[0]
  2625. b1 = 0.0
  2626. for i in range(1, len(vals)):
  2627. b2 = b1
  2628. b1 = b0
  2629. b0 = x*b1 - b2 + vals[i]
  2630. return 0.5*(b0 - b2)
  2631. def _i0_1(x):
  2632. return exp(x) * _chbevl(x/2.0-2, _i0A)
  2633. def _i0_2(x):
  2634. return exp(x) * _chbevl(32.0/x - 2.0, _i0B) / sqrt(x)
  2635. def _i0_dispatcher(x):
  2636. return (x,)
  2637. @array_function_dispatch(_i0_dispatcher)
  2638. def i0(x):
  2639. """
  2640. Modified Bessel function of the first kind, order 0.
  2641. Usually denoted :math:`I_0`.
  2642. Parameters
  2643. ----------
  2644. x : array_like of float
  2645. Argument of the Bessel function.
  2646. Returns
  2647. -------
  2648. out : ndarray, shape = x.shape, dtype = float
  2649. The modified Bessel function evaluated at each of the elements of `x`.
  2650. See Also
  2651. --------
  2652. scipy.special.i0, scipy.special.iv, scipy.special.ive
  2653. Notes
  2654. -----
  2655. The scipy implementation is recommended over this function: it is a
  2656. proper ufunc written in C, and more than an order of magnitude faster.
  2657. We use the algorithm published by Clenshaw [1]_ and referenced by
  2658. Abramowitz and Stegun [2]_, for which the function domain is
  2659. partitioned into the two intervals [0,8] and (8,inf), and Chebyshev
  2660. polynomial expansions are employed in each interval. Relative error on
  2661. the domain [0,30] using IEEE arithmetic is documented [3]_ as having a
  2662. peak of 5.8e-16 with an rms of 1.4e-16 (n = 30000).
  2663. References
  2664. ----------
  2665. .. [1] C. W. Clenshaw, "Chebyshev series for mathematical functions", in
  2666. *National Physical Laboratory Mathematical Tables*, vol. 5, London:
  2667. Her Majesty's Stationery Office, 1962.
  2668. .. [2] M. Abramowitz and I. A. Stegun, *Handbook of Mathematical
  2669. Functions*, 10th printing, New York: Dover, 1964, pp. 379.
  2670. http://www.math.sfu.ca/~cbm/aands/page_379.htm
  2671. .. [3] https://metacpan.org/pod/distribution/Math-Cephes/lib/Math/Cephes.pod#i0:-Modified-Bessel-function-of-order-zero
  2672. Examples
  2673. --------
  2674. >>> np.i0(0.)
  2675. array(1.0)
  2676. >>> np.i0([0, 1, 2, 3])
  2677. array([1. , 1.26606588, 2.2795853 , 4.88079259])
  2678. """
  2679. x = np.asanyarray(x)
  2680. if x.dtype.kind == 'c':
  2681. raise TypeError("i0 not supported for complex values")
  2682. if x.dtype.kind != 'f':
  2683. x = x.astype(float)
  2684. x = np.abs(x)
  2685. return piecewise(x, [x <= 8.0], [_i0_1, _i0_2])
  2686. ## End of cephes code for i0
  2687. @set_module('numpy')
  2688. def kaiser(M, beta):
  2689. """
  2690. Return the Kaiser window.
  2691. The Kaiser window is a taper formed by using a Bessel function.
  2692. Parameters
  2693. ----------
  2694. M : int
  2695. Number of points in the output window. If zero or less, an
  2696. empty array is returned.
  2697. beta : float
  2698. Shape parameter for window.
  2699. Returns
  2700. -------
  2701. out : array
  2702. The window, with the maximum value normalized to one (the value
  2703. one appears only if the number of samples is odd).
  2704. See Also
  2705. --------
  2706. bartlett, blackman, hamming, hanning
  2707. Notes
  2708. -----
  2709. The Kaiser window is defined as
  2710. .. math:: w(n) = I_0\\left( \\beta \\sqrt{1-\\frac{4n^2}{(M-1)^2}}
  2711. \\right)/I_0(\\beta)
  2712. with
  2713. .. math:: \\quad -\\frac{M-1}{2} \\leq n \\leq \\frac{M-1}{2},
  2714. where :math:`I_0` is the modified zeroth-order Bessel function.
  2715. The Kaiser was named for Jim Kaiser, who discovered a simple
  2716. approximation to the DPSS window based on Bessel functions. The Kaiser
  2717. window is a very good approximation to the Digital Prolate Spheroidal
  2718. Sequence, or Slepian window, which is the transform which maximizes the
  2719. energy in the main lobe of the window relative to total energy.
  2720. The Kaiser can approximate many other windows by varying the beta
  2721. parameter.
  2722. ==== =======================
  2723. beta Window shape
  2724. ==== =======================
  2725. 0 Rectangular
  2726. 5 Similar to a Hamming
  2727. 6 Similar to a Hanning
  2728. 8.6 Similar to a Blackman
  2729. ==== =======================
  2730. A beta value of 14 is probably a good starting point. Note that as beta
  2731. gets large, the window narrows, and so the number of samples needs to be
  2732. large enough to sample the increasingly narrow spike, otherwise NaNs will
  2733. get returned.
  2734. Most references to the Kaiser window come from the signal processing
  2735. literature, where it is used as one of many windowing functions for
  2736. smoothing values. It is also known as an apodization (which means
  2737. "removing the foot", i.e. smoothing discontinuities at the beginning
  2738. and end of the sampled signal) or tapering function.
  2739. References
  2740. ----------
  2741. .. [1] J. F. Kaiser, "Digital Filters" - Ch 7 in "Systems analysis by
  2742. digital computer", Editors: F.F. Kuo and J.F. Kaiser, p 218-285.
  2743. John Wiley and Sons, New York, (1966).
  2744. .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics", The
  2745. University of Alberta Press, 1975, pp. 177-178.
  2746. .. [3] Wikipedia, "Window function",
  2747. https://en.wikipedia.org/wiki/Window_function
  2748. Examples
  2749. --------
  2750. >>> import matplotlib.pyplot as plt
  2751. >>> np.kaiser(12, 14)
  2752. array([7.72686684e-06, 3.46009194e-03, 4.65200189e-02, # may vary
  2753. 2.29737120e-01, 5.99885316e-01, 9.45674898e-01,
  2754. 9.45674898e-01, 5.99885316e-01, 2.29737120e-01,
  2755. 4.65200189e-02, 3.46009194e-03, 7.72686684e-06])
  2756. Plot the window and the frequency response:
  2757. >>> from numpy.fft import fft, fftshift
  2758. >>> window = np.kaiser(51, 14)
  2759. >>> plt.plot(window)
  2760. [<matplotlib.lines.Line2D object at 0x...>]
  2761. >>> plt.title("Kaiser window")
  2762. Text(0.5, 1.0, 'Kaiser window')
  2763. >>> plt.ylabel("Amplitude")
  2764. Text(0, 0.5, 'Amplitude')
  2765. >>> plt.xlabel("Sample")
  2766. Text(0.5, 0, 'Sample')
  2767. >>> plt.show()
  2768. >>> plt.figure()
  2769. <Figure size 640x480 with 0 Axes>
  2770. >>> A = fft(window, 2048) / 25.5
  2771. >>> mag = np.abs(fftshift(A))
  2772. >>> freq = np.linspace(-0.5, 0.5, len(A))
  2773. >>> response = 20 * np.log10(mag)
  2774. >>> response = np.clip(response, -100, 100)
  2775. >>> plt.plot(freq, response)
  2776. [<matplotlib.lines.Line2D object at 0x...>]
  2777. >>> plt.title("Frequency response of Kaiser window")
  2778. Text(0.5, 1.0, 'Frequency response of Kaiser window')
  2779. >>> plt.ylabel("Magnitude [dB]")
  2780. Text(0, 0.5, 'Magnitude [dB]')
  2781. >>> plt.xlabel("Normalized frequency [cycles per sample]")
  2782. Text(0.5, 0, 'Normalized frequency [cycles per sample]')
  2783. >>> plt.axis('tight')
  2784. (-0.5, 0.5, -100.0, ...) # may vary
  2785. >>> plt.show()
  2786. """
  2787. if M == 1:
  2788. return np.array([1.])
  2789. n = arange(0, M)
  2790. alpha = (M-1)/2.0
  2791. return i0(beta * sqrt(1-((n-alpha)/alpha)**2.0))/i0(float(beta))
  2792. def _sinc_dispatcher(x):
  2793. return (x,)
  2794. @array_function_dispatch(_sinc_dispatcher)
  2795. def sinc(x):
  2796. r"""
  2797. Return the normalized sinc function.
  2798. The sinc function is :math:`\sin(\pi x)/(\pi x)`.
  2799. .. note::
  2800. Note the normalization factor of ``pi`` used in the definition.
  2801. This is the most commonly used definition in signal processing.
  2802. Use ``sinc(x / np.pi)`` to obtain the unnormalized sinc function
  2803. :math:`\sin(x)/(x)` that is more common in mathematics.
  2804. Parameters
  2805. ----------
  2806. x : ndarray
  2807. Array (possibly multi-dimensional) of values for which to to
  2808. calculate ``sinc(x)``.
  2809. Returns
  2810. -------
  2811. out : ndarray
  2812. ``sinc(x)``, which has the same shape as the input.
  2813. Notes
  2814. -----
  2815. ``sinc(0)`` is the limit value 1.
  2816. The name sinc is short for "sine cardinal" or "sinus cardinalis".
  2817. The sinc function is used in various signal processing applications,
  2818. including in anti-aliasing, in the construction of a Lanczos resampling
  2819. filter, and in interpolation.
  2820. For bandlimited interpolation of discrete-time signals, the ideal
  2821. interpolation kernel is proportional to the sinc function.
  2822. References
  2823. ----------
  2824. .. [1] Weisstein, Eric W. "Sinc Function." From MathWorld--A Wolfram Web
  2825. Resource. http://mathworld.wolfram.com/SincFunction.html
  2826. .. [2] Wikipedia, "Sinc function",
  2827. https://en.wikipedia.org/wiki/Sinc_function
  2828. Examples
  2829. --------
  2830. >>> import matplotlib.pyplot as plt
  2831. >>> x = np.linspace(-4, 4, 41)
  2832. >>> np.sinc(x)
  2833. array([-3.89804309e-17, -4.92362781e-02, -8.40918587e-02, # may vary
  2834. -8.90384387e-02, -5.84680802e-02, 3.89804309e-17,
  2835. 6.68206631e-02, 1.16434881e-01, 1.26137788e-01,
  2836. 8.50444803e-02, -3.89804309e-17, -1.03943254e-01,
  2837. -1.89206682e-01, -2.16236208e-01, -1.55914881e-01,
  2838. 3.89804309e-17, 2.33872321e-01, 5.04551152e-01,
  2839. 7.56826729e-01, 9.35489284e-01, 1.00000000e+00,
  2840. 9.35489284e-01, 7.56826729e-01, 5.04551152e-01,
  2841. 2.33872321e-01, 3.89804309e-17, -1.55914881e-01,
  2842. -2.16236208e-01, -1.89206682e-01, -1.03943254e-01,
  2843. -3.89804309e-17, 8.50444803e-02, 1.26137788e-01,
  2844. 1.16434881e-01, 6.68206631e-02, 3.89804309e-17,
  2845. -5.84680802e-02, -8.90384387e-02, -8.40918587e-02,
  2846. -4.92362781e-02, -3.89804309e-17])
  2847. >>> plt.plot(x, np.sinc(x))
  2848. [<matplotlib.lines.Line2D object at 0x...>]
  2849. >>> plt.title("Sinc Function")
  2850. Text(0.5, 1.0, 'Sinc Function')
  2851. >>> plt.ylabel("Amplitude")
  2852. Text(0, 0.5, 'Amplitude')
  2853. >>> plt.xlabel("X")
  2854. Text(0.5, 0, 'X')
  2855. >>> plt.show()
  2856. """
  2857. x = np.asanyarray(x)
  2858. y = pi * where(x == 0, 1.0e-20, x)
  2859. return sin(y)/y
  2860. def _msort_dispatcher(a):
  2861. return (a,)
  2862. @array_function_dispatch(_msort_dispatcher)
  2863. def msort(a):
  2864. """
  2865. Return a copy of an array sorted along the first axis.
  2866. Parameters
  2867. ----------
  2868. a : array_like
  2869. Array to be sorted.
  2870. Returns
  2871. -------
  2872. sorted_array : ndarray
  2873. Array of the same type and shape as `a`.
  2874. See Also
  2875. --------
  2876. sort
  2877. Notes
  2878. -----
  2879. ``np.msort(a)`` is equivalent to ``np.sort(a, axis=0)``.
  2880. """
  2881. b = array(a, subok=True, copy=True)
  2882. b.sort(0)
  2883. return b
  2884. def _ureduce(a, func, **kwargs):
  2885. """
  2886. Internal Function.
  2887. Call `func` with `a` as first argument swapping the axes to use extended
  2888. axis on functions that don't support it natively.
  2889. Returns result and a.shape with axis dims set to 1.
  2890. Parameters
  2891. ----------
  2892. a : array_like
  2893. Input array or object that can be converted to an array.
  2894. func : callable
  2895. Reduction function capable of receiving a single axis argument.
  2896. It is called with `a` as first argument followed by `kwargs`.
  2897. kwargs : keyword arguments
  2898. additional keyword arguments to pass to `func`.
  2899. Returns
  2900. -------
  2901. result : tuple
  2902. Result of func(a, **kwargs) and a.shape with axis dims set to 1
  2903. which can be used to reshape the result to the same shape a ufunc with
  2904. keepdims=True would produce.
  2905. """
  2906. a = np.asanyarray(a)
  2907. axis = kwargs.get('axis', None)
  2908. if axis is not None:
  2909. keepdim = list(a.shape)
  2910. nd = a.ndim
  2911. axis = _nx.normalize_axis_tuple(axis, nd)
  2912. for ax in axis:
  2913. keepdim[ax] = 1
  2914. if len(axis) == 1:
  2915. kwargs['axis'] = axis[0]
  2916. else:
  2917. keep = set(range(nd)) - set(axis)
  2918. nkeep = len(keep)
  2919. # swap axis that should not be reduced to front
  2920. for i, s in enumerate(sorted(keep)):
  2921. a = a.swapaxes(i, s)
  2922. # merge reduced axis
  2923. a = a.reshape(a.shape[:nkeep] + (-1,))
  2924. kwargs['axis'] = -1
  2925. keepdim = tuple(keepdim)
  2926. else:
  2927. keepdim = (1,) * a.ndim
  2928. r = func(a, **kwargs)
  2929. return r, keepdim
  2930. def _median_dispatcher(
  2931. a, axis=None, out=None, overwrite_input=None, keepdims=None):
  2932. return (a, out)
  2933. @array_function_dispatch(_median_dispatcher)
  2934. def median(a, axis=None, out=None, overwrite_input=False, keepdims=False):
  2935. """
  2936. Compute the median along the specified axis.
  2937. Returns the median of the array elements.
  2938. Parameters
  2939. ----------
  2940. a : array_like
  2941. Input array or object that can be converted to an array.
  2942. axis : {int, sequence of int, None}, optional
  2943. Axis or axes along which the medians are computed. The default
  2944. is to compute the median along a flattened version of the array.
  2945. A sequence of axes is supported since version 1.9.0.
  2946. out : ndarray, optional
  2947. Alternative output array in which to place the result. It must
  2948. have the same shape and buffer length as the expected output,
  2949. but the type (of the output) will be cast if necessary.
  2950. overwrite_input : bool, optional
  2951. If True, then allow use of memory of input array `a` for
  2952. calculations. The input array will be modified by the call to
  2953. `median`. This will save memory when you do not need to preserve
  2954. the contents of the input array. Treat the input as undefined,
  2955. but it will probably be fully or partially sorted. Default is
  2956. False. If `overwrite_input` is ``True`` and `a` is not already an
  2957. `ndarray`, an error will be raised.
  2958. keepdims : bool, optional
  2959. If this is set to True, the axes which are reduced are left
  2960. in the result as dimensions with size one. With this option,
  2961. the result will broadcast correctly against the original `arr`.
  2962. .. versionadded:: 1.9.0
  2963. Returns
  2964. -------
  2965. median : ndarray
  2966. A new array holding the result. If the input contains integers
  2967. or floats smaller than ``float64``, then the output data-type is
  2968. ``np.float64``. Otherwise, the data-type of the output is the
  2969. same as that of the input. If `out` is specified, that array is
  2970. returned instead.
  2971. See Also
  2972. --------
  2973. mean, percentile
  2974. Notes
  2975. -----
  2976. Given a vector ``V`` of length ``N``, the median of ``V`` is the
  2977. middle value of a sorted copy of ``V``, ``V_sorted`` - i
  2978. e., ``V_sorted[(N-1)/2]``, when ``N`` is odd, and the average of the
  2979. two middle values of ``V_sorted`` when ``N`` is even.
  2980. Examples
  2981. --------
  2982. >>> a = np.array([[10, 7, 4], [3, 2, 1]])
  2983. >>> a
  2984. array([[10, 7, 4],
  2985. [ 3, 2, 1]])
  2986. >>> np.median(a)
  2987. 3.5
  2988. >>> np.median(a, axis=0)
  2989. array([6.5, 4.5, 2.5])
  2990. >>> np.median(a, axis=1)
  2991. array([7., 2.])
  2992. >>> m = np.median(a, axis=0)
  2993. >>> out = np.zeros_like(m)
  2994. >>> np.median(a, axis=0, out=m)
  2995. array([6.5, 4.5, 2.5])
  2996. >>> m
  2997. array([6.5, 4.5, 2.5])
  2998. >>> b = a.copy()
  2999. >>> np.median(b, axis=1, overwrite_input=True)
  3000. array([7., 2.])
  3001. >>> assert not np.all(a==b)
  3002. >>> b = a.copy()
  3003. >>> np.median(b, axis=None, overwrite_input=True)
  3004. 3.5
  3005. >>> assert not np.all(a==b)
  3006. """
  3007. r, k = _ureduce(a, func=_median, axis=axis, out=out,
  3008. overwrite_input=overwrite_input)
  3009. if keepdims:
  3010. return r.reshape(k)
  3011. else:
  3012. return r
  3013. def _median(a, axis=None, out=None, overwrite_input=False):
  3014. # can't be reasonably be implemented in terms of percentile as we have to
  3015. # call mean to not break astropy
  3016. a = np.asanyarray(a)
  3017. # Set the partition indexes
  3018. if axis is None:
  3019. sz = a.size
  3020. else:
  3021. sz = a.shape[axis]
  3022. if sz % 2 == 0:
  3023. szh = sz // 2
  3024. kth = [szh - 1, szh]
  3025. else:
  3026. kth = [(sz - 1) // 2]
  3027. # Check if the array contains any nan's
  3028. if np.issubdtype(a.dtype, np.inexact):
  3029. kth.append(-1)
  3030. if overwrite_input:
  3031. if axis is None:
  3032. part = a.ravel()
  3033. part.partition(kth)
  3034. else:
  3035. a.partition(kth, axis=axis)
  3036. part = a
  3037. else:
  3038. part = partition(a, kth, axis=axis)
  3039. if part.shape == ():
  3040. # make 0-D arrays work
  3041. return part.item()
  3042. if axis is None:
  3043. axis = 0
  3044. indexer = [slice(None)] * part.ndim
  3045. index = part.shape[axis] // 2
  3046. if part.shape[axis] % 2 == 1:
  3047. # index with slice to allow mean (below) to work
  3048. indexer[axis] = slice(index, index+1)
  3049. else:
  3050. indexer[axis] = slice(index-1, index+1)
  3051. indexer = tuple(indexer)
  3052. # Check if the array contains any nan's
  3053. if np.issubdtype(a.dtype, np.inexact) and sz > 0:
  3054. # warn and return nans like mean would
  3055. rout = mean(part[indexer], axis=axis, out=out)
  3056. return np.lib.utils._median_nancheck(part, rout, axis, out)
  3057. else:
  3058. # if there are no nans
  3059. # Use mean in odd and even case to coerce data type
  3060. # and check, use out array.
  3061. return mean(part[indexer], axis=axis, out=out)
  3062. def _percentile_dispatcher(a, q, axis=None, out=None, overwrite_input=None,
  3063. interpolation=None, keepdims=None):
  3064. return (a, q, out)
  3065. @array_function_dispatch(_percentile_dispatcher)
  3066. def percentile(a, q, axis=None, out=None,
  3067. overwrite_input=False, interpolation='linear', keepdims=False):
  3068. """
  3069. Compute the q-th percentile of the data along the specified axis.
  3070. Returns the q-th percentile(s) of the array elements.
  3071. Parameters
  3072. ----------
  3073. a : array_like
  3074. Input array or object that can be converted to an array.
  3075. q : array_like of float
  3076. Percentile or sequence of percentiles to compute, which must be between
  3077. 0 and 100 inclusive.
  3078. axis : {int, tuple of int, None}, optional
  3079. Axis or axes along which the percentiles are computed. The
  3080. default is to compute the percentile(s) along a flattened
  3081. version of the array.
  3082. .. versionchanged:: 1.9.0
  3083. A tuple of axes is supported
  3084. out : ndarray, optional
  3085. Alternative output array in which to place the result. It must
  3086. have the same shape and buffer length as the expected output,
  3087. but the type (of the output) will be cast if necessary.
  3088. overwrite_input : bool, optional
  3089. If True, then allow the input array `a` to be modified by intermediate
  3090. calculations, to save memory. In this case, the contents of the input
  3091. `a` after this function completes is undefined.
  3092. interpolation : {'linear', 'lower', 'higher', 'midpoint', 'nearest'}
  3093. This optional parameter specifies the interpolation method to
  3094. use when the desired percentile lies between two data points
  3095. ``i < j``:
  3096. * 'linear': ``i + (j - i) * fraction``, where ``fraction``
  3097. is the fractional part of the index surrounded by ``i``
  3098. and ``j``.
  3099. * 'lower': ``i``.
  3100. * 'higher': ``j``.
  3101. * 'nearest': ``i`` or ``j``, whichever is nearest.
  3102. * 'midpoint': ``(i + j) / 2``.
  3103. .. versionadded:: 1.9.0
  3104. keepdims : bool, optional
  3105. If this is set to True, the axes which are reduced are left in
  3106. the result as dimensions with size one. With this option, the
  3107. result will broadcast correctly against the original array `a`.
  3108. .. versionadded:: 1.9.0
  3109. Returns
  3110. -------
  3111. percentile : scalar or ndarray
  3112. If `q` is a single percentile and `axis=None`, then the result
  3113. is a scalar. If multiple percentiles are given, first axis of
  3114. the result corresponds to the percentiles. The other axes are
  3115. the axes that remain after the reduction of `a`. If the input
  3116. contains integers or floats smaller than ``float64``, the output
  3117. data-type is ``float64``. Otherwise, the output data-type is the
  3118. same as that of the input. If `out` is specified, that array is
  3119. returned instead.
  3120. See Also
  3121. --------
  3122. mean
  3123. median : equivalent to ``percentile(..., 50)``
  3124. nanpercentile
  3125. quantile : equivalent to percentile, except with q in the range [0, 1].
  3126. Notes
  3127. -----
  3128. Given a vector ``V`` of length ``N``, the q-th percentile of
  3129. ``V`` is the value ``q/100`` of the way from the minimum to the
  3130. maximum in a sorted copy of ``V``. The values and distances of
  3131. the two nearest neighbors as well as the `interpolation` parameter
  3132. will determine the percentile if the normalized ranking does not
  3133. match the location of ``q`` exactly. This function is the same as
  3134. the median if ``q=50``, the same as the minimum if ``q=0`` and the
  3135. same as the maximum if ``q=100``.
  3136. Examples
  3137. --------
  3138. >>> a = np.array([[10, 7, 4], [3, 2, 1]])
  3139. >>> a
  3140. array([[10, 7, 4],
  3141. [ 3, 2, 1]])
  3142. >>> np.percentile(a, 50)
  3143. 3.5
  3144. >>> np.percentile(a, 50, axis=0)
  3145. array([6.5, 4.5, 2.5])
  3146. >>> np.percentile(a, 50, axis=1)
  3147. array([7., 2.])
  3148. >>> np.percentile(a, 50, axis=1, keepdims=True)
  3149. array([[7.],
  3150. [2.]])
  3151. >>> m = np.percentile(a, 50, axis=0)
  3152. >>> out = np.zeros_like(m)
  3153. >>> np.percentile(a, 50, axis=0, out=out)
  3154. array([6.5, 4.5, 2.5])
  3155. >>> m
  3156. array([6.5, 4.5, 2.5])
  3157. >>> b = a.copy()
  3158. >>> np.percentile(b, 50, axis=1, overwrite_input=True)
  3159. array([7., 2.])
  3160. >>> assert not np.all(a == b)
  3161. The different types of interpolation can be visualized graphically:
  3162. .. plot::
  3163. import matplotlib.pyplot as plt
  3164. a = np.arange(4)
  3165. p = np.linspace(0, 100, 6001)
  3166. ax = plt.gca()
  3167. lines = [
  3168. ('linear', None),
  3169. ('higher', '--'),
  3170. ('lower', '--'),
  3171. ('nearest', '-.'),
  3172. ('midpoint', '-.'),
  3173. ]
  3174. for interpolation, style in lines:
  3175. ax.plot(
  3176. p, np.percentile(a, p, interpolation=interpolation),
  3177. label=interpolation, linestyle=style)
  3178. ax.set(
  3179. title='Interpolation methods for list: ' + str(a),
  3180. xlabel='Percentile',
  3181. ylabel='List item returned',
  3182. yticks=a)
  3183. ax.legend()
  3184. plt.show()
  3185. """
  3186. q = np.true_divide(q, 100)
  3187. q = asanyarray(q) # undo any decay that the ufunc performed (see gh-13105)
  3188. if not _quantile_is_valid(q):
  3189. raise ValueError("Percentiles must be in the range [0, 100]")
  3190. return _quantile_unchecked(
  3191. a, q, axis, out, overwrite_input, interpolation, keepdims)
  3192. def _quantile_dispatcher(a, q, axis=None, out=None, overwrite_input=None,
  3193. interpolation=None, keepdims=None):
  3194. return (a, q, out)
  3195. @array_function_dispatch(_quantile_dispatcher)
  3196. def quantile(a, q, axis=None, out=None,
  3197. overwrite_input=False, interpolation='linear', keepdims=False):
  3198. """
  3199. Compute the q-th quantile of the data along the specified axis.
  3200. .. versionadded:: 1.15.0
  3201. Parameters
  3202. ----------
  3203. a : array_like
  3204. Input array or object that can be converted to an array.
  3205. q : array_like of float
  3206. Quantile or sequence of quantiles to compute, which must be between
  3207. 0 and 1 inclusive.
  3208. axis : {int, tuple of int, None}, optional
  3209. Axis or axes along which the quantiles are computed. The
  3210. default is to compute the quantile(s) along a flattened
  3211. version of the array.
  3212. out : ndarray, optional
  3213. Alternative output array in which to place the result. It must
  3214. have the same shape and buffer length as the expected output,
  3215. but the type (of the output) will be cast if necessary.
  3216. overwrite_input : bool, optional
  3217. If True, then allow the input array `a` to be modified by intermediate
  3218. calculations, to save memory. In this case, the contents of the input
  3219. `a` after this function completes is undefined.
  3220. interpolation : {'linear', 'lower', 'higher', 'midpoint', 'nearest'}
  3221. This optional parameter specifies the interpolation method to
  3222. use when the desired quantile lies between two data points
  3223. ``i < j``:
  3224. * linear: ``i + (j - i) * fraction``, where ``fraction``
  3225. is the fractional part of the index surrounded by ``i``
  3226. and ``j``.
  3227. * lower: ``i``.
  3228. * higher: ``j``.
  3229. * nearest: ``i`` or ``j``, whichever is nearest.
  3230. * midpoint: ``(i + j) / 2``.
  3231. keepdims : bool, optional
  3232. If this is set to True, the axes which are reduced are left in
  3233. the result as dimensions with size one. With this option, the
  3234. result will broadcast correctly against the original array `a`.
  3235. Returns
  3236. -------
  3237. quantile : scalar or ndarray
  3238. If `q` is a single quantile and `axis=None`, then the result
  3239. is a scalar. If multiple quantiles are given, first axis of
  3240. the result corresponds to the quantiles. The other axes are
  3241. the axes that remain after the reduction of `a`. If the input
  3242. contains integers or floats smaller than ``float64``, the output
  3243. data-type is ``float64``. Otherwise, the output data-type is the
  3244. same as that of the input. If `out` is specified, that array is
  3245. returned instead.
  3246. See Also
  3247. --------
  3248. mean
  3249. percentile : equivalent to quantile, but with q in the range [0, 100].
  3250. median : equivalent to ``quantile(..., 0.5)``
  3251. nanquantile
  3252. Notes
  3253. -----
  3254. Given a vector ``V`` of length ``N``, the q-th quantile of
  3255. ``V`` is the value ``q`` of the way from the minimum to the
  3256. maximum in a sorted copy of ``V``. The values and distances of
  3257. the two nearest neighbors as well as the `interpolation` parameter
  3258. will determine the quantile if the normalized ranking does not
  3259. match the location of ``q`` exactly. This function is the same as
  3260. the median if ``q=0.5``, the same as the minimum if ``q=0.0`` and the
  3261. same as the maximum if ``q=1.0``.
  3262. Examples
  3263. --------
  3264. >>> a = np.array([[10, 7, 4], [3, 2, 1]])
  3265. >>> a
  3266. array([[10, 7, 4],
  3267. [ 3, 2, 1]])
  3268. >>> np.quantile(a, 0.5)
  3269. 3.5
  3270. >>> np.quantile(a, 0.5, axis=0)
  3271. array([6.5, 4.5, 2.5])
  3272. >>> np.quantile(a, 0.5, axis=1)
  3273. array([7., 2.])
  3274. >>> np.quantile(a, 0.5, axis=1, keepdims=True)
  3275. array([[7.],
  3276. [2.]])
  3277. >>> m = np.quantile(a, 0.5, axis=0)
  3278. >>> out = np.zeros_like(m)
  3279. >>> np.quantile(a, 0.5, axis=0, out=out)
  3280. array([6.5, 4.5, 2.5])
  3281. >>> m
  3282. array([6.5, 4.5, 2.5])
  3283. >>> b = a.copy()
  3284. >>> np.quantile(b, 0.5, axis=1, overwrite_input=True)
  3285. array([7., 2.])
  3286. >>> assert not np.all(a == b)
  3287. """
  3288. q = np.asanyarray(q)
  3289. if not _quantile_is_valid(q):
  3290. raise ValueError("Quantiles must be in the range [0, 1]")
  3291. return _quantile_unchecked(
  3292. a, q, axis, out, overwrite_input, interpolation, keepdims)
  3293. def _quantile_unchecked(a, q, axis=None, out=None, overwrite_input=False,
  3294. interpolation='linear', keepdims=False):
  3295. """Assumes that q is in [0, 1], and is an ndarray"""
  3296. r, k = _ureduce(a, func=_quantile_ureduce_func, q=q, axis=axis, out=out,
  3297. overwrite_input=overwrite_input,
  3298. interpolation=interpolation)
  3299. if keepdims:
  3300. return r.reshape(q.shape + k)
  3301. else:
  3302. return r
  3303. def _quantile_is_valid(q):
  3304. # avoid expensive reductions, relevant for arrays with < O(1000) elements
  3305. if q.ndim == 1 and q.size < 10:
  3306. for i in range(q.size):
  3307. if not (0.0 <= q[i] <= 1.0):
  3308. return False
  3309. else:
  3310. if not (np.all(0 <= q) and np.all(q <= 1)):
  3311. return False
  3312. return True
  3313. def _lerp(a, b, t, out=None):
  3314. """ Linearly interpolate from a to b by a factor of t """
  3315. diff_b_a = subtract(b, a)
  3316. # asanyarray is a stop-gap until gh-13105
  3317. lerp_interpolation = asanyarray(add(a, diff_b_a*t, out=out))
  3318. subtract(b, diff_b_a * (1 - t), out=lerp_interpolation, where=t>=0.5)
  3319. if lerp_interpolation.ndim == 0 and out is None:
  3320. lerp_interpolation = lerp_interpolation[()] # unpack 0d arrays
  3321. return lerp_interpolation
  3322. def _quantile_ureduce_func(a, q, axis=None, out=None, overwrite_input=False,
  3323. interpolation='linear', keepdims=False):
  3324. a = asarray(a)
  3325. # ufuncs cause 0d array results to decay to scalars (see gh-13105), which
  3326. # makes them problematic for __setitem__ and attribute access. As a
  3327. # workaround, we call this on the result of every ufunc on a possibly-0d
  3328. # array.
  3329. not_scalar = np.asanyarray
  3330. # prepare a for partitioning
  3331. if overwrite_input:
  3332. if axis is None:
  3333. ap = a.ravel()
  3334. else:
  3335. ap = a
  3336. else:
  3337. if axis is None:
  3338. ap = a.flatten()
  3339. else:
  3340. ap = a.copy()
  3341. if axis is None:
  3342. axis = 0
  3343. if q.ndim > 2:
  3344. # The code below works fine for nd, but it might not have useful
  3345. # semantics. For now, keep the supported dimensions the same as it was
  3346. # before.
  3347. raise ValueError("q must be a scalar or 1d")
  3348. Nx = ap.shape[axis]
  3349. indices = not_scalar(q * (Nx - 1))
  3350. # round fractional indices according to interpolation method
  3351. if interpolation == 'lower':
  3352. indices = floor(indices).astype(intp)
  3353. elif interpolation == 'higher':
  3354. indices = ceil(indices).astype(intp)
  3355. elif interpolation == 'midpoint':
  3356. indices = 0.5 * (floor(indices) + ceil(indices))
  3357. elif interpolation == 'nearest':
  3358. indices = around(indices).astype(intp)
  3359. elif interpolation == 'linear':
  3360. pass # keep index as fraction and interpolate
  3361. else:
  3362. raise ValueError(
  3363. "interpolation can only be 'linear', 'lower' 'higher', "
  3364. "'midpoint', or 'nearest'")
  3365. # The dimensions of `q` are prepended to the output shape, so we need the
  3366. # axis being sampled from `ap` to be first.
  3367. ap = np.moveaxis(ap, axis, 0)
  3368. del axis
  3369. if np.issubdtype(indices.dtype, np.integer):
  3370. # take the points along axis
  3371. if np.issubdtype(a.dtype, np.inexact):
  3372. # may contain nan, which would sort to the end
  3373. ap.partition(concatenate((indices.ravel(), [-1])), axis=0)
  3374. n = np.isnan(ap[-1])
  3375. else:
  3376. # cannot contain nan
  3377. ap.partition(indices.ravel(), axis=0)
  3378. n = np.array(False, dtype=bool)
  3379. r = take(ap, indices, axis=0, out=out)
  3380. else:
  3381. # weight the points above and below the indices
  3382. indices_below = not_scalar(floor(indices)).astype(intp)
  3383. indices_above = not_scalar(indices_below + 1)
  3384. indices_above[indices_above > Nx - 1] = Nx - 1
  3385. if np.issubdtype(a.dtype, np.inexact):
  3386. # may contain nan, which would sort to the end
  3387. ap.partition(concatenate((
  3388. indices_below.ravel(), indices_above.ravel(), [-1]
  3389. )), axis=0)
  3390. n = np.isnan(ap[-1])
  3391. else:
  3392. # cannot contain nan
  3393. ap.partition(concatenate((
  3394. indices_below.ravel(), indices_above.ravel()
  3395. )), axis=0)
  3396. n = np.array(False, dtype=bool)
  3397. weights_shape = indices.shape + (1,) * (ap.ndim - 1)
  3398. weights_above = not_scalar(indices - indices_below).reshape(weights_shape)
  3399. x_below = take(ap, indices_below, axis=0)
  3400. x_above = take(ap, indices_above, axis=0)
  3401. r = _lerp(x_below, x_above, weights_above, out=out)
  3402. # if any slice contained a nan, then all results on that slice are also nan
  3403. if np.any(n):
  3404. if r.ndim == 0 and out is None:
  3405. # can't write to a scalar
  3406. r = a.dtype.type(np.nan)
  3407. else:
  3408. r[..., n] = a.dtype.type(np.nan)
  3409. return r
  3410. def _trapz_dispatcher(y, x=None, dx=None, axis=None):
  3411. return (y, x)
  3412. @array_function_dispatch(_trapz_dispatcher)
  3413. def trapz(y, x=None, dx=1.0, axis=-1):
  3414. r"""
  3415. Integrate along the given axis using the composite trapezoidal rule.
  3416. If `x` is provided, the integration happens in sequence along its
  3417. elements - they are not sorted.
  3418. Integrate `y` (`x`) along each 1d slice on the given axis, compute
  3419. :math:`\int y(x) dx`.
  3420. When `x` is specified, this integrates along the parametric curve,
  3421. computing :math:`\int_t y(t) dt =
  3422. \int_t y(t) \left.\frac{dx}{dt}\right|_{x=x(t)} dt`.
  3423. Parameters
  3424. ----------
  3425. y : array_like
  3426. Input array to integrate.
  3427. x : array_like, optional
  3428. The sample points corresponding to the `y` values. If `x` is None,
  3429. the sample points are assumed to be evenly spaced `dx` apart. The
  3430. default is None.
  3431. dx : scalar, optional
  3432. The spacing between sample points when `x` is None. The default is 1.
  3433. axis : int, optional
  3434. The axis along which to integrate.
  3435. Returns
  3436. -------
  3437. trapz : float or ndarray
  3438. Definite integral of 'y' = n-dimensional array as approximated along
  3439. a single axis by the trapezoidal rule. If 'y' is a 1-dimensional array,
  3440. then the result is a float. If 'n' is greater than 1, then the result
  3441. is an 'n-1' dimensional array.
  3442. See Also
  3443. --------
  3444. sum, cumsum
  3445. Notes
  3446. -----
  3447. Image [2]_ illustrates trapezoidal rule -- y-axis locations of points
  3448. will be taken from `y` array, by default x-axis distances between
  3449. points will be 1.0, alternatively they can be provided with `x` array
  3450. or with `dx` scalar. Return value will be equal to combined area under
  3451. the red lines.
  3452. References
  3453. ----------
  3454. .. [1] Wikipedia page: https://en.wikipedia.org/wiki/Trapezoidal_rule
  3455. .. [2] Illustration image:
  3456. https://en.wikipedia.org/wiki/File:Composite_trapezoidal_rule_illustration.png
  3457. Examples
  3458. --------
  3459. >>> np.trapz([1,2,3])
  3460. 4.0
  3461. >>> np.trapz([1,2,3], x=[4,6,8])
  3462. 8.0
  3463. >>> np.trapz([1,2,3], dx=2)
  3464. 8.0
  3465. Using a decreasing `x` corresponds to integrating in reverse:
  3466. >>> np.trapz([1,2,3], x=[8,6,4])
  3467. -8.0
  3468. More generally `x` is used to integrate along a parametric curve.
  3469. This finds the area of a circle, noting we repeat the sample which closes
  3470. the curve:
  3471. >>> theta = np.linspace(0, 2 * np.pi, num=1000, endpoint=True)
  3472. >>> np.trapz(np.cos(theta), x=np.sin(theta))
  3473. 3.141571941375841
  3474. >>> a = np.arange(6).reshape(2, 3)
  3475. >>> a
  3476. array([[0, 1, 2],
  3477. [3, 4, 5]])
  3478. >>> np.trapz(a, axis=0)
  3479. array([1.5, 2.5, 3.5])
  3480. >>> np.trapz(a, axis=1)
  3481. array([2., 8.])
  3482. """
  3483. y = asanyarray(y)
  3484. if x is None:
  3485. d = dx
  3486. else:
  3487. x = asanyarray(x)
  3488. if x.ndim == 1:
  3489. d = diff(x)
  3490. # reshape to correct shape
  3491. shape = [1]*y.ndim
  3492. shape[axis] = d.shape[0]
  3493. d = d.reshape(shape)
  3494. else:
  3495. d = diff(x, axis=axis)
  3496. nd = y.ndim
  3497. slice1 = [slice(None)]*nd
  3498. slice2 = [slice(None)]*nd
  3499. slice1[axis] = slice(1, None)
  3500. slice2[axis] = slice(None, -1)
  3501. try:
  3502. ret = (d * (y[tuple(slice1)] + y[tuple(slice2)]) / 2.0).sum(axis)
  3503. except ValueError:
  3504. # Operations didn't work, cast to ndarray
  3505. d = np.asarray(d)
  3506. y = np.asarray(y)
  3507. ret = add.reduce(d * (y[tuple(slice1)]+y[tuple(slice2)])/2.0, axis)
  3508. return ret
  3509. def _meshgrid_dispatcher(*xi, copy=None, sparse=None, indexing=None):
  3510. return xi
  3511. # Based on scitools meshgrid
  3512. @array_function_dispatch(_meshgrid_dispatcher)
  3513. def meshgrid(*xi, copy=True, sparse=False, indexing='xy'):
  3514. """
  3515. Return coordinate matrices from coordinate vectors.
  3516. Make N-D coordinate arrays for vectorized evaluations of
  3517. N-D scalar/vector fields over N-D grids, given
  3518. one-dimensional coordinate arrays x1, x2,..., xn.
  3519. .. versionchanged:: 1.9
  3520. 1-D and 0-D cases are allowed.
  3521. Parameters
  3522. ----------
  3523. x1, x2,..., xn : array_like
  3524. 1-D arrays representing the coordinates of a grid.
  3525. indexing : {'xy', 'ij'}, optional
  3526. Cartesian ('xy', default) or matrix ('ij') indexing of output.
  3527. See Notes for more details.
  3528. .. versionadded:: 1.7.0
  3529. sparse : bool, optional
  3530. If True a sparse grid is returned in order to conserve memory.
  3531. Default is False.
  3532. .. versionadded:: 1.7.0
  3533. copy : bool, optional
  3534. If False, a view into the original arrays are returned in order to
  3535. conserve memory. Default is True. Please note that
  3536. ``sparse=False, copy=False`` will likely return non-contiguous
  3537. arrays. Furthermore, more than one element of a broadcast array
  3538. may refer to a single memory location. If you need to write to the
  3539. arrays, make copies first.
  3540. .. versionadded:: 1.7.0
  3541. Returns
  3542. -------
  3543. X1, X2,..., XN : ndarray
  3544. For vectors `x1`, `x2`,..., 'xn' with lengths ``Ni=len(xi)`` ,
  3545. return ``(N1, N2, N3,...Nn)`` shaped arrays if indexing='ij'
  3546. or ``(N2, N1, N3,...Nn)`` shaped arrays if indexing='xy'
  3547. with the elements of `xi` repeated to fill the matrix along
  3548. the first dimension for `x1`, the second for `x2` and so on.
  3549. Notes
  3550. -----
  3551. This function supports both indexing conventions through the indexing
  3552. keyword argument. Giving the string 'ij' returns a meshgrid with
  3553. matrix indexing, while 'xy' returns a meshgrid with Cartesian indexing.
  3554. In the 2-D case with inputs of length M and N, the outputs are of shape
  3555. (N, M) for 'xy' indexing and (M, N) for 'ij' indexing. In the 3-D case
  3556. with inputs of length M, N and P, outputs are of shape (N, M, P) for
  3557. 'xy' indexing and (M, N, P) for 'ij' indexing. The difference is
  3558. illustrated by the following code snippet::
  3559. xv, yv = np.meshgrid(x, y, sparse=False, indexing='ij')
  3560. for i in range(nx):
  3561. for j in range(ny):
  3562. # treat xv[i,j], yv[i,j]
  3563. xv, yv = np.meshgrid(x, y, sparse=False, indexing='xy')
  3564. for i in range(nx):
  3565. for j in range(ny):
  3566. # treat xv[j,i], yv[j,i]
  3567. In the 1-D and 0-D case, the indexing and sparse keywords have no effect.
  3568. See Also
  3569. --------
  3570. mgrid : Construct a multi-dimensional "meshgrid" using indexing notation.
  3571. ogrid : Construct an open multi-dimensional "meshgrid" using indexing
  3572. notation.
  3573. Examples
  3574. --------
  3575. >>> nx, ny = (3, 2)
  3576. >>> x = np.linspace(0, 1, nx)
  3577. >>> y = np.linspace(0, 1, ny)
  3578. >>> xv, yv = np.meshgrid(x, y)
  3579. >>> xv
  3580. array([[0. , 0.5, 1. ],
  3581. [0. , 0.5, 1. ]])
  3582. >>> yv
  3583. array([[0., 0., 0.],
  3584. [1., 1., 1.]])
  3585. >>> xv, yv = np.meshgrid(x, y, sparse=True) # make sparse output arrays
  3586. >>> xv
  3587. array([[0. , 0.5, 1. ]])
  3588. >>> yv
  3589. array([[0.],
  3590. [1.]])
  3591. `meshgrid` is very useful to evaluate functions on a grid.
  3592. >>> import matplotlib.pyplot as plt
  3593. >>> x = np.arange(-5, 5, 0.1)
  3594. >>> y = np.arange(-5, 5, 0.1)
  3595. >>> xx, yy = np.meshgrid(x, y, sparse=True)
  3596. >>> z = np.sin(xx**2 + yy**2) / (xx**2 + yy**2)
  3597. >>> h = plt.contourf(x, y, z)
  3598. >>> plt.axis('scaled')
  3599. >>> plt.show()
  3600. """
  3601. ndim = len(xi)
  3602. if indexing not in ['xy', 'ij']:
  3603. raise ValueError(
  3604. "Valid values for `indexing` are 'xy' and 'ij'.")
  3605. s0 = (1,) * ndim
  3606. output = [np.asanyarray(x).reshape(s0[:i] + (-1,) + s0[i + 1:])
  3607. for i, x in enumerate(xi)]
  3608. if indexing == 'xy' and ndim > 1:
  3609. # switch first and second axis
  3610. output[0].shape = (1, -1) + s0[2:]
  3611. output[1].shape = (-1, 1) + s0[2:]
  3612. if not sparse:
  3613. # Return the full N-D matrix (not only the 1-D vector)
  3614. output = np.broadcast_arrays(*output, subok=True)
  3615. if copy:
  3616. output = [x.copy() for x in output]
  3617. return output
  3618. def _delete_dispatcher(arr, obj, axis=None):
  3619. return (arr, obj)
  3620. @array_function_dispatch(_delete_dispatcher)
  3621. def delete(arr, obj, axis=None):
  3622. """
  3623. Return a new array with sub-arrays along an axis deleted. For a one
  3624. dimensional array, this returns those entries not returned by
  3625. `arr[obj]`.
  3626. Parameters
  3627. ----------
  3628. arr : array_like
  3629. Input array.
  3630. obj : slice, int or array of ints
  3631. Indicate indices of sub-arrays to remove along the specified axis.
  3632. .. versionchanged:: 1.19.0
  3633. Boolean indices are now treated as a mask of elements to remove,
  3634. rather than being cast to the integers 0 and 1.
  3635. axis : int, optional
  3636. The axis along which to delete the subarray defined by `obj`.
  3637. If `axis` is None, `obj` is applied to the flattened array.
  3638. Returns
  3639. -------
  3640. out : ndarray
  3641. A copy of `arr` with the elements specified by `obj` removed. Note
  3642. that `delete` does not occur in-place. If `axis` is None, `out` is
  3643. a flattened array.
  3644. See Also
  3645. --------
  3646. insert : Insert elements into an array.
  3647. append : Append elements at the end of an array.
  3648. Notes
  3649. -----
  3650. Often it is preferable to use a boolean mask. For example:
  3651. >>> arr = np.arange(12) + 1
  3652. >>> mask = np.ones(len(arr), dtype=bool)
  3653. >>> mask[[0,2,4]] = False
  3654. >>> result = arr[mask,...]
  3655. Is equivalent to `np.delete(arr, [0,2,4], axis=0)`, but allows further
  3656. use of `mask`.
  3657. Examples
  3658. --------
  3659. >>> arr = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
  3660. >>> arr
  3661. array([[ 1, 2, 3, 4],
  3662. [ 5, 6, 7, 8],
  3663. [ 9, 10, 11, 12]])
  3664. >>> np.delete(arr, 1, 0)
  3665. array([[ 1, 2, 3, 4],
  3666. [ 9, 10, 11, 12]])
  3667. >>> np.delete(arr, np.s_[::2], 1)
  3668. array([[ 2, 4],
  3669. [ 6, 8],
  3670. [10, 12]])
  3671. >>> np.delete(arr, [1,3,5], None)
  3672. array([ 1, 3, 5, 7, 8, 9, 10, 11, 12])
  3673. """
  3674. wrap = None
  3675. if type(arr) is not ndarray:
  3676. try:
  3677. wrap = arr.__array_wrap__
  3678. except AttributeError:
  3679. pass
  3680. arr = asarray(arr)
  3681. ndim = arr.ndim
  3682. arrorder = 'F' if arr.flags.fnc else 'C'
  3683. if axis is None:
  3684. if ndim != 1:
  3685. arr = arr.ravel()
  3686. # needed for np.matrix, which is still not 1d after being ravelled
  3687. ndim = arr.ndim
  3688. axis = ndim - 1
  3689. else:
  3690. axis = normalize_axis_index(axis, ndim)
  3691. slobj = [slice(None)]*ndim
  3692. N = arr.shape[axis]
  3693. newshape = list(arr.shape)
  3694. if isinstance(obj, slice):
  3695. start, stop, step = obj.indices(N)
  3696. xr = range(start, stop, step)
  3697. numtodel = len(xr)
  3698. if numtodel <= 0:
  3699. if wrap:
  3700. return wrap(arr.copy(order=arrorder))
  3701. else:
  3702. return arr.copy(order=arrorder)
  3703. # Invert if step is negative:
  3704. if step < 0:
  3705. step = -step
  3706. start = xr[-1]
  3707. stop = xr[0] + 1
  3708. newshape[axis] -= numtodel
  3709. new = empty(newshape, arr.dtype, arrorder)
  3710. # copy initial chunk
  3711. if start == 0:
  3712. pass
  3713. else:
  3714. slobj[axis] = slice(None, start)
  3715. new[tuple(slobj)] = arr[tuple(slobj)]
  3716. # copy end chunk
  3717. if stop == N:
  3718. pass
  3719. else:
  3720. slobj[axis] = slice(stop-numtodel, None)
  3721. slobj2 = [slice(None)]*ndim
  3722. slobj2[axis] = slice(stop, None)
  3723. new[tuple(slobj)] = arr[tuple(slobj2)]
  3724. # copy middle pieces
  3725. if step == 1:
  3726. pass
  3727. else: # use array indexing.
  3728. keep = ones(stop-start, dtype=bool)
  3729. keep[:stop-start:step] = False
  3730. slobj[axis] = slice(start, stop-numtodel)
  3731. slobj2 = [slice(None)]*ndim
  3732. slobj2[axis] = slice(start, stop)
  3733. arr = arr[tuple(slobj2)]
  3734. slobj2[axis] = keep
  3735. new[tuple(slobj)] = arr[tuple(slobj2)]
  3736. if wrap:
  3737. return wrap(new)
  3738. else:
  3739. return new
  3740. if isinstance(obj, (int, integer)) and not isinstance(obj, bool):
  3741. # optimization for a single value
  3742. if (obj < -N or obj >= N):
  3743. raise IndexError(
  3744. "index %i is out of bounds for axis %i with "
  3745. "size %i" % (obj, axis, N))
  3746. if (obj < 0):
  3747. obj += N
  3748. newshape[axis] -= 1
  3749. new = empty(newshape, arr.dtype, arrorder)
  3750. slobj[axis] = slice(None, obj)
  3751. new[tuple(slobj)] = arr[tuple(slobj)]
  3752. slobj[axis] = slice(obj, None)
  3753. slobj2 = [slice(None)]*ndim
  3754. slobj2[axis] = slice(obj+1, None)
  3755. new[tuple(slobj)] = arr[tuple(slobj2)]
  3756. else:
  3757. _obj = obj
  3758. obj = np.asarray(obj)
  3759. if obj.size == 0 and not isinstance(_obj, np.ndarray):
  3760. obj = obj.astype(intp)
  3761. if obj.dtype == bool:
  3762. if obj.shape != (N,):
  3763. raise ValueError('boolean array argument obj to delete '
  3764. 'must be one dimensional and match the axis '
  3765. 'length of {}'.format(N))
  3766. # optimization, the other branch is slower
  3767. keep = ~obj
  3768. else:
  3769. keep = ones(N, dtype=bool)
  3770. keep[obj,] = False
  3771. slobj[axis] = keep
  3772. new = arr[tuple(slobj)]
  3773. if wrap:
  3774. return wrap(new)
  3775. else:
  3776. return new
  3777. def _insert_dispatcher(arr, obj, values, axis=None):
  3778. return (arr, obj, values)
  3779. @array_function_dispatch(_insert_dispatcher)
  3780. def insert(arr, obj, values, axis=None):
  3781. """
  3782. Insert values along the given axis before the given indices.
  3783. Parameters
  3784. ----------
  3785. arr : array_like
  3786. Input array.
  3787. obj : int, slice or sequence of ints
  3788. Object that defines the index or indices before which `values` is
  3789. inserted.
  3790. .. versionadded:: 1.8.0
  3791. Support for multiple insertions when `obj` is a single scalar or a
  3792. sequence with one element (similar to calling insert multiple
  3793. times).
  3794. values : array_like
  3795. Values to insert into `arr`. If the type of `values` is different
  3796. from that of `arr`, `values` is converted to the type of `arr`.
  3797. `values` should be shaped so that ``arr[...,obj,...] = values``
  3798. is legal.
  3799. axis : int, optional
  3800. Axis along which to insert `values`. If `axis` is None then `arr`
  3801. is flattened first.
  3802. Returns
  3803. -------
  3804. out : ndarray
  3805. A copy of `arr` with `values` inserted. Note that `insert`
  3806. does not occur in-place: a new array is returned. If
  3807. `axis` is None, `out` is a flattened array.
  3808. See Also
  3809. --------
  3810. append : Append elements at the end of an array.
  3811. concatenate : Join a sequence of arrays along an existing axis.
  3812. delete : Delete elements from an array.
  3813. Notes
  3814. -----
  3815. Note that for higher dimensional inserts `obj=0` behaves very different
  3816. from `obj=[0]` just like `arr[:,0,:] = values` is different from
  3817. `arr[:,[0],:] = values`.
  3818. Examples
  3819. --------
  3820. >>> a = np.array([[1, 1], [2, 2], [3, 3]])
  3821. >>> a
  3822. array([[1, 1],
  3823. [2, 2],
  3824. [3, 3]])
  3825. >>> np.insert(a, 1, 5)
  3826. array([1, 5, 1, ..., 2, 3, 3])
  3827. >>> np.insert(a, 1, 5, axis=1)
  3828. array([[1, 5, 1],
  3829. [2, 5, 2],
  3830. [3, 5, 3]])
  3831. Difference between sequence and scalars:
  3832. >>> np.insert(a, [1], [[1],[2],[3]], axis=1)
  3833. array([[1, 1, 1],
  3834. [2, 2, 2],
  3835. [3, 3, 3]])
  3836. >>> np.array_equal(np.insert(a, 1, [1, 2, 3], axis=1),
  3837. ... np.insert(a, [1], [[1],[2],[3]], axis=1))
  3838. True
  3839. >>> b = a.flatten()
  3840. >>> b
  3841. array([1, 1, 2, 2, 3, 3])
  3842. >>> np.insert(b, [2, 2], [5, 6])
  3843. array([1, 1, 5, ..., 2, 3, 3])
  3844. >>> np.insert(b, slice(2, 4), [5, 6])
  3845. array([1, 1, 5, ..., 2, 3, 3])
  3846. >>> np.insert(b, [2, 2], [7.13, False]) # type casting
  3847. array([1, 1, 7, ..., 2, 3, 3])
  3848. >>> x = np.arange(8).reshape(2, 4)
  3849. >>> idx = (1, 3)
  3850. >>> np.insert(x, idx, 999, axis=1)
  3851. array([[ 0, 999, 1, 2, 999, 3],
  3852. [ 4, 999, 5, 6, 999, 7]])
  3853. """
  3854. wrap = None
  3855. if type(arr) is not ndarray:
  3856. try:
  3857. wrap = arr.__array_wrap__
  3858. except AttributeError:
  3859. pass
  3860. arr = asarray(arr)
  3861. ndim = arr.ndim
  3862. arrorder = 'F' if arr.flags.fnc else 'C'
  3863. if axis is None:
  3864. if ndim != 1:
  3865. arr = arr.ravel()
  3866. # needed for np.matrix, which is still not 1d after being ravelled
  3867. ndim = arr.ndim
  3868. axis = ndim - 1
  3869. else:
  3870. axis = normalize_axis_index(axis, ndim)
  3871. slobj = [slice(None)]*ndim
  3872. N = arr.shape[axis]
  3873. newshape = list(arr.shape)
  3874. if isinstance(obj, slice):
  3875. # turn it into a range object
  3876. indices = arange(*obj.indices(N), dtype=intp)
  3877. else:
  3878. # need to copy obj, because indices will be changed in-place
  3879. indices = np.array(obj)
  3880. if indices.dtype == bool:
  3881. # See also delete
  3882. # 2012-10-11, NumPy 1.8
  3883. warnings.warn(
  3884. "in the future insert will treat boolean arrays and "
  3885. "array-likes as a boolean index instead of casting it to "
  3886. "integer", FutureWarning, stacklevel=3)
  3887. indices = indices.astype(intp)
  3888. # Code after warning period:
  3889. #if obj.ndim != 1:
  3890. # raise ValueError('boolean array argument obj to insert '
  3891. # 'must be one dimensional')
  3892. #indices = np.flatnonzero(obj)
  3893. elif indices.ndim > 1:
  3894. raise ValueError(
  3895. "index array argument obj to insert must be one dimensional "
  3896. "or scalar")
  3897. if indices.size == 1:
  3898. index = indices.item()
  3899. if index < -N or index > N:
  3900. raise IndexError(
  3901. "index %i is out of bounds for axis %i with "
  3902. "size %i" % (obj, axis, N))
  3903. if (index < 0):
  3904. index += N
  3905. # There are some object array corner cases here, but we cannot avoid
  3906. # that:
  3907. values = array(values, copy=False, ndmin=arr.ndim, dtype=arr.dtype)
  3908. if indices.ndim == 0:
  3909. # broadcasting is very different here, since a[:,0,:] = ... behaves
  3910. # very different from a[:,[0],:] = ...! This changes values so that
  3911. # it works likes the second case. (here a[:,0:1,:])
  3912. values = np.moveaxis(values, 0, axis)
  3913. numnew = values.shape[axis]
  3914. newshape[axis] += numnew
  3915. new = empty(newshape, arr.dtype, arrorder)
  3916. slobj[axis] = slice(None, index)
  3917. new[tuple(slobj)] = arr[tuple(slobj)]
  3918. slobj[axis] = slice(index, index+numnew)
  3919. new[tuple(slobj)] = values
  3920. slobj[axis] = slice(index+numnew, None)
  3921. slobj2 = [slice(None)] * ndim
  3922. slobj2[axis] = slice(index, None)
  3923. new[tuple(slobj)] = arr[tuple(slobj2)]
  3924. if wrap:
  3925. return wrap(new)
  3926. return new
  3927. elif indices.size == 0 and not isinstance(obj, np.ndarray):
  3928. # Can safely cast the empty list to intp
  3929. indices = indices.astype(intp)
  3930. indices[indices < 0] += N
  3931. numnew = len(indices)
  3932. order = indices.argsort(kind='mergesort') # stable sort
  3933. indices[order] += np.arange(numnew)
  3934. newshape[axis] += numnew
  3935. old_mask = ones(newshape[axis], dtype=bool)
  3936. old_mask[indices] = False
  3937. new = empty(newshape, arr.dtype, arrorder)
  3938. slobj2 = [slice(None)]*ndim
  3939. slobj[axis] = indices
  3940. slobj2[axis] = old_mask
  3941. new[tuple(slobj)] = values
  3942. new[tuple(slobj2)] = arr
  3943. if wrap:
  3944. return wrap(new)
  3945. return new
  3946. def _append_dispatcher(arr, values, axis=None):
  3947. return (arr, values)
  3948. @array_function_dispatch(_append_dispatcher)
  3949. def append(arr, values, axis=None):
  3950. """
  3951. Append values to the end of an array.
  3952. Parameters
  3953. ----------
  3954. arr : array_like
  3955. Values are appended to a copy of this array.
  3956. values : array_like
  3957. These values are appended to a copy of `arr`. It must be of the
  3958. correct shape (the same shape as `arr`, excluding `axis`). If
  3959. `axis` is not specified, `values` can be any shape and will be
  3960. flattened before use.
  3961. axis : int, optional
  3962. The axis along which `values` are appended. If `axis` is not
  3963. given, both `arr` and `values` are flattened before use.
  3964. Returns
  3965. -------
  3966. append : ndarray
  3967. A copy of `arr` with `values` appended to `axis`. Note that
  3968. `append` does not occur in-place: a new array is allocated and
  3969. filled. If `axis` is None, `out` is a flattened array.
  3970. See Also
  3971. --------
  3972. insert : Insert elements into an array.
  3973. delete : Delete elements from an array.
  3974. Examples
  3975. --------
  3976. >>> np.append([1, 2, 3], [[4, 5, 6], [7, 8, 9]])
  3977. array([1, 2, 3, ..., 7, 8, 9])
  3978. When `axis` is specified, `values` must have the correct shape.
  3979. >>> np.append([[1, 2, 3], [4, 5, 6]], [[7, 8, 9]], axis=0)
  3980. array([[1, 2, 3],
  3981. [4, 5, 6],
  3982. [7, 8, 9]])
  3983. >>> np.append([[1, 2, 3], [4, 5, 6]], [7, 8, 9], axis=0)
  3984. Traceback (most recent call last):
  3985. ...
  3986. ValueError: all the input arrays must have same number of dimensions, but
  3987. the array at index 0 has 2 dimension(s) and the array at index 1 has 1
  3988. dimension(s)
  3989. """
  3990. arr = asanyarray(arr)
  3991. if axis is None:
  3992. if arr.ndim != 1:
  3993. arr = arr.ravel()
  3994. values = ravel(values)
  3995. axis = arr.ndim-1
  3996. return concatenate((arr, values), axis=axis)
  3997. def _digitize_dispatcher(x, bins, right=None):
  3998. return (x, bins)
  3999. @array_function_dispatch(_digitize_dispatcher)
  4000. def digitize(x, bins, right=False):
  4001. """
  4002. Return the indices of the bins to which each value in input array belongs.
  4003. ========= ============= ============================
  4004. `right` order of bins returned index `i` satisfies
  4005. ========= ============= ============================
  4006. ``False`` increasing ``bins[i-1] <= x < bins[i]``
  4007. ``True`` increasing ``bins[i-1] < x <= bins[i]``
  4008. ``False`` decreasing ``bins[i-1] > x >= bins[i]``
  4009. ``True`` decreasing ``bins[i-1] >= x > bins[i]``
  4010. ========= ============= ============================
  4011. If values in `x` are beyond the bounds of `bins`, 0 or ``len(bins)`` is
  4012. returned as appropriate.
  4013. Parameters
  4014. ----------
  4015. x : array_like
  4016. Input array to be binned. Prior to NumPy 1.10.0, this array had to
  4017. be 1-dimensional, but can now have any shape.
  4018. bins : array_like
  4019. Array of bins. It has to be 1-dimensional and monotonic.
  4020. right : bool, optional
  4021. Indicating whether the intervals include the right or the left bin
  4022. edge. Default behavior is (right==False) indicating that the interval
  4023. does not include the right edge. The left bin end is open in this
  4024. case, i.e., bins[i-1] <= x < bins[i] is the default behavior for
  4025. monotonically increasing bins.
  4026. Returns
  4027. -------
  4028. indices : ndarray of ints
  4029. Output array of indices, of same shape as `x`.
  4030. Raises
  4031. ------
  4032. ValueError
  4033. If `bins` is not monotonic.
  4034. TypeError
  4035. If the type of the input is complex.
  4036. See Also
  4037. --------
  4038. bincount, histogram, unique, searchsorted
  4039. Notes
  4040. -----
  4041. If values in `x` are such that they fall outside the bin range,
  4042. attempting to index `bins` with the indices that `digitize` returns
  4043. will result in an IndexError.
  4044. .. versionadded:: 1.10.0
  4045. `np.digitize` is implemented in terms of `np.searchsorted`. This means
  4046. that a binary search is used to bin the values, which scales much better
  4047. for larger number of bins than the previous linear search. It also removes
  4048. the requirement for the input array to be 1-dimensional.
  4049. For monotonically _increasing_ `bins`, the following are equivalent::
  4050. np.digitize(x, bins, right=True)
  4051. np.searchsorted(bins, x, side='left')
  4052. Note that as the order of the arguments are reversed, the side must be too.
  4053. The `searchsorted` call is marginally faster, as it does not do any
  4054. monotonicity checks. Perhaps more importantly, it supports all dtypes.
  4055. Examples
  4056. --------
  4057. >>> x = np.array([0.2, 6.4, 3.0, 1.6])
  4058. >>> bins = np.array([0.0, 1.0, 2.5, 4.0, 10.0])
  4059. >>> inds = np.digitize(x, bins)
  4060. >>> inds
  4061. array([1, 4, 3, 2])
  4062. >>> for n in range(x.size):
  4063. ... print(bins[inds[n]-1], "<=", x[n], "<", bins[inds[n]])
  4064. ...
  4065. 0.0 <= 0.2 < 1.0
  4066. 4.0 <= 6.4 < 10.0
  4067. 2.5 <= 3.0 < 4.0
  4068. 1.0 <= 1.6 < 2.5
  4069. >>> x = np.array([1.2, 10.0, 12.4, 15.5, 20.])
  4070. >>> bins = np.array([0, 5, 10, 15, 20])
  4071. >>> np.digitize(x,bins,right=True)
  4072. array([1, 2, 3, 4, 4])
  4073. >>> np.digitize(x,bins,right=False)
  4074. array([1, 3, 3, 4, 5])
  4075. """
  4076. x = _nx.asarray(x)
  4077. bins = _nx.asarray(bins)
  4078. # here for compatibility, searchsorted below is happy to take this
  4079. if np.issubdtype(x.dtype, _nx.complexfloating):
  4080. raise TypeError("x may not be complex")
  4081. mono = _monotonicity(bins)
  4082. if mono == 0:
  4083. raise ValueError("bins must be monotonically increasing or decreasing")
  4084. # this is backwards because the arguments below are swapped
  4085. side = 'left' if right else 'right'
  4086. if mono == -1:
  4087. # reverse the bins, and invert the results
  4088. return len(bins) - _nx.searchsorted(bins[::-1], x, side=side)
  4089. else:
  4090. return _nx.searchsorted(bins, x, side=side)