_axes.py 306 KB

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