_axes.py 346 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871
  1. import functools
  2. import itertools
  3. import logging
  4. import math
  5. from numbers import Integral, Number, Real
  6. import re
  7. import numpy as np
  8. import matplotlib as mpl
  9. import matplotlib.category # Register category unit converter as side effect.
  10. import matplotlib.cbook as cbook
  11. import matplotlib.collections as mcoll
  12. import matplotlib.colorizer as mcolorizer
  13. import matplotlib.colors as mcolors
  14. import matplotlib.contour as mcontour
  15. import matplotlib.dates # noqa: F401, Register date unit converter as side effect.
  16. import matplotlib.image as mimage
  17. import matplotlib.inset as minset
  18. import matplotlib.legend as mlegend
  19. import matplotlib.lines as mlines
  20. import matplotlib.markers as mmarkers
  21. import matplotlib.mlab as mlab
  22. import matplotlib.patches as mpatches
  23. import matplotlib.path as mpath
  24. import matplotlib.quiver as mquiver
  25. import matplotlib.stackplot as mstack
  26. import matplotlib.streamplot as mstream
  27. import matplotlib.table as mtable
  28. import matplotlib.text as mtext
  29. import matplotlib.ticker as mticker
  30. import matplotlib.transforms as mtransforms
  31. import matplotlib.tri as mtri
  32. import matplotlib.units as munits
  33. from matplotlib import _api, _docstring, _preprocess_data
  34. from matplotlib.axes._base import (
  35. _AxesBase, _TransformedBoundsLocator, _process_plot_format)
  36. from matplotlib.axes._secondary_axes import SecondaryAxis
  37. from matplotlib.container import BarContainer, ErrorbarContainer, StemContainer
  38. from matplotlib.transforms import _ScaledRotation
  39. _log = logging.getLogger(__name__)
  40. # The axes module contains all the wrappers to plotting functions.
  41. # All the other methods should go in the _AxesBase class.
  42. def _make_axes_method(func):
  43. """
  44. Patch the qualname for functions that are directly added to Axes.
  45. Some Axes functionality is defined in functions in other submodules.
  46. These are simply added as attributes to Axes. As a result, their
  47. ``__qualname__`` is e.g. only "table" and not "Axes.table". This
  48. function fixes that.
  49. Note that the function itself is patched, so that
  50. ``matplotlib.table.table.__qualname__` will also show "Axes.table".
  51. However, since these functions are not intended to be standalone,
  52. this is bearable.
  53. """
  54. func.__qualname__ = f"Axes.{func.__name__}"
  55. return func
  56. @_docstring.interpd
  57. class Axes(_AxesBase):
  58. """
  59. An Axes object encapsulates all the elements of an individual (sub-)plot in
  60. a figure.
  61. It contains most of the (sub-)plot elements: `~.axis.Axis`,
  62. `~.axis.Tick`, `~.lines.Line2D`, `~.text.Text`, `~.patches.Polygon`, etc.,
  63. and sets the coordinate system.
  64. Like all visible elements in a figure, Axes is an `.Artist` subclass.
  65. The `Axes` instance supports callbacks through a callbacks attribute which
  66. is a `~.cbook.CallbackRegistry` instance. The events you can connect to
  67. are 'xlim_changed' and 'ylim_changed' and the callback will be called with
  68. func(*ax*) where *ax* is the `Axes` instance.
  69. .. note::
  70. As a user, you do not instantiate Axes directly, but use Axes creation
  71. methods instead; e.g. from `.pyplot` or `.Figure`:
  72. `~.pyplot.subplots`, `~.pyplot.subplot_mosaic` or `.Figure.add_axes`.
  73. """
  74. ### Labelling, legend and texts
  75. def get_title(self, loc="center"):
  76. """
  77. Get an Axes title.
  78. Get one of the three available Axes titles. The available titles
  79. are positioned above the Axes in the center, flush with the left
  80. edge, and flush with the right edge.
  81. Parameters
  82. ----------
  83. loc : {'center', 'left', 'right'}, str, default: 'center'
  84. Which title to return.
  85. Returns
  86. -------
  87. str
  88. The title text string.
  89. """
  90. titles = {'left': self._left_title,
  91. 'center': self.title,
  92. 'right': self._right_title}
  93. title = _api.check_getitem(titles, loc=loc.lower())
  94. return title.get_text()
  95. def set_title(self, label, fontdict=None, loc=None, pad=None, *, y=None,
  96. **kwargs):
  97. """
  98. Set a title for the Axes.
  99. Set one of the three available Axes titles. The available titles
  100. are positioned above the Axes in the center, flush with the left
  101. edge, and flush with the right edge.
  102. Parameters
  103. ----------
  104. label : str
  105. Text to use for the title
  106. fontdict : dict
  107. .. admonition:: Discouraged
  108. The use of *fontdict* is discouraged. Parameters should be passed as
  109. individual keyword arguments or using dictionary-unpacking
  110. ``set_title(..., **fontdict)``.
  111. A dictionary controlling the appearance of the title text,
  112. the default *fontdict* is::
  113. {'fontsize': rcParams['axes.titlesize'],
  114. 'fontweight': rcParams['axes.titleweight'],
  115. 'color': rcParams['axes.titlecolor'],
  116. 'verticalalignment': 'baseline',
  117. 'horizontalalignment': loc}
  118. loc : {'center', 'left', 'right'}, default: :rc:`axes.titlelocation`
  119. Which title to set.
  120. y : float, default: :rc:`axes.titley`
  121. Vertical Axes location for the title (1.0 is the top). If
  122. None (the default) and :rc:`axes.titley` is also None, y is
  123. determined automatically to avoid decorators on the Axes.
  124. pad : float, default: :rc:`axes.titlepad`
  125. The offset of the title from the top of the Axes, in points.
  126. Returns
  127. -------
  128. `.Text`
  129. The matplotlib text instance representing the title
  130. Other Parameters
  131. ----------------
  132. **kwargs : `~matplotlib.text.Text` properties
  133. Other keyword arguments are text properties, see `.Text` for a list
  134. of valid text properties.
  135. """
  136. if loc is None:
  137. loc = mpl.rcParams['axes.titlelocation']
  138. if y is None:
  139. y = mpl.rcParams['axes.titley']
  140. if y is None:
  141. y = 1.0
  142. else:
  143. self._autotitlepos = False
  144. kwargs['y'] = y
  145. titles = {'left': self._left_title,
  146. 'center': self.title,
  147. 'right': self._right_title}
  148. title = _api.check_getitem(titles, loc=loc.lower())
  149. default = {
  150. 'fontsize': mpl.rcParams['axes.titlesize'],
  151. 'fontweight': mpl.rcParams['axes.titleweight'],
  152. 'verticalalignment': 'baseline',
  153. 'horizontalalignment': loc.lower()}
  154. titlecolor = mpl.rcParams['axes.titlecolor']
  155. if not cbook._str_lower_equal(titlecolor, 'auto'):
  156. default["color"] = titlecolor
  157. if pad is None:
  158. pad = mpl.rcParams['axes.titlepad']
  159. self._set_title_offset_trans(float(pad))
  160. title.set_text(label)
  161. title.update(default)
  162. if fontdict is not None:
  163. title.update(fontdict)
  164. title._internal_update(kwargs)
  165. return title
  166. def get_legend_handles_labels(self, legend_handler_map=None):
  167. """
  168. Return handles and labels for legend
  169. ``ax.legend()`` is equivalent to ::
  170. h, l = ax.get_legend_handles_labels()
  171. ax.legend(h, l)
  172. """
  173. # pass through to legend.
  174. handles, labels = mlegend._get_legend_handles_labels(
  175. [self], legend_handler_map)
  176. return handles, labels
  177. @_docstring.interpd
  178. def legend(self, *args, **kwargs):
  179. """
  180. Place a legend on the Axes.
  181. Call signatures::
  182. legend()
  183. legend(handles, labels)
  184. legend(handles=handles)
  185. legend(labels)
  186. The call signatures correspond to the following different ways to use
  187. this method:
  188. **1. Automatic detection of elements to be shown in the legend**
  189. The elements to be added to the legend are automatically determined,
  190. when you do not pass in any extra arguments.
  191. In this case, the labels are taken from the artist. You can specify
  192. them either at artist creation or by calling the
  193. :meth:`~.Artist.set_label` method on the artist::
  194. ax.plot([1, 2, 3], label='Inline label')
  195. ax.legend()
  196. or::
  197. line, = ax.plot([1, 2, 3])
  198. line.set_label('Label via method')
  199. ax.legend()
  200. .. note::
  201. Specific artists can be excluded from the automatic legend element
  202. selection by using a label starting with an underscore, "_".
  203. A string starting with an underscore is the default label for all
  204. artists, so calling `.Axes.legend` without any arguments and
  205. without setting the labels manually will result in a ``UserWarning``
  206. and an empty legend being drawn.
  207. **2. Explicitly listing the artists and labels in the legend**
  208. For full control of which artists have a legend entry, it is possible
  209. to pass an iterable of legend artists followed by an iterable of
  210. legend labels respectively::
  211. ax.legend([line1, line2, line3], ['label1', 'label2', 'label3'])
  212. **3. Explicitly listing the artists in the legend**
  213. This is similar to 2, but the labels are taken from the artists'
  214. label properties. Example::
  215. line1, = ax.plot([1, 2, 3], label='label1')
  216. line2, = ax.plot([1, 2, 3], label='label2')
  217. ax.legend(handles=[line1, line2])
  218. **4. Labeling existing plot elements**
  219. .. admonition:: Discouraged
  220. This call signature is discouraged, because the relation between
  221. plot elements and labels is only implicit by their order and can
  222. easily be mixed up.
  223. To make a legend for all artists on an Axes, call this function with
  224. an iterable of strings, one for each legend item. For example::
  225. ax.plot([1, 2, 3])
  226. ax.plot([5, 6, 7])
  227. ax.legend(['First line', 'Second line'])
  228. Parameters
  229. ----------
  230. handles : list of (`.Artist` or tuple of `.Artist`), optional
  231. A list of Artists (lines, patches) to be added to the legend.
  232. Use this together with *labels*, if you need full control on what
  233. is shown in the legend and the automatic mechanism described above
  234. is not sufficient.
  235. The length of handles and labels should be the same in this
  236. case. If they are not, they are truncated to the smaller length.
  237. If an entry contains a tuple, then the legend handler for all Artists in the
  238. tuple will be placed alongside a single label.
  239. labels : list of str, optional
  240. A list of labels to show next to the artists.
  241. Use this together with *handles*, if you need full control on what
  242. is shown in the legend and the automatic mechanism described above
  243. is not sufficient.
  244. Returns
  245. -------
  246. `~matplotlib.legend.Legend`
  247. Other Parameters
  248. ----------------
  249. %(_legend_kw_axes)s
  250. See Also
  251. --------
  252. .Figure.legend
  253. Notes
  254. -----
  255. Some artists are not supported by this function. See
  256. :ref:`legend_guide` for details.
  257. Examples
  258. --------
  259. .. plot:: gallery/text_labels_and_annotations/legend.py
  260. """
  261. handles, labels, kwargs = mlegend._parse_legend_args([self], *args, **kwargs)
  262. self.legend_ = mlegend.Legend(self, handles, labels, **kwargs)
  263. self.legend_._remove_method = self._remove_legend
  264. return self.legend_
  265. def _remove_legend(self, legend):
  266. self.legend_ = None
  267. def inset_axes(self, bounds, *, transform=None, zorder=5, **kwargs):
  268. """
  269. Add a child inset Axes to this existing Axes.
  270. Parameters
  271. ----------
  272. bounds : [x0, y0, width, height]
  273. Lower-left corner of inset Axes, and its width and height.
  274. transform : `.Transform`
  275. Defaults to `ax.transAxes`, i.e. the units of *rect* are in
  276. Axes-relative coordinates.
  277. projection : {None, 'aitoff', 'hammer', 'lambert', 'mollweide', \
  278. 'polar', 'rectilinear', str}, optional
  279. The projection type of the inset `~.axes.Axes`. *str* is the name
  280. of a custom projection, see `~matplotlib.projections`. The default
  281. None results in a 'rectilinear' projection.
  282. polar : bool, default: False
  283. If True, equivalent to projection='polar'.
  284. axes_class : subclass type of `~.axes.Axes`, optional
  285. The `.axes.Axes` subclass that is instantiated. This parameter
  286. is incompatible with *projection* and *polar*. See
  287. :ref:`axisartist_users-guide-index` for examples.
  288. zorder : number
  289. Defaults to 5 (same as `.Axes.legend`). Adjust higher or lower
  290. to change whether it is above or below data plotted on the
  291. parent Axes.
  292. **kwargs
  293. Other keyword arguments are passed on to the inset Axes class.
  294. Returns
  295. -------
  296. ax
  297. The created `~.axes.Axes` instance.
  298. Examples
  299. --------
  300. This example makes two inset Axes, the first is in Axes-relative
  301. coordinates, and the second in data-coordinates::
  302. fig, ax = plt.subplots()
  303. ax.plot(range(10))
  304. axin1 = ax.inset_axes([0.8, 0.1, 0.15, 0.15])
  305. axin2 = ax.inset_axes(
  306. [5, 7, 2.3, 2.3], transform=ax.transData)
  307. """
  308. if transform is None:
  309. transform = self.transAxes
  310. kwargs.setdefault('label', 'inset_axes')
  311. # This puts the rectangle into figure-relative coordinates.
  312. inset_locator = _TransformedBoundsLocator(bounds, transform)
  313. bounds = inset_locator(self, None).bounds
  314. fig = self.get_figure(root=False)
  315. projection_class, pkw = fig._process_projection_requirements(**kwargs)
  316. inset_ax = projection_class(fig, bounds, zorder=zorder, **pkw)
  317. # this locator lets the axes move if in data coordinates.
  318. # it gets called in `ax.apply_aspect() (of all places)
  319. inset_ax.set_axes_locator(inset_locator)
  320. self.add_child_axes(inset_ax)
  321. return inset_ax
  322. @_docstring.interpd
  323. def indicate_inset(self, bounds=None, inset_ax=None, *, transform=None,
  324. facecolor='none', edgecolor='0.5', alpha=0.5,
  325. zorder=None, **kwargs):
  326. """
  327. Add an inset indicator to the Axes. This is a rectangle on the plot
  328. at the position indicated by *bounds* that optionally has lines that
  329. connect the rectangle to an inset Axes (`.Axes.inset_axes`).
  330. Warnings
  331. --------
  332. This method is experimental as of 3.0, and the API may change.
  333. Parameters
  334. ----------
  335. bounds : [x0, y0, width, height], optional
  336. Lower-left corner of rectangle to be marked, and its width
  337. and height. If not set, the bounds will be calculated from the
  338. data limits of *inset_ax*, which must be supplied.
  339. inset_ax : `.Axes`, optional
  340. An optional inset Axes to draw connecting lines to. Two lines are
  341. drawn connecting the indicator box to the inset Axes on corners
  342. chosen so as to not overlap with the indicator box.
  343. transform : `.Transform`
  344. Transform for the rectangle coordinates. Defaults to
  345. ``ax.transAxes``, i.e. the units of *rect* are in Axes-relative
  346. coordinates.
  347. facecolor : :mpltype:`color`, default: 'none'
  348. Facecolor of the rectangle.
  349. edgecolor : :mpltype:`color`, default: '0.5'
  350. Color of the rectangle and color of the connecting lines.
  351. alpha : float or None, default: 0.5
  352. Transparency of the rectangle and connector lines. If not
  353. ``None``, this overrides any alpha value included in the
  354. *facecolor* and *edgecolor* parameters.
  355. zorder : float, default: 4.99
  356. Drawing order of the rectangle and connector lines. The default,
  357. 4.99, is just below the default level of inset Axes.
  358. **kwargs
  359. Other keyword arguments are passed on to the `.Rectangle` patch:
  360. %(Rectangle:kwdoc)s
  361. Returns
  362. -------
  363. inset_indicator : `.inset.InsetIndicator`
  364. An artist which contains
  365. inset_indicator.rectangle : `.Rectangle`
  366. The indicator frame.
  367. inset_indicator.connectors : 4-tuple of `.patches.ConnectionPatch`
  368. The four connector lines connecting to (lower_left, upper_left,
  369. lower_right upper_right) corners of *inset_ax*. Two lines are
  370. set with visibility to *False*, but the user can set the
  371. visibility to True if the automatic choice is not deemed correct.
  372. .. versionchanged:: 3.10
  373. Previously the rectangle and connectors tuple were returned.
  374. """
  375. # to make the Axes connectors work, we need to apply the aspect to
  376. # the parent Axes.
  377. self.apply_aspect()
  378. if transform is None:
  379. transform = self.transData
  380. kwargs.setdefault('label', '_indicate_inset')
  381. indicator_patch = minset.InsetIndicator(
  382. bounds, inset_ax=inset_ax,
  383. facecolor=facecolor, edgecolor=edgecolor, alpha=alpha,
  384. zorder=zorder, transform=transform, **kwargs)
  385. self.add_artist(indicator_patch)
  386. return indicator_patch
  387. def indicate_inset_zoom(self, inset_ax, **kwargs):
  388. """
  389. Add an inset indicator rectangle to the Axes based on the axis
  390. limits for an *inset_ax* and draw connectors between *inset_ax*
  391. and the rectangle.
  392. Warnings
  393. --------
  394. This method is experimental as of 3.0, and the API may change.
  395. Parameters
  396. ----------
  397. inset_ax : `.Axes`
  398. Inset Axes to draw connecting lines to. Two lines are
  399. drawn connecting the indicator box to the inset Axes on corners
  400. chosen so as to not overlap with the indicator box.
  401. **kwargs
  402. Other keyword arguments are passed on to `.Axes.indicate_inset`
  403. Returns
  404. -------
  405. inset_indicator : `.inset.InsetIndicator`
  406. An artist which contains
  407. inset_indicator.rectangle : `.Rectangle`
  408. The indicator frame.
  409. inset_indicator.connectors : 4-tuple of `.patches.ConnectionPatch`
  410. The four connector lines connecting to (lower_left, upper_left,
  411. lower_right upper_right) corners of *inset_ax*. Two lines are
  412. set with visibility to *False*, but the user can set the
  413. visibility to True if the automatic choice is not deemed correct.
  414. .. versionchanged:: 3.10
  415. Previously the rectangle and connectors tuple were returned.
  416. """
  417. return self.indicate_inset(None, inset_ax, **kwargs)
  418. @_docstring.interpd
  419. def secondary_xaxis(self, location, functions=None, *, transform=None, **kwargs):
  420. """
  421. Add a second x-axis to this `~.axes.Axes`.
  422. For example if we want to have a second scale for the data plotted on
  423. the xaxis.
  424. %(_secax_docstring)s
  425. Examples
  426. --------
  427. The main axis shows frequency, and the secondary axis shows period.
  428. .. plot::
  429. fig, ax = plt.subplots()
  430. ax.loglog(range(1, 360, 5), range(1, 360, 5))
  431. ax.set_xlabel('frequency [Hz]')
  432. def invert(x):
  433. # 1/x with special treatment of x == 0
  434. x = np.array(x).astype(float)
  435. near_zero = np.isclose(x, 0)
  436. x[near_zero] = np.inf
  437. x[~near_zero] = 1 / x[~near_zero]
  438. return x
  439. # the inverse of 1/x is itself
  440. secax = ax.secondary_xaxis('top', functions=(invert, invert))
  441. secax.set_xlabel('Period [s]')
  442. plt.show()
  443. To add a secondary axis relative to your data, you can pass a transform
  444. to the new axis.
  445. .. plot::
  446. fig, ax = plt.subplots()
  447. ax.plot(range(0, 5), range(-1, 4))
  448. # Pass 'ax.transData' as a transform to place the axis
  449. # relative to your data at y=0
  450. secax = ax.secondary_xaxis(0, transform=ax.transData)
  451. """
  452. if not (location in ['top', 'bottom'] or isinstance(location, Real)):
  453. raise ValueError('secondary_xaxis location must be either '
  454. 'a float or "top"/"bottom"')
  455. secondary_ax = SecondaryAxis(self, 'x', location, functions,
  456. transform, **kwargs)
  457. self.add_child_axes(secondary_ax)
  458. return secondary_ax
  459. @_docstring.interpd
  460. def secondary_yaxis(self, location, functions=None, *, transform=None, **kwargs):
  461. """
  462. Add a second y-axis to this `~.axes.Axes`.
  463. For example if we want to have a second scale for the data plotted on
  464. the yaxis.
  465. %(_secax_docstring)s
  466. Examples
  467. --------
  468. Add a secondary Axes that converts from radians to degrees
  469. .. plot::
  470. fig, ax = plt.subplots()
  471. ax.plot(range(1, 360, 5), range(1, 360, 5))
  472. ax.set_ylabel('degrees')
  473. secax = ax.secondary_yaxis('right', functions=(np.deg2rad,
  474. np.rad2deg))
  475. secax.set_ylabel('radians')
  476. To add a secondary axis relative to your data, you can pass a transform
  477. to the new axis.
  478. .. plot::
  479. fig, ax = plt.subplots()
  480. ax.plot(range(0, 5), range(-1, 4))
  481. # Pass 'ax.transData' as a transform to place the axis
  482. # relative to your data at x=3
  483. secax = ax.secondary_yaxis(3, transform=ax.transData)
  484. """
  485. if not (location in ['left', 'right'] or isinstance(location, Real)):
  486. raise ValueError('secondary_yaxis location must be either '
  487. 'a float or "left"/"right"')
  488. secondary_ax = SecondaryAxis(self, 'y', location, functions,
  489. transform, **kwargs)
  490. self.add_child_axes(secondary_ax)
  491. return secondary_ax
  492. @_docstring.interpd
  493. def text(self, x, y, s, fontdict=None, **kwargs):
  494. """
  495. Add text to the Axes.
  496. Add the text *s* to the Axes at location *x*, *y* in data coordinates,
  497. with a default ``horizontalalignment`` on the ``left`` and
  498. ``verticalalignment`` at the ``baseline``. See
  499. :doc:`/gallery/text_labels_and_annotations/text_alignment`.
  500. Parameters
  501. ----------
  502. x, y : float
  503. The position to place the text. By default, this is in data
  504. coordinates. The coordinate system can be changed using the
  505. *transform* parameter.
  506. s : str
  507. The text.
  508. fontdict : dict, default: None
  509. .. admonition:: Discouraged
  510. The use of *fontdict* is discouraged. Parameters should be passed as
  511. individual keyword arguments or using dictionary-unpacking
  512. ``text(..., **fontdict)``.
  513. A dictionary to override the default text properties. If fontdict
  514. is None, the defaults are determined by `.rcParams`.
  515. Returns
  516. -------
  517. `.Text`
  518. The created `.Text` instance.
  519. Other Parameters
  520. ----------------
  521. **kwargs : `~matplotlib.text.Text` properties.
  522. Other miscellaneous text parameters.
  523. %(Text:kwdoc)s
  524. Examples
  525. --------
  526. Individual keyword arguments can be used to override any given
  527. parameter::
  528. >>> text(x, y, s, fontsize=12)
  529. The default transform specifies that text is in data coords,
  530. alternatively, you can specify text in axis coords ((0, 0) is
  531. lower-left and (1, 1) is upper-right). The example below places
  532. text in the center of the Axes::
  533. >>> text(0.5, 0.5, 'matplotlib', horizontalalignment='center',
  534. ... verticalalignment='center', transform=ax.transAxes)
  535. You can put a rectangular box around the text instance (e.g., to
  536. set a background color) by using the keyword *bbox*. *bbox* is
  537. a dictionary of `~matplotlib.patches.Rectangle`
  538. properties. For example::
  539. >>> text(x, y, s, bbox=dict(facecolor='red', alpha=0.5))
  540. """
  541. effective_kwargs = {
  542. 'verticalalignment': 'baseline',
  543. 'horizontalalignment': 'left',
  544. 'transform': self.transData,
  545. 'clip_on': False,
  546. **(fontdict if fontdict is not None else {}),
  547. **kwargs,
  548. }
  549. t = mtext.Text(x, y, text=s, **effective_kwargs)
  550. if t.get_clip_path() is None:
  551. t.set_clip_path(self.patch)
  552. self._add_text(t)
  553. return t
  554. @_docstring.interpd
  555. def annotate(self, text, xy, xytext=None, xycoords='data', textcoords=None,
  556. arrowprops=None, annotation_clip=None, **kwargs):
  557. # Signature must match Annotation. This is verified in
  558. # test_annotate_signature().
  559. a = mtext.Annotation(text, xy, xytext=xytext, xycoords=xycoords,
  560. textcoords=textcoords, arrowprops=arrowprops,
  561. annotation_clip=annotation_clip, **kwargs)
  562. a.set_transform(mtransforms.IdentityTransform())
  563. if kwargs.get('clip_on', False) and a.get_clip_path() is None:
  564. a.set_clip_path(self.patch)
  565. self._add_text(a)
  566. return a
  567. annotate.__doc__ = mtext.Annotation.__init__.__doc__
  568. #### Lines and spans
  569. @_docstring.interpd
  570. def axhline(self, y=0, xmin=0, xmax=1, **kwargs):
  571. """
  572. Add a horizontal line spanning the whole or fraction of the Axes.
  573. Note: If you want to set x-limits in data coordinates, use
  574. `~.Axes.hlines` instead.
  575. Parameters
  576. ----------
  577. y : float, default: 0
  578. y position in :ref:`data coordinates <coordinate-systems>`.
  579. xmin : float, default: 0
  580. The start x-position in :ref:`axes coordinates <coordinate-systems>`.
  581. Should be between 0 and 1, 0 being the far left of the plot,
  582. 1 the far right of the plot.
  583. xmax : float, default: 1
  584. The end x-position in :ref:`axes coordinates <coordinate-systems>`.
  585. Should be between 0 and 1, 0 being the far left of the plot,
  586. 1 the far right of the plot.
  587. Returns
  588. -------
  589. `~matplotlib.lines.Line2D`
  590. A `.Line2D` specified via two points ``(xmin, y)``, ``(xmax, y)``.
  591. Its transform is set such that *x* is in
  592. :ref:`axes coordinates <coordinate-systems>` and *y* is in
  593. :ref:`data coordinates <coordinate-systems>`.
  594. This is still a generic line and the horizontal character is only
  595. realized through using identical *y* values for both points. Thus,
  596. if you want to change the *y* value later, you have to provide two
  597. values ``line.set_ydata([3, 3])``.
  598. Other Parameters
  599. ----------------
  600. **kwargs
  601. Valid keyword arguments are `.Line2D` properties, except for
  602. 'transform':
  603. %(Line2D:kwdoc)s
  604. See Also
  605. --------
  606. hlines : Add horizontal lines in data coordinates.
  607. axhspan : Add a horizontal span (rectangle) across the axis.
  608. axline : Add a line with an arbitrary slope.
  609. Examples
  610. --------
  611. * draw a thick red hline at 'y' = 0 that spans the xrange::
  612. >>> axhline(linewidth=4, color='r')
  613. * draw a default hline at 'y' = 1 that spans the xrange::
  614. >>> axhline(y=1)
  615. * draw a default hline at 'y' = .5 that spans the middle half of
  616. the xrange::
  617. >>> axhline(y=.5, xmin=0.25, xmax=0.75)
  618. """
  619. self._check_no_units([xmin, xmax], ['xmin', 'xmax'])
  620. if "transform" in kwargs:
  621. raise ValueError("'transform' is not allowed as a keyword "
  622. "argument; axhline generates its own transform.")
  623. ymin, ymax = self.get_ybound()
  624. # Strip away the units for comparison with non-unitized bounds.
  625. yy, = self._process_unit_info([("y", y)], kwargs)
  626. scaley = (yy < ymin) or (yy > ymax)
  627. trans = self.get_yaxis_transform(which='grid')
  628. l = mlines.Line2D([xmin, xmax], [y, y], transform=trans, **kwargs)
  629. self.add_line(l)
  630. l.get_path()._interpolation_steps = mpl.axis.GRIDLINE_INTERPOLATION_STEPS
  631. if scaley:
  632. self._request_autoscale_view("y")
  633. return l
  634. @_docstring.interpd
  635. def axvline(self, x=0, ymin=0, ymax=1, **kwargs):
  636. """
  637. Add a vertical line spanning the whole or fraction of the Axes.
  638. Note: If you want to set y-limits in data coordinates, use
  639. `~.Axes.vlines` instead.
  640. Parameters
  641. ----------
  642. x : float, default: 0
  643. x position in :ref:`data coordinates <coordinate-systems>`.
  644. ymin : float, default: 0
  645. The start y-position in :ref:`axes coordinates <coordinate-systems>`.
  646. Should be between 0 and 1, 0 being the bottom of the plot, 1 the
  647. top of the plot.
  648. ymax : float, default: 1
  649. The end y-position in :ref:`axes coordinates <coordinate-systems>`.
  650. Should be between 0 and 1, 0 being the bottom of the plot, 1 the
  651. top of the plot.
  652. Returns
  653. -------
  654. `~matplotlib.lines.Line2D`
  655. A `.Line2D` specified via two points ``(x, ymin)``, ``(x, ymax)``.
  656. Its transform is set such that *x* is in
  657. :ref:`data coordinates <coordinate-systems>` and *y* is in
  658. :ref:`axes coordinates <coordinate-systems>`.
  659. This is still a generic line and the vertical character is only
  660. realized through using identical *x* values for both points. Thus,
  661. if you want to change the *x* value later, you have to provide two
  662. values ``line.set_xdata([3, 3])``.
  663. Other Parameters
  664. ----------------
  665. **kwargs
  666. Valid keyword arguments are `.Line2D` properties, except for
  667. 'transform':
  668. %(Line2D:kwdoc)s
  669. See Also
  670. --------
  671. vlines : Add vertical lines in data coordinates.
  672. axvspan : Add a vertical span (rectangle) across the axis.
  673. axline : Add a line with an arbitrary slope.
  674. Examples
  675. --------
  676. * draw a thick red vline at *x* = 0 that spans the yrange::
  677. >>> axvline(linewidth=4, color='r')
  678. * draw a default vline at *x* = 1 that spans the yrange::
  679. >>> axvline(x=1)
  680. * draw a default vline at *x* = .5 that spans the middle half of
  681. the yrange::
  682. >>> axvline(x=.5, ymin=0.25, ymax=0.75)
  683. """
  684. self._check_no_units([ymin, ymax], ['ymin', 'ymax'])
  685. if "transform" in kwargs:
  686. raise ValueError("'transform' is not allowed as a keyword "
  687. "argument; axvline generates its own transform.")
  688. xmin, xmax = self.get_xbound()
  689. # Strip away the units for comparison with non-unitized bounds.
  690. xx, = self._process_unit_info([("x", x)], kwargs)
  691. scalex = (xx < xmin) or (xx > xmax)
  692. trans = self.get_xaxis_transform(which='grid')
  693. l = mlines.Line2D([x, x], [ymin, ymax], transform=trans, **kwargs)
  694. self.add_line(l)
  695. l.get_path()._interpolation_steps = mpl.axis.GRIDLINE_INTERPOLATION_STEPS
  696. if scalex:
  697. self._request_autoscale_view("x")
  698. return l
  699. @staticmethod
  700. def _check_no_units(vals, names):
  701. # Helper method to check that vals are not unitized
  702. for val, name in zip(vals, names):
  703. if not munits._is_natively_supported(val):
  704. raise ValueError(f"{name} must be a single scalar value, "
  705. f"but got {val}")
  706. @_docstring.interpd
  707. def axline(self, xy1, xy2=None, *, slope=None, **kwargs):
  708. """
  709. Add an infinitely long straight line.
  710. The line can be defined either by two points *xy1* and *xy2*, or
  711. by one point *xy1* and a *slope*.
  712. This draws a straight line "on the screen", regardless of the x and y
  713. scales, and is thus also suitable for drawing exponential decays in
  714. semilog plots, power laws in loglog plots, etc. However, *slope*
  715. should only be used with linear scales; It has no clear meaning for
  716. all other scales, and thus the behavior is undefined. Please specify
  717. the line using the points *xy1*, *xy2* for non-linear scales.
  718. The *transform* keyword argument only applies to the points *xy1*,
  719. *xy2*. The *slope* (if given) is always in data coordinates. This can
  720. be used e.g. with ``ax.transAxes`` for drawing grid lines with a fixed
  721. slope.
  722. Parameters
  723. ----------
  724. xy1, xy2 : (float, float)
  725. Points for the line to pass through.
  726. Either *xy2* or *slope* has to be given.
  727. slope : float, optional
  728. The slope of the line. Either *xy2* or *slope* has to be given.
  729. Returns
  730. -------
  731. `.AxLine`
  732. Other Parameters
  733. ----------------
  734. **kwargs
  735. Valid kwargs are `.Line2D` properties
  736. %(Line2D:kwdoc)s
  737. See Also
  738. --------
  739. axhline : for horizontal lines
  740. axvline : for vertical lines
  741. Examples
  742. --------
  743. Draw a thick red line passing through (0, 0) and (1, 1)::
  744. >>> axline((0, 0), (1, 1), linewidth=4, color='r')
  745. """
  746. if slope is not None and (self.get_xscale() != 'linear' or
  747. self.get_yscale() != 'linear'):
  748. raise TypeError("'slope' cannot be used with non-linear scales")
  749. datalim = [xy1] if xy2 is None else [xy1, xy2]
  750. if "transform" in kwargs:
  751. # if a transform is passed (i.e. line points not in data space),
  752. # data limits should not be adjusted.
  753. datalim = []
  754. line = mlines.AxLine(xy1, xy2, slope, **kwargs)
  755. # Like add_line, but correctly handling data limits.
  756. self._set_artist_props(line)
  757. if line.get_clip_path() is None:
  758. line.set_clip_path(self.patch)
  759. if not line.get_label():
  760. line.set_label(f"_child{len(self._children)}")
  761. self._children.append(line)
  762. line._remove_method = self._children.remove
  763. self.update_datalim(datalim)
  764. self._request_autoscale_view()
  765. return line
  766. @_docstring.interpd
  767. def axhspan(self, ymin, ymax, xmin=0, xmax=1, **kwargs):
  768. """
  769. Add a horizontal span (rectangle) across the Axes.
  770. The rectangle spans from *ymin* to *ymax* vertically, and, by default,
  771. the whole x-axis horizontally. The x-span can be set using *xmin*
  772. (default: 0) and *xmax* (default: 1) which are in axis units; e.g.
  773. ``xmin = 0.5`` always refers to the middle of the x-axis regardless of
  774. the limits set by `~.Axes.set_xlim`.
  775. Parameters
  776. ----------
  777. ymin : float
  778. Lower y-coordinate of the span, in data units.
  779. ymax : float
  780. Upper y-coordinate of the span, in data units.
  781. xmin : float, default: 0
  782. Lower x-coordinate of the span, in x-axis (0-1) units.
  783. xmax : float, default: 1
  784. Upper x-coordinate of the span, in x-axis (0-1) units.
  785. Returns
  786. -------
  787. `~matplotlib.patches.Rectangle`
  788. Horizontal span (rectangle) from (xmin, ymin) to (xmax, ymax).
  789. Other Parameters
  790. ----------------
  791. **kwargs : `~matplotlib.patches.Rectangle` properties
  792. %(Rectangle:kwdoc)s
  793. See Also
  794. --------
  795. axvspan : Add a vertical span across the Axes.
  796. """
  797. # Strip units away.
  798. self._check_no_units([xmin, xmax], ['xmin', 'xmax'])
  799. (ymin, ymax), = self._process_unit_info([("y", [ymin, ymax])], kwargs)
  800. p = mpatches.Rectangle((xmin, ymin), xmax - xmin, ymax - ymin, **kwargs)
  801. p.set_transform(self.get_yaxis_transform(which="grid"))
  802. # For Rectangles and non-separable transforms, add_patch can be buggy
  803. # and update the x limits even though it shouldn't do so for an
  804. # yaxis_transformed patch, so undo that update.
  805. ix = self.dataLim.intervalx.copy()
  806. mx = self.dataLim.minposx
  807. self.add_patch(p)
  808. self.dataLim.intervalx = ix
  809. self.dataLim.minposx = mx
  810. p.get_path()._interpolation_steps = mpl.axis.GRIDLINE_INTERPOLATION_STEPS
  811. self._request_autoscale_view("y")
  812. return p
  813. @_docstring.interpd
  814. def axvspan(self, xmin, xmax, ymin=0, ymax=1, **kwargs):
  815. """
  816. Add a vertical span (rectangle) across the Axes.
  817. The rectangle spans from *xmin* to *xmax* horizontally, and, by
  818. default, the whole y-axis vertically. The y-span can be set using
  819. *ymin* (default: 0) and *ymax* (default: 1) which are in axis units;
  820. e.g. ``ymin = 0.5`` always refers to the middle of the y-axis
  821. regardless of the limits set by `~.Axes.set_ylim`.
  822. Parameters
  823. ----------
  824. xmin : float
  825. Lower x-coordinate of the span, in data units.
  826. xmax : float
  827. Upper x-coordinate of the span, in data units.
  828. ymin : float, default: 0
  829. Lower y-coordinate of the span, in y-axis units (0-1).
  830. ymax : float, default: 1
  831. Upper y-coordinate of the span, in y-axis units (0-1).
  832. Returns
  833. -------
  834. `~matplotlib.patches.Rectangle`
  835. Vertical span (rectangle) from (xmin, ymin) to (xmax, ymax).
  836. Other Parameters
  837. ----------------
  838. **kwargs : `~matplotlib.patches.Rectangle` properties
  839. %(Rectangle:kwdoc)s
  840. See Also
  841. --------
  842. axhspan : Add a horizontal span across the Axes.
  843. Examples
  844. --------
  845. Draw a vertical, green, translucent rectangle from x = 1.25 to
  846. x = 1.55 that spans the yrange of the Axes.
  847. >>> axvspan(1.25, 1.55, facecolor='g', alpha=0.5)
  848. """
  849. # Strip units away.
  850. self._check_no_units([ymin, ymax], ['ymin', 'ymax'])
  851. (xmin, xmax), = self._process_unit_info([("x", [xmin, xmax])], kwargs)
  852. p = mpatches.Rectangle((xmin, ymin), xmax - xmin, ymax - ymin, **kwargs)
  853. p.set_transform(self.get_xaxis_transform(which="grid"))
  854. # For Rectangles and non-separable transforms, add_patch can be buggy
  855. # and update the y limits even though it shouldn't do so for an
  856. # xaxis_transformed patch, so undo that update.
  857. iy = self.dataLim.intervaly.copy()
  858. my = self.dataLim.minposy
  859. self.add_patch(p)
  860. self.dataLim.intervaly = iy
  861. self.dataLim.minposy = my
  862. p.get_path()._interpolation_steps = mpl.axis.GRIDLINE_INTERPOLATION_STEPS
  863. self._request_autoscale_view("x")
  864. return p
  865. @_api.make_keyword_only("3.10", "label")
  866. @_preprocess_data(replace_names=["y", "xmin", "xmax", "colors"],
  867. label_namer="y")
  868. def hlines(self, y, xmin, xmax, colors=None, linestyles='solid',
  869. label='', **kwargs):
  870. """
  871. Plot horizontal lines at each *y* from *xmin* to *xmax*.
  872. Parameters
  873. ----------
  874. y : float or array-like
  875. y-indexes where to plot the lines.
  876. xmin, xmax : float or array-like
  877. Respective beginning and end of each line. If scalars are
  878. provided, all lines will have the same length.
  879. colors : :mpltype:`color` or list of color , default: :rc:`lines.color`
  880. linestyles : {'solid', 'dashed', 'dashdot', 'dotted'}, default: 'solid'
  881. label : str, default: ''
  882. Returns
  883. -------
  884. `~matplotlib.collections.LineCollection`
  885. Other Parameters
  886. ----------------
  887. data : indexable object, optional
  888. DATA_PARAMETER_PLACEHOLDER
  889. **kwargs : `~matplotlib.collections.LineCollection` properties.
  890. See Also
  891. --------
  892. vlines : vertical lines
  893. axhline : horizontal line across the Axes
  894. """
  895. # We do the conversion first since not all unitized data is uniform
  896. xmin, xmax, y = self._process_unit_info(
  897. [("x", xmin), ("x", xmax), ("y", y)], kwargs)
  898. if not np.iterable(y):
  899. y = [y]
  900. if not np.iterable(xmin):
  901. xmin = [xmin]
  902. if not np.iterable(xmax):
  903. xmax = [xmax]
  904. # Create and combine masked_arrays from input
  905. y, xmin, xmax = cbook._combine_masks(y, xmin, xmax)
  906. y = np.ravel(y)
  907. xmin = np.ravel(xmin)
  908. xmax = np.ravel(xmax)
  909. masked_verts = np.ma.empty((len(y), 2, 2))
  910. masked_verts[:, 0, 0] = xmin
  911. masked_verts[:, 0, 1] = y
  912. masked_verts[:, 1, 0] = xmax
  913. masked_verts[:, 1, 1] = y
  914. lines = mcoll.LineCollection(masked_verts, colors=colors,
  915. linestyles=linestyles, label=label)
  916. self.add_collection(lines, autolim=False)
  917. lines._internal_update(kwargs)
  918. if len(y) > 0:
  919. # Extreme values of xmin/xmax/y. Using masked_verts here handles
  920. # the case of y being a masked *object* array (as can be generated
  921. # e.g. by errorbar()), which would make nanmin/nanmax stumble.
  922. updatex = True
  923. updatey = True
  924. if self.name == "rectilinear":
  925. datalim = lines.get_datalim(self.transData)
  926. t = lines.get_transform()
  927. updatex, updatey = t.contains_branch_seperately(self.transData)
  928. minx = np.nanmin(datalim.xmin)
  929. maxx = np.nanmax(datalim.xmax)
  930. miny = np.nanmin(datalim.ymin)
  931. maxy = np.nanmax(datalim.ymax)
  932. else:
  933. minx = np.nanmin(masked_verts[..., 0])
  934. maxx = np.nanmax(masked_verts[..., 0])
  935. miny = np.nanmin(masked_verts[..., 1])
  936. maxy = np.nanmax(masked_verts[..., 1])
  937. corners = (minx, miny), (maxx, maxy)
  938. self.update_datalim(corners, updatex, updatey)
  939. self._request_autoscale_view()
  940. return lines
  941. @_api.make_keyword_only("3.10", "label")
  942. @_preprocess_data(replace_names=["x", "ymin", "ymax", "colors"],
  943. label_namer="x")
  944. def vlines(self, x, ymin, ymax, colors=None, linestyles='solid',
  945. label='', **kwargs):
  946. """
  947. Plot vertical lines at each *x* from *ymin* to *ymax*.
  948. Parameters
  949. ----------
  950. x : float or array-like
  951. x-indexes where to plot the lines.
  952. ymin, ymax : float or array-like
  953. Respective beginning and end of each line. If scalars are
  954. provided, all lines will have the same length.
  955. colors : :mpltype:`color` or list of color, default: :rc:`lines.color`
  956. linestyles : {'solid', 'dashed', 'dashdot', 'dotted'}, default: 'solid'
  957. label : str, default: ''
  958. Returns
  959. -------
  960. `~matplotlib.collections.LineCollection`
  961. Other Parameters
  962. ----------------
  963. data : indexable object, optional
  964. DATA_PARAMETER_PLACEHOLDER
  965. **kwargs : `~matplotlib.collections.LineCollection` properties.
  966. See Also
  967. --------
  968. hlines : horizontal lines
  969. axvline : vertical line across the Axes
  970. """
  971. # We do the conversion first since not all unitized data is uniform
  972. x, ymin, ymax = self._process_unit_info(
  973. [("x", x), ("y", ymin), ("y", ymax)], kwargs)
  974. if not np.iterable(x):
  975. x = [x]
  976. if not np.iterable(ymin):
  977. ymin = [ymin]
  978. if not np.iterable(ymax):
  979. ymax = [ymax]
  980. # Create and combine masked_arrays from input
  981. x, ymin, ymax = cbook._combine_masks(x, ymin, ymax)
  982. x = np.ravel(x)
  983. ymin = np.ravel(ymin)
  984. ymax = np.ravel(ymax)
  985. masked_verts = np.ma.empty((len(x), 2, 2))
  986. masked_verts[:, 0, 0] = x
  987. masked_verts[:, 0, 1] = ymin
  988. masked_verts[:, 1, 0] = x
  989. masked_verts[:, 1, 1] = ymax
  990. lines = mcoll.LineCollection(masked_verts, colors=colors,
  991. linestyles=linestyles, label=label)
  992. self.add_collection(lines, autolim=False)
  993. lines._internal_update(kwargs)
  994. if len(x) > 0:
  995. # Extreme values of x/ymin/ymax. Using masked_verts here handles
  996. # the case of x being a masked *object* array (as can be generated
  997. # e.g. by errorbar()), which would make nanmin/nanmax stumble.
  998. updatex = True
  999. updatey = True
  1000. if self.name == "rectilinear":
  1001. datalim = lines.get_datalim(self.transData)
  1002. t = lines.get_transform()
  1003. updatex, updatey = t.contains_branch_seperately(self.transData)
  1004. minx = np.nanmin(datalim.xmin)
  1005. maxx = np.nanmax(datalim.xmax)
  1006. miny = np.nanmin(datalim.ymin)
  1007. maxy = np.nanmax(datalim.ymax)
  1008. else:
  1009. minx = np.nanmin(masked_verts[..., 0])
  1010. maxx = np.nanmax(masked_verts[..., 0])
  1011. miny = np.nanmin(masked_verts[..., 1])
  1012. maxy = np.nanmax(masked_verts[..., 1])
  1013. corners = (minx, miny), (maxx, maxy)
  1014. self.update_datalim(corners, updatex, updatey)
  1015. self._request_autoscale_view()
  1016. return lines
  1017. @_api.make_keyword_only("3.10", "orientation")
  1018. @_preprocess_data(replace_names=["positions", "lineoffsets",
  1019. "linelengths", "linewidths",
  1020. "colors", "linestyles"])
  1021. @_docstring.interpd
  1022. def eventplot(self, positions, orientation='horizontal', lineoffsets=1,
  1023. linelengths=1, linewidths=None, colors=None, alpha=None,
  1024. linestyles='solid', **kwargs):
  1025. """
  1026. Plot identical parallel lines at the given positions.
  1027. This type of plot is commonly used in neuroscience for representing
  1028. neural events, where it is usually called a spike raster, dot raster,
  1029. or raster plot.
  1030. However, it is useful in any situation where you wish to show the
  1031. timing or position of multiple sets of discrete events, such as the
  1032. arrival times of people to a business on each day of the month or the
  1033. date of hurricanes each year of the last century.
  1034. Parameters
  1035. ----------
  1036. positions : array-like or list of array-like
  1037. A 1D array-like defines the positions of one sequence of events.
  1038. Multiple groups of events may be passed as a list of array-likes.
  1039. Each group can be styled independently by passing lists of values
  1040. to *lineoffsets*, *linelengths*, *linewidths*, *colors* and
  1041. *linestyles*.
  1042. Note that *positions* can be a 2D array, but in practice different
  1043. event groups usually have different counts so that one will use a
  1044. list of different-length arrays rather than a 2D array.
  1045. orientation : {'horizontal', 'vertical'}, default: 'horizontal'
  1046. The direction of the event sequence:
  1047. - 'horizontal': the events are arranged horizontally.
  1048. The indicator lines are vertical.
  1049. - 'vertical': the events are arranged vertically.
  1050. The indicator lines are horizontal.
  1051. lineoffsets : float or array-like, default: 1
  1052. The offset of the center of the lines from the origin, in the
  1053. direction orthogonal to *orientation*.
  1054. If *positions* is 2D, this can be a sequence with length matching
  1055. the length of *positions*.
  1056. linelengths : float or array-like, default: 1
  1057. The total height of the lines (i.e. the lines stretches from
  1058. ``lineoffset - linelength/2`` to ``lineoffset + linelength/2``).
  1059. If *positions* is 2D, this can be a sequence with length matching
  1060. the length of *positions*.
  1061. linewidths : float or array-like, default: :rc:`lines.linewidth`
  1062. The line width(s) of the event lines, in points.
  1063. If *positions* is 2D, this can be a sequence with length matching
  1064. the length of *positions*.
  1065. colors : :mpltype:`color` or list of color, default: :rc:`lines.color`
  1066. The color(s) of the event lines.
  1067. If *positions* is 2D, this can be a sequence with length matching
  1068. the length of *positions*.
  1069. alpha : float or array-like, default: 1
  1070. The alpha blending value(s), between 0 (transparent) and 1
  1071. (opaque).
  1072. If *positions* is 2D, this can be a sequence with length matching
  1073. the length of *positions*.
  1074. linestyles : str or tuple or list of such values, default: 'solid'
  1075. Default is 'solid'. Valid strings are ['solid', 'dashed',
  1076. 'dashdot', 'dotted', '-', '--', '-.', ':']. Dash tuples
  1077. should be of the form::
  1078. (offset, onoffseq),
  1079. where *onoffseq* is an even length tuple of on and off ink
  1080. in points.
  1081. If *positions* is 2D, this can be a sequence with length matching
  1082. the length of *positions*.
  1083. data : indexable object, optional
  1084. DATA_PARAMETER_PLACEHOLDER
  1085. **kwargs
  1086. Other keyword arguments are line collection properties. See
  1087. `.LineCollection` for a list of the valid properties.
  1088. Returns
  1089. -------
  1090. list of `.EventCollection`
  1091. The `.EventCollection` that were added.
  1092. Notes
  1093. -----
  1094. For *linelengths*, *linewidths*, *colors*, *alpha* and *linestyles*, if
  1095. only a single value is given, that value is applied to all lines. If an
  1096. array-like is given, it must have the same length as *positions*, and
  1097. each value will be applied to the corresponding row of the array.
  1098. Examples
  1099. --------
  1100. .. plot:: gallery/lines_bars_and_markers/eventplot_demo.py
  1101. """
  1102. lineoffsets, linelengths = self._process_unit_info(
  1103. [("y", lineoffsets), ("y", linelengths)], kwargs)
  1104. # fix positions, noting that it can be a list of lists:
  1105. if not np.iterable(positions):
  1106. positions = [positions]
  1107. elif any(np.iterable(position) for position in positions):
  1108. positions = [np.asanyarray(position) for position in positions]
  1109. else:
  1110. positions = [np.asanyarray(positions)]
  1111. poss = []
  1112. for position in positions:
  1113. poss += self._process_unit_info([("x", position)], kwargs)
  1114. positions = poss
  1115. # prevent 'singular' keys from **kwargs dict from overriding the effect
  1116. # of 'plural' keyword arguments (e.g. 'color' overriding 'colors')
  1117. colors = cbook._local_over_kwdict(colors, kwargs, 'color')
  1118. linewidths = cbook._local_over_kwdict(linewidths, kwargs, 'linewidth')
  1119. linestyles = cbook._local_over_kwdict(linestyles, kwargs, 'linestyle')
  1120. if not np.iterable(lineoffsets):
  1121. lineoffsets = [lineoffsets]
  1122. if not np.iterable(linelengths):
  1123. linelengths = [linelengths]
  1124. if not np.iterable(linewidths):
  1125. linewidths = [linewidths]
  1126. if not np.iterable(colors):
  1127. colors = [colors]
  1128. if not np.iterable(alpha):
  1129. alpha = [alpha]
  1130. if hasattr(linestyles, 'lower') or not np.iterable(linestyles):
  1131. linestyles = [linestyles]
  1132. lineoffsets = np.asarray(lineoffsets)
  1133. linelengths = np.asarray(linelengths)
  1134. linewidths = np.asarray(linewidths)
  1135. if len(lineoffsets) == 0:
  1136. raise ValueError('lineoffsets cannot be empty')
  1137. if len(linelengths) == 0:
  1138. raise ValueError('linelengths cannot be empty')
  1139. if len(linestyles) == 0:
  1140. raise ValueError('linestyles cannot be empty')
  1141. if len(linewidths) == 0:
  1142. raise ValueError('linewidths cannot be empty')
  1143. if len(alpha) == 0:
  1144. raise ValueError('alpha cannot be empty')
  1145. if len(colors) == 0:
  1146. colors = [None]
  1147. try:
  1148. # Early conversion of the colors into RGBA values to take care
  1149. # of cases like colors='0.5' or colors='C1'. (Issue #8193)
  1150. colors = mcolors.to_rgba_array(colors)
  1151. except ValueError:
  1152. # Will fail if any element of *colors* is None. But as long
  1153. # as len(colors) == 1 or len(positions), the rest of the
  1154. # code should process *colors* properly.
  1155. pass
  1156. if len(lineoffsets) == 1 and len(positions) != 1:
  1157. lineoffsets = np.tile(lineoffsets, len(positions))
  1158. lineoffsets[0] = 0
  1159. lineoffsets = np.cumsum(lineoffsets)
  1160. if len(linelengths) == 1:
  1161. linelengths = np.tile(linelengths, len(positions))
  1162. if len(linewidths) == 1:
  1163. linewidths = np.tile(linewidths, len(positions))
  1164. if len(colors) == 1:
  1165. colors = list(colors) * len(positions)
  1166. if len(alpha) == 1:
  1167. alpha = list(alpha) * len(positions)
  1168. if len(linestyles) == 1:
  1169. linestyles = [linestyles] * len(positions)
  1170. if len(lineoffsets) != len(positions):
  1171. raise ValueError('lineoffsets and positions are unequal sized '
  1172. 'sequences')
  1173. if len(linelengths) != len(positions):
  1174. raise ValueError('linelengths and positions are unequal sized '
  1175. 'sequences')
  1176. if len(linewidths) != len(positions):
  1177. raise ValueError('linewidths and positions are unequal sized '
  1178. 'sequences')
  1179. if len(colors) != len(positions):
  1180. raise ValueError('colors and positions are unequal sized '
  1181. 'sequences')
  1182. if len(alpha) != len(positions):
  1183. raise ValueError('alpha and positions are unequal sized '
  1184. 'sequences')
  1185. if len(linestyles) != len(positions):
  1186. raise ValueError('linestyles and positions are unequal sized '
  1187. 'sequences')
  1188. colls = []
  1189. for position, lineoffset, linelength, linewidth, color, alpha_, \
  1190. linestyle in \
  1191. zip(positions, lineoffsets, linelengths, linewidths,
  1192. colors, alpha, linestyles):
  1193. coll = mcoll.EventCollection(position,
  1194. orientation=orientation,
  1195. lineoffset=lineoffset,
  1196. linelength=linelength,
  1197. linewidth=linewidth,
  1198. color=color,
  1199. alpha=alpha_,
  1200. linestyle=linestyle)
  1201. self.add_collection(coll, autolim=False)
  1202. coll._internal_update(kwargs)
  1203. colls.append(coll)
  1204. if len(positions) > 0:
  1205. # try to get min/max
  1206. min_max = [(np.min(_p), np.max(_p)) for _p in positions
  1207. if len(_p) > 0]
  1208. # if we have any non-empty positions, try to autoscale
  1209. if len(min_max) > 0:
  1210. mins, maxes = zip(*min_max)
  1211. minpos = np.min(mins)
  1212. maxpos = np.max(maxes)
  1213. minline = (lineoffsets - linelengths).min()
  1214. maxline = (lineoffsets + linelengths).max()
  1215. if orientation == "vertical":
  1216. corners = (minline, minpos), (maxline, maxpos)
  1217. else: # "horizontal"
  1218. corners = (minpos, minline), (maxpos, maxline)
  1219. self.update_datalim(corners)
  1220. self._request_autoscale_view()
  1221. return colls
  1222. #### Basic plotting
  1223. # Uses a custom implementation of data-kwarg handling in
  1224. # _process_plot_var_args.
  1225. @_docstring.interpd
  1226. def plot(self, *args, scalex=True, scaley=True, data=None, **kwargs):
  1227. """
  1228. Plot y versus x as lines and/or markers.
  1229. Call signatures::
  1230. plot([x], y, [fmt], *, data=None, **kwargs)
  1231. plot([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs)
  1232. The coordinates of the points or line nodes are given by *x*, *y*.
  1233. The optional parameter *fmt* is a convenient way for defining basic
  1234. formatting like color, marker and linestyle. It's a shortcut string
  1235. notation described in the *Notes* section below.
  1236. >>> plot(x, y) # plot x and y using default line style and color
  1237. >>> plot(x, y, 'bo') # plot x and y using blue circle markers
  1238. >>> plot(y) # plot y using x as index array 0..N-1
  1239. >>> plot(y, 'r+') # ditto, but with red plusses
  1240. You can use `.Line2D` properties as keyword arguments for more
  1241. control on the appearance. Line properties and *fmt* can be mixed.
  1242. The following two calls yield identical results:
  1243. >>> plot(x, y, 'go--', linewidth=2, markersize=12)
  1244. >>> plot(x, y, color='green', marker='o', linestyle='dashed',
  1245. ... linewidth=2, markersize=12)
  1246. When conflicting with *fmt*, keyword arguments take precedence.
  1247. **Plotting labelled data**
  1248. There's a convenient way for plotting objects with labelled data (i.e.
  1249. data that can be accessed by index ``obj['y']``). Instead of giving
  1250. the data in *x* and *y*, you can provide the object in the *data*
  1251. parameter and just give the labels for *x* and *y*::
  1252. >>> plot('xlabel', 'ylabel', data=obj)
  1253. All indexable objects are supported. This could e.g. be a `dict`, a
  1254. `pandas.DataFrame` or a structured numpy array.
  1255. **Plotting multiple sets of data**
  1256. There are various ways to plot multiple sets of data.
  1257. - The most straight forward way is just to call `plot` multiple times.
  1258. Example:
  1259. >>> plot(x1, y1, 'bo')
  1260. >>> plot(x2, y2, 'go')
  1261. - If *x* and/or *y* are 2D arrays, a separate data set will be drawn
  1262. for every column. If both *x* and *y* are 2D, they must have the
  1263. same shape. If only one of them is 2D with shape (N, m) the other
  1264. must have length N and will be used for every data set m.
  1265. Example:
  1266. >>> x = [1, 2, 3]
  1267. >>> y = np.array([[1, 2], [3, 4], [5, 6]])
  1268. >>> plot(x, y)
  1269. is equivalent to:
  1270. >>> for col in range(y.shape[1]):
  1271. ... plot(x, y[:, col])
  1272. - The third way is to specify multiple sets of *[x]*, *y*, *[fmt]*
  1273. groups::
  1274. >>> plot(x1, y1, 'g^', x2, y2, 'g-')
  1275. In this case, any additional keyword argument applies to all
  1276. datasets. Also, this syntax cannot be combined with the *data*
  1277. parameter.
  1278. By default, each line is assigned a different style specified by a
  1279. 'style cycle'. The *fmt* and line property parameters are only
  1280. necessary if you want explicit deviations from these defaults.
  1281. Alternatively, you can also change the style cycle using
  1282. :rc:`axes.prop_cycle`.
  1283. Parameters
  1284. ----------
  1285. x, y : array-like or float
  1286. The horizontal / vertical coordinates of the data points.
  1287. *x* values are optional and default to ``range(len(y))``.
  1288. Commonly, these parameters are 1D arrays.
  1289. They can also be scalars, or two-dimensional (in that case, the
  1290. columns represent separate data sets).
  1291. These arguments cannot be passed as keywords.
  1292. fmt : str, optional
  1293. A format string, e.g. 'ro' for red circles. See the *Notes*
  1294. section for a full description of the format strings.
  1295. Format strings are just an abbreviation for quickly setting
  1296. basic line properties. All of these and more can also be
  1297. controlled by keyword arguments.
  1298. This argument cannot be passed as keyword.
  1299. data : indexable object, optional
  1300. An object with labelled data. If given, provide the label names to
  1301. plot in *x* and *y*.
  1302. .. note::
  1303. Technically there's a slight ambiguity in calls where the
  1304. second label is a valid *fmt*. ``plot('n', 'o', data=obj)``
  1305. could be ``plt(x, y)`` or ``plt(y, fmt)``. In such cases,
  1306. the former interpretation is chosen, but a warning is issued.
  1307. You may suppress the warning by adding an empty format string
  1308. ``plot('n', 'o', '', data=obj)``.
  1309. Returns
  1310. -------
  1311. list of `.Line2D`
  1312. A list of lines representing the plotted data.
  1313. Other Parameters
  1314. ----------------
  1315. scalex, scaley : bool, default: True
  1316. These parameters determine if the view limits are adapted to the
  1317. data limits. The values are passed on to
  1318. `~.axes.Axes.autoscale_view`.
  1319. **kwargs : `~matplotlib.lines.Line2D` properties, optional
  1320. *kwargs* are used to specify properties like a line label (for
  1321. auto legends), linewidth, antialiasing, marker face color.
  1322. Example::
  1323. >>> plot([1, 2, 3], [1, 2, 3], 'go-', label='line 1', linewidth=2)
  1324. >>> plot([1, 2, 3], [1, 4, 9], 'rs', label='line 2')
  1325. If you specify multiple lines with one plot call, the kwargs apply
  1326. to all those lines. In case the label object is iterable, each
  1327. element is used as labels for each set of data.
  1328. Here is a list of available `.Line2D` properties:
  1329. %(Line2D:kwdoc)s
  1330. See Also
  1331. --------
  1332. scatter : XY scatter plot with markers of varying size and/or color (
  1333. sometimes also called bubble chart).
  1334. Notes
  1335. -----
  1336. **Format Strings**
  1337. A format string consists of a part for color, marker and line::
  1338. fmt = '[marker][line][color]'
  1339. Each of them is optional. If not provided, the value from the style
  1340. cycle is used. Exception: If ``line`` is given, but no ``marker``,
  1341. the data will be a line without markers.
  1342. Other combinations such as ``[color][marker][line]`` are also
  1343. supported, but note that their parsing may be ambiguous.
  1344. **Markers**
  1345. ============= ===============================
  1346. character description
  1347. ============= ===============================
  1348. ``'.'`` point marker
  1349. ``','`` pixel marker
  1350. ``'o'`` circle marker
  1351. ``'v'`` triangle_down marker
  1352. ``'^'`` triangle_up marker
  1353. ``'<'`` triangle_left marker
  1354. ``'>'`` triangle_right marker
  1355. ``'1'`` tri_down marker
  1356. ``'2'`` tri_up marker
  1357. ``'3'`` tri_left marker
  1358. ``'4'`` tri_right marker
  1359. ``'8'`` octagon marker
  1360. ``'s'`` square marker
  1361. ``'p'`` pentagon marker
  1362. ``'P'`` plus (filled) marker
  1363. ``'*'`` star marker
  1364. ``'h'`` hexagon1 marker
  1365. ``'H'`` hexagon2 marker
  1366. ``'+'`` plus marker
  1367. ``'x'`` x marker
  1368. ``'X'`` x (filled) marker
  1369. ``'D'`` diamond marker
  1370. ``'d'`` thin_diamond marker
  1371. ``'|'`` vline marker
  1372. ``'_'`` hline marker
  1373. ============= ===============================
  1374. **Line Styles**
  1375. ============= ===============================
  1376. character description
  1377. ============= ===============================
  1378. ``'-'`` solid line style
  1379. ``'--'`` dashed line style
  1380. ``'-.'`` dash-dot line style
  1381. ``':'`` dotted line style
  1382. ============= ===============================
  1383. Example format strings::
  1384. 'b' # blue markers with default shape
  1385. 'or' # red circles
  1386. '-g' # green solid line
  1387. '--' # dashed line with default color
  1388. '^k:' # black triangle_up markers connected by a dotted line
  1389. **Colors**
  1390. The supported color abbreviations are the single letter codes
  1391. ============= ===============================
  1392. character color
  1393. ============= ===============================
  1394. ``'b'`` blue
  1395. ``'g'`` green
  1396. ``'r'`` red
  1397. ``'c'`` cyan
  1398. ``'m'`` magenta
  1399. ``'y'`` yellow
  1400. ``'k'`` black
  1401. ``'w'`` white
  1402. ============= ===============================
  1403. and the ``'CN'`` colors that index into the default property cycle.
  1404. If the color is the only part of the format string, you can
  1405. additionally use any `matplotlib.colors` spec, e.g. full names
  1406. (``'green'``) or hex strings (``'#008000'``).
  1407. """
  1408. kwargs = cbook.normalize_kwargs(kwargs, mlines.Line2D)
  1409. lines = [*self._get_lines(self, *args, data=data, **kwargs)]
  1410. for line in lines:
  1411. self.add_line(line)
  1412. if scalex:
  1413. self._request_autoscale_view("x")
  1414. if scaley:
  1415. self._request_autoscale_view("y")
  1416. return lines
  1417. @_api.deprecated("3.9", alternative="plot")
  1418. @_preprocess_data(replace_names=["x", "y"], label_namer="y")
  1419. @_docstring.interpd
  1420. def plot_date(self, x, y, fmt='o', tz=None, xdate=True, ydate=False,
  1421. **kwargs):
  1422. """
  1423. Plot coercing the axis to treat floats as dates.
  1424. .. deprecated:: 3.9
  1425. This method exists for historic reasons and will be removed in version 3.11.
  1426. - ``datetime``-like data should directly be plotted using
  1427. `~.Axes.plot`.
  1428. - If you need to plot plain numeric data as :ref:`date-format` or
  1429. need to set a timezone, call ``ax.xaxis.axis_date`` /
  1430. ``ax.yaxis.axis_date`` before `~.Axes.plot`. See
  1431. `.Axis.axis_date`.
  1432. Similar to `.plot`, this plots *y* vs. *x* as lines or markers.
  1433. However, the axis labels are formatted as dates depending on *xdate*
  1434. and *ydate*. Note that `.plot` will work with `datetime` and
  1435. `numpy.datetime64` objects without resorting to this method.
  1436. Parameters
  1437. ----------
  1438. x, y : array-like
  1439. The coordinates of the data points. If *xdate* or *ydate* is
  1440. *True*, the respective values *x* or *y* are interpreted as
  1441. :ref:`Matplotlib dates <date-format>`.
  1442. fmt : str, optional
  1443. The plot format string. For details, see the corresponding
  1444. parameter in `.plot`.
  1445. tz : timezone string or `datetime.tzinfo`, default: :rc:`timezone`
  1446. The time zone to use in labeling dates.
  1447. xdate : bool, default: True
  1448. If *True*, the *x*-axis will be interpreted as Matplotlib dates.
  1449. ydate : bool, default: False
  1450. If *True*, the *y*-axis will be interpreted as Matplotlib dates.
  1451. Returns
  1452. -------
  1453. list of `.Line2D`
  1454. Objects representing the plotted data.
  1455. Other Parameters
  1456. ----------------
  1457. data : indexable object, optional
  1458. DATA_PARAMETER_PLACEHOLDER
  1459. **kwargs
  1460. Keyword arguments control the `.Line2D` properties:
  1461. %(Line2D:kwdoc)s
  1462. See Also
  1463. --------
  1464. matplotlib.dates : Helper functions on dates.
  1465. matplotlib.dates.date2num : Convert dates to num.
  1466. matplotlib.dates.num2date : Convert num to dates.
  1467. matplotlib.dates.drange : Create an equally spaced sequence of dates.
  1468. Notes
  1469. -----
  1470. If you are using custom date tickers and formatters, it may be
  1471. necessary to set the formatters/locators after the call to
  1472. `.plot_date`. `.plot_date` will set the default tick locator to
  1473. `.AutoDateLocator` (if the tick locator is not already set to a
  1474. `.DateLocator` instance) and the default tick formatter to
  1475. `.AutoDateFormatter` (if the tick formatter is not already set to a
  1476. `.DateFormatter` instance).
  1477. """
  1478. if xdate:
  1479. self.xaxis_date(tz)
  1480. if ydate:
  1481. self.yaxis_date(tz)
  1482. return self.plot(x, y, fmt, **kwargs)
  1483. # @_preprocess_data() # let 'plot' do the unpacking..
  1484. @_docstring.interpd
  1485. def loglog(self, *args, **kwargs):
  1486. """
  1487. Make a plot with log scaling on both the x- and y-axis.
  1488. Call signatures::
  1489. loglog([x], y, [fmt], data=None, **kwargs)
  1490. loglog([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs)
  1491. This is just a thin wrapper around `.plot` which additionally changes
  1492. both the x-axis and the y-axis to log scaling. All the concepts and
  1493. parameters of plot can be used here as well.
  1494. The additional parameters *base*, *subs* and *nonpositive* control the
  1495. x/y-axis properties. They are just forwarded to `.Axes.set_xscale` and
  1496. `.Axes.set_yscale`. To use different properties on the x-axis and the
  1497. y-axis, use e.g.
  1498. ``ax.set_xscale("log", base=10); ax.set_yscale("log", base=2)``.
  1499. Parameters
  1500. ----------
  1501. base : float, default: 10
  1502. Base of the logarithm.
  1503. subs : sequence, optional
  1504. The location of the minor ticks. If *None*, reasonable locations
  1505. are automatically chosen depending on the number of decades in the
  1506. plot. See `.Axes.set_xscale`/`.Axes.set_yscale` for details.
  1507. nonpositive : {'mask', 'clip'}, default: 'clip'
  1508. Non-positive values can be masked as invalid, or clipped to a very
  1509. small positive number.
  1510. **kwargs
  1511. All parameters supported by `.plot`.
  1512. Returns
  1513. -------
  1514. list of `.Line2D`
  1515. Objects representing the plotted data.
  1516. """
  1517. dx = {k: v for k, v in kwargs.items()
  1518. if k in ['base', 'subs', 'nonpositive',
  1519. 'basex', 'subsx', 'nonposx']}
  1520. self.set_xscale('log', **dx)
  1521. dy = {k: v for k, v in kwargs.items()
  1522. if k in ['base', 'subs', 'nonpositive',
  1523. 'basey', 'subsy', 'nonposy']}
  1524. self.set_yscale('log', **dy)
  1525. return self.plot(
  1526. *args, **{k: v for k, v in kwargs.items() if k not in {*dx, *dy}})
  1527. # @_preprocess_data() # let 'plot' do the unpacking..
  1528. @_docstring.interpd
  1529. def semilogx(self, *args, **kwargs):
  1530. """
  1531. Make a plot with log scaling on the x-axis.
  1532. Call signatures::
  1533. semilogx([x], y, [fmt], data=None, **kwargs)
  1534. semilogx([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs)
  1535. This is just a thin wrapper around `.plot` which additionally changes
  1536. the x-axis to log scaling. All the concepts and parameters of plot can
  1537. be used here as well.
  1538. The additional parameters *base*, *subs*, and *nonpositive* control the
  1539. x-axis properties. They are just forwarded to `.Axes.set_xscale`.
  1540. Parameters
  1541. ----------
  1542. base : float, default: 10
  1543. Base of the x logarithm.
  1544. subs : array-like, optional
  1545. The location of the minor xticks. If *None*, reasonable locations
  1546. are automatically chosen depending on the number of decades in the
  1547. plot. See `.Axes.set_xscale` for details.
  1548. nonpositive : {'mask', 'clip'}, default: 'clip'
  1549. Non-positive values in x can be masked as invalid, or clipped to a
  1550. very small positive number.
  1551. **kwargs
  1552. All parameters supported by `.plot`.
  1553. Returns
  1554. -------
  1555. list of `.Line2D`
  1556. Objects representing the plotted data.
  1557. """
  1558. d = {k: v for k, v in kwargs.items()
  1559. if k in ['base', 'subs', 'nonpositive',
  1560. 'basex', 'subsx', 'nonposx']}
  1561. self.set_xscale('log', **d)
  1562. return self.plot(
  1563. *args, **{k: v for k, v in kwargs.items() if k not in d})
  1564. # @_preprocess_data() # let 'plot' do the unpacking..
  1565. @_docstring.interpd
  1566. def semilogy(self, *args, **kwargs):
  1567. """
  1568. Make a plot with log scaling on the y-axis.
  1569. Call signatures::
  1570. semilogy([x], y, [fmt], data=None, **kwargs)
  1571. semilogy([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs)
  1572. This is just a thin wrapper around `.plot` which additionally changes
  1573. the y-axis to log scaling. All the concepts and parameters of plot can
  1574. be used here as well.
  1575. The additional parameters *base*, *subs*, and *nonpositive* control the
  1576. y-axis properties. They are just forwarded to `.Axes.set_yscale`.
  1577. Parameters
  1578. ----------
  1579. base : float, default: 10
  1580. Base of the y logarithm.
  1581. subs : array-like, optional
  1582. The location of the minor yticks. If *None*, reasonable locations
  1583. are automatically chosen depending on the number of decades in the
  1584. plot. See `.Axes.set_yscale` for details.
  1585. nonpositive : {'mask', 'clip'}, default: 'clip'
  1586. Non-positive values in y can be masked as invalid, or clipped to a
  1587. very small positive number.
  1588. **kwargs
  1589. All parameters supported by `.plot`.
  1590. Returns
  1591. -------
  1592. list of `.Line2D`
  1593. Objects representing the plotted data.
  1594. """
  1595. d = {k: v for k, v in kwargs.items()
  1596. if k in ['base', 'subs', 'nonpositive',
  1597. 'basey', 'subsy', 'nonposy']}
  1598. self.set_yscale('log', **d)
  1599. return self.plot(
  1600. *args, **{k: v for k, v in kwargs.items() if k not in d})
  1601. @_preprocess_data(replace_names=["x"], label_namer="x")
  1602. def acorr(self, x, **kwargs):
  1603. """
  1604. Plot the autocorrelation of *x*.
  1605. Parameters
  1606. ----------
  1607. x : array-like
  1608. Not run through Matplotlib's unit conversion, so this should
  1609. be a unit-less array.
  1610. detrend : callable, default: `.mlab.detrend_none` (no detrending)
  1611. A detrending function applied to *x*. It must have the
  1612. signature ::
  1613. detrend(x: np.ndarray) -> np.ndarray
  1614. normed : bool, default: True
  1615. If ``True``, input vectors are normalised to unit length.
  1616. usevlines : bool, default: True
  1617. Determines the plot style.
  1618. If ``True``, vertical lines are plotted from 0 to the acorr value
  1619. using `.Axes.vlines`. Additionally, a horizontal line is plotted
  1620. at y=0 using `.Axes.axhline`.
  1621. If ``False``, markers are plotted at the acorr values using
  1622. `.Axes.plot`.
  1623. maxlags : int, default: 10
  1624. Number of lags to show. If ``None``, will return all
  1625. ``2 * len(x) - 1`` lags.
  1626. Returns
  1627. -------
  1628. lags : array (length ``2*maxlags+1``)
  1629. The lag vector.
  1630. c : array (length ``2*maxlags+1``)
  1631. The auto correlation vector.
  1632. line : `.LineCollection` or `.Line2D`
  1633. `.Artist` added to the Axes of the correlation:
  1634. - `.LineCollection` if *usevlines* is True.
  1635. - `.Line2D` if *usevlines* is False.
  1636. b : `~matplotlib.lines.Line2D` or None
  1637. Horizontal line at 0 if *usevlines* is True
  1638. None *usevlines* is False.
  1639. Other Parameters
  1640. ----------------
  1641. linestyle : `~matplotlib.lines.Line2D` property, optional
  1642. The linestyle for plotting the data points.
  1643. Only used if *usevlines* is ``False``.
  1644. marker : str, default: 'o'
  1645. The marker for plotting the data points.
  1646. Only used if *usevlines* is ``False``.
  1647. data : indexable object, optional
  1648. DATA_PARAMETER_PLACEHOLDER
  1649. **kwargs
  1650. Additional parameters are passed to `.Axes.vlines` and
  1651. `.Axes.axhline` if *usevlines* is ``True``; otherwise they are
  1652. passed to `.Axes.plot`.
  1653. Notes
  1654. -----
  1655. The cross correlation is performed with `numpy.correlate` with
  1656. ``mode = "full"``.
  1657. """
  1658. return self.xcorr(x, x, **kwargs)
  1659. @_api.make_keyword_only("3.10", "normed")
  1660. @_preprocess_data(replace_names=["x", "y"], label_namer="y")
  1661. def xcorr(self, x, y, normed=True, detrend=mlab.detrend_none,
  1662. usevlines=True, maxlags=10, **kwargs):
  1663. r"""
  1664. Plot the cross correlation between *x* and *y*.
  1665. The correlation with lag k is defined as
  1666. :math:`\sum_n x[n+k] \cdot y^*[n]`, where :math:`y^*` is the complex
  1667. conjugate of :math:`y`.
  1668. Parameters
  1669. ----------
  1670. x, y : array-like of length n
  1671. Neither *x* nor *y* are run through Matplotlib's unit conversion, so
  1672. these should be unit-less arrays.
  1673. detrend : callable, default: `.mlab.detrend_none` (no detrending)
  1674. A detrending function applied to *x* and *y*. It must have the
  1675. signature ::
  1676. detrend(x: np.ndarray) -> np.ndarray
  1677. normed : bool, default: True
  1678. If ``True``, input vectors are normalised to unit length.
  1679. usevlines : bool, default: True
  1680. Determines the plot style.
  1681. If ``True``, vertical lines are plotted from 0 to the xcorr value
  1682. using `.Axes.vlines`. Additionally, a horizontal line is plotted
  1683. at y=0 using `.Axes.axhline`.
  1684. If ``False``, markers are plotted at the xcorr values using
  1685. `.Axes.plot`.
  1686. maxlags : int, default: 10
  1687. Number of lags to show. If None, will return all ``2 * len(x) - 1``
  1688. lags.
  1689. Returns
  1690. -------
  1691. lags : array (length ``2*maxlags+1``)
  1692. The lag vector.
  1693. c : array (length ``2*maxlags+1``)
  1694. The auto correlation vector.
  1695. line : `.LineCollection` or `.Line2D`
  1696. `.Artist` added to the Axes of the correlation:
  1697. - `.LineCollection` if *usevlines* is True.
  1698. - `.Line2D` if *usevlines* is False.
  1699. b : `~matplotlib.lines.Line2D` or None
  1700. Horizontal line at 0 if *usevlines* is True
  1701. None *usevlines* is False.
  1702. Other Parameters
  1703. ----------------
  1704. linestyle : `~matplotlib.lines.Line2D` property, optional
  1705. The linestyle for plotting the data points.
  1706. Only used if *usevlines* is ``False``.
  1707. marker : str, default: 'o'
  1708. The marker for plotting the data points.
  1709. Only used if *usevlines* is ``False``.
  1710. data : indexable object, optional
  1711. DATA_PARAMETER_PLACEHOLDER
  1712. **kwargs
  1713. Additional parameters are passed to `.Axes.vlines` and
  1714. `.Axes.axhline` if *usevlines* is ``True``; otherwise they are
  1715. passed to `.Axes.plot`.
  1716. Notes
  1717. -----
  1718. The cross correlation is performed with `numpy.correlate` with
  1719. ``mode = "full"``.
  1720. """
  1721. Nx = len(x)
  1722. if Nx != len(y):
  1723. raise ValueError('x and y must be equal length')
  1724. x = detrend(np.asarray(x))
  1725. y = detrend(np.asarray(y))
  1726. correls = np.correlate(x, y, mode="full")
  1727. if normed:
  1728. correls = correls / np.sqrt(np.dot(x, x) * np.dot(y, y))
  1729. if maxlags is None:
  1730. maxlags = Nx - 1
  1731. if maxlags >= Nx or maxlags < 1:
  1732. raise ValueError('maxlags must be None or strictly '
  1733. 'positive < %d' % Nx)
  1734. lags = np.arange(-maxlags, maxlags + 1)
  1735. correls = correls[Nx - 1 - maxlags:Nx + maxlags]
  1736. if usevlines:
  1737. a = self.vlines(lags, [0], correls, **kwargs)
  1738. # Make label empty so only vertical lines get a legend entry
  1739. kwargs.pop('label', '')
  1740. b = self.axhline(**kwargs)
  1741. else:
  1742. kwargs.setdefault('marker', 'o')
  1743. kwargs.setdefault('linestyle', 'None')
  1744. a, = self.plot(lags, correls, **kwargs)
  1745. b = None
  1746. return lags, correls, a, b
  1747. #### Specialized plotting
  1748. # @_preprocess_data() # let 'plot' do the unpacking..
  1749. def step(self, x, y, *args, where='pre', data=None, **kwargs):
  1750. """
  1751. Make a step plot.
  1752. Call signatures::
  1753. step(x, y, [fmt], *, data=None, where='pre', **kwargs)
  1754. step(x, y, [fmt], x2, y2, [fmt2], ..., *, where='pre', **kwargs)
  1755. This is just a thin wrapper around `.plot` which changes some
  1756. formatting options. Most of the concepts and parameters of plot can be
  1757. used here as well.
  1758. .. note::
  1759. This method uses a standard plot with a step drawstyle: The *x*
  1760. values are the reference positions and steps extend left/right/both
  1761. directions depending on *where*.
  1762. For the common case where you know the values and edges of the
  1763. steps, use `~.Axes.stairs` instead.
  1764. Parameters
  1765. ----------
  1766. x : array-like
  1767. 1D sequence of x positions. It is assumed, but not checked, that
  1768. it is uniformly increasing.
  1769. y : array-like
  1770. 1D sequence of y levels.
  1771. fmt : str, optional
  1772. A format string, e.g. 'g' for a green line. See `.plot` for a more
  1773. detailed description.
  1774. Note: While full format strings are accepted, it is recommended to
  1775. only specify the color. Line styles are currently ignored (use
  1776. the keyword argument *linestyle* instead). Markers are accepted
  1777. and plotted on the given positions, however, this is a rarely
  1778. needed feature for step plots.
  1779. where : {'pre', 'post', 'mid'}, default: 'pre'
  1780. Define where the steps should be placed:
  1781. - 'pre': The y value is continued constantly to the left from
  1782. every *x* position, i.e. the interval ``(x[i-1], x[i]]`` has the
  1783. value ``y[i]``.
  1784. - 'post': The y value is continued constantly to the right from
  1785. every *x* position, i.e. the interval ``[x[i], x[i+1])`` has the
  1786. value ``y[i]``.
  1787. - 'mid': Steps occur half-way between the *x* positions.
  1788. data : indexable object, optional
  1789. An object with labelled data. If given, provide the label names to
  1790. plot in *x* and *y*.
  1791. **kwargs
  1792. Additional parameters are the same as those for `.plot`.
  1793. Returns
  1794. -------
  1795. list of `.Line2D`
  1796. Objects representing the plotted data.
  1797. """
  1798. _api.check_in_list(('pre', 'post', 'mid'), where=where)
  1799. kwargs['drawstyle'] = 'steps-' + where
  1800. return self.plot(x, y, *args, data=data, **kwargs)
  1801. @staticmethod
  1802. def _convert_dx(dx, x0, xconv, convert):
  1803. """
  1804. Small helper to do logic of width conversion flexibly.
  1805. *dx* and *x0* have units, but *xconv* has already been converted
  1806. to unitless (and is an ndarray). This allows the *dx* to have units
  1807. that are different from *x0*, but are still accepted by the
  1808. ``__add__`` operator of *x0*.
  1809. """
  1810. # x should be an array...
  1811. assert type(xconv) is np.ndarray
  1812. if xconv.size == 0:
  1813. # xconv has already been converted, but maybe empty...
  1814. return convert(dx)
  1815. try:
  1816. # attempt to add the width to x0; this works for
  1817. # datetime+timedelta, for instance
  1818. # only use the first element of x and x0. This saves
  1819. # having to be sure addition works across the whole
  1820. # vector. This is particularly an issue if
  1821. # x0 and dx are lists so x0 + dx just concatenates the lists.
  1822. # We can't just cast x0 and dx to numpy arrays because that
  1823. # removes the units from unit packages like `pint` that
  1824. # wrap numpy arrays.
  1825. try:
  1826. x0 = cbook._safe_first_finite(x0)
  1827. except (TypeError, IndexError, KeyError):
  1828. pass
  1829. try:
  1830. x = cbook._safe_first_finite(xconv)
  1831. except (TypeError, IndexError, KeyError):
  1832. x = xconv
  1833. delist = False
  1834. if not np.iterable(dx):
  1835. dx = [dx]
  1836. delist = True
  1837. dx = [convert(x0 + ddx) - x for ddx in dx]
  1838. if delist:
  1839. dx = dx[0]
  1840. except (ValueError, TypeError, AttributeError):
  1841. # if the above fails (for any reason) just fallback to what
  1842. # we do by default and convert dx by itself.
  1843. dx = convert(dx)
  1844. return dx
  1845. def _parse_bar_color_args(self, kwargs):
  1846. """
  1847. Helper function to process color-related arguments of `.Axes.bar`.
  1848. Argument precedence for facecolors:
  1849. - kwargs['facecolor']
  1850. - kwargs['color']
  1851. - 'Result of ``self._get_patches_for_fill.get_next_color``
  1852. Argument precedence for edgecolors:
  1853. - kwargs['edgecolor']
  1854. - None
  1855. Parameters
  1856. ----------
  1857. self : Axes
  1858. kwargs : dict
  1859. Additional kwargs. If these keys exist, we pop and process them:
  1860. 'facecolor', 'edgecolor', 'color'
  1861. Note: The dict is modified by this function.
  1862. Returns
  1863. -------
  1864. facecolor
  1865. The facecolor. One or more colors as (N, 4) rgba array.
  1866. edgecolor
  1867. The edgecolor. Not normalized; may be any valid color spec or None.
  1868. """
  1869. color = kwargs.pop('color', None)
  1870. facecolor = kwargs.pop('facecolor', color)
  1871. edgecolor = kwargs.pop('edgecolor', None)
  1872. facecolor = (facecolor if facecolor is not None
  1873. else self._get_patches_for_fill.get_next_color())
  1874. try:
  1875. facecolor = mcolors.to_rgba_array(facecolor)
  1876. except ValueError as err:
  1877. raise ValueError(
  1878. "'facecolor' or 'color' argument must be a valid color or "
  1879. "sequence of colors."
  1880. ) from err
  1881. return facecolor, edgecolor
  1882. @_preprocess_data()
  1883. @_docstring.interpd
  1884. def bar(self, x, height, width=0.8, bottom=None, *, align="center",
  1885. **kwargs):
  1886. r"""
  1887. Make a bar plot.
  1888. The bars are positioned at *x* with the given *align*\ment. Their
  1889. dimensions are given by *height* and *width*. The vertical baseline
  1890. is *bottom* (default 0).
  1891. Many parameters can take either a single value applying to all bars
  1892. or a sequence of values, one for each bar.
  1893. Parameters
  1894. ----------
  1895. x : float or array-like
  1896. The x coordinates of the bars. See also *align* for the
  1897. alignment of the bars to the coordinates.
  1898. Bars are often used for categorical data, i.e. string labels below
  1899. the bars. You can provide a list of strings directly to *x*.
  1900. ``bar(['A', 'B', 'C'], [1, 2, 3])`` is often a shorter and more
  1901. convenient notation compared to
  1902. ``bar(range(3), [1, 2, 3], tick_label=['A', 'B', 'C'])``. They are
  1903. equivalent as long as the names are unique. The explicit *tick_label*
  1904. notation draws the names in the sequence given. However, when having
  1905. duplicate values in categorical *x* data, these values map to the same
  1906. numerical x coordinate, and hence the corresponding bars are drawn on
  1907. top of each other.
  1908. height : float or array-like
  1909. The height(s) of the bars.
  1910. Note that if *bottom* has units (e.g. datetime), *height* should be in
  1911. units that are a difference from the value of *bottom* (e.g. timedelta).
  1912. width : float or array-like, default: 0.8
  1913. The width(s) of the bars.
  1914. Note that if *x* has units (e.g. datetime), then *width* should be in
  1915. units that are a difference (e.g. timedelta) around the *x* values.
  1916. bottom : float or array-like, default: 0
  1917. The y coordinate(s) of the bottom side(s) of the bars.
  1918. Note that if *bottom* has units, then the y-axis will get a Locator and
  1919. Formatter appropriate for the units (e.g. dates, or categorical).
  1920. align : {'center', 'edge'}, default: 'center'
  1921. Alignment of the bars to the *x* coordinates:
  1922. - 'center': Center the base on the *x* positions.
  1923. - 'edge': Align the left edges of the bars with the *x* positions.
  1924. To align the bars on the right edge pass a negative *width* and
  1925. ``align='edge'``.
  1926. Returns
  1927. -------
  1928. `.BarContainer`
  1929. Container with all the bars and optionally errorbars.
  1930. Other Parameters
  1931. ----------------
  1932. color : :mpltype:`color` or list of :mpltype:`color`, optional
  1933. The colors of the bar faces. This is an alias for *facecolor*.
  1934. If both are given, *facecolor* takes precedence.
  1935. facecolor : :mpltype:`color` or list of :mpltype:`color`, optional
  1936. The colors of the bar faces.
  1937. If both *color* and *facecolor are given, *facecolor* takes precedence.
  1938. edgecolor : :mpltype:`color` or list of :mpltype:`color`, optional
  1939. The colors of the bar edges.
  1940. linewidth : float or array-like, optional
  1941. Width of the bar edge(s). If 0, don't draw edges.
  1942. tick_label : str or list of str, optional
  1943. The tick labels of the bars.
  1944. Default: None (Use default numeric labels.)
  1945. label : str or list of str, optional
  1946. A single label is attached to the resulting `.BarContainer` as a
  1947. label for the whole dataset.
  1948. If a list is provided, it must be the same length as *x* and
  1949. labels the individual bars. Repeated labels are not de-duplicated
  1950. and will cause repeated label entries, so this is best used when
  1951. bars also differ in style (e.g., by passing a list to *color*.)
  1952. xerr, yerr : float or array-like of shape(N,) or shape(2, N), optional
  1953. If not *None*, add horizontal / vertical errorbars to the bar tips.
  1954. The values are +/- sizes relative to the data:
  1955. - scalar: symmetric +/- values for all bars
  1956. - shape(N,): symmetric +/- values for each bar
  1957. - shape(2, N): Separate - and + values for each bar. First row
  1958. contains the lower errors, the second row contains the upper
  1959. errors.
  1960. - *None*: No errorbar. (Default)
  1961. See :doc:`/gallery/statistics/errorbar_features` for an example on
  1962. the usage of *xerr* and *yerr*.
  1963. ecolor : :mpltype:`color` or list of :mpltype:`color`, default: 'black'
  1964. The line color of the errorbars.
  1965. capsize : float, default: :rc:`errorbar.capsize`
  1966. The length of the error bar caps in points.
  1967. error_kw : dict, optional
  1968. Dictionary of keyword arguments to be passed to the
  1969. `~.Axes.errorbar` method. Values of *ecolor* or *capsize* defined
  1970. here take precedence over the independent keyword arguments.
  1971. log : bool, default: False
  1972. If *True*, set the y-axis to be log scale.
  1973. data : indexable object, optional
  1974. DATA_PARAMETER_PLACEHOLDER
  1975. **kwargs : `.Rectangle` properties
  1976. %(Rectangle:kwdoc)s
  1977. See Also
  1978. --------
  1979. barh : Plot a horizontal bar plot.
  1980. Notes
  1981. -----
  1982. Stacked bars can be achieved by passing individual *bottom* values per
  1983. bar. See :doc:`/gallery/lines_bars_and_markers/bar_stacked`.
  1984. """
  1985. kwargs = cbook.normalize_kwargs(kwargs, mpatches.Patch)
  1986. facecolor, edgecolor = self._parse_bar_color_args(kwargs)
  1987. linewidth = kwargs.pop('linewidth', None)
  1988. hatch = kwargs.pop('hatch', None)
  1989. # Because xerr and yerr will be passed to errorbar, most dimension
  1990. # checking and processing will be left to the errorbar method.
  1991. xerr = kwargs.pop('xerr', None)
  1992. yerr = kwargs.pop('yerr', None)
  1993. error_kw = kwargs.pop('error_kw', None)
  1994. error_kw = {} if error_kw is None else error_kw.copy()
  1995. ezorder = error_kw.pop('zorder', None)
  1996. if ezorder is None:
  1997. ezorder = kwargs.get('zorder', None)
  1998. if ezorder is not None:
  1999. # If using the bar zorder, increment slightly to make sure
  2000. # errorbars are drawn on top of bars
  2001. ezorder += 0.01
  2002. error_kw.setdefault('zorder', ezorder)
  2003. ecolor = kwargs.pop('ecolor', 'k')
  2004. capsize = kwargs.pop('capsize', mpl.rcParams["errorbar.capsize"])
  2005. error_kw.setdefault('ecolor', ecolor)
  2006. error_kw.setdefault('capsize', capsize)
  2007. # The keyword argument *orientation* is used by barh() to defer all
  2008. # logic and drawing to bar(). It is considered internal and is
  2009. # intentionally not mentioned in the docstring.
  2010. orientation = kwargs.pop('orientation', 'vertical')
  2011. _api.check_in_list(['vertical', 'horizontal'], orientation=orientation)
  2012. log = kwargs.pop('log', False)
  2013. label = kwargs.pop('label', '')
  2014. tick_labels = kwargs.pop('tick_label', None)
  2015. y = bottom # Matches barh call signature.
  2016. if orientation == 'vertical':
  2017. if y is None:
  2018. y = 0
  2019. else: # horizontal
  2020. if x is None:
  2021. x = 0
  2022. if orientation == 'vertical':
  2023. # It is possible for y (bottom) to contain unit information.
  2024. # However, it is also possible for y=0 for the default and height
  2025. # to contain unit information. This will prioritize the units of y.
  2026. self._process_unit_info(
  2027. [("x", x), ("y", y), ("y", height)], kwargs, convert=False)
  2028. if log:
  2029. self.set_yscale('log', nonpositive='clip')
  2030. else: # horizontal
  2031. # It is possible for x (left) to contain unit information.
  2032. # However, it is also possible for x=0 for the default and width
  2033. # to contain unit information. This will prioritize the units of x.
  2034. self._process_unit_info(
  2035. [("x", x), ("x", width), ("y", y)], kwargs, convert=False)
  2036. if log:
  2037. self.set_xscale('log', nonpositive='clip')
  2038. # lets do some conversions now since some types cannot be
  2039. # subtracted uniformly
  2040. if self.xaxis is not None:
  2041. x0 = x
  2042. x = np.asarray(self.convert_xunits(x))
  2043. width = self._convert_dx(width, x0, x, self.convert_xunits)
  2044. if xerr is not None:
  2045. xerr = self._convert_dx(xerr, x0, x, self.convert_xunits)
  2046. if self.yaxis is not None:
  2047. y0 = y
  2048. y = np.asarray(self.convert_yunits(y))
  2049. height = self._convert_dx(height, y0, y, self.convert_yunits)
  2050. if yerr is not None:
  2051. yerr = self._convert_dx(yerr, y0, y, self.convert_yunits)
  2052. x, height, width, y, linewidth, hatch = np.broadcast_arrays(
  2053. # Make args iterable too.
  2054. np.atleast_1d(x), height, width, y, linewidth, hatch)
  2055. # Now that units have been converted, set the tick locations.
  2056. if orientation == 'vertical':
  2057. tick_label_axis = self.xaxis
  2058. tick_label_position = x
  2059. else: # horizontal
  2060. tick_label_axis = self.yaxis
  2061. tick_label_position = y
  2062. if not isinstance(label, str) and np.iterable(label):
  2063. bar_container_label = '_nolegend_'
  2064. patch_labels = label
  2065. else:
  2066. bar_container_label = label
  2067. patch_labels = ['_nolegend_'] * len(x)
  2068. if len(patch_labels) != len(x):
  2069. raise ValueError(f'number of labels ({len(patch_labels)}) '
  2070. f'does not match number of bars ({len(x)}).')
  2071. linewidth = itertools.cycle(np.atleast_1d(linewidth))
  2072. hatch = itertools.cycle(np.atleast_1d(hatch))
  2073. facecolor = itertools.chain(itertools.cycle(facecolor),
  2074. # Fallback if color == "none".
  2075. itertools.repeat('none'))
  2076. if edgecolor is None:
  2077. edgecolor = itertools.repeat(None)
  2078. else:
  2079. edgecolor = itertools.chain(
  2080. itertools.cycle(mcolors.to_rgba_array(edgecolor)),
  2081. # Fallback if edgecolor == "none".
  2082. itertools.repeat('none'))
  2083. # We will now resolve the alignment and really have
  2084. # left, bottom, width, height vectors
  2085. _api.check_in_list(['center', 'edge'], align=align)
  2086. if align == 'center':
  2087. if orientation == 'vertical':
  2088. try:
  2089. left = x - width / 2
  2090. except TypeError as e:
  2091. raise TypeError(f'the dtypes of parameters x ({x.dtype}) '
  2092. f'and width ({width.dtype}) '
  2093. f'are incompatible') from e
  2094. bottom = y
  2095. else: # horizontal
  2096. try:
  2097. bottom = y - height / 2
  2098. except TypeError as e:
  2099. raise TypeError(f'the dtypes of parameters y ({y.dtype}) '
  2100. f'and height ({height.dtype}) '
  2101. f'are incompatible') from e
  2102. left = x
  2103. else: # edge
  2104. left = x
  2105. bottom = y
  2106. patches = []
  2107. args = zip(left, bottom, width, height, facecolor, edgecolor, linewidth,
  2108. hatch, patch_labels)
  2109. for l, b, w, h, c, e, lw, htch, lbl in args:
  2110. r = mpatches.Rectangle(
  2111. xy=(l, b), width=w, height=h,
  2112. facecolor=c,
  2113. edgecolor=e,
  2114. linewidth=lw,
  2115. label=lbl,
  2116. hatch=htch,
  2117. )
  2118. r._internal_update(kwargs)
  2119. r.get_path()._interpolation_steps = 100
  2120. if orientation == 'vertical':
  2121. r.sticky_edges.y.append(b)
  2122. else: # horizontal
  2123. r.sticky_edges.x.append(l)
  2124. self.add_patch(r)
  2125. patches.append(r)
  2126. if xerr is not None or yerr is not None:
  2127. if orientation == 'vertical':
  2128. # using list comps rather than arrays to preserve unit info
  2129. ex = [l + 0.5 * w for l, w in zip(left, width)]
  2130. ey = [b + h for b, h in zip(bottom, height)]
  2131. else: # horizontal
  2132. # using list comps rather than arrays to preserve unit info
  2133. ex = [l + w for l, w in zip(left, width)]
  2134. ey = [b + 0.5 * h for b, h in zip(bottom, height)]
  2135. error_kw.setdefault("label", '_nolegend_')
  2136. errorbar = self.errorbar(ex, ey, yerr=yerr, xerr=xerr, fmt='none',
  2137. **error_kw)
  2138. else:
  2139. errorbar = None
  2140. self._request_autoscale_view()
  2141. if orientation == 'vertical':
  2142. datavalues = height
  2143. else: # horizontal
  2144. datavalues = width
  2145. bar_container = BarContainer(patches, errorbar, datavalues=datavalues,
  2146. orientation=orientation,
  2147. label=bar_container_label)
  2148. self.add_container(bar_container)
  2149. if tick_labels is not None:
  2150. tick_labels = np.broadcast_to(tick_labels, len(patches))
  2151. tick_label_axis.set_ticks(tick_label_position)
  2152. tick_label_axis.set_ticklabels(tick_labels)
  2153. return bar_container
  2154. # @_preprocess_data() # let 'bar' do the unpacking..
  2155. @_docstring.interpd
  2156. def barh(self, y, width, height=0.8, left=None, *, align="center",
  2157. data=None, **kwargs):
  2158. r"""
  2159. Make a horizontal bar plot.
  2160. The bars are positioned at *y* with the given *align*\ment. Their
  2161. dimensions are given by *width* and *height*. The horizontal baseline
  2162. is *left* (default 0).
  2163. Many parameters can take either a single value applying to all bars
  2164. or a sequence of values, one for each bar.
  2165. Parameters
  2166. ----------
  2167. y : float or array-like
  2168. The y coordinates of the bars. See also *align* for the
  2169. alignment of the bars to the coordinates.
  2170. Bars are often used for categorical data, i.e. string labels below
  2171. the bars. You can provide a list of strings directly to *y*.
  2172. ``barh(['A', 'B', 'C'], [1, 2, 3])`` is often a shorter and more
  2173. convenient notation compared to
  2174. ``barh(range(3), [1, 2, 3], tick_label=['A', 'B', 'C'])``. They are
  2175. equivalent as long as the names are unique. The explicit *tick_label*
  2176. notation draws the names in the sequence given. However, when having
  2177. duplicate values in categorical *y* data, these values map to the same
  2178. numerical y coordinate, and hence the corresponding bars are drawn on
  2179. top of each other.
  2180. width : float or array-like
  2181. The width(s) of the bars.
  2182. Note that if *left* has units (e.g. datetime), *width* should be in
  2183. units that are a difference from the value of *left* (e.g. timedelta).
  2184. height : float or array-like, default: 0.8
  2185. The heights of the bars.
  2186. Note that if *y* has units (e.g. datetime), then *height* should be in
  2187. units that are a difference (e.g. timedelta) around the *y* values.
  2188. left : float or array-like, default: 0
  2189. The x coordinates of the left side(s) of the bars.
  2190. Note that if *left* has units, then the x-axis will get a Locator and
  2191. Formatter appropriate for the units (e.g. dates, or categorical).
  2192. align : {'center', 'edge'}, default: 'center'
  2193. Alignment of the base to the *y* coordinates*:
  2194. - 'center': Center the bars on the *y* positions.
  2195. - 'edge': Align the bottom edges of the bars with the *y*
  2196. positions.
  2197. To align the bars on the top edge pass a negative *height* and
  2198. ``align='edge'``.
  2199. Returns
  2200. -------
  2201. `.BarContainer`
  2202. Container with all the bars and optionally errorbars.
  2203. Other Parameters
  2204. ----------------
  2205. color : :mpltype:`color` or list of :mpltype:`color`, optional
  2206. The colors of the bar faces.
  2207. edgecolor : :mpltype:`color` or list of :mpltype:`color`, optional
  2208. The colors of the bar edges.
  2209. linewidth : float or array-like, optional
  2210. Width of the bar edge(s). If 0, don't draw edges.
  2211. tick_label : str or list of str, optional
  2212. The tick labels of the bars.
  2213. Default: None (Use default numeric labels.)
  2214. label : str or list of str, optional
  2215. A single label is attached to the resulting `.BarContainer` as a
  2216. label for the whole dataset.
  2217. If a list is provided, it must be the same length as *y* and
  2218. labels the individual bars. Repeated labels are not de-duplicated
  2219. and will cause repeated label entries, so this is best used when
  2220. bars also differ in style (e.g., by passing a list to *color*.)
  2221. xerr, yerr : float or array-like of shape(N,) or shape(2, N), optional
  2222. If not *None*, add horizontal / vertical errorbars to the bar tips.
  2223. The values are +/- sizes relative to the data:
  2224. - scalar: symmetric +/- values for all bars
  2225. - shape(N,): symmetric +/- values for each bar
  2226. - shape(2, N): Separate - and + values for each bar. First row
  2227. contains the lower errors, the second row contains the upper
  2228. errors.
  2229. - *None*: No errorbar. (default)
  2230. See :doc:`/gallery/statistics/errorbar_features` for an example on
  2231. the usage of *xerr* and *yerr*.
  2232. ecolor : :mpltype:`color` or list of :mpltype:`color`, default: 'black'
  2233. The line color of the errorbars.
  2234. capsize : float, default: :rc:`errorbar.capsize`
  2235. The length of the error bar caps in points.
  2236. error_kw : dict, optional
  2237. Dictionary of keyword arguments to be passed to the
  2238. `~.Axes.errorbar` method. Values of *ecolor* or *capsize* defined
  2239. here take precedence over the independent keyword arguments.
  2240. log : bool, default: False
  2241. If ``True``, set the x-axis to be log scale.
  2242. data : indexable object, optional
  2243. If given, all parameters also accept a string ``s``, which is
  2244. interpreted as ``data[s]`` if ``s`` is a key in ``data``.
  2245. **kwargs : `.Rectangle` properties
  2246. %(Rectangle:kwdoc)s
  2247. See Also
  2248. --------
  2249. bar : Plot a vertical bar plot.
  2250. Notes
  2251. -----
  2252. Stacked bars can be achieved by passing individual *left* values per
  2253. bar. See
  2254. :doc:`/gallery/lines_bars_and_markers/horizontal_barchart_distribution`.
  2255. """
  2256. kwargs.setdefault('orientation', 'horizontal')
  2257. patches = self.bar(x=left, height=height, width=width, bottom=y,
  2258. align=align, data=data, **kwargs)
  2259. return patches
  2260. def bar_label(self, container, labels=None, *, fmt="%g", label_type="edge",
  2261. padding=0, **kwargs):
  2262. """
  2263. Label a bar plot.
  2264. Adds labels to bars in the given `.BarContainer`.
  2265. You may need to adjust the axis limits to fit the labels.
  2266. Parameters
  2267. ----------
  2268. container : `.BarContainer`
  2269. Container with all the bars and optionally errorbars, likely
  2270. returned from `.bar` or `.barh`.
  2271. labels : array-like, optional
  2272. A list of label texts, that should be displayed. If not given, the
  2273. label texts will be the data values formatted with *fmt*.
  2274. fmt : str or callable, default: '%g'
  2275. An unnamed %-style or {}-style format string for the label or a
  2276. function to call with the value as the first argument.
  2277. When *fmt* is a string and can be interpreted in both formats,
  2278. %-style takes precedence over {}-style.
  2279. .. versionadded:: 3.7
  2280. Support for {}-style format string and callables.
  2281. label_type : {'edge', 'center'}, default: 'edge'
  2282. The label type. Possible values:
  2283. - 'edge': label placed at the end-point of the bar segment, and the
  2284. value displayed will be the position of that end-point.
  2285. - 'center': label placed in the center of the bar segment, and the
  2286. value displayed will be the length of that segment.
  2287. (useful for stacked bars, i.e.,
  2288. :doc:`/gallery/lines_bars_and_markers/bar_label_demo`)
  2289. padding : float, default: 0
  2290. Distance of label from the end of the bar, in points.
  2291. **kwargs
  2292. Any remaining keyword arguments are passed through to
  2293. `.Axes.annotate`. The alignment parameters (
  2294. *horizontalalignment* / *ha*, *verticalalignment* / *va*) are
  2295. not supported because the labels are automatically aligned to
  2296. the bars.
  2297. Returns
  2298. -------
  2299. list of `.Annotation`
  2300. A list of `.Annotation` instances for the labels.
  2301. """
  2302. for key in ['horizontalalignment', 'ha', 'verticalalignment', 'va']:
  2303. if key in kwargs:
  2304. raise ValueError(
  2305. f"Passing {key!r} to bar_label() is not supported.")
  2306. a, b = self.yaxis.get_view_interval()
  2307. y_inverted = a > b
  2308. c, d = self.xaxis.get_view_interval()
  2309. x_inverted = c > d
  2310. # want to know whether to put label on positive or negative direction
  2311. # cannot use np.sign here because it will return 0 if x == 0
  2312. def sign(x):
  2313. return 1 if x >= 0 else -1
  2314. _api.check_in_list(['edge', 'center'], label_type=label_type)
  2315. bars = container.patches
  2316. errorbar = container.errorbar
  2317. datavalues = container.datavalues
  2318. orientation = container.orientation
  2319. if errorbar:
  2320. # check "ErrorbarContainer" for the definition of these elements
  2321. lines = errorbar.lines # attribute of "ErrorbarContainer" (tuple)
  2322. barlinecols = lines[2] # 0: data_line, 1: caplines, 2: barlinecols
  2323. barlinecol = barlinecols[0] # the "LineCollection" of error bars
  2324. errs = barlinecol.get_segments()
  2325. else:
  2326. errs = []
  2327. if labels is None:
  2328. labels = []
  2329. annotations = []
  2330. for bar, err, dat, lbl in itertools.zip_longest(
  2331. bars, errs, datavalues, labels
  2332. ):
  2333. (x0, y0), (x1, y1) = bar.get_bbox().get_points()
  2334. xc, yc = (x0 + x1) / 2, (y0 + y1) / 2
  2335. if orientation == "vertical":
  2336. extrema = max(y0, y1) if dat >= 0 else min(y0, y1)
  2337. length = abs(y0 - y1)
  2338. else: # horizontal
  2339. extrema = max(x0, x1) if dat >= 0 else min(x0, x1)
  2340. length = abs(x0 - x1)
  2341. if err is None or np.size(err) == 0:
  2342. endpt = extrema
  2343. elif orientation == "vertical":
  2344. endpt = err[:, 1].max() if dat >= 0 else err[:, 1].min()
  2345. else: # horizontal
  2346. endpt = err[:, 0].max() if dat >= 0 else err[:, 0].min()
  2347. if label_type == "center":
  2348. value = sign(dat) * length
  2349. else: # edge
  2350. value = extrema
  2351. if label_type == "center":
  2352. xy = (0.5, 0.5)
  2353. kwargs["xycoords"] = (
  2354. lambda r, b=bar:
  2355. mtransforms.Bbox.intersection(
  2356. b.get_window_extent(r), b.get_clip_box()
  2357. ) or mtransforms.Bbox.null()
  2358. )
  2359. else: # edge
  2360. if orientation == "vertical":
  2361. xy = xc, endpt
  2362. else: # horizontal
  2363. xy = endpt, yc
  2364. if orientation == "vertical":
  2365. y_direction = -1 if y_inverted else 1
  2366. xytext = 0, y_direction * sign(dat) * padding
  2367. else: # horizontal
  2368. x_direction = -1 if x_inverted else 1
  2369. xytext = x_direction * sign(dat) * padding, 0
  2370. if label_type == "center":
  2371. ha, va = "center", "center"
  2372. else: # edge
  2373. if orientation == "vertical":
  2374. ha = 'center'
  2375. if y_inverted:
  2376. va = 'top' if dat > 0 else 'bottom' # also handles NaN
  2377. else:
  2378. va = 'top' if dat < 0 else 'bottom' # also handles NaN
  2379. else: # horizontal
  2380. if x_inverted:
  2381. ha = 'right' if dat > 0 else 'left' # also handles NaN
  2382. else:
  2383. ha = 'right' if dat < 0 else 'left' # also handles NaN
  2384. va = 'center'
  2385. if np.isnan(dat):
  2386. lbl = ''
  2387. if lbl is None:
  2388. if isinstance(fmt, str):
  2389. lbl = cbook._auto_format_str(fmt, value)
  2390. elif callable(fmt):
  2391. lbl = fmt(value)
  2392. else:
  2393. raise TypeError("fmt must be a str or callable")
  2394. annotation = self.annotate(lbl,
  2395. xy, xytext, textcoords="offset points",
  2396. ha=ha, va=va, **kwargs)
  2397. annotations.append(annotation)
  2398. return annotations
  2399. @_preprocess_data()
  2400. @_docstring.interpd
  2401. def broken_barh(self, xranges, yrange, **kwargs):
  2402. """
  2403. Plot a horizontal sequence of rectangles.
  2404. A rectangle is drawn for each element of *xranges*. All rectangles
  2405. have the same vertical position and size defined by *yrange*.
  2406. Parameters
  2407. ----------
  2408. xranges : sequence of tuples (*xmin*, *xwidth*)
  2409. The x-positions and extents of the rectangles. For each tuple
  2410. (*xmin*, *xwidth*) a rectangle is drawn from *xmin* to *xmin* +
  2411. *xwidth*.
  2412. yrange : (*ymin*, *yheight*)
  2413. The y-position and extent for all the rectangles.
  2414. Returns
  2415. -------
  2416. `~.collections.PolyCollection`
  2417. Other Parameters
  2418. ----------------
  2419. data : indexable object, optional
  2420. DATA_PARAMETER_PLACEHOLDER
  2421. **kwargs : `.PolyCollection` properties
  2422. Each *kwarg* can be either a single argument applying to all
  2423. rectangles, e.g.::
  2424. facecolors='black'
  2425. or a sequence of arguments over which is cycled, e.g.::
  2426. facecolors=('black', 'blue')
  2427. would create interleaving black and blue rectangles.
  2428. Supported keywords:
  2429. %(PolyCollection:kwdoc)s
  2430. """
  2431. # process the unit information
  2432. xdata = cbook._safe_first_finite(xranges) if len(xranges) else None
  2433. ydata = cbook._safe_first_finite(yrange) if len(yrange) else None
  2434. self._process_unit_info(
  2435. [("x", xdata), ("y", ydata)], kwargs, convert=False)
  2436. vertices = []
  2437. y0, dy = yrange
  2438. y0, y1 = self.convert_yunits((y0, y0 + dy))
  2439. for xr in xranges: # convert the absolute values, not the x and dx
  2440. try:
  2441. x0, dx = xr
  2442. except Exception:
  2443. raise ValueError(
  2444. "each range in xrange must be a sequence with two "
  2445. "elements (i.e. xrange must be an (N, 2) array)") from None
  2446. x0, x1 = self.convert_xunits((x0, x0 + dx))
  2447. vertices.append([(x0, y0), (x0, y1), (x1, y1), (x1, y0)])
  2448. col = mcoll.PolyCollection(np.array(vertices), **kwargs)
  2449. self.add_collection(col, autolim=True)
  2450. self._request_autoscale_view()
  2451. return col
  2452. @_preprocess_data()
  2453. def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0,
  2454. label=None, orientation='vertical'):
  2455. """
  2456. Create a stem plot.
  2457. A stem plot draws lines perpendicular to a baseline at each location
  2458. *locs* from the baseline to *heads*, and places a marker there. For
  2459. vertical stem plots (the default), the *locs* are *x* positions, and
  2460. the *heads* are *y* values. For horizontal stem plots, the *locs* are
  2461. *y* positions, and the *heads* are *x* values.
  2462. Call signature::
  2463. stem([locs,] heads, linefmt=None, markerfmt=None, basefmt=None)
  2464. The *locs*-positions are optional. *linefmt* may be provided as
  2465. positional, but all other formats must be provided as keyword
  2466. arguments.
  2467. Parameters
  2468. ----------
  2469. locs : array-like, default: (0, 1, ..., len(heads) - 1)
  2470. For vertical stem plots, the x-positions of the stems.
  2471. For horizontal stem plots, the y-positions of the stems.
  2472. heads : array-like
  2473. For vertical stem plots, the y-values of the stem heads.
  2474. For horizontal stem plots, the x-values of the stem heads.
  2475. linefmt : str, optional
  2476. A string defining the color and/or linestyle of the vertical lines:
  2477. ========= =============
  2478. Character Line Style
  2479. ========= =============
  2480. ``'-'`` solid line
  2481. ``'--'`` dashed line
  2482. ``'-.'`` dash-dot line
  2483. ``':'`` dotted line
  2484. ========= =============
  2485. Default: 'C0-', i.e. solid line with the first color of the color
  2486. cycle.
  2487. Note: Markers specified through this parameter (e.g. 'x') will be
  2488. silently ignored. Instead, markers should be specified using
  2489. *markerfmt*.
  2490. markerfmt : str, optional
  2491. A string defining the color and/or shape of the markers at the stem
  2492. heads. If the marker is not given, use the marker 'o', i.e. filled
  2493. circles. If the color is not given, use the color from *linefmt*.
  2494. basefmt : str, default: 'C3-' ('C2-' in classic mode)
  2495. A format string defining the properties of the baseline.
  2496. orientation : {'vertical', 'horizontal'}, default: 'vertical'
  2497. The orientation of the stems.
  2498. bottom : float, default: 0
  2499. The y/x-position of the baseline (depending on *orientation*).
  2500. label : str, optional
  2501. The label to use for the stems in legends.
  2502. data : indexable object, optional
  2503. DATA_PARAMETER_PLACEHOLDER
  2504. Returns
  2505. -------
  2506. `.StemContainer`
  2507. The container may be treated like a tuple
  2508. (*markerline*, *stemlines*, *baseline*)
  2509. Notes
  2510. -----
  2511. .. seealso::
  2512. The MATLAB function
  2513. `stem <https://www.mathworks.com/help/matlab/ref/stem.html>`_
  2514. which inspired this method.
  2515. """
  2516. if not 1 <= len(args) <= 3:
  2517. raise _api.nargs_error('stem', '1-3', len(args))
  2518. _api.check_in_list(['horizontal', 'vertical'], orientation=orientation)
  2519. if len(args) == 1:
  2520. heads, = args
  2521. locs = np.arange(len(heads))
  2522. args = ()
  2523. elif isinstance(args[1], str):
  2524. heads, *args = args
  2525. locs = np.arange(len(heads))
  2526. else:
  2527. locs, heads, *args = args
  2528. if orientation == 'vertical':
  2529. locs, heads = self._process_unit_info([("x", locs), ("y", heads)])
  2530. else: # horizontal
  2531. heads, locs = self._process_unit_info([("x", heads), ("y", locs)])
  2532. heads = cbook._check_1d(heads)
  2533. locs = cbook._check_1d(locs)
  2534. # resolve line format
  2535. if linefmt is None:
  2536. linefmt = args[0] if len(args) > 0 else "C0-"
  2537. linestyle, linemarker, linecolor = _process_plot_format(linefmt)
  2538. # resolve marker format
  2539. if markerfmt is None:
  2540. # if not given as kwarg, fall back to 'o'
  2541. markerfmt = "o"
  2542. if markerfmt == '':
  2543. markerfmt = ' ' # = empty line style; '' would resolve rcParams
  2544. markerstyle, markermarker, markercolor = \
  2545. _process_plot_format(markerfmt)
  2546. if markermarker is None:
  2547. markermarker = 'o'
  2548. if markerstyle is None:
  2549. markerstyle = 'None'
  2550. if markercolor is None:
  2551. markercolor = linecolor
  2552. # resolve baseline format
  2553. if basefmt is None:
  2554. basefmt = ("C2-" if mpl.rcParams["_internal.classic_mode"] else
  2555. "C3-")
  2556. basestyle, basemarker, basecolor = _process_plot_format(basefmt)
  2557. # New behaviour in 3.1 is to use a LineCollection for the stemlines
  2558. if linestyle is None:
  2559. linestyle = mpl.rcParams['lines.linestyle']
  2560. xlines = self.vlines if orientation == "vertical" else self.hlines
  2561. stemlines = xlines(
  2562. locs, bottom, heads,
  2563. colors=linecolor, linestyles=linestyle, label="_nolegend_")
  2564. if orientation == 'horizontal':
  2565. marker_x = heads
  2566. marker_y = locs
  2567. baseline_x = [bottom, bottom]
  2568. baseline_y = [np.min(locs), np.max(locs)]
  2569. else:
  2570. marker_x = locs
  2571. marker_y = heads
  2572. baseline_x = [np.min(locs), np.max(locs)]
  2573. baseline_y = [bottom, bottom]
  2574. markerline, = self.plot(marker_x, marker_y,
  2575. color=markercolor, linestyle=markerstyle,
  2576. marker=markermarker, label="_nolegend_")
  2577. baseline, = self.plot(baseline_x, baseline_y,
  2578. color=basecolor, linestyle=basestyle,
  2579. marker=basemarker, label="_nolegend_")
  2580. stem_container = StemContainer((markerline, stemlines, baseline),
  2581. label=label)
  2582. self.add_container(stem_container)
  2583. return stem_container
  2584. @_api.make_keyword_only("3.10", "explode")
  2585. @_preprocess_data(replace_names=["x", "explode", "labels", "colors"])
  2586. def pie(self, x, explode=None, labels=None, colors=None,
  2587. autopct=None, pctdistance=0.6, shadow=False, labeldistance=1.1,
  2588. startangle=0, radius=1, counterclock=True,
  2589. wedgeprops=None, textprops=None, center=(0, 0),
  2590. frame=False, rotatelabels=False, *, normalize=True, hatch=None):
  2591. """
  2592. Plot a pie chart.
  2593. Make a pie chart of array *x*. The fractional area of each wedge is
  2594. given by ``x/sum(x)``.
  2595. The wedges are plotted counterclockwise, by default starting from the
  2596. x-axis.
  2597. Parameters
  2598. ----------
  2599. x : 1D array-like
  2600. The wedge sizes.
  2601. explode : array-like, default: None
  2602. If not *None*, is a ``len(x)`` array which specifies the fraction
  2603. of the radius with which to offset each wedge.
  2604. labels : list, default: None
  2605. A sequence of strings providing the labels for each wedge
  2606. colors : :mpltype:`color` or list of :mpltype:`color`, default: None
  2607. A sequence of colors through which the pie chart will cycle. If
  2608. *None*, will use the colors in the currently active cycle.
  2609. hatch : str or list, default: None
  2610. Hatching pattern applied to all pie wedges or sequence of patterns
  2611. through which the chart will cycle. For a list of valid patterns,
  2612. see :doc:`/gallery/shapes_and_collections/hatch_style_reference`.
  2613. .. versionadded:: 3.7
  2614. autopct : None or str or callable, default: None
  2615. If not *None*, *autopct* is a string or function used to label the
  2616. wedges with their numeric value. The label will be placed inside
  2617. the wedge. If *autopct* is a format string, the label will be
  2618. ``fmt % pct``. If *autopct* is a function, then it will be called.
  2619. pctdistance : float, default: 0.6
  2620. The relative distance along the radius at which the text
  2621. generated by *autopct* is drawn. To draw the text outside the pie,
  2622. set *pctdistance* > 1. This parameter is ignored if *autopct* is
  2623. ``None``.
  2624. labeldistance : float or None, default: 1.1
  2625. The relative distance along the radius at which the labels are
  2626. drawn. To draw the labels inside the pie, set *labeldistance* < 1.
  2627. If set to ``None``, labels are not drawn but are still stored for
  2628. use in `.legend`.
  2629. shadow : bool or dict, default: False
  2630. If bool, whether to draw a shadow beneath the pie. If dict, draw a shadow
  2631. passing the properties in the dict to `.Shadow`.
  2632. .. versionadded:: 3.8
  2633. *shadow* can be a dict.
  2634. startangle : float, default: 0 degrees
  2635. The angle by which the start of the pie is rotated,
  2636. counterclockwise from the x-axis.
  2637. radius : float, default: 1
  2638. The radius of the pie.
  2639. counterclock : bool, default: True
  2640. Specify fractions direction, clockwise or counterclockwise.
  2641. wedgeprops : dict, default: None
  2642. Dict of arguments passed to each `.patches.Wedge` of the pie.
  2643. For example, ``wedgeprops = {'linewidth': 3}`` sets the width of
  2644. the wedge border lines equal to 3. By default, ``clip_on=False``.
  2645. When there is a conflict between these properties and other
  2646. keywords, properties passed to *wedgeprops* take precedence.
  2647. textprops : dict, default: None
  2648. Dict of arguments to pass to the text objects.
  2649. center : (float, float), default: (0, 0)
  2650. The coordinates of the center of the chart.
  2651. frame : bool, default: False
  2652. Plot Axes frame with the chart if true.
  2653. rotatelabels : bool, default: False
  2654. Rotate each label to the angle of the corresponding slice if true.
  2655. normalize : bool, default: True
  2656. When *True*, always make a full pie by normalizing x so that
  2657. ``sum(x) == 1``. *False* makes a partial pie if ``sum(x) <= 1``
  2658. and raises a `ValueError` for ``sum(x) > 1``.
  2659. data : indexable object, optional
  2660. DATA_PARAMETER_PLACEHOLDER
  2661. Returns
  2662. -------
  2663. patches : list
  2664. A sequence of `matplotlib.patches.Wedge` instances
  2665. texts : list
  2666. A list of the label `.Text` instances.
  2667. autotexts : list
  2668. A list of `.Text` instances for the numeric labels. This will only
  2669. be returned if the parameter *autopct* is not *None*.
  2670. Notes
  2671. -----
  2672. The pie chart will probably look best if the figure and Axes are
  2673. square, or the Axes aspect is equal.
  2674. This method sets the aspect ratio of the axis to "equal".
  2675. The Axes aspect ratio can be controlled with `.Axes.set_aspect`.
  2676. """
  2677. self.set_aspect('equal')
  2678. # The use of float32 is "historical", but can't be changed without
  2679. # regenerating the test baselines.
  2680. x = np.asarray(x, np.float32)
  2681. if x.ndim > 1:
  2682. raise ValueError("x must be 1D")
  2683. if np.any(x < 0):
  2684. raise ValueError("Wedge sizes 'x' must be non negative values")
  2685. sx = x.sum()
  2686. if normalize:
  2687. x = x / sx
  2688. elif sx > 1:
  2689. raise ValueError('Cannot plot an unnormalized pie with sum(x) > 1')
  2690. if labels is None:
  2691. labels = [''] * len(x)
  2692. if explode is None:
  2693. explode = [0] * len(x)
  2694. if len(x) != len(labels):
  2695. raise ValueError(f"'labels' must be of length 'x', not {len(labels)}")
  2696. if len(x) != len(explode):
  2697. raise ValueError(f"'explode' must be of length 'x', not {len(explode)}")
  2698. if colors is None:
  2699. get_next_color = self._get_patches_for_fill.get_next_color
  2700. else:
  2701. color_cycle = itertools.cycle(colors)
  2702. def get_next_color():
  2703. return next(color_cycle)
  2704. hatch_cycle = itertools.cycle(np.atleast_1d(hatch))
  2705. _api.check_isinstance(Real, radius=radius, startangle=startangle)
  2706. if radius <= 0:
  2707. raise ValueError(f"'radius' must be a positive number, not {radius}")
  2708. # Starting theta1 is the start fraction of the circle
  2709. theta1 = startangle / 360
  2710. if wedgeprops is None:
  2711. wedgeprops = {}
  2712. if textprops is None:
  2713. textprops = {}
  2714. texts = []
  2715. slices = []
  2716. autotexts = []
  2717. for frac, label, expl in zip(x, labels, explode):
  2718. x, y = center
  2719. theta2 = (theta1 + frac) if counterclock else (theta1 - frac)
  2720. thetam = 2 * np.pi * 0.5 * (theta1 + theta2)
  2721. x += expl * math.cos(thetam)
  2722. y += expl * math.sin(thetam)
  2723. w = mpatches.Wedge((x, y), radius, 360. * min(theta1, theta2),
  2724. 360. * max(theta1, theta2),
  2725. facecolor=get_next_color(),
  2726. hatch=next(hatch_cycle),
  2727. clip_on=False,
  2728. label=label)
  2729. w.set(**wedgeprops)
  2730. slices.append(w)
  2731. self.add_patch(w)
  2732. if shadow:
  2733. # Make sure to add a shadow after the call to add_patch so the
  2734. # figure and transform props will be set.
  2735. shadow_dict = {'ox': -0.02, 'oy': -0.02, 'label': '_nolegend_'}
  2736. if isinstance(shadow, dict):
  2737. shadow_dict.update(shadow)
  2738. self.add_patch(mpatches.Shadow(w, **shadow_dict))
  2739. if labeldistance is not None:
  2740. xt = x + labeldistance * radius * math.cos(thetam)
  2741. yt = y + labeldistance * radius * math.sin(thetam)
  2742. label_alignment_h = 'left' if xt > 0 else 'right'
  2743. label_alignment_v = 'center'
  2744. label_rotation = 'horizontal'
  2745. if rotatelabels:
  2746. label_alignment_v = 'bottom' if yt > 0 else 'top'
  2747. label_rotation = (np.rad2deg(thetam)
  2748. + (0 if xt > 0 else 180))
  2749. t = self.text(xt, yt, label,
  2750. clip_on=False,
  2751. horizontalalignment=label_alignment_h,
  2752. verticalalignment=label_alignment_v,
  2753. rotation=label_rotation,
  2754. size=mpl.rcParams['xtick.labelsize'])
  2755. t.set(**textprops)
  2756. texts.append(t)
  2757. if autopct is not None:
  2758. xt = x + pctdistance * radius * math.cos(thetam)
  2759. yt = y + pctdistance * radius * math.sin(thetam)
  2760. if isinstance(autopct, str):
  2761. s = autopct % (100. * frac)
  2762. elif callable(autopct):
  2763. s = autopct(100. * frac)
  2764. else:
  2765. raise TypeError(
  2766. 'autopct must be callable or a format string')
  2767. if mpl._val_or_rc(textprops.get("usetex"), "text.usetex"):
  2768. # escape % (i.e. \%) if it is not already escaped
  2769. s = re.sub(r"([^\\])%", r"\1\\%", s)
  2770. t = self.text(xt, yt, s,
  2771. clip_on=False,
  2772. horizontalalignment='center',
  2773. verticalalignment='center')
  2774. t.set(**textprops)
  2775. autotexts.append(t)
  2776. theta1 = theta2
  2777. if frame:
  2778. self._request_autoscale_view()
  2779. else:
  2780. self.set(frame_on=False, xticks=[], yticks=[],
  2781. xlim=(-1.25 + center[0], 1.25 + center[0]),
  2782. ylim=(-1.25 + center[1], 1.25 + center[1]))
  2783. if autopct is None:
  2784. return slices, texts
  2785. else:
  2786. return slices, texts, autotexts
  2787. @staticmethod
  2788. def _errorevery_to_mask(x, errorevery):
  2789. """
  2790. Normalize `errorbar`'s *errorevery* to be a boolean mask for data *x*.
  2791. This function is split out to be usable both by 2D and 3D errorbars.
  2792. """
  2793. if isinstance(errorevery, Integral):
  2794. errorevery = (0, errorevery)
  2795. if isinstance(errorevery, tuple):
  2796. if (len(errorevery) == 2 and
  2797. isinstance(errorevery[0], Integral) and
  2798. isinstance(errorevery[1], Integral)):
  2799. errorevery = slice(errorevery[0], None, errorevery[1])
  2800. else:
  2801. raise ValueError(
  2802. f'{errorevery=!r} is a not a tuple of two integers')
  2803. elif isinstance(errorevery, slice):
  2804. pass
  2805. elif not isinstance(errorevery, str) and np.iterable(errorevery):
  2806. try:
  2807. x[errorevery] # fancy indexing
  2808. except (ValueError, IndexError) as err:
  2809. raise ValueError(
  2810. f"{errorevery=!r} is iterable but not a valid NumPy fancy "
  2811. "index to match 'xerr'/'yerr'") from err
  2812. else:
  2813. raise ValueError(f"{errorevery=!r} is not a recognized value")
  2814. everymask = np.zeros(len(x), bool)
  2815. everymask[errorevery] = True
  2816. return everymask
  2817. @_api.make_keyword_only("3.10", "ecolor")
  2818. @_preprocess_data(replace_names=["x", "y", "xerr", "yerr"],
  2819. label_namer="y")
  2820. @_docstring.interpd
  2821. def errorbar(self, x, y, yerr=None, xerr=None,
  2822. fmt='', ecolor=None, elinewidth=None, capsize=None,
  2823. barsabove=False, lolims=False, uplims=False,
  2824. xlolims=False, xuplims=False, errorevery=1, capthick=None,
  2825. **kwargs):
  2826. """
  2827. Plot y versus x as lines and/or markers with attached errorbars.
  2828. *x*, *y* define the data locations, *xerr*, *yerr* define the errorbar
  2829. sizes. By default, this draws the data markers/lines as well as the
  2830. errorbars. Use fmt='none' to draw errorbars without any data markers.
  2831. .. versionadded:: 3.7
  2832. Caps and error lines are drawn in polar coordinates on polar plots.
  2833. Parameters
  2834. ----------
  2835. x, y : float or array-like
  2836. The data positions.
  2837. xerr, yerr : float or array-like, shape(N,) or shape(2, N), optional
  2838. The errorbar sizes:
  2839. - scalar: Symmetric +/- values for all data points.
  2840. - shape(N,): Symmetric +/-values for each data point.
  2841. - shape(2, N): Separate - and + values for each bar. First row
  2842. contains the lower errors, the second row contains the upper
  2843. errors.
  2844. - *None*: No errorbar.
  2845. All values must be >= 0.
  2846. See :doc:`/gallery/statistics/errorbar_features`
  2847. for an example on the usage of ``xerr`` and ``yerr``.
  2848. fmt : str, default: ''
  2849. The format for the data points / data lines. See `.plot` for
  2850. details.
  2851. Use 'none' (case-insensitive) to plot errorbars without any data
  2852. markers.
  2853. ecolor : :mpltype:`color`, default: None
  2854. The color of the errorbar lines. If None, use the color of the
  2855. line connecting the markers.
  2856. elinewidth : float, default: None
  2857. The linewidth of the errorbar lines. If None, the linewidth of
  2858. the current style is used.
  2859. capsize : float, default: :rc:`errorbar.capsize`
  2860. The length of the error bar caps in points.
  2861. capthick : float, default: None
  2862. An alias to the keyword argument *markeredgewidth* (a.k.a. *mew*).
  2863. This setting is a more sensible name for the property that
  2864. controls the thickness of the error bar cap in points. For
  2865. backwards compatibility, if *mew* or *markeredgewidth* are given,
  2866. then they will over-ride *capthick*. This may change in future
  2867. releases.
  2868. barsabove : bool, default: False
  2869. If True, will plot the errorbars above the plot
  2870. symbols. Default is below.
  2871. lolims, uplims, xlolims, xuplims : bool or array-like, default: False
  2872. These arguments can be used to indicate that a value gives only
  2873. upper/lower limits. In that case a caret symbol is used to
  2874. indicate this. *lims*-arguments may be scalars, or array-likes of
  2875. the same length as *xerr* and *yerr*. To use limits with inverted
  2876. axes, `~.Axes.set_xlim` or `~.Axes.set_ylim` must be called before
  2877. :meth:`errorbar`. Note the tricky parameter names: setting e.g.
  2878. *lolims* to True means that the y-value is a *lower* limit of the
  2879. True value, so, only an *upward*-pointing arrow will be drawn!
  2880. errorevery : int or (int, int), default: 1
  2881. draws error bars on a subset of the data. *errorevery* =N draws
  2882. error bars on the points (x[::N], y[::N]).
  2883. *errorevery* =(start, N) draws error bars on the points
  2884. (x[start::N], y[start::N]). e.g. errorevery=(6, 3)
  2885. adds error bars to the data at (x[6], x[9], x[12], x[15], ...).
  2886. Used to avoid overlapping error bars when two series share x-axis
  2887. values.
  2888. Returns
  2889. -------
  2890. `.ErrorbarContainer`
  2891. The container contains:
  2892. - data_line : A `~matplotlib.lines.Line2D` instance of x, y plot markers
  2893. and/or line.
  2894. - caplines : A tuple of `~matplotlib.lines.Line2D` instances of the error
  2895. bar caps.
  2896. - barlinecols : A tuple of `.LineCollection` with the horizontal and
  2897. vertical error ranges.
  2898. Other Parameters
  2899. ----------------
  2900. data : indexable object, optional
  2901. DATA_PARAMETER_PLACEHOLDER
  2902. **kwargs
  2903. All other keyword arguments are passed on to the `~.Axes.plot` call
  2904. drawing the markers. For example, this code makes big red squares
  2905. with thick green edges::
  2906. x, y, yerr = rand(3, 10)
  2907. errorbar(x, y, yerr, marker='s', mfc='red',
  2908. mec='green', ms=20, mew=4)
  2909. where *mfc*, *mec*, *ms* and *mew* are aliases for the longer
  2910. property names, *markerfacecolor*, *markeredgecolor*, *markersize*
  2911. and *markeredgewidth*.
  2912. Valid kwargs for the marker properties are:
  2913. - *dashes*
  2914. - *dash_capstyle*
  2915. - *dash_joinstyle*
  2916. - *drawstyle*
  2917. - *fillstyle*
  2918. - *linestyle*
  2919. - *marker*
  2920. - *markeredgecolor*
  2921. - *markeredgewidth*
  2922. - *markerfacecolor*
  2923. - *markerfacecoloralt*
  2924. - *markersize*
  2925. - *markevery*
  2926. - *solid_capstyle*
  2927. - *solid_joinstyle*
  2928. Refer to the corresponding `.Line2D` property for more details:
  2929. %(Line2D:kwdoc)s
  2930. """
  2931. kwargs = cbook.normalize_kwargs(kwargs, mlines.Line2D)
  2932. # Drop anything that comes in as None to use the default instead.
  2933. kwargs = {k: v for k, v in kwargs.items() if v is not None}
  2934. kwargs.setdefault('zorder', 2)
  2935. # Casting to object arrays preserves units.
  2936. if not isinstance(x, np.ndarray):
  2937. x = np.asarray(x, dtype=object)
  2938. if not isinstance(y, np.ndarray):
  2939. y = np.asarray(y, dtype=object)
  2940. def _upcast_err(err):
  2941. """
  2942. Safely handle tuple of containers that carry units.
  2943. This function covers the case where the input to the xerr/yerr is a
  2944. length 2 tuple of equal length ndarray-subclasses that carry the
  2945. unit information in the container.
  2946. If we have a tuple of nested numpy array (subclasses), we defer
  2947. coercing the units to be consistent to the underlying unit
  2948. library (and implicitly the broadcasting).
  2949. Otherwise, fallback to casting to an object array.
  2950. """
  2951. if (
  2952. # make sure it is not a scalar
  2953. np.iterable(err) and
  2954. # and it is not empty
  2955. len(err) > 0 and
  2956. # and the first element is an array sub-class use
  2957. # safe_first_element because getitem is index-first not
  2958. # location first on pandas objects so err[0] almost always
  2959. # fails.
  2960. isinstance(cbook._safe_first_finite(err), np.ndarray)
  2961. ):
  2962. # Get the type of the first element
  2963. atype = type(cbook._safe_first_finite(err))
  2964. # Promote the outer container to match the inner container
  2965. if atype is np.ndarray:
  2966. # Converts using np.asarray, because data cannot
  2967. # be directly passed to init of np.ndarray
  2968. return np.asarray(err, dtype=object)
  2969. # If atype is not np.ndarray, directly pass data to init.
  2970. # This works for types such as unyts and astropy units
  2971. return atype(err)
  2972. # Otherwise wrap it in an object array
  2973. return np.asarray(err, dtype=object)
  2974. if xerr is not None and not isinstance(xerr, np.ndarray):
  2975. xerr = _upcast_err(xerr)
  2976. if yerr is not None and not isinstance(yerr, np.ndarray):
  2977. yerr = _upcast_err(yerr)
  2978. x, y = np.atleast_1d(x, y) # Make sure all the args are iterable.
  2979. if len(x) != len(y):
  2980. raise ValueError("'x' and 'y' must have the same size")
  2981. everymask = self._errorevery_to_mask(x, errorevery)
  2982. label = kwargs.pop("label", None)
  2983. kwargs['label'] = '_nolegend_'
  2984. # Create the main line and determine overall kwargs for child artists.
  2985. # We avoid calling self.plot() directly, or self._get_lines(), because
  2986. # that would call self._process_unit_info again, and do other indirect
  2987. # data processing.
  2988. (data_line, base_style), = self._get_lines._plot_args(
  2989. self, (x, y) if fmt == '' else (x, y, fmt), kwargs, return_kwargs=True)
  2990. # Do this after creating `data_line` to avoid modifying `base_style`.
  2991. if barsabove:
  2992. data_line.set_zorder(kwargs['zorder'] - .1)
  2993. else:
  2994. data_line.set_zorder(kwargs['zorder'] + .1)
  2995. # Add line to plot, or throw it away and use it to determine kwargs.
  2996. if fmt.lower() != 'none':
  2997. self.add_line(data_line)
  2998. else:
  2999. data_line = None
  3000. # Remove alpha=0 color that _get_lines._plot_args returns for
  3001. # 'none' format, and replace it with user-specified color, if
  3002. # supplied.
  3003. base_style.pop('color')
  3004. if 'color' in kwargs:
  3005. base_style['color'] = kwargs.pop('color')
  3006. if 'color' not in base_style:
  3007. base_style['color'] = 'C0'
  3008. if ecolor is None:
  3009. ecolor = base_style['color']
  3010. # Eject any line-specific information from format string, as it's not
  3011. # needed for bars or caps.
  3012. for key in ['marker', 'markersize', 'markerfacecolor',
  3013. 'markerfacecoloralt',
  3014. 'markeredgewidth', 'markeredgecolor', 'markevery',
  3015. 'linestyle', 'fillstyle', 'drawstyle', 'dash_capstyle',
  3016. 'dash_joinstyle', 'solid_capstyle', 'solid_joinstyle',
  3017. 'dashes']:
  3018. base_style.pop(key, None)
  3019. # Make the style dict for the line collections (the bars).
  3020. eb_lines_style = {**base_style, 'color': ecolor}
  3021. if elinewidth is not None:
  3022. eb_lines_style['linewidth'] = elinewidth
  3023. elif 'linewidth' in kwargs:
  3024. eb_lines_style['linewidth'] = kwargs['linewidth']
  3025. for key in ('transform', 'alpha', 'zorder', 'rasterized'):
  3026. if key in kwargs:
  3027. eb_lines_style[key] = kwargs[key]
  3028. # Make the style dict for caps (the "hats").
  3029. eb_cap_style = {**base_style, 'linestyle': 'none'}
  3030. if capsize is None:
  3031. capsize = mpl.rcParams["errorbar.capsize"]
  3032. if capsize > 0:
  3033. eb_cap_style['markersize'] = 2. * capsize
  3034. if capthick is not None:
  3035. eb_cap_style['markeredgewidth'] = capthick
  3036. # For backwards-compat, allow explicit setting of
  3037. # 'markeredgewidth' to over-ride capthick.
  3038. for key in ('markeredgewidth', 'transform', 'alpha',
  3039. 'zorder', 'rasterized'):
  3040. if key in kwargs:
  3041. eb_cap_style[key] = kwargs[key]
  3042. eb_cap_style["markeredgecolor"] = ecolor
  3043. barcols = []
  3044. caplines = {'x': [], 'y': []}
  3045. # Vectorized fancy-indexer.
  3046. def apply_mask(arrays, mask):
  3047. return [array[mask] for array in arrays]
  3048. # dep: dependent dataset, indep: independent dataset
  3049. for (dep_axis, dep, err, lolims, uplims, indep, lines_func,
  3050. marker, lomarker, himarker) in [
  3051. ("x", x, xerr, xlolims, xuplims, y, self.hlines,
  3052. "|", mlines.CARETRIGHTBASE, mlines.CARETLEFTBASE),
  3053. ("y", y, yerr, lolims, uplims, x, self.vlines,
  3054. "_", mlines.CARETUPBASE, mlines.CARETDOWNBASE),
  3055. ]:
  3056. if err is None:
  3057. continue
  3058. lolims = np.broadcast_to(lolims, len(dep)).astype(bool)
  3059. uplims = np.broadcast_to(uplims, len(dep)).astype(bool)
  3060. try:
  3061. np.broadcast_to(err, (2, len(dep)))
  3062. except ValueError:
  3063. raise ValueError(
  3064. f"'{dep_axis}err' (shape: {np.shape(err)}) must be a "
  3065. f"scalar or a 1D or (2, n) array-like whose shape matches "
  3066. f"'{dep_axis}' (shape: {np.shape(dep)})") from None
  3067. if err.dtype is np.dtype(object) and np.any(err == None): # noqa: E711
  3068. raise ValueError(
  3069. f"'{dep_axis}err' must not contain None. "
  3070. "Use NaN if you want to skip a value.")
  3071. # Raise if any errors are negative, but not if they are nan.
  3072. # To avoid nan comparisons (which lead to warnings on some
  3073. # platforms), we select with `err==err` (which is False for nan).
  3074. # Also, since datetime.timedelta cannot be compared with 0,
  3075. # we compare with the negative error instead.
  3076. if np.any((check := err[err == err]) < -check):
  3077. raise ValueError(
  3078. f"'{dep_axis}err' must not contain negative values")
  3079. # This is like
  3080. # elow, ehigh = np.broadcast_to(...)
  3081. # return dep - elow * ~lolims, dep + ehigh * ~uplims
  3082. # except that broadcast_to would strip units.
  3083. low, high = dep + np.vstack([-(1 - lolims), 1 - uplims]) * err
  3084. barcols.append(lines_func(
  3085. *apply_mask([indep, low, high], everymask), **eb_lines_style))
  3086. if self.name == "polar" and dep_axis == "x":
  3087. for b in barcols:
  3088. for p in b.get_paths():
  3089. p._interpolation_steps = 2
  3090. # Normal errorbars for points without upper/lower limits.
  3091. nolims = ~(lolims | uplims)
  3092. if nolims.any() and capsize > 0:
  3093. indep_masked, lo_masked, hi_masked = apply_mask(
  3094. [indep, low, high], nolims & everymask)
  3095. for lh_masked in [lo_masked, hi_masked]:
  3096. # Since this has to work for x and y as dependent data, we
  3097. # first set both x and y to the independent variable and
  3098. # overwrite the respective dependent data in a second step.
  3099. line = mlines.Line2D(indep_masked, indep_masked,
  3100. marker=marker, **eb_cap_style)
  3101. line.set(**{f"{dep_axis}data": lh_masked})
  3102. caplines[dep_axis].append(line)
  3103. for idx, (lims, hl) in enumerate([(lolims, high), (uplims, low)]):
  3104. if not lims.any():
  3105. continue
  3106. hlmarker = (
  3107. himarker
  3108. if self._axis_map[dep_axis].get_inverted() ^ idx
  3109. else lomarker)
  3110. x_masked, y_masked, hl_masked = apply_mask(
  3111. [x, y, hl], lims & everymask)
  3112. # As above, we set the dependent data in a second step.
  3113. line = mlines.Line2D(x_masked, y_masked,
  3114. marker=hlmarker, **eb_cap_style)
  3115. line.set(**{f"{dep_axis}data": hl_masked})
  3116. caplines[dep_axis].append(line)
  3117. if capsize > 0:
  3118. caplines[dep_axis].append(mlines.Line2D(
  3119. x_masked, y_masked, marker=marker, **eb_cap_style))
  3120. if self.name == 'polar':
  3121. trans_shift = self.transShift
  3122. for axis in caplines:
  3123. for l in caplines[axis]:
  3124. # Rotate caps to be perpendicular to the error bars
  3125. for theta, r in zip(l.get_xdata(), l.get_ydata()):
  3126. rotation = _ScaledRotation(theta=theta, trans_shift=trans_shift)
  3127. if axis == 'y':
  3128. rotation += mtransforms.Affine2D().rotate(np.pi / 2)
  3129. ms = mmarkers.MarkerStyle(marker=marker,
  3130. transform=rotation)
  3131. self.add_line(mlines.Line2D([theta], [r], marker=ms,
  3132. **eb_cap_style))
  3133. else:
  3134. for axis in caplines:
  3135. for l in caplines[axis]:
  3136. self.add_line(l)
  3137. self._request_autoscale_view()
  3138. caplines = caplines['x'] + caplines['y']
  3139. errorbar_container = ErrorbarContainer(
  3140. (data_line, tuple(caplines), tuple(barcols)),
  3141. has_xerr=(xerr is not None), has_yerr=(yerr is not None),
  3142. label=label)
  3143. self.add_container(errorbar_container)
  3144. return errorbar_container # (l0, caplines, barcols)
  3145. @_api.make_keyword_only("3.10", "notch")
  3146. @_preprocess_data()
  3147. @_api.rename_parameter("3.9", "labels", "tick_labels")
  3148. def boxplot(self, x, notch=None, sym=None, vert=None,
  3149. orientation='vertical', whis=None, positions=None,
  3150. widths=None, patch_artist=None, bootstrap=None,
  3151. usermedians=None, conf_intervals=None,
  3152. meanline=None, showmeans=None, showcaps=None,
  3153. showbox=None, showfliers=None, boxprops=None,
  3154. tick_labels=None, flierprops=None, medianprops=None,
  3155. meanprops=None, capprops=None, whiskerprops=None,
  3156. manage_ticks=True, autorange=False, zorder=None,
  3157. capwidths=None, label=None):
  3158. """
  3159. Draw a box and whisker plot.
  3160. The box extends from the first quartile (Q1) to the third
  3161. quartile (Q3) of the data, with a line at the median.
  3162. The whiskers extend from the box to the farthest data point
  3163. lying within 1.5x the inter-quartile range (IQR) from the box.
  3164. Flier points are those past the end of the whiskers.
  3165. See https://en.wikipedia.org/wiki/Box_plot for reference.
  3166. .. code-block:: none
  3167. Q1-1.5IQR Q1 median Q3 Q3+1.5IQR
  3168. |-----:-----|
  3169. o |--------| : |--------| o o
  3170. |-----:-----|
  3171. flier <-----------> fliers
  3172. IQR
  3173. Parameters
  3174. ----------
  3175. x : Array or a sequence of vectors.
  3176. The input data. If a 2D array, a boxplot is drawn for each column
  3177. in *x*. If a sequence of 1D arrays, a boxplot is drawn for each
  3178. array in *x*.
  3179. notch : bool, default: :rc:`boxplot.notch`
  3180. Whether to draw a notched boxplot (`True`), or a rectangular
  3181. boxplot (`False`). The notches represent the confidence interval
  3182. (CI) around the median. The documentation for *bootstrap*
  3183. describes how the locations of the notches are computed by
  3184. default, but their locations may also be overridden by setting the
  3185. *conf_intervals* parameter.
  3186. .. note::
  3187. In cases where the values of the CI are less than the
  3188. lower quartile or greater than the upper quartile, the
  3189. notches will extend beyond the box, giving it a
  3190. distinctive "flipped" appearance. This is expected
  3191. behavior and consistent with other statistical
  3192. visualization packages.
  3193. sym : str, optional
  3194. The default symbol for flier points. An empty string ('') hides
  3195. the fliers. If `None`, then the fliers default to 'b+'. More
  3196. control is provided by the *flierprops* parameter.
  3197. vert : bool, optional
  3198. .. deprecated:: 3.11
  3199. Use *orientation* instead.
  3200. This is a pending deprecation for 3.10, with full deprecation
  3201. in 3.11 and removal in 3.13.
  3202. If this is given during the deprecation period, it overrides
  3203. the *orientation* parameter.
  3204. If True, plots the boxes vertically.
  3205. If False, plots the boxes horizontally.
  3206. orientation : {'vertical', 'horizontal'}, default: 'vertical'
  3207. If 'horizontal', plots the boxes horizontally.
  3208. Otherwise, plots the boxes vertically.
  3209. .. versionadded:: 3.10
  3210. whis : float or (float, float), default: 1.5
  3211. The position of the whiskers.
  3212. If a float, the lower whisker is at the lowest datum above
  3213. ``Q1 - whis*(Q3-Q1)``, and the upper whisker at the highest datum
  3214. below ``Q3 + whis*(Q3-Q1)``, where Q1 and Q3 are the first and
  3215. third quartiles. The default value of ``whis = 1.5`` corresponds
  3216. to Tukey's original definition of boxplots.
  3217. If a pair of floats, they indicate the percentiles at which to
  3218. draw the whiskers (e.g., (5, 95)). In particular, setting this to
  3219. (0, 100) results in whiskers covering the whole range of the data.
  3220. In the edge case where ``Q1 == Q3``, *whis* is automatically set
  3221. to (0, 100) (cover the whole range of the data) if *autorange* is
  3222. True.
  3223. Beyond the whiskers, data are considered outliers and are plotted
  3224. as individual points.
  3225. bootstrap : int, optional
  3226. Specifies whether to bootstrap the confidence intervals
  3227. around the median for notched boxplots. If *bootstrap* is
  3228. None, no bootstrapping is performed, and notches are
  3229. calculated using a Gaussian-based asymptotic approximation
  3230. (see McGill, R., Tukey, J.W., and Larsen, W.A., 1978, and
  3231. Kendall and Stuart, 1967). Otherwise, bootstrap specifies
  3232. the number of times to bootstrap the median to determine its
  3233. 95% confidence intervals. Values between 1000 and 10000 are
  3234. recommended.
  3235. usermedians : 1D array-like, optional
  3236. A 1D array-like of length ``len(x)``. Each entry that is not
  3237. `None` forces the value of the median for the corresponding
  3238. dataset. For entries that are `None`, the medians are computed
  3239. by Matplotlib as normal.
  3240. conf_intervals : array-like, optional
  3241. A 2D array-like of shape ``(len(x), 2)``. Each entry that is not
  3242. None forces the location of the corresponding notch (which is
  3243. only drawn if *notch* is `True`). For entries that are `None`,
  3244. the notches are computed by the method specified by the other
  3245. parameters (e.g., *bootstrap*).
  3246. positions : array-like, optional
  3247. The positions of the boxes. The ticks and limits are
  3248. automatically set to match the positions. Defaults to
  3249. ``range(1, N+1)`` where N is the number of boxes to be drawn.
  3250. widths : float or array-like
  3251. The widths of the boxes. The default is 0.5, or ``0.15*(distance
  3252. between extreme positions)``, if that is smaller.
  3253. patch_artist : bool, default: :rc:`boxplot.patchartist`
  3254. If `False` produces boxes with the Line2D artist. Otherwise,
  3255. boxes are drawn with Patch artists.
  3256. tick_labels : list of str, optional
  3257. The tick labels of each boxplot.
  3258. Ticks are always placed at the box *positions*. If *tick_labels* is given,
  3259. the ticks are labelled accordingly. Otherwise, they keep their numeric
  3260. values.
  3261. .. versionchanged:: 3.9
  3262. Renamed from *labels*, which is deprecated since 3.9
  3263. and will be removed in 3.11.
  3264. manage_ticks : bool, default: True
  3265. If True, the tick locations and labels will be adjusted to match
  3266. the boxplot positions.
  3267. autorange : bool, default: False
  3268. When `True` and the data are distributed such that the 25th and
  3269. 75th percentiles are equal, *whis* is set to (0, 100) such
  3270. that the whisker ends are at the minimum and maximum of the data.
  3271. meanline : bool, default: :rc:`boxplot.meanline`
  3272. If `True` (and *showmeans* is `True`), will try to render the
  3273. mean as a line spanning the full width of the box according to
  3274. *meanprops* (see below). Not recommended if *shownotches* is also
  3275. True. Otherwise, means will be shown as points.
  3276. zorder : float, default: ``Line2D.zorder = 2``
  3277. The zorder of the boxplot.
  3278. Returns
  3279. -------
  3280. dict
  3281. A dictionary mapping each component of the boxplot to a list
  3282. of the `.Line2D` instances created. That dictionary has the
  3283. following keys (assuming vertical boxplots):
  3284. - ``boxes``: the main body of the boxplot showing the
  3285. quartiles and the median's confidence intervals if
  3286. enabled.
  3287. - ``medians``: horizontal lines at the median of each box.
  3288. - ``whiskers``: the vertical lines extending to the most
  3289. extreme, non-outlier data points.
  3290. - ``caps``: the horizontal lines at the ends of the
  3291. whiskers.
  3292. - ``fliers``: points representing data that extend beyond
  3293. the whiskers (fliers).
  3294. - ``means``: points or lines representing the means.
  3295. Other Parameters
  3296. ----------------
  3297. showcaps : bool, default: :rc:`boxplot.showcaps`
  3298. Show the caps on the ends of whiskers.
  3299. showbox : bool, default: :rc:`boxplot.showbox`
  3300. Show the central box.
  3301. showfliers : bool, default: :rc:`boxplot.showfliers`
  3302. Show the outliers beyond the caps.
  3303. showmeans : bool, default: :rc:`boxplot.showmeans`
  3304. Show the arithmetic means.
  3305. capprops : dict, default: None
  3306. The style of the caps.
  3307. capwidths : float or array, default: None
  3308. The widths of the caps.
  3309. boxprops : dict, default: None
  3310. The style of the box.
  3311. whiskerprops : dict, default: None
  3312. The style of the whiskers.
  3313. flierprops : dict, default: None
  3314. The style of the fliers.
  3315. medianprops : dict, default: None
  3316. The style of the median.
  3317. meanprops : dict, default: None
  3318. The style of the mean.
  3319. label : str or list of str, optional
  3320. Legend labels. Use a single string when all boxes have the same style and
  3321. you only want a single legend entry for them. Use a list of strings to
  3322. label all boxes individually. To be distinguishable, the boxes should be
  3323. styled individually, which is currently only possible by modifying the
  3324. returned artists, see e.g. :doc:`/gallery/statistics/boxplot_demo`.
  3325. In the case of a single string, the legend entry will technically be
  3326. associated with the first box only. By default, the legend will show the
  3327. median line (``result["medians"]``); if *patch_artist* is True, the legend
  3328. will show the box `.Patch` artists (``result["boxes"]``) instead.
  3329. .. versionadded:: 3.9
  3330. data : indexable object, optional
  3331. DATA_PARAMETER_PLACEHOLDER
  3332. See Also
  3333. --------
  3334. .Axes.bxp : Draw a boxplot from pre-computed statistics.
  3335. violinplot : Draw an estimate of the probability density function.
  3336. """
  3337. # Missing arguments default to rcParams.
  3338. if whis is None:
  3339. whis = mpl.rcParams['boxplot.whiskers']
  3340. if bootstrap is None:
  3341. bootstrap = mpl.rcParams['boxplot.bootstrap']
  3342. bxpstats = cbook.boxplot_stats(x, whis=whis, bootstrap=bootstrap,
  3343. labels=tick_labels, autorange=autorange)
  3344. if notch is None:
  3345. notch = mpl.rcParams['boxplot.notch']
  3346. if patch_artist is None:
  3347. patch_artist = mpl.rcParams['boxplot.patchartist']
  3348. if meanline is None:
  3349. meanline = mpl.rcParams['boxplot.meanline']
  3350. if showmeans is None:
  3351. showmeans = mpl.rcParams['boxplot.showmeans']
  3352. if showcaps is None:
  3353. showcaps = mpl.rcParams['boxplot.showcaps']
  3354. if showbox is None:
  3355. showbox = mpl.rcParams['boxplot.showbox']
  3356. if showfliers is None:
  3357. showfliers = mpl.rcParams['boxplot.showfliers']
  3358. if boxprops is None:
  3359. boxprops = {}
  3360. if whiskerprops is None:
  3361. whiskerprops = {}
  3362. if capprops is None:
  3363. capprops = {}
  3364. if medianprops is None:
  3365. medianprops = {}
  3366. if meanprops is None:
  3367. meanprops = {}
  3368. if flierprops is None:
  3369. flierprops = {}
  3370. if patch_artist:
  3371. boxprops['linestyle'] = 'solid' # Not consistent with bxp.
  3372. if 'color' in boxprops:
  3373. boxprops['edgecolor'] = boxprops.pop('color')
  3374. # if non-default sym value, put it into the flier dictionary
  3375. # the logic for providing the default symbol ('b+') now lives
  3376. # in bxp in the initial value of flierkw
  3377. # handle all of the *sym* related logic here so we only have to pass
  3378. # on the flierprops dict.
  3379. if sym is not None:
  3380. # no-flier case, which should really be done with
  3381. # 'showfliers=False' but none-the-less deal with it to keep back
  3382. # compatibility
  3383. if sym == '':
  3384. # blow away existing dict and make one for invisible markers
  3385. flierprops = dict(linestyle='none', marker='', color='none')
  3386. # turn the fliers off just to be safe
  3387. showfliers = False
  3388. # now process the symbol string
  3389. else:
  3390. # process the symbol string
  3391. # discarded linestyle
  3392. _, marker, color = _process_plot_format(sym)
  3393. # if we have a marker, use it
  3394. if marker is not None:
  3395. flierprops['marker'] = marker
  3396. # if we have a color, use it
  3397. if color is not None:
  3398. # assume that if color is passed in the user want
  3399. # filled symbol, if the users want more control use
  3400. # flierprops
  3401. flierprops['color'] = color
  3402. flierprops['markerfacecolor'] = color
  3403. flierprops['markeredgecolor'] = color
  3404. # replace medians if necessary:
  3405. if usermedians is not None:
  3406. if (len(np.ravel(usermedians)) != len(bxpstats) or
  3407. np.shape(usermedians)[0] != len(bxpstats)):
  3408. raise ValueError(
  3409. "'usermedians' and 'x' have different lengths")
  3410. else:
  3411. # reassign medians as necessary
  3412. for stats, med in zip(bxpstats, usermedians):
  3413. if med is not None:
  3414. stats['med'] = med
  3415. if conf_intervals is not None:
  3416. if len(conf_intervals) != len(bxpstats):
  3417. raise ValueError(
  3418. "'conf_intervals' and 'x' have different lengths")
  3419. else:
  3420. for stats, ci in zip(bxpstats, conf_intervals):
  3421. if ci is not None:
  3422. if len(ci) != 2:
  3423. raise ValueError('each confidence interval must '
  3424. 'have two values')
  3425. else:
  3426. if ci[0] is not None:
  3427. stats['cilo'] = ci[0]
  3428. if ci[1] is not None:
  3429. stats['cihi'] = ci[1]
  3430. artists = self.bxp(bxpstats, positions=positions, widths=widths,
  3431. vert=vert, patch_artist=patch_artist,
  3432. shownotches=notch, showmeans=showmeans,
  3433. showcaps=showcaps, showbox=showbox,
  3434. boxprops=boxprops, flierprops=flierprops,
  3435. medianprops=medianprops, meanprops=meanprops,
  3436. meanline=meanline, showfliers=showfliers,
  3437. capprops=capprops, whiskerprops=whiskerprops,
  3438. manage_ticks=manage_ticks, zorder=zorder,
  3439. capwidths=capwidths, label=label,
  3440. orientation=orientation)
  3441. return artists
  3442. @_api.make_keyword_only("3.10", "widths")
  3443. def bxp(self, bxpstats, positions=None, widths=None, vert=None,
  3444. orientation='vertical', patch_artist=False, shownotches=False,
  3445. showmeans=False, showcaps=True, showbox=True, showfliers=True,
  3446. boxprops=None, whiskerprops=None, flierprops=None,
  3447. medianprops=None, capprops=None, meanprops=None,
  3448. meanline=False, manage_ticks=True, zorder=None,
  3449. capwidths=None, label=None):
  3450. """
  3451. Draw a box and whisker plot from pre-computed statistics.
  3452. The box extends from the first quartile *q1* to the third
  3453. quartile *q3* of the data, with a line at the median (*med*).
  3454. The whiskers extend from *whislow* to *whishi*.
  3455. Flier points are markers past the end of the whiskers.
  3456. See https://en.wikipedia.org/wiki/Box_plot for reference.
  3457. .. code-block:: none
  3458. whislow q1 med q3 whishi
  3459. |-----:-----|
  3460. o |--------| : |--------| o o
  3461. |-----:-----|
  3462. flier fliers
  3463. .. note::
  3464. This is a low-level drawing function for when you already
  3465. have the statistical parameters. If you want a boxplot based
  3466. on a dataset, use `~.Axes.boxplot` instead.
  3467. Parameters
  3468. ----------
  3469. bxpstats : list of dicts
  3470. A list of dictionaries containing stats for each boxplot.
  3471. Required keys are:
  3472. - ``med``: Median (float).
  3473. - ``q1``, ``q3``: First & third quartiles (float).
  3474. - ``whislo``, ``whishi``: Lower & upper whisker positions (float).
  3475. Optional keys are:
  3476. - ``mean``: Mean (float). Needed if ``showmeans=True``.
  3477. - ``fliers``: Data beyond the whiskers (array-like).
  3478. Needed if ``showfliers=True``.
  3479. - ``cilo``, ``cihi``: Lower & upper confidence intervals
  3480. about the median. Needed if ``shownotches=True``.
  3481. - ``label``: Name of the dataset (str). If available,
  3482. this will be used a tick label for the boxplot
  3483. positions : array-like, default: [1, 2, ..., n]
  3484. The positions of the boxes. The ticks and limits
  3485. are automatically set to match the positions.
  3486. widths : float or array-like, default: None
  3487. The widths of the boxes. The default is
  3488. ``clip(0.15*(distance between extreme positions), 0.15, 0.5)``.
  3489. capwidths : float or array-like, default: None
  3490. Either a scalar or a vector and sets the width of each cap.
  3491. The default is ``0.5*(width of the box)``, see *widths*.
  3492. vert : bool, optional
  3493. .. deprecated:: 3.11
  3494. Use *orientation* instead.
  3495. This is a pending deprecation for 3.10, with full deprecation
  3496. in 3.11 and removal in 3.13.
  3497. If this is given during the deprecation period, it overrides
  3498. the *orientation* parameter.
  3499. If True, plots the boxes vertically.
  3500. If False, plots the boxes horizontally.
  3501. orientation : {'vertical', 'horizontal'}, default: 'vertical'
  3502. If 'horizontal', plots the boxes horizontally.
  3503. Otherwise, plots the boxes vertically.
  3504. .. versionadded:: 3.10
  3505. patch_artist : bool, default: False
  3506. If `False` produces boxes with the `.Line2D` artist.
  3507. If `True` produces boxes with the `~matplotlib.patches.Patch` artist.
  3508. shownotches, showmeans, showcaps, showbox, showfliers : bool
  3509. Whether to draw the CI notches, the mean value (both default to
  3510. False), the caps, the box, and the fliers (all three default to
  3511. True).
  3512. boxprops, whiskerprops, capprops, flierprops, medianprops, meanprops :\
  3513. dict, optional
  3514. Artist properties for the boxes, whiskers, caps, fliers, medians, and
  3515. means.
  3516. meanline : bool, default: False
  3517. If `True` (and *showmeans* is `True`), will try to render the mean
  3518. as a line spanning the full width of the box according to
  3519. *meanprops*. Not recommended if *shownotches* is also True.
  3520. Otherwise, means will be shown as points.
  3521. manage_ticks : bool, default: True
  3522. If True, the tick locations and labels will be adjusted to match the
  3523. boxplot positions.
  3524. label : str or list of str, optional
  3525. Legend labels. Use a single string when all boxes have the same style and
  3526. you only want a single legend entry for them. Use a list of strings to
  3527. label all boxes individually. To be distinguishable, the boxes should be
  3528. styled individually, which is currently only possible by modifying the
  3529. returned artists, see e.g. :doc:`/gallery/statistics/boxplot_demo`.
  3530. In the case of a single string, the legend entry will technically be
  3531. associated with the first box only. By default, the legend will show the
  3532. median line (``result["medians"]``); if *patch_artist* is True, the legend
  3533. will show the box `.Patch` artists (``result["boxes"]``) instead.
  3534. .. versionadded:: 3.9
  3535. zorder : float, default: ``Line2D.zorder = 2``
  3536. The zorder of the resulting boxplot.
  3537. Returns
  3538. -------
  3539. dict
  3540. A dictionary mapping each component of the boxplot to a list
  3541. of the `.Line2D` instances created. That dictionary has the
  3542. following keys (assuming vertical boxplots):
  3543. - ``boxes``: main bodies of the boxplot showing the quartiles, and
  3544. the median's confidence intervals if enabled.
  3545. - ``medians``: horizontal lines at the median of each box.
  3546. - ``whiskers``: vertical lines up to the last non-outlier data.
  3547. - ``caps``: horizontal lines at the ends of the whiskers.
  3548. - ``fliers``: points representing data beyond the whiskers (fliers).
  3549. - ``means``: points or lines representing the means.
  3550. See Also
  3551. --------
  3552. boxplot : Draw a boxplot from data instead of pre-computed statistics.
  3553. """
  3554. # Clamp median line to edge of box by default.
  3555. medianprops = {
  3556. "solid_capstyle": "butt",
  3557. "dash_capstyle": "butt",
  3558. **(medianprops or {}),
  3559. }
  3560. meanprops = {
  3561. "solid_capstyle": "butt",
  3562. "dash_capstyle": "butt",
  3563. **(meanprops or {}),
  3564. }
  3565. # lists of artists to be output
  3566. whiskers = []
  3567. caps = []
  3568. boxes = []
  3569. medians = []
  3570. means = []
  3571. fliers = []
  3572. # empty list of xticklabels
  3573. datalabels = []
  3574. # Use default zorder if none specified
  3575. if zorder is None:
  3576. zorder = mlines.Line2D.zorder
  3577. zdelta = 0.1
  3578. def merge_kw_rc(subkey, explicit, zdelta=0, usemarker=True):
  3579. d = {k.split('.')[-1]: v for k, v in mpl.rcParams.items()
  3580. if k.startswith(f'boxplot.{subkey}props')}
  3581. d['zorder'] = zorder + zdelta
  3582. if not usemarker:
  3583. d['marker'] = ''
  3584. d.update(cbook.normalize_kwargs(explicit, mlines.Line2D))
  3585. return d
  3586. box_kw = {
  3587. 'linestyle': mpl.rcParams['boxplot.boxprops.linestyle'],
  3588. 'linewidth': mpl.rcParams['boxplot.boxprops.linewidth'],
  3589. 'edgecolor': mpl.rcParams['boxplot.boxprops.color'],
  3590. 'facecolor': ('white' if mpl.rcParams['_internal.classic_mode']
  3591. else mpl.rcParams['patch.facecolor']),
  3592. 'zorder': zorder,
  3593. **cbook.normalize_kwargs(boxprops, mpatches.PathPatch)
  3594. } if patch_artist else merge_kw_rc('box', boxprops, usemarker=False)
  3595. whisker_kw = merge_kw_rc('whisker', whiskerprops, usemarker=False)
  3596. cap_kw = merge_kw_rc('cap', capprops, usemarker=False)
  3597. flier_kw = merge_kw_rc('flier', flierprops)
  3598. median_kw = merge_kw_rc('median', medianprops, zdelta, usemarker=False)
  3599. mean_kw = merge_kw_rc('mean', meanprops, zdelta)
  3600. removed_prop = 'marker' if meanline else 'linestyle'
  3601. # Only remove the property if it's not set explicitly as a parameter.
  3602. if meanprops is None or removed_prop not in meanprops:
  3603. mean_kw[removed_prop] = ''
  3604. # vert and orientation parameters are linked until vert's
  3605. # deprecation period expires. vert only takes precedence
  3606. # if set to False.
  3607. if vert is None:
  3608. vert = mpl.rcParams['boxplot.vertical']
  3609. else:
  3610. _api.warn_deprecated(
  3611. "3.11",
  3612. name="vert: bool",
  3613. alternative="orientation: {'vertical', 'horizontal'}",
  3614. pending=True,
  3615. )
  3616. if vert is False:
  3617. orientation = 'horizontal'
  3618. _api.check_in_list(['horizontal', 'vertical'], orientation=orientation)
  3619. if not mpl.rcParams['boxplot.vertical']:
  3620. _api.warn_deprecated(
  3621. "3.10",
  3622. name='boxplot.vertical', obj_type="rcparam"
  3623. )
  3624. # vertical or horizontal plot?
  3625. maybe_swap = slice(None) if orientation == 'vertical' else slice(None, None, -1)
  3626. def do_plot(xs, ys, **kwargs):
  3627. return self.plot(*[xs, ys][maybe_swap], **kwargs)[0]
  3628. def do_patch(xs, ys, **kwargs):
  3629. path = mpath.Path._create_closed(
  3630. np.column_stack([xs, ys][maybe_swap]))
  3631. patch = mpatches.PathPatch(path, **kwargs)
  3632. self.add_artist(patch)
  3633. return patch
  3634. # input validation
  3635. N = len(bxpstats)
  3636. datashape_message = ("List of boxplot statistics and `{0}` "
  3637. "values must have same the length")
  3638. # check position
  3639. if positions is None:
  3640. positions = list(range(1, N + 1))
  3641. elif len(positions) != N:
  3642. raise ValueError(datashape_message.format("positions"))
  3643. positions = np.array(positions)
  3644. if len(positions) > 0 and not all(isinstance(p, Real) for p in positions):
  3645. raise TypeError("positions should be an iterable of numbers")
  3646. # width
  3647. if widths is None:
  3648. widths = [np.clip(0.15 * np.ptp(positions), 0.15, 0.5)] * N
  3649. elif np.isscalar(widths):
  3650. widths = [widths] * N
  3651. elif len(widths) != N:
  3652. raise ValueError(datashape_message.format("widths"))
  3653. # capwidth
  3654. if capwidths is None:
  3655. capwidths = 0.5 * np.array(widths)
  3656. elif np.isscalar(capwidths):
  3657. capwidths = [capwidths] * N
  3658. elif len(capwidths) != N:
  3659. raise ValueError(datashape_message.format("capwidths"))
  3660. for pos, width, stats, capwidth in zip(positions, widths, bxpstats,
  3661. capwidths):
  3662. # try to find a new label
  3663. datalabels.append(stats.get('label', pos))
  3664. # whisker coords
  3665. whis_x = [pos, pos]
  3666. whislo_y = [stats['q1'], stats['whislo']]
  3667. whishi_y = [stats['q3'], stats['whishi']]
  3668. # cap coords
  3669. cap_left = pos - capwidth * 0.5
  3670. cap_right = pos + capwidth * 0.5
  3671. cap_x = [cap_left, cap_right]
  3672. cap_lo = np.full(2, stats['whislo'])
  3673. cap_hi = np.full(2, stats['whishi'])
  3674. # box and median coords
  3675. box_left = pos - width * 0.5
  3676. box_right = pos + width * 0.5
  3677. med_y = [stats['med'], stats['med']]
  3678. # notched boxes
  3679. if shownotches:
  3680. notch_left = pos - width * 0.25
  3681. notch_right = pos + width * 0.25
  3682. box_x = [box_left, box_right, box_right, notch_right,
  3683. box_right, box_right, box_left, box_left, notch_left,
  3684. box_left, box_left]
  3685. box_y = [stats['q1'], stats['q1'], stats['cilo'],
  3686. stats['med'], stats['cihi'], stats['q3'],
  3687. stats['q3'], stats['cihi'], stats['med'],
  3688. stats['cilo'], stats['q1']]
  3689. med_x = [notch_left, notch_right]
  3690. # plain boxes
  3691. else:
  3692. box_x = [box_left, box_right, box_right, box_left, box_left]
  3693. box_y = [stats['q1'], stats['q1'], stats['q3'], stats['q3'],
  3694. stats['q1']]
  3695. med_x = [box_left, box_right]
  3696. # maybe draw the box
  3697. if showbox:
  3698. do_box = do_patch if patch_artist else do_plot
  3699. boxes.append(do_box(box_x, box_y, **box_kw))
  3700. median_kw.setdefault('label', '_nolegend_')
  3701. # draw the whiskers
  3702. whisker_kw.setdefault('label', '_nolegend_')
  3703. whiskers.append(do_plot(whis_x, whislo_y, **whisker_kw))
  3704. whiskers.append(do_plot(whis_x, whishi_y, **whisker_kw))
  3705. # maybe draw the caps
  3706. if showcaps:
  3707. cap_kw.setdefault('label', '_nolegend_')
  3708. caps.append(do_plot(cap_x, cap_lo, **cap_kw))
  3709. caps.append(do_plot(cap_x, cap_hi, **cap_kw))
  3710. # draw the medians
  3711. medians.append(do_plot(med_x, med_y, **median_kw))
  3712. # maybe draw the means
  3713. if showmeans:
  3714. if meanline:
  3715. means.append(do_plot(
  3716. [box_left, box_right], [stats['mean'], stats['mean']],
  3717. **mean_kw
  3718. ))
  3719. else:
  3720. means.append(do_plot([pos], [stats['mean']], **mean_kw))
  3721. # maybe draw the fliers
  3722. if showfliers:
  3723. flier_kw.setdefault('label', '_nolegend_')
  3724. flier_x = np.full(len(stats['fliers']), pos, dtype=np.float64)
  3725. flier_y = stats['fliers']
  3726. fliers.append(do_plot(flier_x, flier_y, **flier_kw))
  3727. # Set legend labels
  3728. if label:
  3729. box_or_med = boxes if showbox and patch_artist else medians
  3730. if cbook.is_scalar_or_string(label):
  3731. # assign the label only to the first box
  3732. box_or_med[0].set_label(label)
  3733. else: # label is a sequence
  3734. if len(box_or_med) != len(label):
  3735. raise ValueError(datashape_message.format("label"))
  3736. for artist, lbl in zip(box_or_med, label):
  3737. artist.set_label(lbl)
  3738. if manage_ticks:
  3739. axis_name = "x" if orientation == 'vertical' else "y"
  3740. interval = getattr(self.dataLim, f"interval{axis_name}")
  3741. axis = self._axis_map[axis_name]
  3742. positions = axis.convert_units(positions)
  3743. # The 0.5 additional padding ensures reasonable-looking boxes
  3744. # even when drawing a single box. We set the sticky edge to
  3745. # prevent margins expansion, in order to match old behavior (back
  3746. # when separate calls to boxplot() would completely reset the axis
  3747. # limits regardless of what was drawn before). The sticky edges
  3748. # are attached to the median lines, as they are always present.
  3749. interval[:] = (min(interval[0], min(positions) - .5),
  3750. max(interval[1], max(positions) + .5))
  3751. for median, position in zip(medians, positions):
  3752. getattr(median.sticky_edges, axis_name).extend(
  3753. [position - .5, position + .5])
  3754. # Modified from Axis.set_ticks and Axis.set_ticklabels.
  3755. locator = axis.get_major_locator()
  3756. if not isinstance(axis.get_major_locator(),
  3757. mticker.FixedLocator):
  3758. locator = mticker.FixedLocator([])
  3759. axis.set_major_locator(locator)
  3760. locator.locs = np.array([*locator.locs, *positions])
  3761. formatter = axis.get_major_formatter()
  3762. if not isinstance(axis.get_major_formatter(),
  3763. mticker.FixedFormatter):
  3764. formatter = mticker.FixedFormatter([])
  3765. axis.set_major_formatter(formatter)
  3766. formatter.seq = [*formatter.seq, *datalabels]
  3767. self._request_autoscale_view()
  3768. return dict(whiskers=whiskers, caps=caps, boxes=boxes,
  3769. medians=medians, fliers=fliers, means=means)
  3770. @staticmethod
  3771. def _parse_scatter_color_args(c, edgecolors, kwargs, xsize,
  3772. get_next_color_func):
  3773. """
  3774. Helper function to process color related arguments of `.Axes.scatter`.
  3775. Argument precedence for facecolors:
  3776. - c (if not None)
  3777. - kwargs['facecolor']
  3778. - kwargs['facecolors']
  3779. - kwargs['color'] (==kwcolor)
  3780. - 'b' if in classic mode else the result of ``get_next_color_func()``
  3781. Argument precedence for edgecolors:
  3782. - kwargs['edgecolor']
  3783. - edgecolors (is an explicit kw argument in scatter())
  3784. - kwargs['color'] (==kwcolor)
  3785. - 'face' if not in classic mode else None
  3786. Parameters
  3787. ----------
  3788. c : :mpltype:`color` or array-like or list of :mpltype:`color` or None
  3789. See argument description of `.Axes.scatter`.
  3790. edgecolors : :mpltype:`color` or sequence of color or {'face', 'none'} or None
  3791. See argument description of `.Axes.scatter`.
  3792. kwargs : dict
  3793. Additional kwargs. If these keys exist, we pop and process them:
  3794. 'facecolors', 'facecolor', 'edgecolor', 'color'
  3795. Note: The dict is modified by this function.
  3796. xsize : int
  3797. The size of the x and y arrays passed to `.Axes.scatter`.
  3798. get_next_color_func : callable
  3799. A callable that returns a color. This color is used as facecolor
  3800. if no other color is provided.
  3801. Note, that this is a function rather than a fixed color value to
  3802. support conditional evaluation of the next color. As of the
  3803. current implementation obtaining the next color from the
  3804. property cycle advances the cycle. This must only happen if we
  3805. actually use the color, which will only be decided within this
  3806. method.
  3807. Returns
  3808. -------
  3809. c
  3810. The input *c* if it was not *None*, else a color derived from the
  3811. other inputs or defaults.
  3812. colors : array(N, 4) or None
  3813. The facecolors as RGBA values, or *None* if a colormap is used.
  3814. edgecolors
  3815. The edgecolor.
  3816. """
  3817. facecolors = kwargs.pop('facecolors', None)
  3818. facecolors = kwargs.pop('facecolor', facecolors)
  3819. edgecolors = kwargs.pop('edgecolor', edgecolors)
  3820. kwcolor = kwargs.pop('color', None)
  3821. if kwcolor is not None and c is not None:
  3822. raise ValueError("Supply a 'c' argument or a 'color'"
  3823. " kwarg but not both; they differ but"
  3824. " their functionalities overlap.")
  3825. if kwcolor is not None:
  3826. try:
  3827. mcolors.to_rgba_array(kwcolor)
  3828. except ValueError as err:
  3829. raise ValueError(
  3830. "'color' kwarg must be a color or sequence of color "
  3831. "specs. For a sequence of values to be color-mapped, use "
  3832. "the 'c' argument instead.") from err
  3833. if edgecolors is None:
  3834. edgecolors = kwcolor
  3835. if facecolors is None:
  3836. facecolors = kwcolor
  3837. if edgecolors is None and not mpl.rcParams['_internal.classic_mode']:
  3838. edgecolors = mpl.rcParams['scatter.edgecolors']
  3839. # Raise a warning if both `c` and `facecolor` are set (issue #24404).
  3840. if c is not None and facecolors is not None:
  3841. _api.warn_external(
  3842. "You passed both c and facecolor/facecolors for the markers. "
  3843. "c has precedence over facecolor/facecolors. "
  3844. "This behavior may change in the future."
  3845. )
  3846. c_was_none = c is None
  3847. if c is None:
  3848. c = (facecolors if facecolors is not None
  3849. else "b" if mpl.rcParams['_internal.classic_mode']
  3850. else get_next_color_func())
  3851. c_is_string_or_strings = (
  3852. isinstance(c, str)
  3853. or (np.iterable(c) and len(c) > 0
  3854. and isinstance(cbook._safe_first_finite(c), str)))
  3855. def invalid_shape_exception(csize, xsize):
  3856. return ValueError(
  3857. f"'c' argument has {csize} elements, which is inconsistent "
  3858. f"with 'x' and 'y' with size {xsize}.")
  3859. c_is_mapped = False # Unless proven otherwise below.
  3860. valid_shape = True # Unless proven otherwise below.
  3861. if not c_was_none and kwcolor is None and not c_is_string_or_strings:
  3862. try: # First, does 'c' look suitable for value-mapping?
  3863. c = np.asanyarray(c, dtype=float)
  3864. except ValueError:
  3865. pass # Failed to convert to float array; must be color specs.
  3866. else:
  3867. # handle the documented special case of a 2D array with 1
  3868. # row which as RGB(A) to broadcast.
  3869. if c.shape == (1, 4) or c.shape == (1, 3):
  3870. c_is_mapped = False
  3871. if c.size != xsize:
  3872. valid_shape = False
  3873. # If c can be either mapped values or an RGB(A) color, prefer
  3874. # the former if shapes match, the latter otherwise.
  3875. elif c.size == xsize:
  3876. c = c.ravel()
  3877. c_is_mapped = True
  3878. else: # Wrong size; it must not be intended for mapping.
  3879. if c.shape in ((3,), (4,)):
  3880. _api.warn_external(
  3881. "*c* argument looks like a single numeric RGB or "
  3882. "RGBA sequence, which should be avoided as value-"
  3883. "mapping will have precedence in case its length "
  3884. "matches with *x* & *y*. Please use the *color* "
  3885. "keyword-argument or provide a 2D array "
  3886. "with a single row if you intend to specify "
  3887. "the same RGB or RGBA value for all points.")
  3888. valid_shape = False
  3889. if not c_is_mapped:
  3890. try: # Is 'c' acceptable as PathCollection facecolors?
  3891. colors = mcolors.to_rgba_array(c)
  3892. except (TypeError, ValueError) as err:
  3893. if "RGBA values should be within 0-1 range" in str(err):
  3894. raise
  3895. else:
  3896. if not valid_shape:
  3897. raise invalid_shape_exception(c.size, xsize) from err
  3898. # Both the mapping *and* the RGBA conversion failed: pretty
  3899. # severe failure => one may appreciate a verbose feedback.
  3900. raise ValueError(
  3901. f"'c' argument must be a color, a sequence of colors, "
  3902. f"or a sequence of numbers, not {c!r}") from err
  3903. else:
  3904. if len(colors) not in (0, 1, xsize):
  3905. # NB: remember that a single color is also acceptable.
  3906. # Besides *colors* will be an empty array if c == 'none'.
  3907. raise invalid_shape_exception(len(colors), xsize)
  3908. else:
  3909. colors = None # use cmap, norm after collection is created
  3910. return c, colors, edgecolors
  3911. @_api.make_keyword_only("3.10", "marker")
  3912. @_preprocess_data(replace_names=["x", "y", "s", "linewidths",
  3913. "edgecolors", "c", "facecolor",
  3914. "facecolors", "color"],
  3915. label_namer="y")
  3916. @_docstring.interpd
  3917. def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None,
  3918. vmin=None, vmax=None, alpha=None, linewidths=None, *,
  3919. edgecolors=None, colorizer=None, plotnonfinite=False, **kwargs):
  3920. """
  3921. A scatter plot of *y* vs. *x* with varying marker size and/or color.
  3922. Parameters
  3923. ----------
  3924. x, y : float or array-like, shape (n, )
  3925. The data positions.
  3926. s : float or array-like, shape (n, ), optional
  3927. The marker size in points**2 (typographic points are 1/72 in.).
  3928. Default is ``rcParams['lines.markersize'] ** 2``.
  3929. The linewidth and edgecolor can visually interact with the marker
  3930. size, and can lead to artifacts if the marker size is smaller than
  3931. the linewidth.
  3932. If the linewidth is greater than 0 and the edgecolor is anything
  3933. but *'none'*, then the effective size of the marker will be
  3934. increased by half the linewidth because the stroke will be centered
  3935. on the edge of the shape.
  3936. To eliminate the marker edge either set *linewidth=0* or
  3937. *edgecolor='none'*.
  3938. c : array-like or list of :mpltype:`color` or :mpltype:`color`, optional
  3939. The marker colors. Possible values:
  3940. - A scalar or sequence of n numbers to be mapped to colors using
  3941. *cmap* and *norm*.
  3942. - A 2D array in which the rows are RGB or RGBA.
  3943. - A sequence of colors of length n.
  3944. - A single color format string.
  3945. Note that *c* should not be a single numeric RGB or RGBA sequence
  3946. because that is indistinguishable from an array of values to be
  3947. colormapped. If you want to specify the same RGB or RGBA value for
  3948. all points, use a 2D array with a single row. Otherwise,
  3949. value-matching will have precedence in case of a size matching with
  3950. *x* and *y*.
  3951. If you wish to specify a single color for all points
  3952. prefer the *color* keyword argument.
  3953. Defaults to `None`. In that case the marker color is determined
  3954. by the value of *color*, *facecolor* or *facecolors*. In case
  3955. those are not specified or `None`, the marker color is determined
  3956. by the next color of the ``Axes``' current "shape and fill" color
  3957. cycle. This cycle defaults to :rc:`axes.prop_cycle`.
  3958. marker : `~.markers.MarkerStyle`, default: :rc:`scatter.marker`
  3959. The marker style. *marker* can be either an instance of the class
  3960. or the text shorthand for a particular marker.
  3961. See :mod:`matplotlib.markers` for more information about marker
  3962. styles.
  3963. %(cmap_doc)s
  3964. This parameter is ignored if *c* is RGB(A).
  3965. %(norm_doc)s
  3966. This parameter is ignored if *c* is RGB(A).
  3967. %(vmin_vmax_doc)s
  3968. This parameter is ignored if *c* is RGB(A).
  3969. alpha : float, default: None
  3970. The alpha blending value, between 0 (transparent) and 1 (opaque).
  3971. linewidths : float or array-like, default: :rc:`lines.linewidth`
  3972. The linewidth of the marker edges. Note: The default *edgecolors*
  3973. is 'face'. You may want to change this as well.
  3974. edgecolors : {'face', 'none', *None*} or :mpltype:`color` or list of \
  3975. :mpltype:`color`, default: :rc:`scatter.edgecolors`
  3976. The edge color of the marker. Possible values:
  3977. - 'face': The edge color will always be the same as the face color.
  3978. - 'none': No patch boundary will be drawn.
  3979. - A color or sequence of colors.
  3980. For non-filled markers, *edgecolors* is ignored. Instead, the color
  3981. is determined like with 'face', i.e. from *c*, *colors*, or
  3982. *facecolors*.
  3983. %(colorizer_doc)s
  3984. This parameter is ignored if *c* is RGB(A).
  3985. plotnonfinite : bool, default: False
  3986. Whether to plot points with nonfinite *c* (i.e. ``inf``, ``-inf``
  3987. or ``nan``). If ``True`` the points are drawn with the *bad*
  3988. colormap color (see `.Colormap.set_bad`).
  3989. Returns
  3990. -------
  3991. `~matplotlib.collections.PathCollection`
  3992. Other Parameters
  3993. ----------------
  3994. data : indexable object, optional
  3995. DATA_PARAMETER_PLACEHOLDER
  3996. **kwargs : `~matplotlib.collections.PathCollection` properties
  3997. %(PathCollection:kwdoc)s
  3998. See Also
  3999. --------
  4000. plot : To plot scatter plots when markers are identical in size and
  4001. color.
  4002. Notes
  4003. -----
  4004. * The `.plot` function will be faster for scatterplots where markers
  4005. don't vary in size or color.
  4006. * Any or all of *x*, *y*, *s*, and *c* may be masked arrays, in which
  4007. case all masks will be combined and only unmasked points will be
  4008. plotted.
  4009. * Fundamentally, scatter works with 1D arrays; *x*, *y*, *s*, and *c*
  4010. may be input as N-D arrays, but within scatter they will be
  4011. flattened. The exception is *c*, which will be flattened only if its
  4012. size matches the size of *x* and *y*.
  4013. """
  4014. # add edgecolors and linewidths to kwargs so they
  4015. # can be processed by normailze_kwargs
  4016. if edgecolors is not None:
  4017. kwargs.update({'edgecolors': edgecolors})
  4018. if linewidths is not None:
  4019. kwargs.update({'linewidths': linewidths})
  4020. kwargs = cbook.normalize_kwargs(kwargs, mcoll.Collection)
  4021. # re direct linewidth and edgecolor so it can be
  4022. # further processed by the rest of the function
  4023. linewidths = kwargs.pop('linewidth', None)
  4024. edgecolors = kwargs.pop('edgecolor', None)
  4025. # Process **kwargs to handle aliases, conflicts with explicit kwargs:
  4026. x, y = self._process_unit_info([("x", x), ("y", y)], kwargs)
  4027. # np.ma.ravel yields an ndarray, not a masked array,
  4028. # unless its argument is a masked array.
  4029. x = np.ma.ravel(x)
  4030. y = np.ma.ravel(y)
  4031. if x.size != y.size:
  4032. raise ValueError("x and y must be the same size")
  4033. if s is None:
  4034. s = (20 if mpl.rcParams['_internal.classic_mode'] else
  4035. mpl.rcParams['lines.markersize'] ** 2.0)
  4036. s = np.ma.ravel(s)
  4037. if (len(s) not in (1, x.size) or
  4038. (not np.issubdtype(s.dtype, np.floating) and
  4039. not np.issubdtype(s.dtype, np.integer))):
  4040. raise ValueError(
  4041. "s must be a scalar, "
  4042. "or float array-like with the same size as x and y")
  4043. # get the original edgecolor the user passed before we normalize
  4044. orig_edgecolor = edgecolors
  4045. if edgecolors is None:
  4046. orig_edgecolor = kwargs.get('edgecolor', None)
  4047. c, colors, edgecolors = \
  4048. self._parse_scatter_color_args(
  4049. c, edgecolors, kwargs, x.size,
  4050. get_next_color_func=self._get_patches_for_fill.get_next_color)
  4051. if plotnonfinite and colors is None:
  4052. c = np.ma.masked_invalid(c)
  4053. x, y, s, edgecolors, linewidths = \
  4054. cbook._combine_masks(x, y, s, edgecolors, linewidths)
  4055. else:
  4056. x, y, s, c, colors, edgecolors, linewidths = \
  4057. cbook._combine_masks(
  4058. x, y, s, c, colors, edgecolors, linewidths)
  4059. # Unmask edgecolors if it was actually a single RGB or RGBA.
  4060. if (x.size in (3, 4)
  4061. and np.ma.is_masked(edgecolors)
  4062. and not np.ma.is_masked(orig_edgecolor)):
  4063. edgecolors = edgecolors.data
  4064. scales = s # Renamed for readability below.
  4065. # load default marker from rcParams
  4066. if marker is None:
  4067. marker = mpl.rcParams['scatter.marker']
  4068. if isinstance(marker, mmarkers.MarkerStyle):
  4069. marker_obj = marker
  4070. else:
  4071. marker_obj = mmarkers.MarkerStyle(marker)
  4072. path = marker_obj.get_path().transformed(
  4073. marker_obj.get_transform())
  4074. if not marker_obj.is_filled():
  4075. if orig_edgecolor is not None:
  4076. _api.warn_external(
  4077. f"You passed a edgecolor/edgecolors ({orig_edgecolor!r}) "
  4078. f"for an unfilled marker ({marker!r}). Matplotlib is "
  4079. "ignoring the edgecolor in favor of the facecolor. This "
  4080. "behavior may change in the future."
  4081. )
  4082. # We need to handle markers that cannot be filled (like
  4083. # '+' and 'x') differently than markers that can be
  4084. # filled, but have their fillstyle set to 'none'. This is
  4085. # to get:
  4086. #
  4087. # - respecting the fillestyle if set
  4088. # - maintaining back-compatibility for querying the facecolor of
  4089. # the un-fillable markers.
  4090. #
  4091. # While not an ideal situation, but is better than the
  4092. # alternatives.
  4093. if marker_obj.get_fillstyle() == 'none':
  4094. # promote the facecolor to be the edgecolor
  4095. edgecolors = colors
  4096. # set the facecolor to 'none' (at the last chance) because
  4097. # we cannot fill a path if the facecolor is non-null
  4098. # (which is defendable at the renderer level).
  4099. colors = 'none'
  4100. else:
  4101. # if we are not nulling the face color we can do this
  4102. # simpler
  4103. edgecolors = 'face'
  4104. if linewidths is None:
  4105. linewidths = mpl.rcParams['lines.linewidth']
  4106. elif np.iterable(linewidths):
  4107. linewidths = [
  4108. lw if lw is not None else mpl.rcParams['lines.linewidth']
  4109. for lw in linewidths]
  4110. offsets = np.ma.column_stack([x, y])
  4111. collection = mcoll.PathCollection(
  4112. (path,), scales,
  4113. facecolors=colors,
  4114. edgecolors=edgecolors,
  4115. linewidths=linewidths,
  4116. offsets=offsets,
  4117. offset_transform=kwargs.pop('transform', self.transData),
  4118. alpha=alpha,
  4119. )
  4120. collection.set_transform(mtransforms.IdentityTransform())
  4121. if colors is None:
  4122. if colorizer:
  4123. collection._set_colorizer_check_keywords(colorizer, cmap=cmap,
  4124. norm=norm, vmin=vmin,
  4125. vmax=vmax)
  4126. else:
  4127. collection.set_cmap(cmap)
  4128. collection.set_norm(norm)
  4129. collection.set_array(c)
  4130. collection._scale_norm(norm, vmin, vmax)
  4131. else:
  4132. extra_kwargs = {
  4133. 'cmap': cmap, 'norm': norm, 'vmin': vmin, 'vmax': vmax
  4134. }
  4135. extra_keys = [k for k, v in extra_kwargs.items() if v is not None]
  4136. if any(extra_keys):
  4137. keys_str = ", ".join(f"'{k}'" for k in extra_keys)
  4138. _api.warn_external(
  4139. "No data for colormapping provided via 'c'. "
  4140. f"Parameters {keys_str} will be ignored")
  4141. collection._internal_update(kwargs)
  4142. # Classic mode only:
  4143. # ensure there are margins to allow for the
  4144. # finite size of the symbols. In v2.x, margins
  4145. # are present by default, so we disable this
  4146. # scatter-specific override.
  4147. if mpl.rcParams['_internal.classic_mode']:
  4148. if self._xmargin < 0.05 and x.size > 0:
  4149. self.set_xmargin(0.05)
  4150. if self._ymargin < 0.05 and x.size > 0:
  4151. self.set_ymargin(0.05)
  4152. self.add_collection(collection)
  4153. self._request_autoscale_view()
  4154. return collection
  4155. @_api.make_keyword_only("3.10", "gridsize")
  4156. @_preprocess_data(replace_names=["x", "y", "C"], label_namer="y")
  4157. @_docstring.interpd
  4158. def hexbin(self, x, y, C=None, gridsize=100, bins=None,
  4159. xscale='linear', yscale='linear', extent=None,
  4160. cmap=None, norm=None, vmin=None, vmax=None,
  4161. alpha=None, linewidths=None, edgecolors='face',
  4162. reduce_C_function=np.mean, mincnt=None, marginals=False,
  4163. colorizer=None, **kwargs):
  4164. """
  4165. Make a 2D hexagonal binning plot of points *x*, *y*.
  4166. If *C* is *None*, the value of the hexagon is determined by the number
  4167. of points in the hexagon. Otherwise, *C* specifies values at the
  4168. coordinate (x[i], y[i]). For each hexagon, these values are reduced
  4169. using *reduce_C_function*.
  4170. Parameters
  4171. ----------
  4172. x, y : array-like
  4173. The data positions. *x* and *y* must be of the same length.
  4174. C : array-like, optional
  4175. If given, these values are accumulated in the bins. Otherwise,
  4176. every point has a value of 1. Must be of the same length as *x*
  4177. and *y*.
  4178. gridsize : int or (int, int), default: 100
  4179. If a single int, the number of hexagons in the *x*-direction.
  4180. The number of hexagons in the *y*-direction is chosen such that
  4181. the hexagons are approximately regular.
  4182. Alternatively, if a tuple (*nx*, *ny*), the number of hexagons
  4183. in the *x*-direction and the *y*-direction. In the
  4184. *y*-direction, counting is done along vertically aligned
  4185. hexagons, not along the zig-zag chains of hexagons; see the
  4186. following illustration.
  4187. .. plot::
  4188. import numpy
  4189. import matplotlib.pyplot as plt
  4190. np.random.seed(19680801)
  4191. n= 300
  4192. x = np.random.standard_normal(n)
  4193. y = np.random.standard_normal(n)
  4194. fig, ax = plt.subplots(figsize=(4, 4))
  4195. h = ax.hexbin(x, y, gridsize=(5, 3))
  4196. hx, hy = h.get_offsets().T
  4197. ax.plot(hx[24::3], hy[24::3], 'ro-')
  4198. ax.plot(hx[-3:], hy[-3:], 'ro-')
  4199. ax.set_title('gridsize=(5, 3)')
  4200. ax.axis('off')
  4201. To get approximately regular hexagons, choose
  4202. :math:`n_x = \\sqrt{3}\\,n_y`.
  4203. bins : 'log' or int or sequence, default: None
  4204. Discretization of the hexagon values.
  4205. - If *None*, no binning is applied; the color of each hexagon
  4206. directly corresponds to its count value.
  4207. - If 'log', use a logarithmic scale for the colormap.
  4208. Internally, :math:`log_{10}(i+1)` is used to determine the
  4209. hexagon color. This is equivalent to ``norm=LogNorm()``.
  4210. - If an integer, divide the counts in the specified number
  4211. of bins, and color the hexagons accordingly.
  4212. - If a sequence of values, the values of the lower bound of
  4213. the bins to be used.
  4214. xscale : {'linear', 'log'}, default: 'linear'
  4215. Use a linear or log10 scale on the horizontal axis.
  4216. yscale : {'linear', 'log'}, default: 'linear'
  4217. Use a linear or log10 scale on the vertical axis.
  4218. mincnt : int >= 0, default: *None*
  4219. If not *None*, only display cells with at least *mincnt*
  4220. number of points in the cell.
  4221. marginals : bool, default: *False*
  4222. If marginals is *True*, plot the marginal density as
  4223. colormapped rectangles along the bottom of the x-axis and
  4224. left of the y-axis.
  4225. extent : 4-tuple of float, default: *None*
  4226. The limits of the bins (xmin, xmax, ymin, ymax).
  4227. The default assigns the limits based on
  4228. *gridsize*, *x*, *y*, *xscale* and *yscale*.
  4229. If *xscale* or *yscale* is set to 'log', the limits are
  4230. expected to be the exponent for a power of 10. E.g. for
  4231. x-limits of 1 and 50 in 'linear' scale and y-limits
  4232. of 10 and 1000 in 'log' scale, enter (1, 50, 1, 3).
  4233. Returns
  4234. -------
  4235. `~matplotlib.collections.PolyCollection`
  4236. A `.PolyCollection` defining the hexagonal bins.
  4237. - `.PolyCollection.get_offsets` contains a Mx2 array containing
  4238. the x, y positions of the M hexagon centers in data coordinates.
  4239. - `.PolyCollection.get_array` contains the values of the M
  4240. hexagons.
  4241. If *marginals* is *True*, horizontal
  4242. bar and vertical bar (both PolyCollections) will be attached
  4243. to the return collection as attributes *hbar* and *vbar*.
  4244. Other Parameters
  4245. ----------------
  4246. %(cmap_doc)s
  4247. %(norm_doc)s
  4248. %(vmin_vmax_doc)s
  4249. alpha : float between 0 and 1, optional
  4250. The alpha blending value, between 0 (transparent) and 1 (opaque).
  4251. linewidths : float, default: *None*
  4252. If *None*, defaults to :rc:`patch.linewidth`.
  4253. edgecolors : {'face', 'none', *None*} or color, default: 'face'
  4254. The color of the hexagon edges. Possible values are:
  4255. - 'face': Draw the edges in the same color as the fill color.
  4256. - 'none': No edges are drawn. This can sometimes lead to unsightly
  4257. unpainted pixels between the hexagons.
  4258. - *None*: Draw outlines in the default color.
  4259. - An explicit color.
  4260. reduce_C_function : callable, default: `numpy.mean`
  4261. The function to aggregate *C* within the bins. It is ignored if
  4262. *C* is not given. This must have the signature::
  4263. def reduce_C_function(C: array) -> float
  4264. Commonly used functions are:
  4265. - `numpy.mean`: average of the points
  4266. - `numpy.sum`: integral of the point values
  4267. - `numpy.amax`: value taken from the largest point
  4268. By default will only reduce cells with at least 1 point because some
  4269. reduction functions (such as `numpy.amax`) will error/warn with empty
  4270. input. Changing *mincnt* will adjust the cutoff, and if set to 0 will
  4271. pass empty input to the reduction function.
  4272. %(colorizer_doc)s
  4273. data : indexable object, optional
  4274. DATA_PARAMETER_PLACEHOLDER
  4275. **kwargs : `~matplotlib.collections.PolyCollection` properties
  4276. All other keyword arguments are passed on to `.PolyCollection`:
  4277. %(PolyCollection:kwdoc)s
  4278. See Also
  4279. --------
  4280. hist2d : 2D histogram rectangular bins
  4281. """
  4282. self._process_unit_info([("x", x), ("y", y)], kwargs, convert=False)
  4283. x, y, C = cbook.delete_masked_points(x, y, C)
  4284. # Set the size of the hexagon grid
  4285. if np.iterable(gridsize):
  4286. nx, ny = gridsize
  4287. else:
  4288. nx = gridsize
  4289. ny = int(nx / math.sqrt(3))
  4290. # Count the number of data in each hexagon
  4291. x = np.asarray(x, float)
  4292. y = np.asarray(y, float)
  4293. # Will be log()'d if necessary, and then rescaled.
  4294. tx = x
  4295. ty = y
  4296. if xscale == 'log':
  4297. if np.any(x <= 0.0):
  4298. raise ValueError(
  4299. "x contains non-positive values, so cannot be log-scaled")
  4300. tx = np.log10(tx)
  4301. if yscale == 'log':
  4302. if np.any(y <= 0.0):
  4303. raise ValueError(
  4304. "y contains non-positive values, so cannot be log-scaled")
  4305. ty = np.log10(ty)
  4306. if extent is not None:
  4307. xmin, xmax, ymin, ymax = extent
  4308. if xmin > xmax:
  4309. raise ValueError("In extent, xmax must be greater than xmin")
  4310. if ymin > ymax:
  4311. raise ValueError("In extent, ymax must be greater than ymin")
  4312. else:
  4313. xmin, xmax = (tx.min(), tx.max()) if len(x) else (0, 1)
  4314. ymin, ymax = (ty.min(), ty.max()) if len(y) else (0, 1)
  4315. # to avoid issues with singular data, expand the min/max pairs
  4316. xmin, xmax = mtransforms.nonsingular(xmin, xmax, expander=0.1)
  4317. ymin, ymax = mtransforms.nonsingular(ymin, ymax, expander=0.1)
  4318. nx1 = nx + 1
  4319. ny1 = ny + 1
  4320. nx2 = nx
  4321. ny2 = ny
  4322. n = nx1 * ny1 + nx2 * ny2
  4323. # In the x-direction, the hexagons exactly cover the region from
  4324. # xmin to xmax. Need some padding to avoid roundoff errors.
  4325. padding = 1.e-9 * (xmax - xmin)
  4326. xmin -= padding
  4327. xmax += padding
  4328. sx = (xmax - xmin) / nx
  4329. sy = (ymax - ymin) / ny
  4330. # Positions in hexagon index coordinates.
  4331. ix = (tx - xmin) / sx
  4332. iy = (ty - ymin) / sy
  4333. ix1 = np.round(ix).astype(int)
  4334. iy1 = np.round(iy).astype(int)
  4335. ix2 = np.floor(ix).astype(int)
  4336. iy2 = np.floor(iy).astype(int)
  4337. # flat indices, plus one so that out-of-range points go to position 0.
  4338. i1 = np.where((0 <= ix1) & (ix1 < nx1) & (0 <= iy1) & (iy1 < ny1),
  4339. ix1 * ny1 + iy1 + 1, 0)
  4340. i2 = np.where((0 <= ix2) & (ix2 < nx2) & (0 <= iy2) & (iy2 < ny2),
  4341. ix2 * ny2 + iy2 + 1, 0)
  4342. d1 = (ix - ix1) ** 2 + 3.0 * (iy - iy1) ** 2
  4343. d2 = (ix - ix2 - 0.5) ** 2 + 3.0 * (iy - iy2 - 0.5) ** 2
  4344. bdist = (d1 < d2)
  4345. if C is None: # [1:] drops out-of-range points.
  4346. counts1 = np.bincount(i1[bdist], minlength=1 + nx1 * ny1)[1:]
  4347. counts2 = np.bincount(i2[~bdist], minlength=1 + nx2 * ny2)[1:]
  4348. accum = np.concatenate([counts1, counts2]).astype(float)
  4349. if mincnt is not None:
  4350. accum[accum < mincnt] = np.nan
  4351. C = np.ones(len(x))
  4352. else:
  4353. # store the C values in a list per hexagon index
  4354. Cs_at_i1 = [[] for _ in range(1 + nx1 * ny1)]
  4355. Cs_at_i2 = [[] for _ in range(1 + nx2 * ny2)]
  4356. for i in range(len(x)):
  4357. if bdist[i]:
  4358. Cs_at_i1[i1[i]].append(C[i])
  4359. else:
  4360. Cs_at_i2[i2[i]].append(C[i])
  4361. if mincnt is None:
  4362. mincnt = 1
  4363. accum = np.array(
  4364. [reduce_C_function(acc) if len(acc) >= mincnt else np.nan
  4365. for Cs_at_i in [Cs_at_i1, Cs_at_i2]
  4366. for acc in Cs_at_i[1:]], # [1:] drops out-of-range points.
  4367. float)
  4368. good_idxs = ~np.isnan(accum)
  4369. offsets = np.zeros((n, 2), float)
  4370. offsets[:nx1 * ny1, 0] = np.repeat(np.arange(nx1), ny1)
  4371. offsets[:nx1 * ny1, 1] = np.tile(np.arange(ny1), nx1)
  4372. offsets[nx1 * ny1:, 0] = np.repeat(np.arange(nx2) + 0.5, ny2)
  4373. offsets[nx1 * ny1:, 1] = np.tile(np.arange(ny2), nx2) + 0.5
  4374. offsets[:, 0] *= sx
  4375. offsets[:, 1] *= sy
  4376. offsets[:, 0] += xmin
  4377. offsets[:, 1] += ymin
  4378. # remove accumulation bins with no data
  4379. offsets = offsets[good_idxs, :]
  4380. accum = accum[good_idxs]
  4381. polygon = [sx, sy / 3] * np.array(
  4382. [[.5, -.5], [.5, .5], [0., 1.], [-.5, .5], [-.5, -.5], [0., -1.]])
  4383. if linewidths is None:
  4384. linewidths = [mpl.rcParams['patch.linewidth']]
  4385. if xscale == 'log' or yscale == 'log':
  4386. polygons = np.expand_dims(polygon, 0)
  4387. if xscale == 'log':
  4388. polygons[:, :, 0] = 10.0 ** polygons[:, :, 0]
  4389. xmin = 10.0 ** xmin
  4390. xmax = 10.0 ** xmax
  4391. self.set_xscale(xscale)
  4392. if yscale == 'log':
  4393. polygons[:, :, 1] = 10.0 ** polygons[:, :, 1]
  4394. ymin = 10.0 ** ymin
  4395. ymax = 10.0 ** ymax
  4396. self.set_yscale(yscale)
  4397. else:
  4398. polygons = [polygon]
  4399. collection = mcoll.PolyCollection(
  4400. polygons,
  4401. edgecolors=edgecolors,
  4402. linewidths=linewidths,
  4403. offsets=offsets,
  4404. offset_transform=mtransforms.AffineDeltaTransform(self.transData)
  4405. )
  4406. # Set normalizer if bins is 'log'
  4407. if cbook._str_equal(bins, 'log'):
  4408. if norm is not None:
  4409. _api.warn_external("Only one of 'bins' and 'norm' arguments "
  4410. f"can be supplied, ignoring {bins=}")
  4411. else:
  4412. norm = mcolors.LogNorm(vmin=vmin, vmax=vmax)
  4413. vmin = vmax = None
  4414. bins = None
  4415. if bins is not None:
  4416. if not np.iterable(bins):
  4417. minimum, maximum = min(accum), max(accum)
  4418. bins -= 1 # one less edge than bins
  4419. bins = minimum + (maximum - minimum) * np.arange(bins) / bins
  4420. bins = np.sort(bins)
  4421. accum = bins.searchsorted(accum)
  4422. if colorizer:
  4423. collection._set_colorizer_check_keywords(colorizer, cmap=cmap,
  4424. norm=norm, vmin=vmin,
  4425. vmax=vmax)
  4426. else:
  4427. collection.set_cmap(cmap)
  4428. collection.set_norm(norm)
  4429. collection.set_array(accum)
  4430. collection.set_alpha(alpha)
  4431. collection._internal_update(kwargs)
  4432. collection._scale_norm(norm, vmin, vmax)
  4433. # autoscale the norm with current accum values if it hasn't been set
  4434. if norm is not None:
  4435. if collection.norm.vmin is None and collection.norm.vmax is None:
  4436. collection.norm.autoscale()
  4437. corners = ((xmin, ymin), (xmax, ymax))
  4438. self.update_datalim(corners)
  4439. self._request_autoscale_view(tight=True)
  4440. # add the collection last
  4441. self.add_collection(collection, autolim=False)
  4442. if not marginals:
  4443. return collection
  4444. # Process marginals
  4445. bars = []
  4446. for zname, z, zmin, zmax, zscale, nbins in [
  4447. ("x", x, xmin, xmax, xscale, nx),
  4448. ("y", y, ymin, ymax, yscale, 2 * ny),
  4449. ]:
  4450. if zscale == "log":
  4451. bin_edges = np.geomspace(zmin, zmax, nbins + 1)
  4452. else:
  4453. bin_edges = np.linspace(zmin, zmax, nbins + 1)
  4454. verts = np.empty((nbins, 4, 2))
  4455. verts[:, 0, 0] = verts[:, 1, 0] = bin_edges[:-1]
  4456. verts[:, 2, 0] = verts[:, 3, 0] = bin_edges[1:]
  4457. verts[:, 0, 1] = verts[:, 3, 1] = .00
  4458. verts[:, 1, 1] = verts[:, 2, 1] = .05
  4459. if zname == "y":
  4460. verts = verts[:, :, ::-1] # Swap x and y.
  4461. # Sort z-values into bins defined by bin_edges.
  4462. bin_idxs = np.searchsorted(bin_edges, z) - 1
  4463. values = np.empty(nbins)
  4464. for i in range(nbins):
  4465. # Get C-values for each bin, and compute bin value with
  4466. # reduce_C_function.
  4467. ci = C[bin_idxs == i]
  4468. values[i] = reduce_C_function(ci) if len(ci) > 0 else np.nan
  4469. mask = ~np.isnan(values)
  4470. verts = verts[mask]
  4471. values = values[mask]
  4472. trans = getattr(self, f"get_{zname}axis_transform")(which="grid")
  4473. bar = mcoll.PolyCollection(
  4474. verts, transform=trans, edgecolors="face")
  4475. bar.set_array(values)
  4476. bar.set_cmap(cmap)
  4477. bar.set_norm(norm)
  4478. bar.set_alpha(alpha)
  4479. bar._internal_update(kwargs)
  4480. bars.append(self.add_collection(bar, autolim=False))
  4481. collection.hbar, collection.vbar = bars
  4482. def on_changed(collection):
  4483. collection.hbar.set_cmap(collection.get_cmap())
  4484. collection.hbar.set_cmap(collection.get_cmap())
  4485. collection.vbar.set_clim(collection.get_clim())
  4486. collection.vbar.set_clim(collection.get_clim())
  4487. collection.callbacks.connect('changed', on_changed)
  4488. return collection
  4489. @_docstring.interpd
  4490. def arrow(self, x, y, dx, dy, **kwargs):
  4491. """
  4492. [*Discouraged*] Add an arrow to the Axes.
  4493. This draws an arrow from ``(x, y)`` to ``(x+dx, y+dy)``.
  4494. .. admonition:: Discouraged
  4495. The use of this method is discouraged because it is not guaranteed
  4496. that the arrow renders reasonably. For example, the resulting arrow
  4497. is affected by the Axes aspect ratio and limits, which may distort
  4498. the arrow.
  4499. Consider using `~.Axes.annotate` without a text instead, e.g. ::
  4500. ax.annotate("", xytext=(0, 0), xy=(0.5, 0.5),
  4501. arrowprops=dict(arrowstyle="->"))
  4502. Parameters
  4503. ----------
  4504. %(FancyArrow)s
  4505. Returns
  4506. -------
  4507. `.FancyArrow`
  4508. The created `.FancyArrow` object.
  4509. """
  4510. # Strip away units for the underlying patch since units
  4511. # do not make sense to most patch-like code
  4512. x = self.convert_xunits(x)
  4513. y = self.convert_yunits(y)
  4514. dx = self.convert_xunits(dx)
  4515. dy = self.convert_yunits(dy)
  4516. a = mpatches.FancyArrow(x, y, dx, dy, **kwargs)
  4517. self.add_patch(a)
  4518. self._request_autoscale_view()
  4519. return a
  4520. @_docstring.copy(mquiver.QuiverKey.__init__)
  4521. def quiverkey(self, Q, X, Y, U, label, **kwargs):
  4522. qk = mquiver.QuiverKey(Q, X, Y, U, label, **kwargs)
  4523. self.add_artist(qk)
  4524. return qk
  4525. # Handle units for x and y, if they've been passed
  4526. def _quiver_units(self, args, kwargs):
  4527. if len(args) > 3:
  4528. x, y = args[0:2]
  4529. x, y = self._process_unit_info([("x", x), ("y", y)], kwargs)
  4530. return (x, y) + args[2:]
  4531. return args
  4532. # args can be a combination of X, Y, U, V, C and all should be replaced
  4533. @_preprocess_data()
  4534. @_docstring.interpd
  4535. def quiver(self, *args, **kwargs):
  4536. """%(quiver_doc)s"""
  4537. # Make sure units are handled for x and y values
  4538. args = self._quiver_units(args, kwargs)
  4539. q = mquiver.Quiver(self, *args, **kwargs)
  4540. self.add_collection(q, autolim=True)
  4541. self._request_autoscale_view()
  4542. return q
  4543. # args can be some combination of X, Y, U, V, C and all should be replaced
  4544. @_preprocess_data()
  4545. @_docstring.interpd
  4546. def barbs(self, *args, **kwargs):
  4547. """%(barbs_doc)s"""
  4548. # Make sure units are handled for x and y values
  4549. args = self._quiver_units(args, kwargs)
  4550. b = mquiver.Barbs(self, *args, **kwargs)
  4551. self.add_collection(b, autolim=True)
  4552. self._request_autoscale_view()
  4553. return b
  4554. # Uses a custom implementation of data-kwarg handling in
  4555. # _process_plot_var_args.
  4556. def fill(self, *args, data=None, **kwargs):
  4557. """
  4558. Plot filled polygons.
  4559. Parameters
  4560. ----------
  4561. *args : sequence of x, y, [color]
  4562. Each polygon is defined by the lists of *x* and *y* positions of
  4563. its nodes, optionally followed by a *color* specifier. See
  4564. :mod:`matplotlib.colors` for supported color specifiers. The
  4565. standard color cycle is used for polygons without a color
  4566. specifier.
  4567. You can plot multiple polygons by providing multiple *x*, *y*,
  4568. *[color]* groups.
  4569. For example, each of the following is legal::
  4570. ax.fill(x, y) # a polygon with default color
  4571. ax.fill(x, y, "b") # a blue polygon
  4572. ax.fill(x, y, x2, y2) # two polygons
  4573. ax.fill(x, y, "b", x2, y2, "r") # a blue and a red polygon
  4574. data : indexable object, optional
  4575. An object with labelled data. If given, provide the label names to
  4576. plot in *x* and *y*, e.g.::
  4577. ax.fill("time", "signal",
  4578. data={"time": [0, 1, 2], "signal": [0, 1, 0]})
  4579. Returns
  4580. -------
  4581. list of `~matplotlib.patches.Polygon`
  4582. Other Parameters
  4583. ----------------
  4584. **kwargs : `~matplotlib.patches.Polygon` properties
  4585. Notes
  4586. -----
  4587. Use :meth:`fill_between` if you would like to fill the region between
  4588. two curves.
  4589. """
  4590. # For compatibility(!), get aliases from Line2D rather than Patch.
  4591. kwargs = cbook.normalize_kwargs(kwargs, mlines.Line2D)
  4592. # _get_patches_for_fill returns a generator, convert it to a list.
  4593. patches = [*self._get_patches_for_fill(self, *args, data=data, **kwargs)]
  4594. for poly in patches:
  4595. self.add_patch(poly)
  4596. self._request_autoscale_view()
  4597. return patches
  4598. def _fill_between_x_or_y(
  4599. self, ind_dir, ind, dep1, dep2=0, *,
  4600. where=None, interpolate=False, step=None, **kwargs):
  4601. # Common implementation between fill_between (*ind_dir*="x") and
  4602. # fill_betweenx (*ind_dir*="y"). *ind* is the independent variable,
  4603. # *dep* the dependent variable. The docstring below is interpolated
  4604. # to generate both methods' docstrings.
  4605. """
  4606. Fill the area between two {dir} curves.
  4607. The curves are defined by the points (*{ind}*, *{dep}1*) and (*{ind}*,
  4608. *{dep}2*). This creates one or multiple polygons describing the filled
  4609. area.
  4610. You may exclude some {dir} sections from filling using *where*.
  4611. By default, the edges connect the given points directly. Use *step*
  4612. if the filling should be a step function, i.e. constant in between
  4613. *{ind}*.
  4614. Parameters
  4615. ----------
  4616. {ind} : array-like
  4617. The {ind} coordinates of the nodes defining the curves.
  4618. {dep}1 : array-like or float
  4619. The {dep} coordinates of the nodes defining the first curve.
  4620. {dep}2 : array-like or float, default: 0
  4621. The {dep} coordinates of the nodes defining the second curve.
  4622. where : array-like of bool, optional
  4623. Define *where* to exclude some {dir} regions from being filled.
  4624. The filled regions are defined by the coordinates ``{ind}[where]``.
  4625. More precisely, fill between ``{ind}[i]`` and ``{ind}[i+1]`` if
  4626. ``where[i] and where[i+1]``. Note that this definition implies
  4627. that an isolated *True* value between two *False* values in *where*
  4628. will not result in filling. Both sides of the *True* position
  4629. remain unfilled due to the adjacent *False* values.
  4630. interpolate : bool, default: False
  4631. This option is only relevant if *where* is used and the two curves
  4632. are crossing each other.
  4633. Semantically, *where* is often used for *{dep}1* > *{dep}2* or
  4634. similar. By default, the nodes of the polygon defining the filled
  4635. region will only be placed at the positions in the *{ind}* array.
  4636. Such a polygon cannot describe the above semantics close to the
  4637. intersection. The {ind}-sections containing the intersection are
  4638. simply clipped.
  4639. Setting *interpolate* to *True* will calculate the actual
  4640. intersection point and extend the filled region up to this point.
  4641. step : {{'pre', 'post', 'mid'}}, optional
  4642. Define *step* if the filling should be a step function,
  4643. i.e. constant in between *{ind}*. The value determines where the
  4644. step will occur:
  4645. - 'pre': The {dep} value is continued constantly to the left from
  4646. every *{ind}* position, i.e. the interval ``({ind}[i-1], {ind}[i]]``
  4647. has the value ``{dep}[i]``.
  4648. - 'post': The y value is continued constantly to the right from
  4649. every *{ind}* position, i.e. the interval ``[{ind}[i], {ind}[i+1])``
  4650. has the value ``{dep}[i]``.
  4651. - 'mid': Steps occur half-way between the *{ind}* positions.
  4652. Returns
  4653. -------
  4654. `.FillBetweenPolyCollection`
  4655. A `.FillBetweenPolyCollection` containing the plotted polygons.
  4656. Other Parameters
  4657. ----------------
  4658. data : indexable object, optional
  4659. DATA_PARAMETER_PLACEHOLDER
  4660. **kwargs
  4661. All other keyword arguments are passed on to
  4662. `.FillBetweenPolyCollection`. They control the `.Polygon` properties:
  4663. %(FillBetweenPolyCollection:kwdoc)s
  4664. See Also
  4665. --------
  4666. fill_between : Fill between two sets of y-values.
  4667. fill_betweenx : Fill between two sets of x-values.
  4668. """
  4669. dep_dir = mcoll.FillBetweenPolyCollection._f_dir_from_t(ind_dir)
  4670. if not mpl.rcParams["_internal.classic_mode"]:
  4671. kwargs = cbook.normalize_kwargs(kwargs, mcoll.Collection)
  4672. if not any(c in kwargs for c in ("color", "facecolor")):
  4673. kwargs["facecolor"] = self._get_patches_for_fill.get_next_color()
  4674. ind, dep1, dep2 = self._fill_between_process_units(
  4675. ind_dir, dep_dir, ind, dep1, dep2, **kwargs)
  4676. collection = mcoll.FillBetweenPolyCollection(
  4677. ind_dir, ind, dep1, dep2,
  4678. where=where, interpolate=interpolate, step=step, **kwargs)
  4679. self.add_collection(collection)
  4680. self._request_autoscale_view()
  4681. return collection
  4682. def _fill_between_process_units(self, ind_dir, dep_dir, ind, dep1, dep2, **kwargs):
  4683. """Handle united data, such as dates."""
  4684. return map(np.ma.masked_invalid, self._process_unit_info(
  4685. [(ind_dir, ind), (dep_dir, dep1), (dep_dir, dep2)], kwargs))
  4686. def fill_between(self, x, y1, y2=0, where=None, interpolate=False,
  4687. step=None, **kwargs):
  4688. return self._fill_between_x_or_y(
  4689. "x", x, y1, y2,
  4690. where=where, interpolate=interpolate, step=step, **kwargs)
  4691. if _fill_between_x_or_y.__doc__:
  4692. fill_between.__doc__ = _fill_between_x_or_y.__doc__.format(
  4693. dir="horizontal", ind="x", dep="y"
  4694. )
  4695. fill_between = _preprocess_data(
  4696. _docstring.interpd(fill_between),
  4697. replace_names=["x", "y1", "y2", "where"])
  4698. def fill_betweenx(self, y, x1, x2=0, where=None,
  4699. step=None, interpolate=False, **kwargs):
  4700. return self._fill_between_x_or_y(
  4701. "y", y, x1, x2,
  4702. where=where, interpolate=interpolate, step=step, **kwargs)
  4703. if _fill_between_x_or_y.__doc__:
  4704. fill_betweenx.__doc__ = _fill_between_x_or_y.__doc__.format(
  4705. dir="vertical", ind="y", dep="x"
  4706. )
  4707. fill_betweenx = _preprocess_data(
  4708. _docstring.interpd(fill_betweenx),
  4709. replace_names=["y", "x1", "x2", "where"])
  4710. #### plotting z(x, y): imshow, pcolor and relatives, contour
  4711. @_preprocess_data()
  4712. @_docstring.interpd
  4713. def imshow(self, X, cmap=None, norm=None, *, aspect=None,
  4714. interpolation=None, alpha=None,
  4715. vmin=None, vmax=None, colorizer=None, origin=None, extent=None,
  4716. interpolation_stage=None, filternorm=True, filterrad=4.0,
  4717. resample=None, url=None, **kwargs):
  4718. """
  4719. Display data as an image, i.e., on a 2D regular raster.
  4720. The input may either be actual RGB(A) data, or 2D scalar data, which
  4721. will be rendered as a pseudocolor image. For displaying a grayscale
  4722. image, set up the colormapping using the parameters
  4723. ``cmap='gray', vmin=0, vmax=255``.
  4724. The number of pixels used to render an image is set by the Axes size
  4725. and the figure *dpi*. This can lead to aliasing artifacts when
  4726. the image is resampled, because the displayed image size will usually
  4727. not match the size of *X* (see
  4728. :doc:`/gallery/images_contours_and_fields/image_antialiasing`).
  4729. The resampling can be controlled via the *interpolation* parameter
  4730. and/or :rc:`image.interpolation`.
  4731. Parameters
  4732. ----------
  4733. X : array-like or PIL image
  4734. The image data. Supported array shapes are:
  4735. - (M, N): an image with scalar data. The values are mapped to
  4736. colors using normalization and a colormap. See parameters *norm*,
  4737. *cmap*, *vmin*, *vmax*.
  4738. - (M, N, 3): an image with RGB values (0-1 float or 0-255 int).
  4739. - (M, N, 4): an image with RGBA values (0-1 float or 0-255 int),
  4740. i.e. including transparency.
  4741. The first two dimensions (M, N) define the rows and columns of
  4742. the image.
  4743. Out-of-range RGB(A) values are clipped.
  4744. %(cmap_doc)s
  4745. This parameter is ignored if *X* is RGB(A).
  4746. %(norm_doc)s
  4747. This parameter is ignored if *X* is RGB(A).
  4748. %(vmin_vmax_doc)s
  4749. This parameter is ignored if *X* is RGB(A).
  4750. %(colorizer_doc)s
  4751. This parameter is ignored if *X* is RGB(A).
  4752. aspect : {'equal', 'auto'} or float or None, default: None
  4753. The aspect ratio of the Axes. This parameter is particularly
  4754. relevant for images since it determines whether data pixels are
  4755. square.
  4756. This parameter is a shortcut for explicitly calling
  4757. `.Axes.set_aspect`. See there for further details.
  4758. - 'equal': Ensures an aspect ratio of 1. Pixels will be square
  4759. (unless pixel sizes are explicitly made non-square in data
  4760. coordinates using *extent*).
  4761. - 'auto': The Axes is kept fixed and the aspect is adjusted so
  4762. that the data fit in the Axes. In general, this will result in
  4763. non-square pixels.
  4764. Normally, None (the default) means to use :rc:`image.aspect`. However, if
  4765. the image uses a transform that does not contain the axes data transform,
  4766. then None means to not modify the axes aspect at all (in that case, directly
  4767. call `.Axes.set_aspect` if desired).
  4768. interpolation : str, default: :rc:`image.interpolation`
  4769. The interpolation method used.
  4770. Supported values are 'none', 'auto', 'nearest', 'bilinear',
  4771. 'bicubic', 'spline16', 'spline36', 'hanning', 'hamming', 'hermite',
  4772. 'kaiser', 'quadric', 'catrom', 'gaussian', 'bessel', 'mitchell',
  4773. 'sinc', 'lanczos', 'blackman'.
  4774. The data *X* is resampled to the pixel size of the image on the
  4775. figure canvas, using the interpolation method to either up- or
  4776. downsample the data.
  4777. If *interpolation* is 'none', then for the ps, pdf, and svg
  4778. backends no down- or upsampling occurs, and the image data is
  4779. passed to the backend as a native image. Note that different ps,
  4780. pdf, and svg viewers may display these raw pixels differently. On
  4781. other backends, 'none' is the same as 'nearest'.
  4782. If *interpolation* is the default 'auto', then 'nearest'
  4783. interpolation is used if the image is upsampled by more than a
  4784. factor of three (i.e. the number of display pixels is at least
  4785. three times the size of the data array). If the upsampling rate is
  4786. smaller than 3, or the image is downsampled, then 'hanning'
  4787. interpolation is used to act as an anti-aliasing filter, unless the
  4788. image happens to be upsampled by exactly a factor of two or one.
  4789. See
  4790. :doc:`/gallery/images_contours_and_fields/interpolation_methods`
  4791. for an overview of the supported interpolation methods, and
  4792. :doc:`/gallery/images_contours_and_fields/image_antialiasing` for
  4793. a discussion of image antialiasing.
  4794. Some interpolation methods require an additional radius parameter,
  4795. which can be set by *filterrad*. Additionally, the antigrain image
  4796. resize filter is controlled by the parameter *filternorm*.
  4797. interpolation_stage : {'auto', 'data', 'rgba'}, default: 'auto'
  4798. Supported values:
  4799. - 'data': Interpolation is carried out on the data provided by the user
  4800. This is useful if interpolating between pixels during upsampling.
  4801. - 'rgba': The interpolation is carried out in RGBA-space after the
  4802. color-mapping has been applied. This is useful if downsampling and
  4803. combining pixels visually.
  4804. - 'auto': Select a suitable interpolation stage automatically. This uses
  4805. 'rgba' when downsampling, or upsampling at a rate less than 3, and
  4806. 'data' when upsampling at a higher rate.
  4807. See :doc:`/gallery/images_contours_and_fields/image_antialiasing` for
  4808. a discussion of image antialiasing.
  4809. alpha : float or array-like, optional
  4810. The alpha blending value, between 0 (transparent) and 1 (opaque).
  4811. If *alpha* is an array, the alpha blending values are applied pixel
  4812. by pixel, and *alpha* must have the same shape as *X*.
  4813. origin : {'upper', 'lower'}, default: :rc:`image.origin`
  4814. Place the [0, 0] index of the array in the upper left or lower
  4815. left corner of the Axes. The convention (the default) 'upper' is
  4816. typically used for matrices and images.
  4817. Note that the vertical axis points upward for 'lower'
  4818. but downward for 'upper'.
  4819. See the :ref:`imshow_extent` tutorial for
  4820. examples and a more detailed description.
  4821. extent : floats (left, right, bottom, top), optional
  4822. The bounding box in data coordinates that the image will fill.
  4823. These values may be unitful and match the units of the Axes.
  4824. The image is stretched individually along x and y to fill the box.
  4825. The default extent is determined by the following conditions.
  4826. Pixels have unit size in data coordinates. Their centers are on
  4827. integer coordinates, and their center coordinates range from 0 to
  4828. columns-1 horizontally and from 0 to rows-1 vertically.
  4829. Note that the direction of the vertical axis and thus the default
  4830. values for top and bottom depend on *origin*:
  4831. - For ``origin == 'upper'`` the default is
  4832. ``(-0.5, numcols-0.5, numrows-0.5, -0.5)``.
  4833. - For ``origin == 'lower'`` the default is
  4834. ``(-0.5, numcols-0.5, -0.5, numrows-0.5)``.
  4835. See the :ref:`imshow_extent` tutorial for
  4836. examples and a more detailed description.
  4837. filternorm : bool, default: True
  4838. A parameter for the antigrain image resize filter (see the
  4839. antigrain documentation). If *filternorm* is set, the filter
  4840. normalizes integer values and corrects the rounding errors. It
  4841. doesn't do anything with the source floating point values, it
  4842. corrects only integers according to the rule of 1.0 which means
  4843. that any sum of pixel weights must be equal to 1.0. So, the
  4844. filter function must produce a graph of the proper shape.
  4845. filterrad : float > 0, default: 4.0
  4846. The filter radius for filters that have a radius parameter, i.e.
  4847. when interpolation is one of: 'sinc', 'lanczos' or 'blackman'.
  4848. resample : bool, default: :rc:`image.resample`
  4849. When *True*, use a full resampling method. When *False*, only
  4850. resample when the output image is larger than the input image.
  4851. url : str, optional
  4852. Set the url of the created `.AxesImage`. See `.Artist.set_url`.
  4853. Returns
  4854. -------
  4855. `~matplotlib.image.AxesImage`
  4856. Other Parameters
  4857. ----------------
  4858. data : indexable object, optional
  4859. DATA_PARAMETER_PLACEHOLDER
  4860. **kwargs : `~matplotlib.artist.Artist` properties
  4861. These parameters are passed on to the constructor of the
  4862. `.AxesImage` artist.
  4863. See Also
  4864. --------
  4865. matshow : Plot a matrix or an array as an image.
  4866. Notes
  4867. -----
  4868. Unless *extent* is used, pixel centers will be located at integer
  4869. coordinates. In other words: the origin will coincide with the center
  4870. of pixel (0, 0).
  4871. There are two common representations for RGB images with an alpha
  4872. channel:
  4873. - Straight (unassociated) alpha: R, G, and B channels represent the
  4874. color of the pixel, disregarding its opacity.
  4875. - Premultiplied (associated) alpha: R, G, and B channels represent
  4876. the color of the pixel, adjusted for its opacity by multiplication.
  4877. `~matplotlib.pyplot.imshow` expects RGB images adopting the straight
  4878. (unassociated) alpha representation.
  4879. """
  4880. im = mimage.AxesImage(self, cmap=cmap, norm=norm, colorizer=colorizer,
  4881. interpolation=interpolation, origin=origin,
  4882. extent=extent, filternorm=filternorm,
  4883. filterrad=filterrad, resample=resample,
  4884. interpolation_stage=interpolation_stage,
  4885. **kwargs)
  4886. if aspect is None and not (
  4887. im.is_transform_set()
  4888. and not im.get_transform().contains_branch(self.transData)):
  4889. aspect = mpl.rcParams['image.aspect']
  4890. if aspect is not None:
  4891. self.set_aspect(aspect)
  4892. im.set_data(X)
  4893. im.set_alpha(alpha)
  4894. if im.get_clip_path() is None:
  4895. # image does not already have clipping set, clip to Axes patch
  4896. im.set_clip_path(self.patch)
  4897. im._check_exclusionary_keywords(colorizer, vmin=vmin, vmax=vmax)
  4898. im._scale_norm(norm, vmin, vmax)
  4899. im.set_url(url)
  4900. # update ax.dataLim, and, if autoscaling, set viewLim
  4901. # to tightly fit the image, regardless of dataLim.
  4902. im.set_extent(im.get_extent())
  4903. self.add_image(im)
  4904. return im
  4905. def _pcolorargs(self, funcname, *args, shading='auto', **kwargs):
  4906. # - create X and Y if not present;
  4907. # - reshape X and Y as needed if they are 1-D;
  4908. # - check for proper sizes based on `shading` kwarg;
  4909. # - reset shading if shading='auto' to flat or nearest
  4910. # depending on size;
  4911. _valid_shading = ['gouraud', 'nearest', 'flat', 'auto']
  4912. try:
  4913. _api.check_in_list(_valid_shading, shading=shading)
  4914. except ValueError:
  4915. _api.warn_external(f"shading value '{shading}' not in list of "
  4916. f"valid values {_valid_shading}. Setting "
  4917. "shading='auto'.")
  4918. shading = 'auto'
  4919. if len(args) == 1:
  4920. C = np.asanyarray(args[0])
  4921. nrows, ncols = C.shape[:2]
  4922. if shading in ['gouraud', 'nearest']:
  4923. X, Y = np.meshgrid(np.arange(ncols), np.arange(nrows))
  4924. else:
  4925. X, Y = np.meshgrid(np.arange(ncols + 1), np.arange(nrows + 1))
  4926. shading = 'flat'
  4927. elif len(args) == 3:
  4928. # Check x and y for bad data...
  4929. C = np.asanyarray(args[2])
  4930. # unit conversion allows e.g. datetime objects as axis values
  4931. X, Y = args[:2]
  4932. X, Y = self._process_unit_info([("x", X), ("y", Y)], kwargs)
  4933. X, Y = (cbook.safe_masked_invalid(a, copy=True) for a in [X, Y])
  4934. if funcname == 'pcolormesh':
  4935. if np.ma.is_masked(X) or np.ma.is_masked(Y):
  4936. raise ValueError(
  4937. 'x and y arguments to pcolormesh cannot have '
  4938. 'non-finite values or be of type '
  4939. 'numpy.ma.MaskedArray with masked values')
  4940. nrows, ncols = C.shape[:2]
  4941. else:
  4942. raise _api.nargs_error(funcname, takes="1 or 3", given=len(args))
  4943. Nx = X.shape[-1]
  4944. Ny = Y.shape[0]
  4945. if X.ndim != 2 or X.shape[0] == 1:
  4946. x = X.reshape(1, Nx)
  4947. X = x.repeat(Ny, axis=0)
  4948. if Y.ndim != 2 or Y.shape[1] == 1:
  4949. y = Y.reshape(Ny, 1)
  4950. Y = y.repeat(Nx, axis=1)
  4951. if X.shape != Y.shape:
  4952. raise TypeError(f'Incompatible X, Y inputs to {funcname}; '
  4953. f'see help({funcname})')
  4954. if shading == 'auto':
  4955. if ncols == Nx and nrows == Ny:
  4956. shading = 'nearest'
  4957. else:
  4958. shading = 'flat'
  4959. if shading == 'flat':
  4960. if (Nx, Ny) != (ncols + 1, nrows + 1):
  4961. raise TypeError(f"Dimensions of C {C.shape} should"
  4962. f" be one smaller than X({Nx}) and Y({Ny})"
  4963. f" while using shading='flat'"
  4964. f" see help({funcname})")
  4965. else: # ['nearest', 'gouraud']:
  4966. if (Nx, Ny) != (ncols, nrows):
  4967. raise TypeError('Dimensions of C %s are incompatible with'
  4968. ' X (%d) and/or Y (%d); see help(%s)' % (
  4969. C.shape, Nx, Ny, funcname))
  4970. if shading == 'nearest':
  4971. # grid is specified at the center, so define corners
  4972. # at the midpoints between the grid centers and then use the
  4973. # flat algorithm.
  4974. def _interp_grid(X, require_monotonicity=False):
  4975. # helper for below. To ensure the cell edges are calculated
  4976. # correctly, when expanding columns, the monotonicity of
  4977. # X coords needs to be checked. When expanding rows, the
  4978. # monotonicity of Y coords needs to be checked.
  4979. if np.shape(X)[1] > 1:
  4980. dX = np.diff(X, axis=1) * 0.5
  4981. if (require_monotonicity and
  4982. not (np.all(dX >= 0) or np.all(dX <= 0))):
  4983. _api.warn_external(
  4984. f"The input coordinates to {funcname} are "
  4985. "interpreted as cell centers, but are not "
  4986. "monotonically increasing or decreasing. "
  4987. "This may lead to incorrectly calculated cell "
  4988. "edges, in which case, please supply "
  4989. f"explicit cell edges to {funcname}.")
  4990. hstack = np.ma.hstack if np.ma.isMA(X) else np.hstack
  4991. X = hstack((X[:, [0]] - dX[:, [0]],
  4992. X[:, :-1] + dX,
  4993. X[:, [-1]] + dX[:, [-1]]))
  4994. else:
  4995. # This is just degenerate, but we can't reliably guess
  4996. # a dX if there is just one value.
  4997. X = np.hstack((X, X))
  4998. return X
  4999. if ncols == Nx:
  5000. X = _interp_grid(X, require_monotonicity=True)
  5001. Y = _interp_grid(Y)
  5002. if nrows == Ny:
  5003. X = _interp_grid(X.T).T
  5004. Y = _interp_grid(Y.T, require_monotonicity=True).T
  5005. shading = 'flat'
  5006. C = cbook.safe_masked_invalid(C, copy=True)
  5007. return X, Y, C, shading
  5008. @_preprocess_data()
  5009. @_docstring.interpd
  5010. def pcolor(self, *args, shading=None, alpha=None, norm=None, cmap=None,
  5011. vmin=None, vmax=None, colorizer=None, **kwargs):
  5012. r"""
  5013. Create a pseudocolor plot with a non-regular rectangular grid.
  5014. Call signature::
  5015. pcolor([X, Y,] C, /, **kwargs)
  5016. *X* and *Y* can be used to specify the corners of the quadrilaterals.
  5017. The arguments *X*, *Y*, *C* are positional-only.
  5018. .. hint::
  5019. ``pcolor()`` can be very slow for large arrays. In most
  5020. cases you should use the similar but much faster
  5021. `~.Axes.pcolormesh` instead. See
  5022. :ref:`Differences between pcolor() and pcolormesh()
  5023. <differences-pcolor-pcolormesh>` for a discussion of the
  5024. differences.
  5025. Parameters
  5026. ----------
  5027. C : 2D array-like
  5028. The color-mapped values. Color-mapping is controlled by *cmap*,
  5029. *norm*, *vmin*, and *vmax*.
  5030. X, Y : array-like, optional
  5031. The coordinates of the corners of quadrilaterals of a pcolormesh::
  5032. (X[i+1, j], Y[i+1, j]) (X[i+1, j+1], Y[i+1, j+1])
  5033. ●╶───╴●
  5034. │ │
  5035. ●╶───╴●
  5036. (X[i, j], Y[i, j]) (X[i, j+1], Y[i, j+1])
  5037. Note that the column index corresponds to the x-coordinate, and
  5038. the row index corresponds to y. For details, see the
  5039. :ref:`Notes <axes-pcolormesh-grid-orientation>` section below.
  5040. If ``shading='flat'`` the dimensions of *X* and *Y* should be one
  5041. greater than those of *C*, and the quadrilateral is colored due
  5042. to the value at ``C[i, j]``. If *X*, *Y* and *C* have equal
  5043. dimensions, a warning will be raised and the last row and column
  5044. of *C* will be ignored.
  5045. If ``shading='nearest'``, the dimensions of *X* and *Y* should be
  5046. the same as those of *C* (if not, a ValueError will be raised). The
  5047. color ``C[i, j]`` will be centered on ``(X[i, j], Y[i, j])``.
  5048. If *X* and/or *Y* are 1-D arrays or column vectors they will be
  5049. expanded as needed into the appropriate 2D arrays, making a
  5050. rectangular grid.
  5051. shading : {'flat', 'nearest', 'auto'}, default: :rc:`pcolor.shading`
  5052. The fill style for the quadrilateral. Possible values:
  5053. - 'flat': A solid color is used for each quad. The color of the
  5054. quad (i, j), (i+1, j), (i, j+1), (i+1, j+1) is given by
  5055. ``C[i, j]``. The dimensions of *X* and *Y* should be
  5056. one greater than those of *C*; if they are the same as *C*,
  5057. then a deprecation warning is raised, and the last row
  5058. and column of *C* are dropped.
  5059. - 'nearest': Each grid point will have a color centered on it,
  5060. extending halfway between the adjacent grid centers. The
  5061. dimensions of *X* and *Y* must be the same as *C*.
  5062. - 'auto': Choose 'flat' if dimensions of *X* and *Y* are one
  5063. larger than *C*. Choose 'nearest' if dimensions are the same.
  5064. See :doc:`/gallery/images_contours_and_fields/pcolormesh_grids`
  5065. for more description.
  5066. %(cmap_doc)s
  5067. %(norm_doc)s
  5068. %(vmin_vmax_doc)s
  5069. %(colorizer_doc)s
  5070. edgecolors : {'none', None, 'face', color, color sequence}, optional
  5071. The color of the edges. Defaults to 'none'. Possible values:
  5072. - 'none' or '': No edge.
  5073. - *None*: :rc:`patch.edgecolor` will be used. Note that currently
  5074. :rc:`patch.force_edgecolor` has to be True for this to work.
  5075. - 'face': Use the adjacent face color.
  5076. - A color or sequence of colors will set the edge color.
  5077. The singular form *edgecolor* works as an alias.
  5078. alpha : float, default: None
  5079. The alpha blending value of the face color, between 0 (transparent)
  5080. and 1 (opaque). Note: The edgecolor is currently not affected by
  5081. this.
  5082. snap : bool, default: False
  5083. Whether to snap the mesh to pixel boundaries.
  5084. Returns
  5085. -------
  5086. `matplotlib.collections.PolyQuadMesh`
  5087. Other Parameters
  5088. ----------------
  5089. antialiaseds : bool, default: False
  5090. The default *antialiaseds* is False if the default
  5091. *edgecolors*\ ="none" is used. This eliminates artificial lines
  5092. at patch boundaries, and works regardless of the value of alpha.
  5093. If *edgecolors* is not "none", then the default *antialiaseds*
  5094. is taken from :rc:`patch.antialiased`.
  5095. Stroking the edges may be preferred if *alpha* is 1, but will
  5096. cause artifacts otherwise.
  5097. data : indexable object, optional
  5098. DATA_PARAMETER_PLACEHOLDER
  5099. **kwargs
  5100. Additionally, the following arguments are allowed. They are passed
  5101. along to the `~matplotlib.collections.PolyQuadMesh` constructor:
  5102. %(PolyCollection:kwdoc)s
  5103. See Also
  5104. --------
  5105. pcolormesh : for an explanation of the differences between
  5106. pcolor and pcolormesh.
  5107. imshow : If *X* and *Y* are each equidistant, `~.Axes.imshow` can be a
  5108. faster alternative.
  5109. Notes
  5110. -----
  5111. **Masked arrays**
  5112. *X*, *Y* and *C* may be masked arrays. If either ``C[i, j]``, or one
  5113. of the vertices surrounding ``C[i, j]`` (*X* or *Y* at
  5114. ``[i, j], [i+1, j], [i, j+1], [i+1, j+1]``) is masked, nothing is
  5115. plotted.
  5116. .. _axes-pcolor-grid-orientation:
  5117. **Grid orientation**
  5118. The grid orientation follows the standard matrix convention: An array
  5119. *C* with shape (nrows, ncolumns) is plotted with the column number as
  5120. *X* and the row number as *Y*.
  5121. """
  5122. if shading is None:
  5123. shading = mpl.rcParams['pcolor.shading']
  5124. shading = shading.lower()
  5125. X, Y, C, shading = self._pcolorargs('pcolor', *args, shading=shading,
  5126. kwargs=kwargs)
  5127. linewidths = (0.25,)
  5128. if 'linewidth' in kwargs:
  5129. kwargs['linewidths'] = kwargs.pop('linewidth')
  5130. kwargs.setdefault('linewidths', linewidths)
  5131. if 'edgecolor' in kwargs:
  5132. kwargs['edgecolors'] = kwargs.pop('edgecolor')
  5133. ec = kwargs.setdefault('edgecolors', 'none')
  5134. # aa setting will default via collections to patch.antialiased
  5135. # unless the boundary is not stroked, in which case the
  5136. # default will be False; with unstroked boundaries, aa
  5137. # makes artifacts that are often disturbing.
  5138. if 'antialiaseds' in kwargs:
  5139. kwargs['antialiased'] = kwargs.pop('antialiaseds')
  5140. if 'antialiased' not in kwargs and cbook._str_lower_equal(ec, "none"):
  5141. kwargs['antialiased'] = False
  5142. kwargs.setdefault('snap', False)
  5143. if np.ma.isMaskedArray(X) or np.ma.isMaskedArray(Y):
  5144. stack = np.ma.stack
  5145. X = np.ma.asarray(X)
  5146. Y = np.ma.asarray(Y)
  5147. # For bounds collections later
  5148. x = X.compressed()
  5149. y = Y.compressed()
  5150. else:
  5151. stack = np.stack
  5152. x = X
  5153. y = Y
  5154. coords = stack([X, Y], axis=-1)
  5155. collection = mcoll.PolyQuadMesh(
  5156. coords, array=C, cmap=cmap, norm=norm, colorizer=colorizer,
  5157. alpha=alpha, **kwargs)
  5158. collection._check_exclusionary_keywords(colorizer, vmin=vmin, vmax=vmax)
  5159. collection._scale_norm(norm, vmin, vmax)
  5160. # Transform from native to data coordinates?
  5161. t = collection._transform
  5162. if (not isinstance(t, mtransforms.Transform) and
  5163. hasattr(t, '_as_mpl_transform')):
  5164. t = t._as_mpl_transform(self.axes)
  5165. if t and any(t.contains_branch_seperately(self.transData)):
  5166. trans_to_data = t - self.transData
  5167. pts = np.vstack([x, y]).T.astype(float)
  5168. transformed_pts = trans_to_data.transform(pts)
  5169. x = transformed_pts[..., 0]
  5170. y = transformed_pts[..., 1]
  5171. self.add_collection(collection, autolim=False)
  5172. minx = np.min(x)
  5173. maxx = np.max(x)
  5174. miny = np.min(y)
  5175. maxy = np.max(y)
  5176. collection.sticky_edges.x[:] = [minx, maxx]
  5177. collection.sticky_edges.y[:] = [miny, maxy]
  5178. corners = (minx, miny), (maxx, maxy)
  5179. self.update_datalim(corners)
  5180. self._request_autoscale_view()
  5181. return collection
  5182. @_preprocess_data()
  5183. @_docstring.interpd
  5184. def pcolormesh(self, *args, alpha=None, norm=None, cmap=None, vmin=None,
  5185. vmax=None, colorizer=None, shading=None, antialiased=False,
  5186. **kwargs):
  5187. """
  5188. Create a pseudocolor plot with a non-regular rectangular grid.
  5189. Call signature::
  5190. pcolormesh([X, Y,] C, /, **kwargs)
  5191. *X* and *Y* can be used to specify the corners of the quadrilaterals.
  5192. The arguments *X*, *Y*, *C* are positional-only.
  5193. .. hint::
  5194. `~.Axes.pcolormesh` is similar to `~.Axes.pcolor`. It is much faster
  5195. and preferred in most cases. For a detailed discussion on the
  5196. differences see :ref:`Differences between pcolor() and pcolormesh()
  5197. <differences-pcolor-pcolormesh>`.
  5198. Parameters
  5199. ----------
  5200. C : array-like
  5201. The mesh data. Supported array shapes are:
  5202. - (M, N) or M*N: a mesh with scalar data. The values are mapped to
  5203. colors using normalization and a colormap. See parameters *norm*,
  5204. *cmap*, *vmin*, *vmax*.
  5205. - (M, N, 3): an image with RGB values (0-1 float or 0-255 int).
  5206. - (M, N, 4): an image with RGBA values (0-1 float or 0-255 int),
  5207. i.e. including transparency.
  5208. The first two dimensions (M, N) define the rows and columns of
  5209. the mesh data.
  5210. X, Y : array-like, optional
  5211. The coordinates of the corners of quadrilaterals of a pcolormesh::
  5212. (X[i+1, j], Y[i+1, j]) (X[i+1, j+1], Y[i+1, j+1])
  5213. ●╶───╴●
  5214. │ │
  5215. ●╶───╴●
  5216. (X[i, j], Y[i, j]) (X[i, j+1], Y[i, j+1])
  5217. Note that the column index corresponds to the x-coordinate, and
  5218. the row index corresponds to y. For details, see the
  5219. :ref:`Notes <axes-pcolormesh-grid-orientation>` section below.
  5220. If ``shading='flat'`` the dimensions of *X* and *Y* should be one
  5221. greater than those of *C*, and the quadrilateral is colored due
  5222. to the value at ``C[i, j]``. If *X*, *Y* and *C* have equal
  5223. dimensions, a warning will be raised and the last row and column
  5224. of *C* will be ignored.
  5225. If ``shading='nearest'`` or ``'gouraud'``, the dimensions of *X*
  5226. and *Y* should be the same as those of *C* (if not, a ValueError
  5227. will be raised). For ``'nearest'`` the color ``C[i, j]`` is
  5228. centered on ``(X[i, j], Y[i, j])``. For ``'gouraud'``, a smooth
  5229. interpolation is carried out between the quadrilateral corners.
  5230. If *X* and/or *Y* are 1-D arrays or column vectors they will be
  5231. expanded as needed into the appropriate 2D arrays, making a
  5232. rectangular grid.
  5233. %(cmap_doc)s
  5234. %(norm_doc)s
  5235. %(vmin_vmax_doc)s
  5236. %(colorizer_doc)s
  5237. edgecolors : {'none', None, 'face', color, color sequence}, optional
  5238. The color of the edges. Defaults to 'none'. Possible values:
  5239. - 'none' or '': No edge.
  5240. - *None*: :rc:`patch.edgecolor` will be used. Note that currently
  5241. :rc:`patch.force_edgecolor` has to be True for this to work.
  5242. - 'face': Use the adjacent face color.
  5243. - A color or sequence of colors will set the edge color.
  5244. The singular form *edgecolor* works as an alias.
  5245. alpha : float, default: None
  5246. The alpha blending value, between 0 (transparent) and 1 (opaque).
  5247. shading : {'flat', 'nearest', 'gouraud', 'auto'}, optional
  5248. The fill style for the quadrilateral; defaults to
  5249. :rc:`pcolor.shading`. Possible values:
  5250. - 'flat': A solid color is used for each quad. The color of the
  5251. quad (i, j), (i+1, j), (i, j+1), (i+1, j+1) is given by
  5252. ``C[i, j]``. The dimensions of *X* and *Y* should be
  5253. one greater than those of *C*; if they are the same as *C*,
  5254. then a deprecation warning is raised, and the last row
  5255. and column of *C* are dropped.
  5256. - 'nearest': Each grid point will have a color centered on it,
  5257. extending halfway between the adjacent grid centers. The
  5258. dimensions of *X* and *Y* must be the same as *C*.
  5259. - 'gouraud': Each quad will be Gouraud shaded: The color of the
  5260. corners (i', j') are given by ``C[i', j']``. The color values of
  5261. the area in between is interpolated from the corner values.
  5262. The dimensions of *X* and *Y* must be the same as *C*. When
  5263. Gouraud shading is used, *edgecolors* is ignored.
  5264. - 'auto': Choose 'flat' if dimensions of *X* and *Y* are one
  5265. larger than *C*. Choose 'nearest' if dimensions are the same.
  5266. See :doc:`/gallery/images_contours_and_fields/pcolormesh_grids`
  5267. for more description.
  5268. snap : bool, default: False
  5269. Whether to snap the mesh to pixel boundaries.
  5270. rasterized : bool, optional
  5271. Rasterize the pcolormesh when drawing vector graphics. This can
  5272. speed up rendering and produce smaller files for large data sets.
  5273. See also :doc:`/gallery/misc/rasterization_demo`.
  5274. Returns
  5275. -------
  5276. `matplotlib.collections.QuadMesh`
  5277. Other Parameters
  5278. ----------------
  5279. data : indexable object, optional
  5280. DATA_PARAMETER_PLACEHOLDER
  5281. **kwargs
  5282. Additionally, the following arguments are allowed. They are passed
  5283. along to the `~matplotlib.collections.QuadMesh` constructor:
  5284. %(QuadMesh:kwdoc)s
  5285. See Also
  5286. --------
  5287. pcolor : An alternative implementation with slightly different
  5288. features. For a detailed discussion on the differences see
  5289. :ref:`Differences between pcolor() and pcolormesh()
  5290. <differences-pcolor-pcolormesh>`.
  5291. imshow : If *X* and *Y* are each equidistant, `~.Axes.imshow` can be a
  5292. faster alternative.
  5293. Notes
  5294. -----
  5295. **Masked arrays**
  5296. *C* may be a masked array. If ``C[i, j]`` is masked, the corresponding
  5297. quadrilateral will be transparent. Masking of *X* and *Y* is not
  5298. supported. Use `~.Axes.pcolor` if you need this functionality.
  5299. .. _axes-pcolormesh-grid-orientation:
  5300. **Grid orientation**
  5301. The grid orientation follows the standard matrix convention: An array
  5302. *C* with shape (nrows, ncolumns) is plotted with the column number as
  5303. *X* and the row number as *Y*.
  5304. .. _differences-pcolor-pcolormesh:
  5305. **Differences between pcolor() and pcolormesh()**
  5306. Both methods are used to create a pseudocolor plot of a 2D array
  5307. using quadrilaterals.
  5308. The main difference lies in the created object and internal data
  5309. handling:
  5310. While `~.Axes.pcolor` returns a `.PolyQuadMesh`, `~.Axes.pcolormesh`
  5311. returns a `.QuadMesh`. The latter is more specialized for the given
  5312. purpose and thus is faster. It should almost always be preferred.
  5313. There is also a slight difference in the handling of masked arrays.
  5314. Both `~.Axes.pcolor` and `~.Axes.pcolormesh` support masked arrays
  5315. for *C*. However, only `~.Axes.pcolor` supports masked arrays for *X*
  5316. and *Y*. The reason lies in the internal handling of the masked values.
  5317. `~.Axes.pcolor` leaves out the respective polygons from the
  5318. PolyQuadMesh. `~.Axes.pcolormesh` sets the facecolor of the masked
  5319. elements to transparent. You can see the difference when using
  5320. edgecolors. While all edges are drawn irrespective of masking in a
  5321. QuadMesh, the edge between two adjacent masked quadrilaterals in
  5322. `~.Axes.pcolor` is not drawn as the corresponding polygons do not
  5323. exist in the PolyQuadMesh. Because PolyQuadMesh draws each individual
  5324. polygon, it also supports applying hatches and linestyles to the collection.
  5325. Another difference is the support of Gouraud shading in
  5326. `~.Axes.pcolormesh`, which is not available with `~.Axes.pcolor`.
  5327. """
  5328. if shading is None:
  5329. shading = mpl.rcParams['pcolor.shading']
  5330. shading = shading.lower()
  5331. kwargs.setdefault('edgecolors', 'none')
  5332. X, Y, C, shading = self._pcolorargs('pcolormesh', *args,
  5333. shading=shading, kwargs=kwargs)
  5334. coords = np.stack([X, Y], axis=-1)
  5335. kwargs.setdefault('snap', mpl.rcParams['pcolormesh.snap'])
  5336. collection = mcoll.QuadMesh(
  5337. coords, antialiased=antialiased, shading=shading,
  5338. array=C, cmap=cmap, norm=norm, colorizer=colorizer, alpha=alpha, **kwargs)
  5339. collection._check_exclusionary_keywords(colorizer, vmin=vmin, vmax=vmax)
  5340. collection._scale_norm(norm, vmin, vmax)
  5341. coords = coords.reshape(-1, 2) # flatten the grid structure; keep x, y
  5342. # Transform from native to data coordinates?
  5343. t = collection._transform
  5344. if (not isinstance(t, mtransforms.Transform) and
  5345. hasattr(t, '_as_mpl_transform')):
  5346. t = t._as_mpl_transform(self.axes)
  5347. if t and any(t.contains_branch_seperately(self.transData)):
  5348. trans_to_data = t - self.transData
  5349. coords = trans_to_data.transform(coords)
  5350. self.add_collection(collection, autolim=False)
  5351. minx, miny = np.min(coords, axis=0)
  5352. maxx, maxy = np.max(coords, axis=0)
  5353. collection.sticky_edges.x[:] = [minx, maxx]
  5354. collection.sticky_edges.y[:] = [miny, maxy]
  5355. corners = (minx, miny), (maxx, maxy)
  5356. self.update_datalim(corners)
  5357. self._request_autoscale_view()
  5358. return collection
  5359. @_preprocess_data()
  5360. @_docstring.interpd
  5361. def pcolorfast(self, *args, alpha=None, norm=None, cmap=None, vmin=None,
  5362. vmax=None, colorizer=None, **kwargs):
  5363. """
  5364. Create a pseudocolor plot with a non-regular rectangular grid.
  5365. Call signature::
  5366. ax.pcolorfast([X, Y], C, /, **kwargs)
  5367. The arguments *X*, *Y*, *C* are positional-only.
  5368. This method is similar to `~.Axes.pcolor` and `~.Axes.pcolormesh`.
  5369. It's designed to provide the fastest pcolor-type plotting with the
  5370. Agg backend. To achieve this, it uses different algorithms internally
  5371. depending on the complexity of the input grid (regular rectangular,
  5372. non-regular rectangular or arbitrary quadrilateral).
  5373. .. warning::
  5374. This method is experimental. Compared to `~.Axes.pcolor` or
  5375. `~.Axes.pcolormesh` it has some limitations:
  5376. - It supports only flat shading (no outlines)
  5377. - It lacks support for log scaling of the axes.
  5378. - It does not have a pyplot wrapper.
  5379. Parameters
  5380. ----------
  5381. C : array-like
  5382. The image data. Supported array shapes are:
  5383. - (M, N): an image with scalar data. Color-mapping is controlled
  5384. by *cmap*, *norm*, *vmin*, and *vmax*.
  5385. - (M, N, 3): an image with RGB values (0-1 float or 0-255 int).
  5386. - (M, N, 4): an image with RGBA values (0-1 float or 0-255 int),
  5387. i.e. including transparency.
  5388. The first two dimensions (M, N) define the rows and columns of
  5389. the image.
  5390. This parameter can only be passed positionally.
  5391. X, Y : tuple or array-like, default: ``(0, N)``, ``(0, M)``
  5392. *X* and *Y* are used to specify the coordinates of the
  5393. quadrilaterals. There are different ways to do this:
  5394. - Use tuples ``X=(xmin, xmax)`` and ``Y=(ymin, ymax)`` to define
  5395. a *uniform rectangular grid*.
  5396. The tuples define the outer edges of the grid. All individual
  5397. quadrilaterals will be of the same size. This is the fastest
  5398. version.
  5399. - Use 1D arrays *X*, *Y* to specify a *non-uniform rectangular
  5400. grid*.
  5401. In this case *X* and *Y* have to be monotonic 1D arrays of length
  5402. *N+1* and *M+1*, specifying the x and y boundaries of the cells.
  5403. The speed is intermediate. Note: The grid is checked, and if
  5404. found to be uniform the fast version is used.
  5405. - Use 2D arrays *X*, *Y* if you need an *arbitrary quadrilateral
  5406. grid* (i.e. if the quadrilaterals are not rectangular).
  5407. In this case *X* and *Y* are 2D arrays with shape (M + 1, N + 1),
  5408. specifying the x and y coordinates of the corners of the colored
  5409. quadrilaterals.
  5410. This is the most general, but the slowest to render. It may
  5411. produce faster and more compact output using ps, pdf, and
  5412. svg backends, however.
  5413. These arguments can only be passed positionally.
  5414. %(cmap_doc)s
  5415. This parameter is ignored if *C* is RGB(A).
  5416. %(norm_doc)s
  5417. This parameter is ignored if *C* is RGB(A).
  5418. %(vmin_vmax_doc)s
  5419. This parameter is ignored if *C* is RGB(A).
  5420. %(colorizer_doc)s
  5421. This parameter is ignored if *C* is RGB(A).
  5422. alpha : float, default: None
  5423. The alpha blending value, between 0 (transparent) and 1 (opaque).
  5424. snap : bool, default: False
  5425. Whether to snap the mesh to pixel boundaries.
  5426. Returns
  5427. -------
  5428. `.AxesImage` or `.PcolorImage` or `.QuadMesh`
  5429. The return type depends on the type of grid:
  5430. - `.AxesImage` for a regular rectangular grid.
  5431. - `.PcolorImage` for a non-regular rectangular grid.
  5432. - `.QuadMesh` for a non-rectangular grid.
  5433. Other Parameters
  5434. ----------------
  5435. data : indexable object, optional
  5436. DATA_PARAMETER_PLACEHOLDER
  5437. **kwargs
  5438. Supported additional parameters depend on the type of grid.
  5439. See return types of *image* for further description.
  5440. """
  5441. C = args[-1]
  5442. nr, nc = np.shape(C)[:2]
  5443. if len(args) == 1:
  5444. style = "image"
  5445. x = [0, nc]
  5446. y = [0, nr]
  5447. elif len(args) == 3:
  5448. x, y = args[:2]
  5449. x = np.asarray(x)
  5450. y = np.asarray(y)
  5451. if x.ndim == 1 and y.ndim == 1:
  5452. if x.size == 2 and y.size == 2:
  5453. style = "image"
  5454. else:
  5455. if x.size != nc + 1:
  5456. raise ValueError(
  5457. f"Length of X ({x.size}) must be one larger than the "
  5458. f"number of columns in C ({nc})")
  5459. if y.size != nr + 1:
  5460. raise ValueError(
  5461. f"Length of Y ({y.size}) must be one larger than the "
  5462. f"number of rows in C ({nr})"
  5463. )
  5464. dx = np.diff(x)
  5465. dy = np.diff(y)
  5466. if (np.ptp(dx) < 0.01 * abs(dx.mean()) and
  5467. np.ptp(dy) < 0.01 * abs(dy.mean())):
  5468. style = "image"
  5469. else:
  5470. style = "pcolorimage"
  5471. elif x.ndim == 2 and y.ndim == 2:
  5472. style = "quadmesh"
  5473. else:
  5474. raise TypeError(
  5475. f"When 3 positional parameters are passed to pcolorfast, the first "
  5476. f"two (X and Y) must be both 1D or both 2D; the given X was "
  5477. f"{x.ndim}D and the given Y was {y.ndim}D")
  5478. else:
  5479. raise _api.nargs_error('pcolorfast', '1 or 3', len(args))
  5480. mcolorizer.ColorizingArtist._check_exclusionary_keywords(colorizer, vmin=vmin,
  5481. vmax=vmax)
  5482. if style == "quadmesh":
  5483. # data point in each cell is value at lower left corner
  5484. coords = np.stack([x, y], axis=-1)
  5485. if np.ndim(C) not in {2, 3}:
  5486. raise ValueError("C must be 2D or 3D")
  5487. collection = mcoll.QuadMesh(
  5488. coords, array=C,
  5489. alpha=alpha, cmap=cmap, norm=norm, colorizer=colorizer,
  5490. antialiased=False, edgecolors="none")
  5491. self.add_collection(collection, autolim=False)
  5492. xl, xr, yb, yt = x.min(), x.max(), y.min(), y.max()
  5493. ret = collection
  5494. else: # It's one of the two image styles.
  5495. extent = xl, xr, yb, yt = x[0], x[-1], y[0], y[-1]
  5496. if style == "image":
  5497. im = mimage.AxesImage(
  5498. self, cmap=cmap, norm=norm, colorizer=colorizer,
  5499. data=C, alpha=alpha, extent=extent,
  5500. interpolation='nearest', origin='lower',
  5501. **kwargs)
  5502. elif style == "pcolorimage":
  5503. im = mimage.PcolorImage(
  5504. self, x, y, C,
  5505. cmap=cmap, norm=norm, colorizer=colorizer, alpha=alpha,
  5506. extent=extent, **kwargs)
  5507. self.add_image(im)
  5508. ret = im
  5509. if np.ndim(C) == 2: # C.ndim == 3 is RGB(A) so doesn't need scaling.
  5510. ret._scale_norm(norm, vmin, vmax)
  5511. if ret.get_clip_path() is None:
  5512. # image does not already have clipping set, clip to Axes patch
  5513. ret.set_clip_path(self.patch)
  5514. ret.sticky_edges.x[:] = [xl, xr]
  5515. ret.sticky_edges.y[:] = [yb, yt]
  5516. self.update_datalim(np.array([[xl, yb], [xr, yt]]))
  5517. self._request_autoscale_view(tight=True)
  5518. return ret
  5519. @_preprocess_data()
  5520. @_docstring.interpd
  5521. def contour(self, *args, **kwargs):
  5522. """
  5523. Plot contour lines.
  5524. Call signature::
  5525. contour([X, Y,] Z, /, [levels], **kwargs)
  5526. The arguments *X*, *Y*, *Z* are positional-only.
  5527. %(contour_doc)s
  5528. """
  5529. kwargs['filled'] = False
  5530. contours = mcontour.QuadContourSet(self, *args, **kwargs)
  5531. self._request_autoscale_view()
  5532. return contours
  5533. @_preprocess_data()
  5534. @_docstring.interpd
  5535. def contourf(self, *args, **kwargs):
  5536. """
  5537. Plot filled contours.
  5538. Call signature::
  5539. contourf([X, Y,] Z, /, [levels], **kwargs)
  5540. The arguments *X*, *Y*, *Z* are positional-only.
  5541. %(contour_doc)s
  5542. """
  5543. kwargs['filled'] = True
  5544. contours = mcontour.QuadContourSet(self, *args, **kwargs)
  5545. self._request_autoscale_view()
  5546. return contours
  5547. def clabel(self, CS, levels=None, **kwargs):
  5548. """
  5549. Label a contour plot.
  5550. Adds labels to line contours in given `.ContourSet`.
  5551. Parameters
  5552. ----------
  5553. CS : `.ContourSet` instance
  5554. Line contours to label.
  5555. levels : array-like, optional
  5556. A list of level values, that should be labeled. The list must be
  5557. a subset of ``CS.levels``. If not given, all levels are labeled.
  5558. **kwargs
  5559. All other parameters are documented in `~.ContourLabeler.clabel`.
  5560. """
  5561. return CS.clabel(levels, **kwargs)
  5562. #### Data analysis
  5563. @_api.make_keyword_only("3.10", "range")
  5564. @_preprocess_data(replace_names=["x", 'weights'], label_namer="x")
  5565. def hist(self, x, bins=None, range=None, density=False, weights=None,
  5566. cumulative=False, bottom=None, histtype='bar', align='mid',
  5567. orientation='vertical', rwidth=None, log=False,
  5568. color=None, label=None, stacked=False, **kwargs):
  5569. """
  5570. Compute and plot a histogram.
  5571. This method uses `numpy.histogram` to bin the data in *x* and count the
  5572. number of values in each bin, then draws the distribution either as a
  5573. `.BarContainer` or `.Polygon`. The *bins*, *range*, *density*, and
  5574. *weights* parameters are forwarded to `numpy.histogram`.
  5575. If the data has already been binned and counted, use `~.bar` or
  5576. `~.stairs` to plot the distribution::
  5577. counts, bins = np.histogram(x)
  5578. plt.stairs(counts, bins)
  5579. Alternatively, plot pre-computed bins and counts using ``hist()`` by
  5580. treating each bin as a single point with a weight equal to its count::
  5581. plt.hist(bins[:-1], bins, weights=counts)
  5582. The data input *x* can be a singular array, a list of datasets of
  5583. potentially different lengths ([*x0*, *x1*, ...]), or a 2D ndarray in
  5584. which each column is a dataset. Note that the ndarray form is
  5585. transposed relative to the list form. If the input is an array, then
  5586. the return value is a tuple (*n*, *bins*, *patches*); if the input is a
  5587. sequence of arrays, then the return value is a tuple
  5588. ([*n0*, *n1*, ...], *bins*, [*patches0*, *patches1*, ...]).
  5589. Masked arrays are not supported.
  5590. Parameters
  5591. ----------
  5592. x : (n,) array or sequence of (n,) arrays
  5593. Input values, this takes either a single array or a sequence of
  5594. arrays which are not required to be of the same length.
  5595. bins : int or sequence or str, default: :rc:`hist.bins`
  5596. If *bins* is an integer, it defines the number of equal-width bins
  5597. in the range.
  5598. If *bins* is a sequence, it defines the bin edges, including the
  5599. left edge of the first bin and the right edge of the last bin;
  5600. in this case, bins may be unequally spaced. All but the last
  5601. (righthand-most) bin is half-open. In other words, if *bins* is::
  5602. [1, 2, 3, 4]
  5603. then the first bin is ``[1, 2)`` (including 1, but excluding 2) and
  5604. the second ``[2, 3)``. The last bin, however, is ``[3, 4]``, which
  5605. *includes* 4.
  5606. If *bins* is a string, it is one of the binning strategies
  5607. supported by `numpy.histogram_bin_edges`: 'auto', 'fd', 'doane',
  5608. 'scott', 'stone', 'rice', 'sturges', or 'sqrt'.
  5609. range : tuple or None, default: None
  5610. The lower and upper range of the bins. Lower and upper outliers
  5611. are ignored. If not provided, *range* is ``(x.min(), x.max())``.
  5612. Range has no effect if *bins* is a sequence.
  5613. If *bins* is a sequence or *range* is specified, autoscaling
  5614. is based on the specified bin range instead of the
  5615. range of x.
  5616. density : bool, default: False
  5617. If ``True``, draw and return a probability density: each bin
  5618. will display the bin's raw count divided by the total number of
  5619. counts *and the bin width*
  5620. (``density = counts / (sum(counts) * np.diff(bins))``),
  5621. so that the area under the histogram integrates to 1
  5622. (``np.sum(density * np.diff(bins)) == 1``).
  5623. If *stacked* is also ``True``, the sum of the histograms is
  5624. normalized to 1.
  5625. weights : (n,) array-like or None, default: None
  5626. An array of weights, of the same shape as *x*. Each value in
  5627. *x* only contributes its associated weight towards the bin count
  5628. (instead of 1). If *density* is ``True``, the weights are
  5629. normalized, so that the integral of the density over the range
  5630. remains 1.
  5631. cumulative : bool or -1, default: False
  5632. If ``True``, then a histogram is computed where each bin gives the
  5633. counts in that bin plus all bins for smaller values. The last bin
  5634. gives the total number of datapoints.
  5635. If *density* is also ``True`` then the histogram is normalized such
  5636. that the last bin equals 1.
  5637. If *cumulative* is a number less than 0 (e.g., -1), the direction
  5638. of accumulation is reversed. In this case, if *density* is also
  5639. ``True``, then the histogram is normalized such that the first bin
  5640. equals 1.
  5641. bottom : array-like or float, default: 0
  5642. Location of the bottom of each bin, i.e. bins are drawn from
  5643. ``bottom`` to ``bottom + hist(x, bins)`` If a scalar, the bottom
  5644. of each bin is shifted by the same amount. If an array, each bin
  5645. is shifted independently and the length of bottom must match the
  5646. number of bins. If None, defaults to 0.
  5647. histtype : {'bar', 'barstacked', 'step', 'stepfilled'}, default: 'bar'
  5648. The type of histogram to draw.
  5649. - 'bar' is a traditional bar-type histogram. If multiple data
  5650. are given the bars are arranged side by side.
  5651. - 'barstacked' is a bar-type histogram where multiple
  5652. data are stacked on top of each other.
  5653. - 'step' generates a lineplot that is by default unfilled.
  5654. - 'stepfilled' generates a lineplot that is by default filled.
  5655. align : {'left', 'mid', 'right'}, default: 'mid'
  5656. The horizontal alignment of the histogram bars.
  5657. - 'left': bars are centered on the left bin edges.
  5658. - 'mid': bars are centered between the bin edges.
  5659. - 'right': bars are centered on the right bin edges.
  5660. orientation : {'vertical', 'horizontal'}, default: 'vertical'
  5661. If 'horizontal', `~.Axes.barh` will be used for bar-type histograms
  5662. and the *bottom* kwarg will be the left edges.
  5663. rwidth : float or None, default: None
  5664. The relative width of the bars as a fraction of the bin width. If
  5665. ``None``, automatically compute the width.
  5666. Ignored if *histtype* is 'step' or 'stepfilled'.
  5667. log : bool, default: False
  5668. If ``True``, the histogram axis will be set to a log scale.
  5669. color : :mpltype:`color` or list of :mpltype:`color` or None, default: None
  5670. Color or sequence of colors, one per dataset. Default (``None``)
  5671. uses the standard line color sequence.
  5672. label : str or list of str, optional
  5673. String, or sequence of strings to match multiple datasets. Bar
  5674. charts yield multiple patches per dataset, but only the first gets
  5675. the label, so that `~.Axes.legend` will work as expected.
  5676. stacked : bool, default: False
  5677. If ``True``, multiple data are stacked on top of each other If
  5678. ``False`` multiple data are arranged side by side if histtype is
  5679. 'bar' or on top of each other if histtype is 'step'
  5680. Returns
  5681. -------
  5682. n : array or list of arrays
  5683. The values of the histogram bins. See *density* and *weights* for a
  5684. description of the possible semantics. If input *x* is an array,
  5685. then this is an array of length *nbins*. If input is a sequence of
  5686. arrays ``[data1, data2, ...]``, then this is a list of arrays with
  5687. the values of the histograms for each of the arrays in the same
  5688. order. The dtype of the array *n* (or of its element arrays) will
  5689. always be float even if no weighting or normalization is used.
  5690. bins : array
  5691. The edges of the bins. Length nbins + 1 (nbins left edges and right
  5692. edge of last bin). Always a single array even when multiple data
  5693. sets are passed in.
  5694. patches : `.BarContainer` or list of a single `.Polygon` or list of \
  5695. such objects
  5696. Container of individual artists used to create the histogram
  5697. or list of such containers if there are multiple input datasets.
  5698. Other Parameters
  5699. ----------------
  5700. data : indexable object, optional
  5701. DATA_PARAMETER_PLACEHOLDER
  5702. **kwargs
  5703. `~matplotlib.patches.Patch` properties. The following properties
  5704. additionally accept a sequence of values corresponding to the
  5705. datasets in *x*:
  5706. *edgecolor*, *facecolor*, *linewidth*, *linestyle*, *hatch*.
  5707. .. versionadded:: 3.10
  5708. Allowing sequences of values in above listed Patch properties.
  5709. See Also
  5710. --------
  5711. hist2d : 2D histogram with rectangular bins
  5712. hexbin : 2D histogram with hexagonal bins
  5713. stairs : Plot a pre-computed histogram
  5714. bar : Plot a pre-computed histogram
  5715. Notes
  5716. -----
  5717. For large numbers of bins (>1000), plotting can be significantly
  5718. accelerated by using `~.Axes.stairs` to plot a pre-computed histogram
  5719. (``plt.stairs(*np.histogram(data))``), or by setting *histtype* to
  5720. 'step' or 'stepfilled' rather than 'bar' or 'barstacked'.
  5721. """
  5722. # Avoid shadowing the builtin.
  5723. bin_range = range
  5724. from builtins import range
  5725. kwargs = cbook.normalize_kwargs(kwargs, mpatches.Patch)
  5726. if np.isscalar(x):
  5727. x = [x]
  5728. if bins is None:
  5729. bins = mpl.rcParams['hist.bins']
  5730. # Validate string inputs here to avoid cluttering subsequent code.
  5731. _api.check_in_list(['bar', 'barstacked', 'step', 'stepfilled'],
  5732. histtype=histtype)
  5733. _api.check_in_list(['left', 'mid', 'right'], align=align)
  5734. _api.check_in_list(['horizontal', 'vertical'], orientation=orientation)
  5735. if histtype == 'barstacked' and not stacked:
  5736. stacked = True
  5737. # Massage 'x' for processing.
  5738. x = cbook._reshape_2D(x, 'x')
  5739. nx = len(x) # number of datasets
  5740. # Process unit information. _process_unit_info sets the unit and
  5741. # converts the first dataset; then we convert each following dataset
  5742. # one at a time.
  5743. if orientation == "vertical":
  5744. convert_units = self.convert_xunits
  5745. x = [*self._process_unit_info([("x", x[0])], kwargs),
  5746. *map(convert_units, x[1:])]
  5747. else: # horizontal
  5748. convert_units = self.convert_yunits
  5749. x = [*self._process_unit_info([("y", x[0])], kwargs),
  5750. *map(convert_units, x[1:])]
  5751. if bin_range is not None:
  5752. bin_range = convert_units(bin_range)
  5753. if not cbook.is_scalar_or_string(bins):
  5754. bins = convert_units(bins)
  5755. # We need to do to 'weights' what was done to 'x'
  5756. if weights is not None:
  5757. w = cbook._reshape_2D(weights, 'weights')
  5758. else:
  5759. w = [None] * nx
  5760. if len(w) != nx:
  5761. raise ValueError('weights should have the same shape as x')
  5762. input_empty = True
  5763. for xi, wi in zip(x, w):
  5764. len_xi = len(xi)
  5765. if wi is not None and len(wi) != len_xi:
  5766. raise ValueError('weights should have the same shape as x')
  5767. if len_xi:
  5768. input_empty = False
  5769. if color is None:
  5770. colors = [self._get_lines.get_next_color() for i in range(nx)]
  5771. else:
  5772. colors = mcolors.to_rgba_array(color)
  5773. if len(colors) != nx:
  5774. raise ValueError(f"The 'color' keyword argument must have one "
  5775. f"color per dataset, but {nx} datasets and "
  5776. f"{len(colors)} colors were provided")
  5777. hist_kwargs = dict()
  5778. # if the bin_range is not given, compute without nan numpy
  5779. # does not do this for us when guessing the range (but will
  5780. # happily ignore nans when computing the histogram).
  5781. if bin_range is None:
  5782. xmin = np.inf
  5783. xmax = -np.inf
  5784. for xi in x:
  5785. if len(xi):
  5786. # python's min/max ignore nan,
  5787. # np.minnan returns nan for all nan input
  5788. xmin = min(xmin, np.nanmin(xi))
  5789. xmax = max(xmax, np.nanmax(xi))
  5790. if xmin <= xmax: # Only happens if we have seen a finite value.
  5791. bin_range = (xmin, xmax)
  5792. # If bins are not specified either explicitly or via range,
  5793. # we need to figure out the range required for all datasets,
  5794. # and supply that to np.histogram.
  5795. if not input_empty and len(x) > 1:
  5796. if weights is not None:
  5797. _w = np.concatenate(w)
  5798. else:
  5799. _w = None
  5800. bins = np.histogram_bin_edges(
  5801. np.concatenate(x), bins, bin_range, _w)
  5802. else:
  5803. hist_kwargs['range'] = bin_range
  5804. density = bool(density)
  5805. if density and not stacked:
  5806. hist_kwargs['density'] = density
  5807. # List to store all the top coordinates of the histograms
  5808. tops = [] # Will have shape (n_datasets, n_bins).
  5809. # Loop through datasets
  5810. for i in range(nx):
  5811. # this will automatically overwrite bins,
  5812. # so that each histogram uses the same bins
  5813. m, bins = np.histogram(x[i], bins, weights=w[i], **hist_kwargs)
  5814. tops.append(m)
  5815. tops = np.array(tops, float) # causes problems later if it's an int
  5816. bins = np.array(bins, float) # causes problems if float16
  5817. if stacked:
  5818. tops = tops.cumsum(axis=0)
  5819. # If a stacked density plot, normalize so the area of all the
  5820. # stacked histograms together is 1
  5821. if density:
  5822. tops = (tops / np.diff(bins)) / tops[-1].sum()
  5823. if cumulative:
  5824. slc = slice(None)
  5825. if isinstance(cumulative, Number) and cumulative < 0:
  5826. slc = slice(None, None, -1)
  5827. if density:
  5828. tops = (tops * np.diff(bins))[:, slc].cumsum(axis=1)[:, slc]
  5829. else:
  5830. tops = tops[:, slc].cumsum(axis=1)[:, slc]
  5831. patches = []
  5832. if histtype.startswith('bar'):
  5833. totwidth = np.diff(bins)
  5834. if rwidth is not None:
  5835. dr = np.clip(rwidth, 0, 1)
  5836. elif (len(tops) > 1 and
  5837. ((not stacked) or mpl.rcParams['_internal.classic_mode'])):
  5838. dr = 0.8
  5839. else:
  5840. dr = 1.0
  5841. if histtype == 'bar' and not stacked:
  5842. width = dr * totwidth / nx
  5843. dw = width
  5844. boffset = -0.5 * dr * totwidth * (1 - 1 / nx)
  5845. elif histtype == 'barstacked' or stacked:
  5846. width = dr * totwidth
  5847. boffset, dw = 0.0, 0.0
  5848. if align == 'mid':
  5849. boffset += 0.5 * totwidth
  5850. elif align == 'right':
  5851. boffset += totwidth
  5852. if orientation == 'horizontal':
  5853. _barfunc = self.barh
  5854. bottom_kwarg = 'left'
  5855. else: # orientation == 'vertical'
  5856. _barfunc = self.bar
  5857. bottom_kwarg = 'bottom'
  5858. for top, color in zip(tops, colors):
  5859. if bottom is None:
  5860. bottom = np.zeros(len(top))
  5861. if stacked:
  5862. height = top - bottom
  5863. else:
  5864. height = top
  5865. bars = _barfunc(bins[:-1]+boffset, height, width,
  5866. align='center', log=log,
  5867. color=color, **{bottom_kwarg: bottom})
  5868. patches.append(bars)
  5869. if stacked:
  5870. bottom = top
  5871. boffset += dw
  5872. # Remove stickies from all bars but the lowest ones, as otherwise
  5873. # margin expansion would be unable to cross the stickies in the
  5874. # middle of the bars.
  5875. for bars in patches[1:]:
  5876. for patch in bars:
  5877. patch.sticky_edges.x[:] = patch.sticky_edges.y[:] = []
  5878. elif histtype.startswith('step'):
  5879. # these define the perimeter of the polygon
  5880. x = np.zeros(4 * len(bins) - 3)
  5881. y = np.zeros(4 * len(bins) - 3)
  5882. x[0:2*len(bins)-1:2], x[1:2*len(bins)-1:2] = bins, bins[:-1]
  5883. x[2*len(bins)-1:] = x[1:2*len(bins)-1][::-1]
  5884. if bottom is None:
  5885. bottom = 0
  5886. y[1:2*len(bins)-1:2] = y[2:2*len(bins):2] = bottom
  5887. y[2*len(bins)-1:] = y[1:2*len(bins)-1][::-1]
  5888. if log:
  5889. if orientation == 'horizontal':
  5890. self.set_xscale('log', nonpositive='clip')
  5891. else: # orientation == 'vertical'
  5892. self.set_yscale('log', nonpositive='clip')
  5893. if align == 'left':
  5894. x -= 0.5*(bins[1]-bins[0])
  5895. elif align == 'right':
  5896. x += 0.5*(bins[1]-bins[0])
  5897. # If fill kwarg is set, it will be passed to the patch collection,
  5898. # overriding this
  5899. fill = (histtype == 'stepfilled')
  5900. xvals, yvals = [], []
  5901. for top in tops:
  5902. if stacked:
  5903. # top of the previous polygon becomes the bottom
  5904. y[2*len(bins)-1:] = y[1:2*len(bins)-1][::-1]
  5905. # set the top of this polygon
  5906. y[1:2*len(bins)-1:2] = y[2:2*len(bins):2] = top + bottom
  5907. # The starting point of the polygon has not yet been
  5908. # updated. So far only the endpoint was adjusted. This
  5909. # assignment closes the polygon. The redundant endpoint is
  5910. # later discarded (for step and stepfilled).
  5911. y[0] = y[-1]
  5912. if orientation == 'horizontal':
  5913. xvals.append(y.copy())
  5914. yvals.append(x.copy())
  5915. else:
  5916. xvals.append(x.copy())
  5917. yvals.append(y.copy())
  5918. # stepfill is closed, step is not
  5919. split = -1 if fill else 2 * len(bins)
  5920. # add patches in reverse order so that when stacking,
  5921. # items lower in the stack are plotted on top of
  5922. # items higher in the stack
  5923. for x, y, color in reversed(list(zip(xvals, yvals, colors))):
  5924. patches.append(self.fill(
  5925. x[:split], y[:split],
  5926. closed=True if fill else None,
  5927. facecolor=color,
  5928. edgecolor=None if fill else color,
  5929. fill=fill if fill else None,
  5930. zorder=None if fill else mlines.Line2D.zorder))
  5931. for patch_list in patches:
  5932. for patch in patch_list:
  5933. if orientation == 'vertical':
  5934. patch.sticky_edges.y.append(0)
  5935. elif orientation == 'horizontal':
  5936. patch.sticky_edges.x.append(0)
  5937. # we return patches, so put it back in the expected order
  5938. patches.reverse()
  5939. # If None, make all labels None (via zip_longest below); otherwise,
  5940. # cast each element to str, but keep a single str as it.
  5941. labels = [] if label is None else np.atleast_1d(np.asarray(label, str))
  5942. if histtype == "step":
  5943. ec = kwargs.get('edgecolor', colors)
  5944. else:
  5945. ec = kwargs.get('edgecolor', None)
  5946. if ec is None or cbook._str_lower_equal(ec, 'none'):
  5947. edgecolors = itertools.repeat(ec)
  5948. else:
  5949. edgecolors = itertools.cycle(mcolors.to_rgba_array(ec))
  5950. fc = kwargs.get('facecolor', colors)
  5951. if cbook._str_lower_equal(fc, 'none'):
  5952. facecolors = itertools.repeat(fc)
  5953. else:
  5954. facecolors = itertools.cycle(mcolors.to_rgba_array(fc))
  5955. hatches = itertools.cycle(np.atleast_1d(kwargs.get('hatch', None)))
  5956. linewidths = itertools.cycle(np.atleast_1d(kwargs.get('linewidth', None)))
  5957. if 'linestyle' in kwargs:
  5958. linestyles = itertools.cycle(mlines._get_dash_patterns(kwargs['linestyle']))
  5959. else:
  5960. linestyles = itertools.repeat(None)
  5961. for patch, lbl in itertools.zip_longest(patches, labels):
  5962. if not patch:
  5963. continue
  5964. p = patch[0]
  5965. kwargs.update({
  5966. 'hatch': next(hatches),
  5967. 'linewidth': next(linewidths),
  5968. 'linestyle': next(linestyles),
  5969. 'edgecolor': next(edgecolors),
  5970. 'facecolor': next(facecolors),
  5971. })
  5972. p._internal_update(kwargs)
  5973. if lbl is not None:
  5974. p.set_label(lbl)
  5975. for p in patch[1:]:
  5976. p._internal_update(kwargs)
  5977. p.set_label('_nolegend_')
  5978. if nx == 1:
  5979. return tops[0], bins, patches[0]
  5980. else:
  5981. patch_type = ("BarContainer" if histtype.startswith("bar")
  5982. else "list[Polygon]")
  5983. return tops, bins, cbook.silent_list(patch_type, patches)
  5984. @_preprocess_data()
  5985. def stairs(self, values, edges=None, *,
  5986. orientation='vertical', baseline=0, fill=False, **kwargs):
  5987. """
  5988. Draw a stepwise constant function as a line or a filled plot.
  5989. *edges* define the x-axis positions of the steps. *values* the function values
  5990. between these steps. Depending on *fill*, the function is drawn either as a
  5991. continuous line with vertical segments at the edges, or as a filled area.
  5992. Parameters
  5993. ----------
  5994. values : array-like
  5995. The step heights.
  5996. edges : array-like
  5997. The step positions, with ``len(edges) == len(vals) + 1``,
  5998. between which the curve takes on vals values.
  5999. orientation : {'vertical', 'horizontal'}, default: 'vertical'
  6000. The direction of the steps. Vertical means that *values* are along
  6001. the y-axis, and edges are along the x-axis.
  6002. baseline : float, array-like or None, default: 0
  6003. The bottom value of the bounding edges or when
  6004. ``fill=True``, position of lower edge. If *fill* is
  6005. True or an array is passed to *baseline*, a closed
  6006. path is drawn.
  6007. If None, then drawn as an unclosed Path.
  6008. fill : bool, default: False
  6009. Whether the area under the step curve should be filled.
  6010. Passing both ``fill=True` and ``baseline=None`` will likely result in
  6011. undesired filling: the first and last points will be connected
  6012. with a straight line and the fill will be between this line and the stairs.
  6013. Returns
  6014. -------
  6015. StepPatch : `~matplotlib.patches.StepPatch`
  6016. Other Parameters
  6017. ----------------
  6018. data : indexable object, optional
  6019. DATA_PARAMETER_PLACEHOLDER
  6020. **kwargs
  6021. `~matplotlib.patches.StepPatch` properties
  6022. """
  6023. if 'color' in kwargs:
  6024. _color = kwargs.pop('color')
  6025. else:
  6026. _color = self._get_lines.get_next_color()
  6027. if fill:
  6028. kwargs.setdefault('linewidth', 0)
  6029. kwargs.setdefault('facecolor', _color)
  6030. else:
  6031. kwargs.setdefault('edgecolor', _color)
  6032. if edges is None:
  6033. edges = np.arange(len(values) + 1)
  6034. edges, values, baseline = self._process_unit_info(
  6035. [("x", edges), ("y", values), ("y", baseline)], kwargs)
  6036. patch = mpatches.StepPatch(values,
  6037. edges,
  6038. baseline=baseline,
  6039. orientation=orientation,
  6040. fill=fill,
  6041. **kwargs)
  6042. self.add_patch(patch)
  6043. if baseline is None and fill:
  6044. _api.warn_external(
  6045. f"Both {baseline=} and {fill=} have been passed. "
  6046. "baseline=None is only intended for unfilled stair plots. "
  6047. "Because baseline is None, the Path used to draw the stairs will "
  6048. "not be closed, thus because fill is True the polygon will be closed "
  6049. "by drawing an (unstroked) edge from the first to last point. It is "
  6050. "very likely that the resulting fill patterns is not the desired "
  6051. "result."
  6052. )
  6053. if baseline is not None:
  6054. if orientation == 'vertical':
  6055. patch.sticky_edges.y.append(np.min(baseline))
  6056. self.update_datalim([(edges[0], np.min(baseline))])
  6057. else:
  6058. patch.sticky_edges.x.append(np.min(baseline))
  6059. self.update_datalim([(np.min(baseline), edges[0])])
  6060. self._request_autoscale_view()
  6061. return patch
  6062. @_api.make_keyword_only("3.10", "range")
  6063. @_preprocess_data(replace_names=["x", "y", "weights"])
  6064. @_docstring.interpd
  6065. def hist2d(self, x, y, bins=10, range=None, density=False, weights=None,
  6066. cmin=None, cmax=None, **kwargs):
  6067. """
  6068. Make a 2D histogram plot.
  6069. Parameters
  6070. ----------
  6071. x, y : array-like, shape (n, )
  6072. Input values
  6073. bins : None or int or [int, int] or array-like or [array, array]
  6074. The bin specification:
  6075. - If int, the number of bins for the two dimensions
  6076. (``nx = ny = bins``).
  6077. - If ``[int, int]``, the number of bins in each dimension
  6078. (``nx, ny = bins``).
  6079. - If array-like, the bin edges for the two dimensions
  6080. (``x_edges = y_edges = bins``).
  6081. - If ``[array, array]``, the bin edges in each dimension
  6082. (``x_edges, y_edges = bins``).
  6083. The default value is 10.
  6084. range : array-like shape(2, 2), optional
  6085. The leftmost and rightmost edges of the bins along each dimension
  6086. (if not specified explicitly in the bins parameters): ``[[xmin,
  6087. xmax], [ymin, ymax]]``. All values outside of this range will be
  6088. considered outliers and not tallied in the histogram.
  6089. density : bool, default: False
  6090. Normalize histogram. See the documentation for the *density*
  6091. parameter of `~.Axes.hist` for more details.
  6092. weights : array-like, shape (n, ), optional
  6093. An array of values w_i weighing each sample (x_i, y_i).
  6094. cmin, cmax : float, default: None
  6095. All bins that has count less than *cmin* or more than *cmax* will not be
  6096. displayed (set to NaN before passing to `~.Axes.pcolormesh`) and these count
  6097. values in the return value count histogram will also be set to nan upon
  6098. return.
  6099. Returns
  6100. -------
  6101. h : 2D array
  6102. The bi-dimensional histogram of samples x and y. Values in x are
  6103. histogrammed along the first dimension and values in y are
  6104. histogrammed along the second dimension.
  6105. xedges : 1D array
  6106. The bin edges along the x-axis.
  6107. yedges : 1D array
  6108. The bin edges along the y-axis.
  6109. image : `~.matplotlib.collections.QuadMesh`
  6110. Other Parameters
  6111. ----------------
  6112. %(cmap_doc)s
  6113. %(norm_doc)s
  6114. %(vmin_vmax_doc)s
  6115. %(colorizer_doc)s
  6116. alpha : ``0 <= scalar <= 1`` or ``None``, optional
  6117. The alpha blending value.
  6118. data : indexable object, optional
  6119. DATA_PARAMETER_PLACEHOLDER
  6120. **kwargs
  6121. Additional parameters are passed along to the
  6122. `~.Axes.pcolormesh` method and `~matplotlib.collections.QuadMesh`
  6123. constructor.
  6124. See Also
  6125. --------
  6126. hist : 1D histogram plotting
  6127. hexbin : 2D histogram with hexagonal bins
  6128. Notes
  6129. -----
  6130. - Currently ``hist2d`` calculates its own axis limits, and any limits
  6131. previously set are ignored.
  6132. - Rendering the histogram with a logarithmic color scale is
  6133. accomplished by passing a `.colors.LogNorm` instance to the *norm*
  6134. keyword argument. Likewise, power-law normalization (similar
  6135. in effect to gamma correction) can be accomplished with
  6136. `.colors.PowerNorm`.
  6137. """
  6138. h, xedges, yedges = np.histogram2d(x, y, bins=bins, range=range,
  6139. density=density, weights=weights)
  6140. if cmin is not None:
  6141. h[h < cmin] = None
  6142. if cmax is not None:
  6143. h[h > cmax] = None
  6144. pc = self.pcolormesh(xedges, yedges, h.T, **kwargs)
  6145. self.set_xlim(xedges[0], xedges[-1])
  6146. self.set_ylim(yedges[0], yedges[-1])
  6147. return h, xedges, yedges, pc
  6148. @_preprocess_data(replace_names=["x", "weights"], label_namer="x")
  6149. @_docstring.interpd
  6150. def ecdf(self, x, weights=None, *, complementary=False,
  6151. orientation="vertical", compress=False, **kwargs):
  6152. """
  6153. Compute and plot the empirical cumulative distribution function of *x*.
  6154. .. versionadded:: 3.8
  6155. Parameters
  6156. ----------
  6157. x : 1d array-like
  6158. The input data. Infinite entries are kept (and move the relevant
  6159. end of the ecdf from 0/1), but NaNs and masked values are errors.
  6160. weights : 1d array-like or None, default: None
  6161. The weights of the entries; must have the same shape as *x*.
  6162. Weights corresponding to NaN data points are dropped, and then the
  6163. remaining weights are normalized to sum to 1. If unset, all
  6164. entries have the same weight.
  6165. complementary : bool, default: False
  6166. Whether to plot a cumulative distribution function, which increases
  6167. from 0 to 1 (the default), or a complementary cumulative
  6168. distribution function, which decreases from 1 to 0.
  6169. orientation : {"vertical", "horizontal"}, default: "vertical"
  6170. Whether the entries are plotted along the x-axis ("vertical", the
  6171. default) or the y-axis ("horizontal"). This parameter takes the
  6172. same values as in `~.Axes.hist`.
  6173. compress : bool, default: False
  6174. Whether multiple entries with the same values are grouped together
  6175. (with a summed weight) before plotting. This is mainly useful if
  6176. *x* contains many identical data points, to decrease the rendering
  6177. complexity of the plot. If *x* contains no duplicate points, this
  6178. has no effect and just uses some time and memory.
  6179. Other Parameters
  6180. ----------------
  6181. data : indexable object, optional
  6182. DATA_PARAMETER_PLACEHOLDER
  6183. **kwargs
  6184. Keyword arguments control the `.Line2D` properties:
  6185. %(Line2D:kwdoc)s
  6186. Returns
  6187. -------
  6188. `.Line2D`
  6189. Notes
  6190. -----
  6191. The ecdf plot can be thought of as a cumulative histogram with one bin
  6192. per data entry; i.e. it reports on the entire dataset without any
  6193. arbitrary binning.
  6194. If *x* contains NaNs or masked entries, either remove them first from
  6195. the array (if they should not taken into account), or replace them by
  6196. -inf or +inf (if they should be sorted at the beginning or the end of
  6197. the array).
  6198. """
  6199. _api.check_in_list(["horizontal", "vertical"], orientation=orientation)
  6200. if "drawstyle" in kwargs or "ds" in kwargs:
  6201. raise TypeError("Cannot pass 'drawstyle' or 'ds' to ecdf()")
  6202. if np.ma.getmask(x).any():
  6203. raise ValueError("ecdf() does not support masked entries")
  6204. x = np.asarray(x)
  6205. if np.isnan(x).any():
  6206. raise ValueError("ecdf() does not support NaNs")
  6207. argsort = np.argsort(x)
  6208. x = x[argsort]
  6209. if weights is None:
  6210. # Ensure that we end at exactly 1, avoiding floating point errors.
  6211. cum_weights = (1 + np.arange(len(x))) / len(x)
  6212. else:
  6213. weights = np.take(weights, argsort) # Reorder weights like we reordered x.
  6214. cum_weights = np.cumsum(weights / np.sum(weights))
  6215. if compress:
  6216. # Get indices of unique x values.
  6217. compress_idxs = [0, *(x[:-1] != x[1:]).nonzero()[0] + 1]
  6218. x = x[compress_idxs]
  6219. cum_weights = cum_weights[compress_idxs]
  6220. if orientation == "vertical":
  6221. if not complementary:
  6222. line, = self.plot([x[0], *x], [0, *cum_weights],
  6223. drawstyle="steps-post", **kwargs)
  6224. else:
  6225. line, = self.plot([*x, x[-1]], [1, *1 - cum_weights],
  6226. drawstyle="steps-pre", **kwargs)
  6227. line.sticky_edges.y[:] = [0, 1]
  6228. else: # orientation == "horizontal":
  6229. if not complementary:
  6230. line, = self.plot([0, *cum_weights], [x[0], *x],
  6231. drawstyle="steps-pre", **kwargs)
  6232. else:
  6233. line, = self.plot([1, *1 - cum_weights], [*x, x[-1]],
  6234. drawstyle="steps-post", **kwargs)
  6235. line.sticky_edges.x[:] = [0, 1]
  6236. return line
  6237. @_api.make_keyword_only("3.10", "NFFT")
  6238. @_preprocess_data(replace_names=["x"])
  6239. @_docstring.interpd
  6240. def psd(self, x, NFFT=None, Fs=None, Fc=None, detrend=None,
  6241. window=None, noverlap=None, pad_to=None,
  6242. sides=None, scale_by_freq=None, return_line=None, **kwargs):
  6243. r"""
  6244. Plot the power spectral density.
  6245. The power spectral density :math:`P_{xx}` by Welch's average
  6246. periodogram method. The vector *x* is divided into *NFFT* length
  6247. segments. Each segment is detrended by function *detrend* and
  6248. windowed by function *window*. *noverlap* gives the length of
  6249. the overlap between segments. The :math:`|\mathrm{fft}(i)|^2`
  6250. of each segment :math:`i` are averaged to compute :math:`P_{xx}`,
  6251. with a scaling to correct for power loss due to windowing.
  6252. If len(*x*) < *NFFT*, it will be zero padded to *NFFT*.
  6253. Parameters
  6254. ----------
  6255. x : 1-D array or sequence
  6256. Array or sequence containing the data
  6257. %(Spectral)s
  6258. %(PSD)s
  6259. noverlap : int, default: 0 (no overlap)
  6260. The number of points of overlap between segments.
  6261. Fc : int, default: 0
  6262. The center frequency of *x*, which offsets the x extents of the
  6263. plot to reflect the frequency range used when a signal is acquired
  6264. and then filtered and downsampled to baseband.
  6265. return_line : bool, default: False
  6266. Whether to include the line object plotted in the returned values.
  6267. Returns
  6268. -------
  6269. Pxx : 1-D array
  6270. The values for the power spectrum :math:`P_{xx}` before scaling
  6271. (real valued).
  6272. freqs : 1-D array
  6273. The frequencies corresponding to the elements in *Pxx*.
  6274. line : `~matplotlib.lines.Line2D`
  6275. The line created by this function.
  6276. Only returned if *return_line* is True.
  6277. Other Parameters
  6278. ----------------
  6279. data : indexable object, optional
  6280. DATA_PARAMETER_PLACEHOLDER
  6281. **kwargs
  6282. Keyword arguments control the `.Line2D` properties:
  6283. %(Line2D:kwdoc)s
  6284. See Also
  6285. --------
  6286. specgram
  6287. Differs in the default overlap; in not returning the mean of the
  6288. segment periodograms; in returning the times of the segments; and
  6289. in plotting a colormap instead of a line.
  6290. magnitude_spectrum
  6291. Plots the magnitude spectrum.
  6292. csd
  6293. Plots the spectral density between two signals.
  6294. Notes
  6295. -----
  6296. For plotting, the power is plotted as
  6297. :math:`10\log_{10}(P_{xx})` for decibels, though *Pxx* itself
  6298. is returned.
  6299. References
  6300. ----------
  6301. Bendat & Piersol -- Random Data: Analysis and Measurement Procedures,
  6302. John Wiley & Sons (1986)
  6303. """
  6304. if Fc is None:
  6305. Fc = 0
  6306. pxx, freqs = mlab.psd(x=x, NFFT=NFFT, Fs=Fs, detrend=detrend,
  6307. window=window, noverlap=noverlap, pad_to=pad_to,
  6308. sides=sides, scale_by_freq=scale_by_freq)
  6309. freqs += Fc
  6310. if scale_by_freq in (None, True):
  6311. psd_units = 'dB/Hz'
  6312. else:
  6313. psd_units = 'dB'
  6314. line = self.plot(freqs, 10 * np.log10(pxx), **kwargs)
  6315. self.set_xlabel('Frequency')
  6316. self.set_ylabel('Power Spectral Density (%s)' % psd_units)
  6317. self.grid(True)
  6318. vmin, vmax = self.get_ybound()
  6319. step = max(10 * int(np.log10(vmax - vmin)), 1)
  6320. ticks = np.arange(math.floor(vmin), math.ceil(vmax) + 1, step)
  6321. self.set_yticks(ticks)
  6322. if return_line is None or not return_line:
  6323. return pxx, freqs
  6324. else:
  6325. return pxx, freqs, line
  6326. @_api.make_keyword_only("3.10", "NFFT")
  6327. @_preprocess_data(replace_names=["x", "y"], label_namer="y")
  6328. @_docstring.interpd
  6329. def csd(self, x, y, NFFT=None, Fs=None, Fc=None, detrend=None,
  6330. window=None, noverlap=None, pad_to=None,
  6331. sides=None, scale_by_freq=None, return_line=None, **kwargs):
  6332. r"""
  6333. Plot the cross-spectral density.
  6334. The cross spectral density :math:`P_{xy}` by Welch's average
  6335. periodogram method. The vectors *x* and *y* are divided into
  6336. *NFFT* length segments. Each segment is detrended by function
  6337. *detrend* and windowed by function *window*. *noverlap* gives
  6338. the length of the overlap between segments. The product of
  6339. the direct FFTs of *x* and *y* are averaged over each segment
  6340. to compute :math:`P_{xy}`, with a scaling to correct for power
  6341. loss due to windowing.
  6342. If len(*x*) < *NFFT* or len(*y*) < *NFFT*, they will be zero
  6343. padded to *NFFT*.
  6344. Parameters
  6345. ----------
  6346. x, y : 1-D arrays or sequences
  6347. Arrays or sequences containing the data.
  6348. %(Spectral)s
  6349. %(PSD)s
  6350. noverlap : int, default: 0 (no overlap)
  6351. The number of points of overlap between segments.
  6352. Fc : int, default: 0
  6353. The center frequency of *x*, which offsets the x extents of the
  6354. plot to reflect the frequency range used when a signal is acquired
  6355. and then filtered and downsampled to baseband.
  6356. return_line : bool, default: False
  6357. Whether to include the line object plotted in the returned values.
  6358. Returns
  6359. -------
  6360. Pxy : 1-D array
  6361. The values for the cross spectrum :math:`P_{xy}` before scaling
  6362. (complex valued).
  6363. freqs : 1-D array
  6364. The frequencies corresponding to the elements in *Pxy*.
  6365. line : `~matplotlib.lines.Line2D`
  6366. The line created by this function.
  6367. Only returned if *return_line* is True.
  6368. Other Parameters
  6369. ----------------
  6370. data : indexable object, optional
  6371. DATA_PARAMETER_PLACEHOLDER
  6372. **kwargs
  6373. Keyword arguments control the `.Line2D` properties:
  6374. %(Line2D:kwdoc)s
  6375. See Also
  6376. --------
  6377. psd : is equivalent to setting ``y = x``.
  6378. Notes
  6379. -----
  6380. For plotting, the power is plotted as
  6381. :math:`10 \log_{10}(P_{xy})` for decibels, though :math:`P_{xy}` itself
  6382. is returned.
  6383. References
  6384. ----------
  6385. Bendat & Piersol -- Random Data: Analysis and Measurement Procedures,
  6386. John Wiley & Sons (1986)
  6387. """
  6388. if Fc is None:
  6389. Fc = 0
  6390. pxy, freqs = mlab.csd(x=x, y=y, NFFT=NFFT, Fs=Fs, detrend=detrend,
  6391. window=window, noverlap=noverlap, pad_to=pad_to,
  6392. sides=sides, scale_by_freq=scale_by_freq)
  6393. # pxy is complex
  6394. freqs += Fc
  6395. line = self.plot(freqs, 10 * np.log10(np.abs(pxy)), **kwargs)
  6396. self.set_xlabel('Frequency')
  6397. self.set_ylabel('Cross Spectrum Magnitude (dB)')
  6398. self.grid(True)
  6399. vmin, vmax = self.get_ybound()
  6400. step = max(10 * int(np.log10(vmax - vmin)), 1)
  6401. ticks = np.arange(math.floor(vmin), math.ceil(vmax) + 1, step)
  6402. self.set_yticks(ticks)
  6403. if return_line is None or not return_line:
  6404. return pxy, freqs
  6405. else:
  6406. return pxy, freqs, line
  6407. @_api.make_keyword_only("3.10", "Fs")
  6408. @_preprocess_data(replace_names=["x"])
  6409. @_docstring.interpd
  6410. def magnitude_spectrum(self, x, Fs=None, Fc=None, window=None,
  6411. pad_to=None, sides=None, scale=None,
  6412. **kwargs):
  6413. """
  6414. Plot the magnitude spectrum.
  6415. Compute the magnitude spectrum of *x*. Data is padded to a
  6416. length of *pad_to* and the windowing function *window* is applied to
  6417. the signal.
  6418. Parameters
  6419. ----------
  6420. x : 1-D array or sequence
  6421. Array or sequence containing the data.
  6422. %(Spectral)s
  6423. %(Single_Spectrum)s
  6424. scale : {'default', 'linear', 'dB'}
  6425. The scaling of the values in the *spec*. 'linear' is no scaling.
  6426. 'dB' returns the values in dB scale, i.e., the dB amplitude
  6427. (20 * log10). 'default' is 'linear'.
  6428. Fc : int, default: 0
  6429. The center frequency of *x*, which offsets the x extents of the
  6430. plot to reflect the frequency range used when a signal is acquired
  6431. and then filtered and downsampled to baseband.
  6432. Returns
  6433. -------
  6434. spectrum : 1-D array
  6435. The values for the magnitude spectrum before scaling (real valued).
  6436. freqs : 1-D array
  6437. The frequencies corresponding to the elements in *spectrum*.
  6438. line : `~matplotlib.lines.Line2D`
  6439. The line created by this function.
  6440. Other Parameters
  6441. ----------------
  6442. data : indexable object, optional
  6443. DATA_PARAMETER_PLACEHOLDER
  6444. **kwargs
  6445. Keyword arguments control the `.Line2D` properties:
  6446. %(Line2D:kwdoc)s
  6447. See Also
  6448. --------
  6449. psd
  6450. Plots the power spectral density.
  6451. angle_spectrum
  6452. Plots the angles of the corresponding frequencies.
  6453. phase_spectrum
  6454. Plots the phase (unwrapped angle) of the corresponding frequencies.
  6455. specgram
  6456. Can plot the magnitude spectrum of segments within the signal in a
  6457. colormap.
  6458. """
  6459. if Fc is None:
  6460. Fc = 0
  6461. spec, freqs = mlab.magnitude_spectrum(x=x, Fs=Fs, window=window,
  6462. pad_to=pad_to, sides=sides)
  6463. freqs += Fc
  6464. yunits = _api.check_getitem(
  6465. {None: 'energy', 'default': 'energy', 'linear': 'energy',
  6466. 'dB': 'dB'},
  6467. scale=scale)
  6468. if yunits == 'energy':
  6469. Z = spec
  6470. else: # yunits == 'dB'
  6471. Z = 20. * np.log10(spec)
  6472. line, = self.plot(freqs, Z, **kwargs)
  6473. self.set_xlabel('Frequency')
  6474. self.set_ylabel('Magnitude (%s)' % yunits)
  6475. return spec, freqs, line
  6476. @_api.make_keyword_only("3.10", "Fs")
  6477. @_preprocess_data(replace_names=["x"])
  6478. @_docstring.interpd
  6479. def angle_spectrum(self, x, Fs=None, Fc=None, window=None,
  6480. pad_to=None, sides=None, **kwargs):
  6481. """
  6482. Plot the angle spectrum.
  6483. Compute the angle spectrum (wrapped phase spectrum) of *x*.
  6484. Data is padded to a length of *pad_to* and the windowing function
  6485. *window* is applied to the signal.
  6486. Parameters
  6487. ----------
  6488. x : 1-D array or sequence
  6489. Array or sequence containing the data.
  6490. %(Spectral)s
  6491. %(Single_Spectrum)s
  6492. Fc : int, default: 0
  6493. The center frequency of *x*, which offsets the x extents of the
  6494. plot to reflect the frequency range used when a signal is acquired
  6495. and then filtered and downsampled to baseband.
  6496. Returns
  6497. -------
  6498. spectrum : 1-D array
  6499. The values for the angle spectrum in radians (real valued).
  6500. freqs : 1-D array
  6501. The frequencies corresponding to the elements in *spectrum*.
  6502. line : `~matplotlib.lines.Line2D`
  6503. The line created by this function.
  6504. Other Parameters
  6505. ----------------
  6506. data : indexable object, optional
  6507. DATA_PARAMETER_PLACEHOLDER
  6508. **kwargs
  6509. Keyword arguments control the `.Line2D` properties:
  6510. %(Line2D:kwdoc)s
  6511. See Also
  6512. --------
  6513. magnitude_spectrum
  6514. Plots the magnitudes of the corresponding frequencies.
  6515. phase_spectrum
  6516. Plots the unwrapped version of this function.
  6517. specgram
  6518. Can plot the angle spectrum of segments within the signal in a
  6519. colormap.
  6520. """
  6521. if Fc is None:
  6522. Fc = 0
  6523. spec, freqs = mlab.angle_spectrum(x=x, Fs=Fs, window=window,
  6524. pad_to=pad_to, sides=sides)
  6525. freqs += Fc
  6526. lines = self.plot(freqs, spec, **kwargs)
  6527. self.set_xlabel('Frequency')
  6528. self.set_ylabel('Angle (radians)')
  6529. return spec, freqs, lines[0]
  6530. @_api.make_keyword_only("3.10", "Fs")
  6531. @_preprocess_data(replace_names=["x"])
  6532. @_docstring.interpd
  6533. def phase_spectrum(self, x, Fs=None, Fc=None, window=None,
  6534. pad_to=None, sides=None, **kwargs):
  6535. """
  6536. Plot the phase spectrum.
  6537. Compute the phase spectrum (unwrapped angle spectrum) of *x*.
  6538. Data is padded to a length of *pad_to* and the windowing function
  6539. *window* is applied to the signal.
  6540. Parameters
  6541. ----------
  6542. x : 1-D array or sequence
  6543. Array or sequence containing the data
  6544. %(Spectral)s
  6545. %(Single_Spectrum)s
  6546. Fc : int, default: 0
  6547. The center frequency of *x*, which offsets the x extents of the
  6548. plot to reflect the frequency range used when a signal is acquired
  6549. and then filtered and downsampled to baseband.
  6550. Returns
  6551. -------
  6552. spectrum : 1-D array
  6553. The values for the phase spectrum in radians (real valued).
  6554. freqs : 1-D array
  6555. The frequencies corresponding to the elements in *spectrum*.
  6556. line : `~matplotlib.lines.Line2D`
  6557. The line created by this function.
  6558. Other Parameters
  6559. ----------------
  6560. data : indexable object, optional
  6561. DATA_PARAMETER_PLACEHOLDER
  6562. **kwargs
  6563. Keyword arguments control the `.Line2D` properties:
  6564. %(Line2D:kwdoc)s
  6565. See Also
  6566. --------
  6567. magnitude_spectrum
  6568. Plots the magnitudes of the corresponding frequencies.
  6569. angle_spectrum
  6570. Plots the wrapped version of this function.
  6571. specgram
  6572. Can plot the phase spectrum of segments within the signal in a
  6573. colormap.
  6574. """
  6575. if Fc is None:
  6576. Fc = 0
  6577. spec, freqs = mlab.phase_spectrum(x=x, Fs=Fs, window=window,
  6578. pad_to=pad_to, sides=sides)
  6579. freqs += Fc
  6580. lines = self.plot(freqs, spec, **kwargs)
  6581. self.set_xlabel('Frequency')
  6582. self.set_ylabel('Phase (radians)')
  6583. return spec, freqs, lines[0]
  6584. @_api.make_keyword_only("3.10", "NFFT")
  6585. @_preprocess_data(replace_names=["x", "y"])
  6586. @_docstring.interpd
  6587. def cohere(self, x, y, NFFT=256, Fs=2, Fc=0, detrend=mlab.detrend_none,
  6588. window=mlab.window_hanning, noverlap=0, pad_to=None,
  6589. sides='default', scale_by_freq=None, **kwargs):
  6590. r"""
  6591. Plot the coherence between *x* and *y*.
  6592. Coherence is the normalized cross spectral density:
  6593. .. math::
  6594. C_{xy} = \frac{|P_{xy}|^2}{P_{xx}P_{yy}}
  6595. Parameters
  6596. ----------
  6597. %(Spectral)s
  6598. %(PSD)s
  6599. noverlap : int, default: 0 (no overlap)
  6600. The number of points of overlap between blocks.
  6601. Fc : int, default: 0
  6602. The center frequency of *x*, which offsets the x extents of the
  6603. plot to reflect the frequency range used when a signal is acquired
  6604. and then filtered and downsampled to baseband.
  6605. Returns
  6606. -------
  6607. Cxy : 1-D array
  6608. The coherence vector.
  6609. freqs : 1-D array
  6610. The frequencies for the elements in *Cxy*.
  6611. Other Parameters
  6612. ----------------
  6613. data : indexable object, optional
  6614. DATA_PARAMETER_PLACEHOLDER
  6615. **kwargs
  6616. Keyword arguments control the `.Line2D` properties:
  6617. %(Line2D:kwdoc)s
  6618. References
  6619. ----------
  6620. Bendat & Piersol -- Random Data: Analysis and Measurement Procedures,
  6621. John Wiley & Sons (1986)
  6622. """
  6623. cxy, freqs = mlab.cohere(x=x, y=y, NFFT=NFFT, Fs=Fs, detrend=detrend,
  6624. window=window, noverlap=noverlap,
  6625. scale_by_freq=scale_by_freq, sides=sides,
  6626. pad_to=pad_to)
  6627. freqs += Fc
  6628. self.plot(freqs, cxy, **kwargs)
  6629. self.set_xlabel('Frequency')
  6630. self.set_ylabel('Coherence')
  6631. self.grid(True)
  6632. return cxy, freqs
  6633. @_api.make_keyword_only("3.10", "NFFT")
  6634. @_preprocess_data(replace_names=["x"])
  6635. @_docstring.interpd
  6636. def specgram(self, x, NFFT=None, Fs=None, Fc=None, detrend=None,
  6637. window=None, noverlap=None,
  6638. cmap=None, xextent=None, pad_to=None, sides=None,
  6639. scale_by_freq=None, mode=None, scale=None,
  6640. vmin=None, vmax=None, **kwargs):
  6641. """
  6642. Plot a spectrogram.
  6643. Compute and plot a spectrogram of data in *x*. Data are split into
  6644. *NFFT* length segments and the spectrum of each section is
  6645. computed. The windowing function *window* is applied to each
  6646. segment, and the amount of overlap of each segment is
  6647. specified with *noverlap*. The spectrogram is plotted as a colormap
  6648. (using imshow).
  6649. Parameters
  6650. ----------
  6651. x : 1-D array or sequence
  6652. Array or sequence containing the data.
  6653. %(Spectral)s
  6654. %(PSD)s
  6655. mode : {'default', 'psd', 'magnitude', 'angle', 'phase'}
  6656. What sort of spectrum to use. Default is 'psd', which takes the
  6657. power spectral density. 'magnitude' returns the magnitude
  6658. spectrum. 'angle' returns the phase spectrum without unwrapping.
  6659. 'phase' returns the phase spectrum with unwrapping.
  6660. noverlap : int, default: 128
  6661. The number of points of overlap between blocks.
  6662. scale : {'default', 'linear', 'dB'}
  6663. The scaling of the values in the *spec*. 'linear' is no scaling.
  6664. 'dB' returns the values in dB scale. When *mode* is 'psd',
  6665. this is dB power (10 * log10). Otherwise, this is dB amplitude
  6666. (20 * log10). 'default' is 'dB' if *mode* is 'psd' or
  6667. 'magnitude' and 'linear' otherwise. This must be 'linear'
  6668. if *mode* is 'angle' or 'phase'.
  6669. Fc : int, default: 0
  6670. The center frequency of *x*, which offsets the x extents of the
  6671. plot to reflect the frequency range used when a signal is acquired
  6672. and then filtered and downsampled to baseband.
  6673. cmap : `.Colormap`, default: :rc:`image.cmap`
  6674. xextent : *None* or (xmin, xmax)
  6675. The image extent along the x-axis. The default sets *xmin* to the
  6676. left border of the first bin (*spectrum* column) and *xmax* to the
  6677. right border of the last bin. Note that for *noverlap>0* the width
  6678. of the bins is smaller than those of the segments.
  6679. data : indexable object, optional
  6680. DATA_PARAMETER_PLACEHOLDER
  6681. vmin, vmax : float, optional
  6682. vmin and vmax define the data range that the colormap covers.
  6683. By default, the colormap covers the complete value range of the
  6684. data.
  6685. **kwargs
  6686. Additional keyword arguments are passed on to `~.axes.Axes.imshow`
  6687. which makes the specgram image. The origin keyword argument
  6688. is not supported.
  6689. Returns
  6690. -------
  6691. spectrum : 2D array
  6692. Columns are the periodograms of successive segments.
  6693. freqs : 1-D array
  6694. The frequencies corresponding to the rows in *spectrum*.
  6695. t : 1-D array
  6696. The times corresponding to midpoints of segments (i.e., the columns
  6697. in *spectrum*).
  6698. im : `.AxesImage`
  6699. The image created by imshow containing the spectrogram.
  6700. See Also
  6701. --------
  6702. psd
  6703. Differs in the default overlap; in returning the mean of the
  6704. segment periodograms; in not returning times; and in generating a
  6705. line plot instead of colormap.
  6706. magnitude_spectrum
  6707. A single spectrum, similar to having a single segment when *mode*
  6708. is 'magnitude'. Plots a line instead of a colormap.
  6709. angle_spectrum
  6710. A single spectrum, similar to having a single segment when *mode*
  6711. is 'angle'. Plots a line instead of a colormap.
  6712. phase_spectrum
  6713. A single spectrum, similar to having a single segment when *mode*
  6714. is 'phase'. Plots a line instead of a colormap.
  6715. Notes
  6716. -----
  6717. The parameters *detrend* and *scale_by_freq* do only apply when *mode*
  6718. is set to 'psd'.
  6719. """
  6720. if NFFT is None:
  6721. NFFT = 256 # same default as in mlab.specgram()
  6722. if Fc is None:
  6723. Fc = 0 # same default as in mlab._spectral_helper()
  6724. if noverlap is None:
  6725. noverlap = 128 # same default as in mlab.specgram()
  6726. if Fs is None:
  6727. Fs = 2 # same default as in mlab._spectral_helper()
  6728. if mode == 'complex':
  6729. raise ValueError('Cannot plot a complex specgram')
  6730. if scale is None or scale == 'default':
  6731. if mode in ['angle', 'phase']:
  6732. scale = 'linear'
  6733. else:
  6734. scale = 'dB'
  6735. elif mode in ['angle', 'phase'] and scale == 'dB':
  6736. raise ValueError('Cannot use dB scale with angle or phase mode')
  6737. spec, freqs, t = mlab.specgram(x=x, NFFT=NFFT, Fs=Fs,
  6738. detrend=detrend, window=window,
  6739. noverlap=noverlap, pad_to=pad_to,
  6740. sides=sides,
  6741. scale_by_freq=scale_by_freq,
  6742. mode=mode)
  6743. if scale == 'linear':
  6744. Z = spec
  6745. elif scale == 'dB':
  6746. if mode is None or mode == 'default' or mode == 'psd':
  6747. Z = 10. * np.log10(spec)
  6748. else:
  6749. Z = 20. * np.log10(spec)
  6750. else:
  6751. raise ValueError(f'Unknown scale {scale!r}')
  6752. Z = np.flipud(Z)
  6753. if xextent is None:
  6754. # padding is needed for first and last segment:
  6755. pad_xextent = (NFFT-noverlap) / Fs / 2
  6756. xextent = np.min(t) - pad_xextent, np.max(t) + pad_xextent
  6757. xmin, xmax = xextent
  6758. freqs += Fc
  6759. extent = xmin, xmax, freqs[0], freqs[-1]
  6760. if 'origin' in kwargs:
  6761. raise _api.kwarg_error("specgram", "origin")
  6762. im = self.imshow(Z, cmap, extent=extent, vmin=vmin, vmax=vmax,
  6763. origin='upper', **kwargs)
  6764. self.axis('auto')
  6765. return spec, freqs, t, im
  6766. @_api.make_keyword_only("3.10", "precision")
  6767. @_docstring.interpd
  6768. def spy(self, Z, precision=0, marker=None, markersize=None,
  6769. aspect='equal', origin="upper", **kwargs):
  6770. """
  6771. Plot the sparsity pattern of a 2D array.
  6772. This visualizes the non-zero values of the array.
  6773. Two plotting styles are available: image and marker. Both
  6774. are available for full arrays, but only the marker style
  6775. works for `scipy.sparse.spmatrix` instances.
  6776. **Image style**
  6777. If *marker* and *markersize* are *None*, `~.Axes.imshow` is used. Any
  6778. extra remaining keyword arguments are passed to this method.
  6779. **Marker style**
  6780. If *Z* is a `scipy.sparse.spmatrix` or *marker* or *markersize* are
  6781. *None*, a `.Line2D` object will be returned with the value of marker
  6782. determining the marker type, and any remaining keyword arguments
  6783. passed to `~.Axes.plot`.
  6784. Parameters
  6785. ----------
  6786. Z : (M, N) array-like
  6787. The array to be plotted.
  6788. precision : float or 'present', default: 0
  6789. If *precision* is 0, any non-zero value will be plotted. Otherwise,
  6790. values of :math:`|Z| > precision` will be plotted.
  6791. For `scipy.sparse.spmatrix` instances, you can also
  6792. pass 'present'. In this case any value present in the array
  6793. will be plotted, even if it is identically zero.
  6794. aspect : {'equal', 'auto', None} or float, default: 'equal'
  6795. The aspect ratio of the Axes. This parameter is particularly
  6796. relevant for images since it determines whether data pixels are
  6797. square.
  6798. This parameter is a shortcut for explicitly calling
  6799. `.Axes.set_aspect`. See there for further details.
  6800. - 'equal': Ensures an aspect ratio of 1. Pixels will be square.
  6801. - 'auto': The Axes is kept fixed and the aspect is adjusted so
  6802. that the data fit in the Axes. In general, this will result in
  6803. non-square pixels.
  6804. - *None*: Use :rc:`image.aspect`.
  6805. origin : {'upper', 'lower'}, default: :rc:`image.origin`
  6806. Place the [0, 0] index of the array in the upper left or lower left
  6807. corner of the Axes. The convention 'upper' is typically used for
  6808. matrices and images.
  6809. Returns
  6810. -------
  6811. `~matplotlib.image.AxesImage` or `.Line2D`
  6812. The return type depends on the plotting style (see above).
  6813. Other Parameters
  6814. ----------------
  6815. **kwargs
  6816. The supported additional parameters depend on the plotting style.
  6817. For the image style, you can pass the following additional
  6818. parameters of `~.Axes.imshow`:
  6819. - *cmap*
  6820. - *alpha*
  6821. - *url*
  6822. - any `.Artist` properties (passed on to the `.AxesImage`)
  6823. For the marker style, you can pass any `.Line2D` property except
  6824. for *linestyle*:
  6825. %(Line2D:kwdoc)s
  6826. """
  6827. if marker is None and markersize is None and hasattr(Z, 'tocoo'):
  6828. marker = 's'
  6829. _api.check_in_list(["upper", "lower"], origin=origin)
  6830. if marker is None and markersize is None:
  6831. Z = np.asarray(Z)
  6832. mask = np.abs(Z) > precision
  6833. if 'cmap' not in kwargs:
  6834. kwargs['cmap'] = mcolors.ListedColormap(['w', 'k'],
  6835. name='binary')
  6836. if 'interpolation' in kwargs:
  6837. raise _api.kwarg_error("spy", "interpolation")
  6838. if 'norm' not in kwargs:
  6839. kwargs['norm'] = mcolors.NoNorm()
  6840. ret = self.imshow(mask, interpolation='nearest',
  6841. aspect=aspect, origin=origin,
  6842. **kwargs)
  6843. else:
  6844. if hasattr(Z, 'tocoo'):
  6845. c = Z.tocoo()
  6846. if precision == 'present':
  6847. y = c.row
  6848. x = c.col
  6849. else:
  6850. nonzero = np.abs(c.data) > precision
  6851. y = c.row[nonzero]
  6852. x = c.col[nonzero]
  6853. else:
  6854. Z = np.asarray(Z)
  6855. nonzero = np.abs(Z) > precision
  6856. y, x = np.nonzero(nonzero)
  6857. if marker is None:
  6858. marker = 's'
  6859. if markersize is None:
  6860. markersize = 10
  6861. if 'linestyle' in kwargs:
  6862. raise _api.kwarg_error("spy", "linestyle")
  6863. ret = mlines.Line2D(
  6864. x, y, linestyle='None', marker=marker, markersize=markersize,
  6865. **kwargs)
  6866. self.add_line(ret)
  6867. nr, nc = Z.shape
  6868. self.set_xlim(-0.5, nc - 0.5)
  6869. if origin == "upper":
  6870. self.set_ylim(nr - 0.5, -0.5)
  6871. else:
  6872. self.set_ylim(-0.5, nr - 0.5)
  6873. self.set_aspect(aspect)
  6874. self.title.set_y(1.05)
  6875. if origin == "upper":
  6876. self.xaxis.tick_top()
  6877. else: # lower
  6878. self.xaxis.tick_bottom()
  6879. self.xaxis.set_ticks_position('both')
  6880. self.xaxis.set_major_locator(
  6881. mticker.MaxNLocator(nbins=9, steps=[1, 2, 5, 10], integer=True))
  6882. self.yaxis.set_major_locator(
  6883. mticker.MaxNLocator(nbins=9, steps=[1, 2, 5, 10], integer=True))
  6884. return ret
  6885. def matshow(self, Z, **kwargs):
  6886. """
  6887. Plot the values of a 2D matrix or array as color-coded image.
  6888. The matrix will be shown the way it would be printed, with the first
  6889. row at the top. Row and column numbering is zero-based.
  6890. Parameters
  6891. ----------
  6892. Z : (M, N) array-like
  6893. The matrix to be displayed.
  6894. Returns
  6895. -------
  6896. `~matplotlib.image.AxesImage`
  6897. Other Parameters
  6898. ----------------
  6899. **kwargs : `~matplotlib.axes.Axes.imshow` arguments
  6900. See Also
  6901. --------
  6902. imshow : More general function to plot data on a 2D regular raster.
  6903. Notes
  6904. -----
  6905. This is just a convenience function wrapping `.imshow` to set useful
  6906. defaults for displaying a matrix. In particular:
  6907. - Set ``origin='upper'``.
  6908. - Set ``interpolation='nearest'``.
  6909. - Set ``aspect='equal'``.
  6910. - Ticks are placed to the left and above.
  6911. - Ticks are formatted to show integer indices.
  6912. """
  6913. Z = np.asanyarray(Z)
  6914. kw = {'origin': 'upper',
  6915. 'interpolation': 'nearest',
  6916. 'aspect': 'equal', # (already the imshow default)
  6917. **kwargs}
  6918. im = self.imshow(Z, **kw)
  6919. self.title.set_y(1.05)
  6920. self.xaxis.tick_top()
  6921. self.xaxis.set_ticks_position('both')
  6922. self.xaxis.set_major_locator(
  6923. mticker.MaxNLocator(nbins=9, steps=[1, 2, 5, 10], integer=True))
  6924. self.yaxis.set_major_locator(
  6925. mticker.MaxNLocator(nbins=9, steps=[1, 2, 5, 10], integer=True))
  6926. return im
  6927. @_api.make_keyword_only("3.10", "vert")
  6928. @_preprocess_data(replace_names=["dataset"])
  6929. def violinplot(self, dataset, positions=None, vert=None,
  6930. orientation='vertical', widths=0.5, showmeans=False,
  6931. showextrema=True, showmedians=False, quantiles=None,
  6932. points=100, bw_method=None, side='both',):
  6933. """
  6934. Make a violin plot.
  6935. Make a violin plot for each column of *dataset* or each vector in
  6936. sequence *dataset*. Each filled area extends to represent the
  6937. entire data range, with optional lines at the mean, the median,
  6938. the minimum, the maximum, and user-specified quantiles.
  6939. Parameters
  6940. ----------
  6941. dataset : Array or a sequence of vectors.
  6942. The input data.
  6943. positions : array-like, default: [1, 2, ..., n]
  6944. The positions of the violins; i.e. coordinates on the x-axis for
  6945. vertical violins (or y-axis for horizontal violins).
  6946. vert : bool, optional
  6947. .. deprecated:: 3.10
  6948. Use *orientation* instead.
  6949. If this is given during the deprecation period, it overrides
  6950. the *orientation* parameter.
  6951. If True, plots the violins vertically.
  6952. If False, plots the violins horizontally.
  6953. orientation : {'vertical', 'horizontal'}, default: 'vertical'
  6954. If 'horizontal', plots the violins horizontally.
  6955. Otherwise, plots the violins vertically.
  6956. .. versionadded:: 3.10
  6957. widths : float or array-like, default: 0.5
  6958. The maximum width of each violin in units of the *positions* axis.
  6959. The default is 0.5, which is half the available space when using default
  6960. *positions*.
  6961. showmeans : bool, default: False
  6962. Whether to show the mean with a line.
  6963. showextrema : bool, default: True
  6964. Whether to show extrema with a line.
  6965. showmedians : bool, default: False
  6966. Whether to show the median with a line.
  6967. quantiles : array-like, default: None
  6968. If not None, set a list of floats in interval [0, 1] for each violin,
  6969. which stands for the quantiles that will be rendered for that
  6970. violin.
  6971. points : int, default: 100
  6972. The number of points to evaluate each of the gaussian kernel density
  6973. estimations at.
  6974. bw_method : {'scott', 'silverman'} or float or callable, default: 'scott'
  6975. The method used to calculate the estimator bandwidth. If a
  6976. float, this will be used directly as `kde.factor`. If a
  6977. callable, it should take a `matplotlib.mlab.GaussianKDE` instance as
  6978. its only parameter and return a float.
  6979. side : {'both', 'low', 'high'}, default: 'both'
  6980. 'both' plots standard violins. 'low'/'high' only
  6981. plots the side below/above the positions value.
  6982. data : indexable object, optional
  6983. DATA_PARAMETER_PLACEHOLDER
  6984. Returns
  6985. -------
  6986. dict
  6987. A dictionary mapping each component of the violinplot to a
  6988. list of the corresponding collection instances created. The
  6989. dictionary has the following keys:
  6990. - ``bodies``: A list of the `~.collections.PolyCollection`
  6991. instances containing the filled area of each violin.
  6992. - ``cmeans``: A `~.collections.LineCollection` instance that marks
  6993. the mean values of each of the violin's distribution.
  6994. - ``cmins``: A `~.collections.LineCollection` instance that marks
  6995. the bottom of each violin's distribution.
  6996. - ``cmaxes``: A `~.collections.LineCollection` instance that marks
  6997. the top of each violin's distribution.
  6998. - ``cbars``: A `~.collections.LineCollection` instance that marks
  6999. the centers of each violin's distribution.
  7000. - ``cmedians``: A `~.collections.LineCollection` instance that
  7001. marks the median values of each of the violin's distribution.
  7002. - ``cquantiles``: A `~.collections.LineCollection` instance created
  7003. to identify the quantile values of each of the violin's
  7004. distribution.
  7005. See Also
  7006. --------
  7007. .Axes.violin : Draw a violin from pre-computed statistics.
  7008. boxplot : Draw a box and whisker plot.
  7009. """
  7010. def _kde_method(X, coords):
  7011. # Unpack in case of e.g. Pandas or xarray object
  7012. X = cbook._unpack_to_numpy(X)
  7013. # fallback gracefully if the vector contains only one value
  7014. if np.all(X[0] == X):
  7015. return (X[0] == coords).astype(float)
  7016. kde = mlab.GaussianKDE(X, bw_method)
  7017. return kde.evaluate(coords)
  7018. vpstats = cbook.violin_stats(dataset, _kde_method, points=points,
  7019. quantiles=quantiles)
  7020. return self.violin(vpstats, positions=positions, vert=vert,
  7021. orientation=orientation, widths=widths,
  7022. showmeans=showmeans, showextrema=showextrema,
  7023. showmedians=showmedians, side=side)
  7024. @_api.make_keyword_only("3.10", "vert")
  7025. def violin(self, vpstats, positions=None, vert=None,
  7026. orientation='vertical', widths=0.5, showmeans=False,
  7027. showextrema=True, showmedians=False, side='both'):
  7028. """
  7029. Draw a violin plot from pre-computed statistics.
  7030. Draw a violin plot for each column of *vpstats*. Each filled area
  7031. extends to represent the entire data range, with optional lines at the
  7032. mean, the median, the minimum, the maximum, and the quantiles values.
  7033. Parameters
  7034. ----------
  7035. vpstats : list of dicts
  7036. A list of dictionaries containing stats for each violin plot.
  7037. Required keys are:
  7038. - ``coords``: A list of scalars containing the coordinates that
  7039. the violin's kernel density estimate were evaluated at.
  7040. - ``vals``: A list of scalars containing the values of the
  7041. kernel density estimate at each of the coordinates given
  7042. in *coords*.
  7043. - ``mean``: The mean value for this violin's dataset.
  7044. - ``median``: The median value for this violin's dataset.
  7045. - ``min``: The minimum value for this violin's dataset.
  7046. - ``max``: The maximum value for this violin's dataset.
  7047. Optional keys are:
  7048. - ``quantiles``: A list of scalars containing the quantile values
  7049. for this violin's dataset.
  7050. positions : array-like, default: [1, 2, ..., n]
  7051. The positions of the violins; i.e. coordinates on the x-axis for
  7052. vertical violins (or y-axis for horizontal violins).
  7053. vert : bool, optional
  7054. .. deprecated:: 3.10
  7055. Use *orientation* instead.
  7056. If this is given during the deprecation period, it overrides
  7057. the *orientation* parameter.
  7058. If True, plots the violins vertically.
  7059. If False, plots the violins horizontally.
  7060. orientation : {'vertical', 'horizontal'}, default: 'vertical'
  7061. If 'horizontal', plots the violins horizontally.
  7062. Otherwise, plots the violins vertically.
  7063. .. versionadded:: 3.10
  7064. widths : float or array-like, default: 0.5
  7065. The maximum width of each violin in units of the *positions* axis.
  7066. The default is 0.5, which is half available space when using default
  7067. *positions*.
  7068. showmeans : bool, default: False
  7069. Whether to show the mean with a line.
  7070. showextrema : bool, default: True
  7071. Whether to show extrema with a line.
  7072. showmedians : bool, default: False
  7073. Whether to show the median with a line.
  7074. side : {'both', 'low', 'high'}, default: 'both'
  7075. 'both' plots standard violins. 'low'/'high' only
  7076. plots the side below/above the positions value.
  7077. Returns
  7078. -------
  7079. dict
  7080. A dictionary mapping each component of the violinplot to a
  7081. list of the corresponding collection instances created. The
  7082. dictionary has the following keys:
  7083. - ``bodies``: A list of the `~.collections.PolyCollection`
  7084. instances containing the filled area of each violin.
  7085. - ``cmeans``: A `~.collections.LineCollection` instance that marks
  7086. the mean values of each of the violin's distribution.
  7087. - ``cmins``: A `~.collections.LineCollection` instance that marks
  7088. the bottom of each violin's distribution.
  7089. - ``cmaxes``: A `~.collections.LineCollection` instance that marks
  7090. the top of each violin's distribution.
  7091. - ``cbars``: A `~.collections.LineCollection` instance that marks
  7092. the centers of each violin's distribution.
  7093. - ``cmedians``: A `~.collections.LineCollection` instance that
  7094. marks the median values of each of the violin's distribution.
  7095. - ``cquantiles``: A `~.collections.LineCollection` instance created
  7096. to identify the quantiles values of each of the violin's
  7097. distribution.
  7098. See Also
  7099. --------
  7100. violinplot :
  7101. Draw a violin plot from data instead of pre-computed statistics.
  7102. """
  7103. # Statistical quantities to be plotted on the violins
  7104. means = []
  7105. mins = []
  7106. maxes = []
  7107. medians = []
  7108. quantiles = []
  7109. qlens = [] # Number of quantiles in each dataset.
  7110. artists = {} # Collections to be returned
  7111. N = len(vpstats)
  7112. datashape_message = ("List of violinplot statistics and `{0}` "
  7113. "values must have the same length")
  7114. # vert and orientation parameters are linked until vert's
  7115. # deprecation period expires. If both are selected,
  7116. # vert takes precedence.
  7117. if vert is not None:
  7118. _api.warn_deprecated(
  7119. "3.11",
  7120. name="vert: bool",
  7121. alternative="orientation: {'vertical', 'horizontal'}",
  7122. pending=True,
  7123. )
  7124. orientation = 'vertical' if vert else 'horizontal'
  7125. _api.check_in_list(['horizontal', 'vertical'], orientation=orientation)
  7126. # Validate positions
  7127. if positions is None:
  7128. positions = range(1, N + 1)
  7129. elif len(positions) != N:
  7130. raise ValueError(datashape_message.format("positions"))
  7131. # Validate widths
  7132. if np.isscalar(widths):
  7133. widths = [widths] * N
  7134. elif len(widths) != N:
  7135. raise ValueError(datashape_message.format("widths"))
  7136. # Validate side
  7137. _api.check_in_list(["both", "low", "high"], side=side)
  7138. # Calculate ranges for statistics lines (shape (2, N)).
  7139. line_ends = [[-0.25 if side in ['both', 'low'] else 0],
  7140. [0.25 if side in ['both', 'high'] else 0]] \
  7141. * np.array(widths) + positions
  7142. # Colors.
  7143. if mpl.rcParams['_internal.classic_mode']:
  7144. fillcolor = 'y'
  7145. linecolor = 'r'
  7146. else:
  7147. fillcolor = linecolor = self._get_lines.get_next_color()
  7148. # Check whether we are rendering vertically or horizontally
  7149. if orientation == 'vertical':
  7150. fill = self.fill_betweenx
  7151. if side in ['low', 'high']:
  7152. perp_lines = functools.partial(self.hlines, colors=linecolor,
  7153. capstyle='projecting')
  7154. par_lines = functools.partial(self.vlines, colors=linecolor,
  7155. capstyle='projecting')
  7156. else:
  7157. perp_lines = functools.partial(self.hlines, colors=linecolor)
  7158. par_lines = functools.partial(self.vlines, colors=linecolor)
  7159. else:
  7160. fill = self.fill_between
  7161. if side in ['low', 'high']:
  7162. perp_lines = functools.partial(self.vlines, colors=linecolor,
  7163. capstyle='projecting')
  7164. par_lines = functools.partial(self.hlines, colors=linecolor,
  7165. capstyle='projecting')
  7166. else:
  7167. perp_lines = functools.partial(self.vlines, colors=linecolor)
  7168. par_lines = functools.partial(self.hlines, colors=linecolor)
  7169. # Render violins
  7170. bodies = []
  7171. for stats, pos, width in zip(vpstats, positions, widths):
  7172. # The 0.5 factor reflects the fact that we plot from v-p to v+p.
  7173. vals = np.array(stats['vals'])
  7174. vals = 0.5 * width * vals / vals.max()
  7175. bodies += [fill(stats['coords'],
  7176. -vals + pos if side in ['both', 'low'] else pos,
  7177. vals + pos if side in ['both', 'high'] else pos,
  7178. facecolor=fillcolor, alpha=0.3)]
  7179. means.append(stats['mean'])
  7180. mins.append(stats['min'])
  7181. maxes.append(stats['max'])
  7182. medians.append(stats['median'])
  7183. q = stats.get('quantiles') # a list of floats, or None
  7184. if q is None:
  7185. q = []
  7186. quantiles.extend(q)
  7187. qlens.append(len(q))
  7188. artists['bodies'] = bodies
  7189. if showmeans: # Render means
  7190. artists['cmeans'] = perp_lines(means, *line_ends)
  7191. if showextrema: # Render extrema
  7192. artists['cmaxes'] = perp_lines(maxes, *line_ends)
  7193. artists['cmins'] = perp_lines(mins, *line_ends)
  7194. artists['cbars'] = par_lines(positions, mins, maxes)
  7195. if showmedians: # Render medians
  7196. artists['cmedians'] = perp_lines(medians, *line_ends)
  7197. if quantiles: # Render quantiles: each width is repeated qlen times.
  7198. artists['cquantiles'] = perp_lines(
  7199. quantiles, *np.repeat(line_ends, qlens, axis=1))
  7200. return artists
  7201. # Methods that are entirely implemented in other modules.
  7202. table = _make_axes_method(mtable.table)
  7203. # args can be either Y or y1, y2, ... and all should be replaced
  7204. stackplot = _preprocess_data()(_make_axes_method(mstack.stackplot))
  7205. streamplot = _preprocess_data(
  7206. replace_names=["x", "y", "u", "v", "start_points"])(
  7207. _make_axes_method(mstream.streamplot))
  7208. tricontour = _make_axes_method(mtri.tricontour)
  7209. tricontourf = _make_axes_method(mtri.tricontourf)
  7210. tripcolor = _make_axes_method(mtri.tripcolor)
  7211. triplot = _make_axes_method(mtri.triplot)
  7212. def _get_aspect_ratio(self):
  7213. """
  7214. Convenience method to calculate the aspect ratio of the Axes in
  7215. the display coordinate system.
  7216. """
  7217. figure_size = self.get_figure().get_size_inches()
  7218. ll, ur = self.get_position() * figure_size
  7219. width, height = ur - ll
  7220. return height / (width * self.get_data_ratio())