core.py 266 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404
  1. """
  2. numpy.ma : a package to handle missing or invalid values.
  3. This package was initially written for numarray by Paul F. Dubois
  4. at Lawrence Livermore National Laboratory.
  5. In 2006, the package was completely rewritten by Pierre Gerard-Marchant
  6. (University of Georgia) to make the MaskedArray class a subclass of ndarray,
  7. and to improve support of structured arrays.
  8. Copyright 1999, 2000, 2001 Regents of the University of California.
  9. Released for unlimited redistribution.
  10. * Adapted for numpy_core 2005 by Travis Oliphant and (mainly) Paul Dubois.
  11. * Subclassing of the base `ndarray` 2006 by Pierre Gerard-Marchant
  12. (pgmdevlist_AT_gmail_DOT_com)
  13. * Improvements suggested by Reggie Dugard (reggie_AT_merfinllc_DOT_com)
  14. .. moduleauthor:: Pierre Gerard-Marchant
  15. """
  16. # pylint: disable-msg=E1002
  17. import builtins
  18. import inspect
  19. import operator
  20. import warnings
  21. import textwrap
  22. import re
  23. from functools import reduce
  24. import numpy as np
  25. import numpy.core.umath as umath
  26. import numpy.core.numerictypes as ntypes
  27. from numpy.core import multiarray as mu
  28. from numpy import ndarray, amax, amin, iscomplexobj, bool_, _NoValue
  29. from numpy import array as narray
  30. from numpy.lib.function_base import angle
  31. from numpy.compat import (
  32. getargspec, formatargspec, long, unicode, bytes
  33. )
  34. from numpy import expand_dims
  35. from numpy.core.numeric import normalize_axis_tuple
  36. __all__ = [
  37. 'MAError', 'MaskError', 'MaskType', 'MaskedArray', 'abs', 'absolute',
  38. 'add', 'all', 'allclose', 'allequal', 'alltrue', 'amax', 'amin',
  39. 'angle', 'anom', 'anomalies', 'any', 'append', 'arange', 'arccos',
  40. 'arccosh', 'arcsin', 'arcsinh', 'arctan', 'arctan2', 'arctanh',
  41. 'argmax', 'argmin', 'argsort', 'around', 'array', 'asanyarray',
  42. 'asarray', 'bitwise_and', 'bitwise_or', 'bitwise_xor', 'bool_', 'ceil',
  43. 'choose', 'clip', 'common_fill_value', 'compress', 'compressed',
  44. 'concatenate', 'conjugate', 'convolve', 'copy', 'correlate', 'cos', 'cosh',
  45. 'count', 'cumprod', 'cumsum', 'default_fill_value', 'diag', 'diagonal',
  46. 'diff', 'divide', 'empty', 'empty_like', 'equal', 'exp',
  47. 'expand_dims', 'fabs', 'filled', 'fix_invalid', 'flatten_mask',
  48. 'flatten_structured_array', 'floor', 'floor_divide', 'fmod',
  49. 'frombuffer', 'fromflex', 'fromfunction', 'getdata', 'getmask',
  50. 'getmaskarray', 'greater', 'greater_equal', 'harden_mask', 'hypot',
  51. 'identity', 'ids', 'indices', 'inner', 'innerproduct', 'isMA',
  52. 'isMaskedArray', 'is_mask', 'is_masked', 'isarray', 'left_shift',
  53. 'less', 'less_equal', 'log', 'log10', 'log2',
  54. 'logical_and', 'logical_not', 'logical_or', 'logical_xor', 'make_mask',
  55. 'make_mask_descr', 'make_mask_none', 'mask_or', 'masked',
  56. 'masked_array', 'masked_equal', 'masked_greater',
  57. 'masked_greater_equal', 'masked_inside', 'masked_invalid',
  58. 'masked_less', 'masked_less_equal', 'masked_not_equal',
  59. 'masked_object', 'masked_outside', 'masked_print_option',
  60. 'masked_singleton', 'masked_values', 'masked_where', 'max', 'maximum',
  61. 'maximum_fill_value', 'mean', 'min', 'minimum', 'minimum_fill_value',
  62. 'mod', 'multiply', 'mvoid', 'ndim', 'negative', 'nomask', 'nonzero',
  63. 'not_equal', 'ones', 'ones_like', 'outer', 'outerproduct', 'power', 'prod',
  64. 'product', 'ptp', 'put', 'putmask', 'ravel', 'remainder',
  65. 'repeat', 'reshape', 'resize', 'right_shift', 'round', 'round_',
  66. 'set_fill_value', 'shape', 'sin', 'sinh', 'size', 'soften_mask',
  67. 'sometrue', 'sort', 'sqrt', 'squeeze', 'std', 'subtract', 'sum',
  68. 'swapaxes', 'take', 'tan', 'tanh', 'trace', 'transpose', 'true_divide',
  69. 'var', 'where', 'zeros', 'zeros_like',
  70. ]
  71. MaskType = np.bool_
  72. nomask = MaskType(0)
  73. class MaskedArrayFutureWarning(FutureWarning):
  74. pass
  75. def _deprecate_argsort_axis(arr):
  76. """
  77. Adjust the axis passed to argsort, warning if necessary
  78. Parameters
  79. ----------
  80. arr
  81. The array which argsort was called on
  82. np.ma.argsort has a long-term bug where the default of the axis argument
  83. is wrong (gh-8701), which now must be kept for backwards compatibility.
  84. Thankfully, this only makes a difference when arrays are 2- or more-
  85. dimensional, so we only need a warning then.
  86. """
  87. if arr.ndim <= 1:
  88. # no warning needed - but switch to -1 anyway, to avoid surprising
  89. # subclasses, which are more likely to implement scalar axes.
  90. return -1
  91. else:
  92. # 2017-04-11, Numpy 1.13.0, gh-8701: warn on axis default
  93. warnings.warn(
  94. "In the future the default for argsort will be axis=-1, not the "
  95. "current None, to match its documentation and np.argsort. "
  96. "Explicitly pass -1 or None to silence this warning.",
  97. MaskedArrayFutureWarning, stacklevel=3)
  98. return None
  99. def doc_note(initialdoc, note):
  100. """
  101. Adds a Notes section to an existing docstring.
  102. """
  103. if initialdoc is None:
  104. return
  105. if note is None:
  106. return initialdoc
  107. notesplit = re.split(r'\n\s*?Notes\n\s*?-----', inspect.cleandoc(initialdoc))
  108. notedoc = "\n\nNotes\n-----\n%s\n" % inspect.cleandoc(note)
  109. return ''.join(notesplit[:1] + [notedoc] + notesplit[1:])
  110. def get_object_signature(obj):
  111. """
  112. Get the signature from obj
  113. """
  114. try:
  115. sig = formatargspec(*getargspec(obj))
  116. except TypeError:
  117. sig = ''
  118. return sig
  119. ###############################################################################
  120. # Exceptions #
  121. ###############################################################################
  122. class MAError(Exception):
  123. """
  124. Class for masked array related errors.
  125. """
  126. pass
  127. class MaskError(MAError):
  128. """
  129. Class for mask related errors.
  130. """
  131. pass
  132. ###############################################################################
  133. # Filling options #
  134. ###############################################################################
  135. # b: boolean - c: complex - f: floats - i: integer - O: object - S: string
  136. default_filler = {'b': True,
  137. 'c': 1.e20 + 0.0j,
  138. 'f': 1.e20,
  139. 'i': 999999,
  140. 'O': '?',
  141. 'S': b'N/A',
  142. 'u': 999999,
  143. 'V': b'???',
  144. 'U': 'N/A'
  145. }
  146. # Add datetime64 and timedelta64 types
  147. for v in ["Y", "M", "W", "D", "h", "m", "s", "ms", "us", "ns", "ps",
  148. "fs", "as"]:
  149. default_filler["M8[" + v + "]"] = np.datetime64("NaT", v)
  150. default_filler["m8[" + v + "]"] = np.timedelta64("NaT", v)
  151. float_types_list = [np.half, np.single, np.double, np.longdouble,
  152. np.csingle, np.cdouble, np.clongdouble]
  153. max_filler = ntypes._minvals
  154. max_filler.update([(k, -np.inf) for k in float_types_list[:4]])
  155. max_filler.update([(k, complex(-np.inf, -np.inf)) for k in float_types_list[-3:]])
  156. min_filler = ntypes._maxvals
  157. min_filler.update([(k, +np.inf) for k in float_types_list[:4]])
  158. min_filler.update([(k, complex(+np.inf, +np.inf)) for k in float_types_list[-3:]])
  159. del float_types_list
  160. def _recursive_fill_value(dtype, f):
  161. """
  162. Recursively produce a fill value for `dtype`, calling f on scalar dtypes
  163. """
  164. if dtype.names is not None:
  165. # We wrap into `array` here, which ensures we use NumPy cast rules
  166. # for integer casts, this allows the use of 99999 as a fill value
  167. # for int8.
  168. # TODO: This is probably a mess, but should best preserve behavior?
  169. vals = tuple(
  170. np.array(_recursive_fill_value(dtype[name], f))
  171. for name in dtype.names)
  172. return np.array(vals, dtype=dtype)[()] # decay to void scalar from 0d
  173. elif dtype.subdtype:
  174. subtype, shape = dtype.subdtype
  175. subval = _recursive_fill_value(subtype, f)
  176. return np.full(shape, subval)
  177. else:
  178. return f(dtype)
  179. def _get_dtype_of(obj):
  180. """ Convert the argument for *_fill_value into a dtype """
  181. if isinstance(obj, np.dtype):
  182. return obj
  183. elif hasattr(obj, 'dtype'):
  184. return obj.dtype
  185. else:
  186. return np.asanyarray(obj).dtype
  187. def default_fill_value(obj):
  188. """
  189. Return the default fill value for the argument object.
  190. The default filling value depends on the datatype of the input
  191. array or the type of the input scalar:
  192. ======== ========
  193. datatype default
  194. ======== ========
  195. bool True
  196. int 999999
  197. float 1.e20
  198. complex 1.e20+0j
  199. object '?'
  200. string 'N/A'
  201. ======== ========
  202. For structured types, a structured scalar is returned, with each field the
  203. default fill value for its type.
  204. For subarray types, the fill value is an array of the same size containing
  205. the default scalar fill value.
  206. Parameters
  207. ----------
  208. obj : ndarray, dtype or scalar
  209. The array data-type or scalar for which the default fill value
  210. is returned.
  211. Returns
  212. -------
  213. fill_value : scalar
  214. The default fill value.
  215. Examples
  216. --------
  217. >>> np.ma.default_fill_value(1)
  218. 999999
  219. >>> np.ma.default_fill_value(np.array([1.1, 2., np.pi]))
  220. 1e+20
  221. >>> np.ma.default_fill_value(np.dtype(complex))
  222. (1e+20+0j)
  223. """
  224. def _scalar_fill_value(dtype):
  225. if dtype.kind in 'Mm':
  226. return default_filler.get(dtype.str[1:], '?')
  227. else:
  228. return default_filler.get(dtype.kind, '?')
  229. dtype = _get_dtype_of(obj)
  230. return _recursive_fill_value(dtype, _scalar_fill_value)
  231. def _extremum_fill_value(obj, extremum, extremum_name):
  232. def _scalar_fill_value(dtype):
  233. try:
  234. return extremum[dtype]
  235. except KeyError as e:
  236. raise TypeError(
  237. f"Unsuitable type {dtype} for calculating {extremum_name}."
  238. ) from None
  239. dtype = _get_dtype_of(obj)
  240. return _recursive_fill_value(dtype, _scalar_fill_value)
  241. def minimum_fill_value(obj):
  242. """
  243. Return the maximum value that can be represented by the dtype of an object.
  244. This function is useful for calculating a fill value suitable for
  245. taking the minimum of an array with a given dtype.
  246. Parameters
  247. ----------
  248. obj : ndarray, dtype or scalar
  249. An object that can be queried for it's numeric type.
  250. Returns
  251. -------
  252. val : scalar
  253. The maximum representable value.
  254. Raises
  255. ------
  256. TypeError
  257. If `obj` isn't a suitable numeric type.
  258. See Also
  259. --------
  260. maximum_fill_value : The inverse function.
  261. set_fill_value : Set the filling value of a masked array.
  262. MaskedArray.fill_value : Return current fill value.
  263. Examples
  264. --------
  265. >>> import numpy.ma as ma
  266. >>> a = np.int8()
  267. >>> ma.minimum_fill_value(a)
  268. 127
  269. >>> a = np.int32()
  270. >>> ma.minimum_fill_value(a)
  271. 2147483647
  272. An array of numeric data can also be passed.
  273. >>> a = np.array([1, 2, 3], dtype=np.int8)
  274. >>> ma.minimum_fill_value(a)
  275. 127
  276. >>> a = np.array([1, 2, 3], dtype=np.float32)
  277. >>> ma.minimum_fill_value(a)
  278. inf
  279. """
  280. return _extremum_fill_value(obj, min_filler, "minimum")
  281. def maximum_fill_value(obj):
  282. """
  283. Return the minimum value that can be represented by the dtype of an object.
  284. This function is useful for calculating a fill value suitable for
  285. taking the maximum of an array with a given dtype.
  286. Parameters
  287. ----------
  288. obj : ndarray, dtype or scalar
  289. An object that can be queried for it's numeric type.
  290. Returns
  291. -------
  292. val : scalar
  293. The minimum representable value.
  294. Raises
  295. ------
  296. TypeError
  297. If `obj` isn't a suitable numeric type.
  298. See Also
  299. --------
  300. minimum_fill_value : The inverse function.
  301. set_fill_value : Set the filling value of a masked array.
  302. MaskedArray.fill_value : Return current fill value.
  303. Examples
  304. --------
  305. >>> import numpy.ma as ma
  306. >>> a = np.int8()
  307. >>> ma.maximum_fill_value(a)
  308. -128
  309. >>> a = np.int32()
  310. >>> ma.maximum_fill_value(a)
  311. -2147483648
  312. An array of numeric data can also be passed.
  313. >>> a = np.array([1, 2, 3], dtype=np.int8)
  314. >>> ma.maximum_fill_value(a)
  315. -128
  316. >>> a = np.array([1, 2, 3], dtype=np.float32)
  317. >>> ma.maximum_fill_value(a)
  318. -inf
  319. """
  320. return _extremum_fill_value(obj, max_filler, "maximum")
  321. def _recursive_set_fill_value(fillvalue, dt):
  322. """
  323. Create a fill value for a structured dtype.
  324. Parameters
  325. ----------
  326. fillvalue : scalar or array_like
  327. Scalar or array representing the fill value. If it is of shorter
  328. length than the number of fields in dt, it will be resized.
  329. dt : dtype
  330. The structured dtype for which to create the fill value.
  331. Returns
  332. -------
  333. val : tuple
  334. A tuple of values corresponding to the structured fill value.
  335. """
  336. fillvalue = np.resize(fillvalue, len(dt.names))
  337. output_value = []
  338. for (fval, name) in zip(fillvalue, dt.names):
  339. cdtype = dt[name]
  340. if cdtype.subdtype:
  341. cdtype = cdtype.subdtype[0]
  342. if cdtype.names is not None:
  343. output_value.append(tuple(_recursive_set_fill_value(fval, cdtype)))
  344. else:
  345. output_value.append(np.array(fval, dtype=cdtype).item())
  346. return tuple(output_value)
  347. def _check_fill_value(fill_value, ndtype):
  348. """
  349. Private function validating the given `fill_value` for the given dtype.
  350. If fill_value is None, it is set to the default corresponding to the dtype.
  351. If fill_value is not None, its value is forced to the given dtype.
  352. The result is always a 0d array.
  353. """
  354. ndtype = np.dtype(ndtype)
  355. if fill_value is None:
  356. fill_value = default_fill_value(ndtype)
  357. elif ndtype.names is not None:
  358. if isinstance(fill_value, (ndarray, np.void)):
  359. try:
  360. fill_value = np.array(fill_value, copy=False, dtype=ndtype)
  361. except ValueError as e:
  362. err_msg = "Unable to transform %s to dtype %s"
  363. raise ValueError(err_msg % (fill_value, ndtype)) from e
  364. else:
  365. fill_value = np.asarray(fill_value, dtype=object)
  366. fill_value = np.array(_recursive_set_fill_value(fill_value, ndtype),
  367. dtype=ndtype)
  368. else:
  369. if isinstance(fill_value, str) and (ndtype.char not in 'OSVU'):
  370. # Note this check doesn't work if fill_value is not a scalar
  371. err_msg = "Cannot set fill value of string with array of dtype %s"
  372. raise TypeError(err_msg % ndtype)
  373. else:
  374. # In case we want to convert 1e20 to int.
  375. # Also in case of converting string arrays.
  376. try:
  377. fill_value = np.array(fill_value, copy=False, dtype=ndtype)
  378. except (OverflowError, ValueError) as e:
  379. # Raise TypeError instead of OverflowError or ValueError.
  380. # OverflowError is seldom used, and the real problem here is
  381. # that the passed fill_value is not compatible with the ndtype.
  382. err_msg = "Cannot convert fill_value %s to dtype %s"
  383. raise TypeError(err_msg % (fill_value, ndtype)) from e
  384. return np.array(fill_value)
  385. def set_fill_value(a, fill_value):
  386. """
  387. Set the filling value of a, if a is a masked array.
  388. This function changes the fill value of the masked array `a` in place.
  389. If `a` is not a masked array, the function returns silently, without
  390. doing anything.
  391. Parameters
  392. ----------
  393. a : array_like
  394. Input array.
  395. fill_value : dtype
  396. Filling value. A consistency test is performed to make sure
  397. the value is compatible with the dtype of `a`.
  398. Returns
  399. -------
  400. None
  401. Nothing returned by this function.
  402. See Also
  403. --------
  404. maximum_fill_value : Return the default fill value for a dtype.
  405. MaskedArray.fill_value : Return current fill value.
  406. MaskedArray.set_fill_value : Equivalent method.
  407. Examples
  408. --------
  409. >>> import numpy.ma as ma
  410. >>> a = np.arange(5)
  411. >>> a
  412. array([0, 1, 2, 3, 4])
  413. >>> a = ma.masked_where(a < 3, a)
  414. >>> a
  415. masked_array(data=[--, --, --, 3, 4],
  416. mask=[ True, True, True, False, False],
  417. fill_value=999999)
  418. >>> ma.set_fill_value(a, -999)
  419. >>> a
  420. masked_array(data=[--, --, --, 3, 4],
  421. mask=[ True, True, True, False, False],
  422. fill_value=-999)
  423. Nothing happens if `a` is not a masked array.
  424. >>> a = list(range(5))
  425. >>> a
  426. [0, 1, 2, 3, 4]
  427. >>> ma.set_fill_value(a, 100)
  428. >>> a
  429. [0, 1, 2, 3, 4]
  430. >>> a = np.arange(5)
  431. >>> a
  432. array([0, 1, 2, 3, 4])
  433. >>> ma.set_fill_value(a, 100)
  434. >>> a
  435. array([0, 1, 2, 3, 4])
  436. """
  437. if isinstance(a, MaskedArray):
  438. a.set_fill_value(fill_value)
  439. return
  440. def get_fill_value(a):
  441. """
  442. Return the filling value of a, if any. Otherwise, returns the
  443. default filling value for that type.
  444. """
  445. if isinstance(a, MaskedArray):
  446. result = a.fill_value
  447. else:
  448. result = default_fill_value(a)
  449. return result
  450. def common_fill_value(a, b):
  451. """
  452. Return the common filling value of two masked arrays, if any.
  453. If ``a.fill_value == b.fill_value``, return the fill value,
  454. otherwise return None.
  455. Parameters
  456. ----------
  457. a, b : MaskedArray
  458. The masked arrays for which to compare fill values.
  459. Returns
  460. -------
  461. fill_value : scalar or None
  462. The common fill value, or None.
  463. Examples
  464. --------
  465. >>> x = np.ma.array([0, 1.], fill_value=3)
  466. >>> y = np.ma.array([0, 1.], fill_value=3)
  467. >>> np.ma.common_fill_value(x, y)
  468. 3.0
  469. """
  470. t1 = get_fill_value(a)
  471. t2 = get_fill_value(b)
  472. if t1 == t2:
  473. return t1
  474. return None
  475. def filled(a, fill_value=None):
  476. """
  477. Return input as an array with masked data replaced by a fill value.
  478. If `a` is not a `MaskedArray`, `a` itself is returned.
  479. If `a` is a `MaskedArray` and `fill_value` is None, `fill_value` is set to
  480. ``a.fill_value``.
  481. Parameters
  482. ----------
  483. a : MaskedArray or array_like
  484. An input object.
  485. fill_value : array_like, optional.
  486. Can be scalar or non-scalar. If non-scalar, the
  487. resulting filled array should be broadcastable
  488. over input array. Default is None.
  489. Returns
  490. -------
  491. a : ndarray
  492. The filled array.
  493. See Also
  494. --------
  495. compressed
  496. Examples
  497. --------
  498. >>> x = np.ma.array(np.arange(9).reshape(3, 3), mask=[[1, 0, 0],
  499. ... [1, 0, 0],
  500. ... [0, 0, 0]])
  501. >>> x.filled()
  502. array([[999999, 1, 2],
  503. [999999, 4, 5],
  504. [ 6, 7, 8]])
  505. >>> x.filled(fill_value=333)
  506. array([[333, 1, 2],
  507. [333, 4, 5],
  508. [ 6, 7, 8]])
  509. >>> x.filled(fill_value=np.arange(3))
  510. array([[0, 1, 2],
  511. [0, 4, 5],
  512. [6, 7, 8]])
  513. """
  514. if hasattr(a, 'filled'):
  515. return a.filled(fill_value)
  516. elif isinstance(a, ndarray):
  517. # Should we check for contiguity ? and a.flags['CONTIGUOUS']:
  518. return a
  519. elif isinstance(a, dict):
  520. return np.array(a, 'O')
  521. else:
  522. return np.array(a)
  523. def get_masked_subclass(*arrays):
  524. """
  525. Return the youngest subclass of MaskedArray from a list of (masked) arrays.
  526. In case of siblings, the first listed takes over.
  527. """
  528. if len(arrays) == 1:
  529. arr = arrays[0]
  530. if isinstance(arr, MaskedArray):
  531. rcls = type(arr)
  532. else:
  533. rcls = MaskedArray
  534. else:
  535. arrcls = [type(a) for a in arrays]
  536. rcls = arrcls[0]
  537. if not issubclass(rcls, MaskedArray):
  538. rcls = MaskedArray
  539. for cls in arrcls[1:]:
  540. if issubclass(cls, rcls):
  541. rcls = cls
  542. # Don't return MaskedConstant as result: revert to MaskedArray
  543. if rcls.__name__ == 'MaskedConstant':
  544. return MaskedArray
  545. return rcls
  546. def getdata(a, subok=True):
  547. """
  548. Return the data of a masked array as an ndarray.
  549. Return the data of `a` (if any) as an ndarray if `a` is a ``MaskedArray``,
  550. else return `a` as a ndarray or subclass (depending on `subok`) if not.
  551. Parameters
  552. ----------
  553. a : array_like
  554. Input ``MaskedArray``, alternatively a ndarray or a subclass thereof.
  555. subok : bool
  556. Whether to force the output to be a `pure` ndarray (False) or to
  557. return a subclass of ndarray if appropriate (True, default).
  558. See Also
  559. --------
  560. getmask : Return the mask of a masked array, or nomask.
  561. getmaskarray : Return the mask of a masked array, or full array of False.
  562. Examples
  563. --------
  564. >>> import numpy.ma as ma
  565. >>> a = ma.masked_equal([[1,2],[3,4]], 2)
  566. >>> a
  567. masked_array(
  568. data=[[1, --],
  569. [3, 4]],
  570. mask=[[False, True],
  571. [False, False]],
  572. fill_value=2)
  573. >>> ma.getdata(a)
  574. array([[1, 2],
  575. [3, 4]])
  576. Equivalently use the ``MaskedArray`` `data` attribute.
  577. >>> a.data
  578. array([[1, 2],
  579. [3, 4]])
  580. """
  581. try:
  582. data = a._data
  583. except AttributeError:
  584. data = np.array(a, copy=False, subok=subok)
  585. if not subok:
  586. return data.view(ndarray)
  587. return data
  588. get_data = getdata
  589. def fix_invalid(a, mask=nomask, copy=True, fill_value=None):
  590. """
  591. Return input with invalid data masked and replaced by a fill value.
  592. Invalid data means values of `nan`, `inf`, etc.
  593. Parameters
  594. ----------
  595. a : array_like
  596. Input array, a (subclass of) ndarray.
  597. mask : sequence, optional
  598. Mask. Must be convertible to an array of booleans with the same
  599. shape as `data`. True indicates a masked (i.e. invalid) data.
  600. copy : bool, optional
  601. Whether to use a copy of `a` (True) or to fix `a` in place (False).
  602. Default is True.
  603. fill_value : scalar, optional
  604. Value used for fixing invalid data. Default is None, in which case
  605. the ``a.fill_value`` is used.
  606. Returns
  607. -------
  608. b : MaskedArray
  609. The input array with invalid entries fixed.
  610. Notes
  611. -----
  612. A copy is performed by default.
  613. Examples
  614. --------
  615. >>> x = np.ma.array([1., -1, np.nan, np.inf], mask=[1] + [0]*3)
  616. >>> x
  617. masked_array(data=[--, -1.0, nan, inf],
  618. mask=[ True, False, False, False],
  619. fill_value=1e+20)
  620. >>> np.ma.fix_invalid(x)
  621. masked_array(data=[--, -1.0, --, --],
  622. mask=[ True, False, True, True],
  623. fill_value=1e+20)
  624. >>> fixed = np.ma.fix_invalid(x)
  625. >>> fixed.data
  626. array([ 1.e+00, -1.e+00, 1.e+20, 1.e+20])
  627. >>> x.data
  628. array([ 1., -1., nan, inf])
  629. """
  630. a = masked_array(a, copy=copy, mask=mask, subok=True)
  631. invalid = np.logical_not(np.isfinite(a._data))
  632. if not invalid.any():
  633. return a
  634. a._mask |= invalid
  635. if fill_value is None:
  636. fill_value = a.fill_value
  637. a._data[invalid] = fill_value
  638. return a
  639. def is_string_or_list_of_strings(val):
  640. return (isinstance(val, str) or
  641. (isinstance(val, list) and val and
  642. builtins.all(isinstance(s, str) for s in val)))
  643. ###############################################################################
  644. # Ufuncs #
  645. ###############################################################################
  646. ufunc_domain = {}
  647. ufunc_fills = {}
  648. class _DomainCheckInterval:
  649. """
  650. Define a valid interval, so that :
  651. ``domain_check_interval(a,b)(x) == True`` where
  652. ``x < a`` or ``x > b``.
  653. """
  654. def __init__(self, a, b):
  655. "domain_check_interval(a,b)(x) = true where x < a or y > b"
  656. if a > b:
  657. (a, b) = (b, a)
  658. self.a = a
  659. self.b = b
  660. def __call__(self, x):
  661. "Execute the call behavior."
  662. # nans at masked positions cause RuntimeWarnings, even though
  663. # they are masked. To avoid this we suppress warnings.
  664. with np.errstate(invalid='ignore'):
  665. return umath.logical_or(umath.greater(x, self.b),
  666. umath.less(x, self.a))
  667. class _DomainTan:
  668. """
  669. Define a valid interval for the `tan` function, so that:
  670. ``domain_tan(eps) = True`` where ``abs(cos(x)) < eps``
  671. """
  672. def __init__(self, eps):
  673. "domain_tan(eps) = true where abs(cos(x)) < eps)"
  674. self.eps = eps
  675. def __call__(self, x):
  676. "Executes the call behavior."
  677. with np.errstate(invalid='ignore'):
  678. return umath.less(umath.absolute(umath.cos(x)), self.eps)
  679. class _DomainSafeDivide:
  680. """
  681. Define a domain for safe division.
  682. """
  683. def __init__(self, tolerance=None):
  684. self.tolerance = tolerance
  685. def __call__(self, a, b):
  686. # Delay the selection of the tolerance to here in order to reduce numpy
  687. # import times. The calculation of these parameters is a substantial
  688. # component of numpy's import time.
  689. if self.tolerance is None:
  690. self.tolerance = np.finfo(float).tiny
  691. # don't call ma ufuncs from __array_wrap__ which would fail for scalars
  692. a, b = np.asarray(a), np.asarray(b)
  693. with np.errstate(invalid='ignore'):
  694. return umath.absolute(a) * self.tolerance >= umath.absolute(b)
  695. class _DomainGreater:
  696. """
  697. DomainGreater(v)(x) is True where x <= v.
  698. """
  699. def __init__(self, critical_value):
  700. "DomainGreater(v)(x) = true where x <= v"
  701. self.critical_value = critical_value
  702. def __call__(self, x):
  703. "Executes the call behavior."
  704. with np.errstate(invalid='ignore'):
  705. return umath.less_equal(x, self.critical_value)
  706. class _DomainGreaterEqual:
  707. """
  708. DomainGreaterEqual(v)(x) is True where x < v.
  709. """
  710. def __init__(self, critical_value):
  711. "DomainGreaterEqual(v)(x) = true where x < v"
  712. self.critical_value = critical_value
  713. def __call__(self, x):
  714. "Executes the call behavior."
  715. with np.errstate(invalid='ignore'):
  716. return umath.less(x, self.critical_value)
  717. class _MaskedUFunc:
  718. def __init__(self, ufunc):
  719. self.f = ufunc
  720. self.__doc__ = ufunc.__doc__
  721. self.__name__ = ufunc.__name__
  722. def __str__(self):
  723. return f"Masked version of {self.f}"
  724. class _MaskedUnaryOperation(_MaskedUFunc):
  725. """
  726. Defines masked version of unary operations, where invalid values are
  727. pre-masked.
  728. Parameters
  729. ----------
  730. mufunc : callable
  731. The function for which to define a masked version. Made available
  732. as ``_MaskedUnaryOperation.f``.
  733. fill : scalar, optional
  734. Filling value, default is 0.
  735. domain : class instance
  736. Domain for the function. Should be one of the ``_Domain*``
  737. classes. Default is None.
  738. """
  739. def __init__(self, mufunc, fill=0, domain=None):
  740. super().__init__(mufunc)
  741. self.fill = fill
  742. self.domain = domain
  743. ufunc_domain[mufunc] = domain
  744. ufunc_fills[mufunc] = fill
  745. def __call__(self, a, *args, **kwargs):
  746. """
  747. Execute the call behavior.
  748. """
  749. d = getdata(a)
  750. # Deal with domain
  751. if self.domain is not None:
  752. # Case 1.1. : Domained function
  753. # nans at masked positions cause RuntimeWarnings, even though
  754. # they are masked. To avoid this we suppress warnings.
  755. with np.errstate(divide='ignore', invalid='ignore'):
  756. result = self.f(d, *args, **kwargs)
  757. # Make a mask
  758. m = ~umath.isfinite(result)
  759. m |= self.domain(d)
  760. m |= getmask(a)
  761. else:
  762. # Case 1.2. : Function without a domain
  763. # Get the result and the mask
  764. with np.errstate(divide='ignore', invalid='ignore'):
  765. result = self.f(d, *args, **kwargs)
  766. m = getmask(a)
  767. if not result.ndim:
  768. # Case 2.1. : The result is scalarscalar
  769. if m:
  770. return masked
  771. return result
  772. if m is not nomask:
  773. # Case 2.2. The result is an array
  774. # We need to fill the invalid data back w/ the input Now,
  775. # that's plain silly: in C, we would just skip the element and
  776. # keep the original, but we do have to do it that way in Python
  777. # In case result has a lower dtype than the inputs (as in
  778. # equal)
  779. try:
  780. np.copyto(result, d, where=m)
  781. except TypeError:
  782. pass
  783. # Transform to
  784. masked_result = result.view(get_masked_subclass(a))
  785. masked_result._mask = m
  786. masked_result._update_from(a)
  787. return masked_result
  788. class _MaskedBinaryOperation(_MaskedUFunc):
  789. """
  790. Define masked version of binary operations, where invalid
  791. values are pre-masked.
  792. Parameters
  793. ----------
  794. mbfunc : function
  795. The function for which to define a masked version. Made available
  796. as ``_MaskedBinaryOperation.f``.
  797. domain : class instance
  798. Default domain for the function. Should be one of the ``_Domain*``
  799. classes. Default is None.
  800. fillx : scalar, optional
  801. Filling value for the first argument, default is 0.
  802. filly : scalar, optional
  803. Filling value for the second argument, default is 0.
  804. """
  805. def __init__(self, mbfunc, fillx=0, filly=0):
  806. """
  807. abfunc(fillx, filly) must be defined.
  808. abfunc(x, filly) = x for all x to enable reduce.
  809. """
  810. super().__init__(mbfunc)
  811. self.fillx = fillx
  812. self.filly = filly
  813. ufunc_domain[mbfunc] = None
  814. ufunc_fills[mbfunc] = (fillx, filly)
  815. def __call__(self, a, b, *args, **kwargs):
  816. """
  817. Execute the call behavior.
  818. """
  819. # Get the data, as ndarray
  820. (da, db) = (getdata(a), getdata(b))
  821. # Get the result
  822. with np.errstate():
  823. np.seterr(divide='ignore', invalid='ignore')
  824. result = self.f(da, db, *args, **kwargs)
  825. # Get the mask for the result
  826. (ma, mb) = (getmask(a), getmask(b))
  827. if ma is nomask:
  828. if mb is nomask:
  829. m = nomask
  830. else:
  831. m = umath.logical_or(getmaskarray(a), mb)
  832. elif mb is nomask:
  833. m = umath.logical_or(ma, getmaskarray(b))
  834. else:
  835. m = umath.logical_or(ma, mb)
  836. # Case 1. : scalar
  837. if not result.ndim:
  838. if m:
  839. return masked
  840. return result
  841. # Case 2. : array
  842. # Revert result to da where masked
  843. if m is not nomask and m.any():
  844. # any errors, just abort; impossible to guarantee masked values
  845. try:
  846. np.copyto(result, da, casting='unsafe', where=m)
  847. except Exception:
  848. pass
  849. # Transforms to a (subclass of) MaskedArray
  850. masked_result = result.view(get_masked_subclass(a, b))
  851. masked_result._mask = m
  852. if isinstance(a, MaskedArray):
  853. masked_result._update_from(a)
  854. elif isinstance(b, MaskedArray):
  855. masked_result._update_from(b)
  856. return masked_result
  857. def reduce(self, target, axis=0, dtype=None):
  858. """
  859. Reduce `target` along the given `axis`.
  860. """
  861. tclass = get_masked_subclass(target)
  862. m = getmask(target)
  863. t = filled(target, self.filly)
  864. if t.shape == ():
  865. t = t.reshape(1)
  866. if m is not nomask:
  867. m = make_mask(m, copy=True)
  868. m.shape = (1,)
  869. if m is nomask:
  870. tr = self.f.reduce(t, axis)
  871. mr = nomask
  872. else:
  873. tr = self.f.reduce(t, axis, dtype=dtype)
  874. mr = umath.logical_and.reduce(m, axis)
  875. if not tr.shape:
  876. if mr:
  877. return masked
  878. else:
  879. return tr
  880. masked_tr = tr.view(tclass)
  881. masked_tr._mask = mr
  882. return masked_tr
  883. def outer(self, a, b):
  884. """
  885. Return the function applied to the outer product of a and b.
  886. """
  887. (da, db) = (getdata(a), getdata(b))
  888. d = self.f.outer(da, db)
  889. ma = getmask(a)
  890. mb = getmask(b)
  891. if ma is nomask and mb is nomask:
  892. m = nomask
  893. else:
  894. ma = getmaskarray(a)
  895. mb = getmaskarray(b)
  896. m = umath.logical_or.outer(ma, mb)
  897. if (not m.ndim) and m:
  898. return masked
  899. if m is not nomask:
  900. np.copyto(d, da, where=m)
  901. if not d.shape:
  902. return d
  903. masked_d = d.view(get_masked_subclass(a, b))
  904. masked_d._mask = m
  905. return masked_d
  906. def accumulate(self, target, axis=0):
  907. """Accumulate `target` along `axis` after filling with y fill
  908. value.
  909. """
  910. tclass = get_masked_subclass(target)
  911. t = filled(target, self.filly)
  912. result = self.f.accumulate(t, axis)
  913. masked_result = result.view(tclass)
  914. return masked_result
  915. class _DomainedBinaryOperation(_MaskedUFunc):
  916. """
  917. Define binary operations that have a domain, like divide.
  918. They have no reduce, outer or accumulate.
  919. Parameters
  920. ----------
  921. mbfunc : function
  922. The function for which to define a masked version. Made available
  923. as ``_DomainedBinaryOperation.f``.
  924. domain : class instance
  925. Default domain for the function. Should be one of the ``_Domain*``
  926. classes.
  927. fillx : scalar, optional
  928. Filling value for the first argument, default is 0.
  929. filly : scalar, optional
  930. Filling value for the second argument, default is 0.
  931. """
  932. def __init__(self, dbfunc, domain, fillx=0, filly=0):
  933. """abfunc(fillx, filly) must be defined.
  934. abfunc(x, filly) = x for all x to enable reduce.
  935. """
  936. super().__init__(dbfunc)
  937. self.domain = domain
  938. self.fillx = fillx
  939. self.filly = filly
  940. ufunc_domain[dbfunc] = domain
  941. ufunc_fills[dbfunc] = (fillx, filly)
  942. def __call__(self, a, b, *args, **kwargs):
  943. "Execute the call behavior."
  944. # Get the data
  945. (da, db) = (getdata(a), getdata(b))
  946. # Get the result
  947. with np.errstate(divide='ignore', invalid='ignore'):
  948. result = self.f(da, db, *args, **kwargs)
  949. # Get the mask as a combination of the source masks and invalid
  950. m = ~umath.isfinite(result)
  951. m |= getmask(a)
  952. m |= getmask(b)
  953. # Apply the domain
  954. domain = ufunc_domain.get(self.f, None)
  955. if domain is not None:
  956. m |= domain(da, db)
  957. # Take care of the scalar case first
  958. if not m.ndim:
  959. if m:
  960. return masked
  961. else:
  962. return result
  963. # When the mask is True, put back da if possible
  964. # any errors, just abort; impossible to guarantee masked values
  965. try:
  966. np.copyto(result, 0, casting='unsafe', where=m)
  967. # avoid using "*" since this may be overlaid
  968. masked_da = umath.multiply(m, da)
  969. # only add back if it can be cast safely
  970. if np.can_cast(masked_da.dtype, result.dtype, casting='safe'):
  971. result += masked_da
  972. except Exception:
  973. pass
  974. # Transforms to a (subclass of) MaskedArray
  975. masked_result = result.view(get_masked_subclass(a, b))
  976. masked_result._mask = m
  977. if isinstance(a, MaskedArray):
  978. masked_result._update_from(a)
  979. elif isinstance(b, MaskedArray):
  980. masked_result._update_from(b)
  981. return masked_result
  982. # Unary ufuncs
  983. exp = _MaskedUnaryOperation(umath.exp)
  984. conjugate = _MaskedUnaryOperation(umath.conjugate)
  985. sin = _MaskedUnaryOperation(umath.sin)
  986. cos = _MaskedUnaryOperation(umath.cos)
  987. arctan = _MaskedUnaryOperation(umath.arctan)
  988. arcsinh = _MaskedUnaryOperation(umath.arcsinh)
  989. sinh = _MaskedUnaryOperation(umath.sinh)
  990. cosh = _MaskedUnaryOperation(umath.cosh)
  991. tanh = _MaskedUnaryOperation(umath.tanh)
  992. abs = absolute = _MaskedUnaryOperation(umath.absolute)
  993. angle = _MaskedUnaryOperation(angle) # from numpy.lib.function_base
  994. fabs = _MaskedUnaryOperation(umath.fabs)
  995. negative = _MaskedUnaryOperation(umath.negative)
  996. floor = _MaskedUnaryOperation(umath.floor)
  997. ceil = _MaskedUnaryOperation(umath.ceil)
  998. around = _MaskedUnaryOperation(np.round_)
  999. logical_not = _MaskedUnaryOperation(umath.logical_not)
  1000. # Domained unary ufuncs
  1001. sqrt = _MaskedUnaryOperation(umath.sqrt, 0.0,
  1002. _DomainGreaterEqual(0.0))
  1003. log = _MaskedUnaryOperation(umath.log, 1.0,
  1004. _DomainGreater(0.0))
  1005. log2 = _MaskedUnaryOperation(umath.log2, 1.0,
  1006. _DomainGreater(0.0))
  1007. log10 = _MaskedUnaryOperation(umath.log10, 1.0,
  1008. _DomainGreater(0.0))
  1009. tan = _MaskedUnaryOperation(umath.tan, 0.0,
  1010. _DomainTan(1e-35))
  1011. arcsin = _MaskedUnaryOperation(umath.arcsin, 0.0,
  1012. _DomainCheckInterval(-1.0, 1.0))
  1013. arccos = _MaskedUnaryOperation(umath.arccos, 0.0,
  1014. _DomainCheckInterval(-1.0, 1.0))
  1015. arccosh = _MaskedUnaryOperation(umath.arccosh, 1.0,
  1016. _DomainGreaterEqual(1.0))
  1017. arctanh = _MaskedUnaryOperation(umath.arctanh, 0.0,
  1018. _DomainCheckInterval(-1.0 + 1e-15, 1.0 - 1e-15))
  1019. # Binary ufuncs
  1020. add = _MaskedBinaryOperation(umath.add)
  1021. subtract = _MaskedBinaryOperation(umath.subtract)
  1022. multiply = _MaskedBinaryOperation(umath.multiply, 1, 1)
  1023. arctan2 = _MaskedBinaryOperation(umath.arctan2, 0.0, 1.0)
  1024. equal = _MaskedBinaryOperation(umath.equal)
  1025. equal.reduce = None
  1026. not_equal = _MaskedBinaryOperation(umath.not_equal)
  1027. not_equal.reduce = None
  1028. less_equal = _MaskedBinaryOperation(umath.less_equal)
  1029. less_equal.reduce = None
  1030. greater_equal = _MaskedBinaryOperation(umath.greater_equal)
  1031. greater_equal.reduce = None
  1032. less = _MaskedBinaryOperation(umath.less)
  1033. less.reduce = None
  1034. greater = _MaskedBinaryOperation(umath.greater)
  1035. greater.reduce = None
  1036. logical_and = _MaskedBinaryOperation(umath.logical_and)
  1037. alltrue = _MaskedBinaryOperation(umath.logical_and, 1, 1).reduce
  1038. logical_or = _MaskedBinaryOperation(umath.logical_or)
  1039. sometrue = logical_or.reduce
  1040. logical_xor = _MaskedBinaryOperation(umath.logical_xor)
  1041. bitwise_and = _MaskedBinaryOperation(umath.bitwise_and)
  1042. bitwise_or = _MaskedBinaryOperation(umath.bitwise_or)
  1043. bitwise_xor = _MaskedBinaryOperation(umath.bitwise_xor)
  1044. hypot = _MaskedBinaryOperation(umath.hypot)
  1045. # Domained binary ufuncs
  1046. divide = _DomainedBinaryOperation(umath.divide, _DomainSafeDivide(), 0, 1)
  1047. true_divide = _DomainedBinaryOperation(umath.true_divide,
  1048. _DomainSafeDivide(), 0, 1)
  1049. floor_divide = _DomainedBinaryOperation(umath.floor_divide,
  1050. _DomainSafeDivide(), 0, 1)
  1051. remainder = _DomainedBinaryOperation(umath.remainder,
  1052. _DomainSafeDivide(), 0, 1)
  1053. fmod = _DomainedBinaryOperation(umath.fmod, _DomainSafeDivide(), 0, 1)
  1054. mod = _DomainedBinaryOperation(umath.mod, _DomainSafeDivide(), 0, 1)
  1055. ###############################################################################
  1056. # Mask creation functions #
  1057. ###############################################################################
  1058. def _replace_dtype_fields_recursive(dtype, primitive_dtype):
  1059. "Private function allowing recursion in _replace_dtype_fields."
  1060. _recurse = _replace_dtype_fields_recursive
  1061. # Do we have some name fields ?
  1062. if dtype.names is not None:
  1063. descr = []
  1064. for name in dtype.names:
  1065. field = dtype.fields[name]
  1066. if len(field) == 3:
  1067. # Prepend the title to the name
  1068. name = (field[-1], name)
  1069. descr.append((name, _recurse(field[0], primitive_dtype)))
  1070. new_dtype = np.dtype(descr)
  1071. # Is this some kind of composite a la (float,2)
  1072. elif dtype.subdtype:
  1073. descr = list(dtype.subdtype)
  1074. descr[0] = _recurse(dtype.subdtype[0], primitive_dtype)
  1075. new_dtype = np.dtype(tuple(descr))
  1076. # this is a primitive type, so do a direct replacement
  1077. else:
  1078. new_dtype = primitive_dtype
  1079. # preserve identity of dtypes
  1080. if new_dtype == dtype:
  1081. new_dtype = dtype
  1082. return new_dtype
  1083. def _replace_dtype_fields(dtype, primitive_dtype):
  1084. """
  1085. Construct a dtype description list from a given dtype.
  1086. Returns a new dtype object, with all fields and subtypes in the given type
  1087. recursively replaced with `primitive_dtype`.
  1088. Arguments are coerced to dtypes first.
  1089. """
  1090. dtype = np.dtype(dtype)
  1091. primitive_dtype = np.dtype(primitive_dtype)
  1092. return _replace_dtype_fields_recursive(dtype, primitive_dtype)
  1093. def make_mask_descr(ndtype):
  1094. """
  1095. Construct a dtype description list from a given dtype.
  1096. Returns a new dtype object, with the type of all fields in `ndtype` to a
  1097. boolean type. Field names are not altered.
  1098. Parameters
  1099. ----------
  1100. ndtype : dtype
  1101. The dtype to convert.
  1102. Returns
  1103. -------
  1104. result : dtype
  1105. A dtype that looks like `ndtype`, the type of all fields is boolean.
  1106. Examples
  1107. --------
  1108. >>> import numpy.ma as ma
  1109. >>> dtype = np.dtype({'names':['foo', 'bar'],
  1110. ... 'formats':[np.float32, np.int64]})
  1111. >>> dtype
  1112. dtype([('foo', '<f4'), ('bar', '<i8')])
  1113. >>> ma.make_mask_descr(dtype)
  1114. dtype([('foo', '|b1'), ('bar', '|b1')])
  1115. >>> ma.make_mask_descr(np.float32)
  1116. dtype('bool')
  1117. """
  1118. return _replace_dtype_fields(ndtype, MaskType)
  1119. def getmask(a):
  1120. """
  1121. Return the mask of a masked array, or nomask.
  1122. Return the mask of `a` as an ndarray if `a` is a `MaskedArray` and the
  1123. mask is not `nomask`, else return `nomask`. To guarantee a full array
  1124. of booleans of the same shape as a, use `getmaskarray`.
  1125. Parameters
  1126. ----------
  1127. a : array_like
  1128. Input `MaskedArray` for which the mask is required.
  1129. See Also
  1130. --------
  1131. getdata : Return the data of a masked array as an ndarray.
  1132. getmaskarray : Return the mask of a masked array, or full array of False.
  1133. Examples
  1134. --------
  1135. >>> import numpy.ma as ma
  1136. >>> a = ma.masked_equal([[1,2],[3,4]], 2)
  1137. >>> a
  1138. masked_array(
  1139. data=[[1, --],
  1140. [3, 4]],
  1141. mask=[[False, True],
  1142. [False, False]],
  1143. fill_value=2)
  1144. >>> ma.getmask(a)
  1145. array([[False, True],
  1146. [False, False]])
  1147. Equivalently use the `MaskedArray` `mask` attribute.
  1148. >>> a.mask
  1149. array([[False, True],
  1150. [False, False]])
  1151. Result when mask == `nomask`
  1152. >>> b = ma.masked_array([[1,2],[3,4]])
  1153. >>> b
  1154. masked_array(
  1155. data=[[1, 2],
  1156. [3, 4]],
  1157. mask=False,
  1158. fill_value=999999)
  1159. >>> ma.nomask
  1160. False
  1161. >>> ma.getmask(b) == ma.nomask
  1162. True
  1163. >>> b.mask == ma.nomask
  1164. True
  1165. """
  1166. return getattr(a, '_mask', nomask)
  1167. get_mask = getmask
  1168. def getmaskarray(arr):
  1169. """
  1170. Return the mask of a masked array, or full boolean array of False.
  1171. Return the mask of `arr` as an ndarray if `arr` is a `MaskedArray` and
  1172. the mask is not `nomask`, else return a full boolean array of False of
  1173. the same shape as `arr`.
  1174. Parameters
  1175. ----------
  1176. arr : array_like
  1177. Input `MaskedArray` for which the mask is required.
  1178. See Also
  1179. --------
  1180. getmask : Return the mask of a masked array, or nomask.
  1181. getdata : Return the data of a masked array as an ndarray.
  1182. Examples
  1183. --------
  1184. >>> import numpy.ma as ma
  1185. >>> a = ma.masked_equal([[1,2],[3,4]], 2)
  1186. >>> a
  1187. masked_array(
  1188. data=[[1, --],
  1189. [3, 4]],
  1190. mask=[[False, True],
  1191. [False, False]],
  1192. fill_value=2)
  1193. >>> ma.getmaskarray(a)
  1194. array([[False, True],
  1195. [False, False]])
  1196. Result when mask == ``nomask``
  1197. >>> b = ma.masked_array([[1,2],[3,4]])
  1198. >>> b
  1199. masked_array(
  1200. data=[[1, 2],
  1201. [3, 4]],
  1202. mask=False,
  1203. fill_value=999999)
  1204. >>> ma.getmaskarray(b)
  1205. array([[False, False],
  1206. [False, False]])
  1207. """
  1208. mask = getmask(arr)
  1209. if mask is nomask:
  1210. mask = make_mask_none(np.shape(arr), getattr(arr, 'dtype', None))
  1211. return mask
  1212. def is_mask(m):
  1213. """
  1214. Return True if m is a valid, standard mask.
  1215. This function does not check the contents of the input, only that the
  1216. type is MaskType. In particular, this function returns False if the
  1217. mask has a flexible dtype.
  1218. Parameters
  1219. ----------
  1220. m : array_like
  1221. Array to test.
  1222. Returns
  1223. -------
  1224. result : bool
  1225. True if `m.dtype.type` is MaskType, False otherwise.
  1226. See Also
  1227. --------
  1228. ma.isMaskedArray : Test whether input is an instance of MaskedArray.
  1229. Examples
  1230. --------
  1231. >>> import numpy.ma as ma
  1232. >>> m = ma.masked_equal([0, 1, 0, 2, 3], 0)
  1233. >>> m
  1234. masked_array(data=[--, 1, --, 2, 3],
  1235. mask=[ True, False, True, False, False],
  1236. fill_value=0)
  1237. >>> ma.is_mask(m)
  1238. False
  1239. >>> ma.is_mask(m.mask)
  1240. True
  1241. Input must be an ndarray (or have similar attributes)
  1242. for it to be considered a valid mask.
  1243. >>> m = [False, True, False]
  1244. >>> ma.is_mask(m)
  1245. False
  1246. >>> m = np.array([False, True, False])
  1247. >>> m
  1248. array([False, True, False])
  1249. >>> ma.is_mask(m)
  1250. True
  1251. Arrays with complex dtypes don't return True.
  1252. >>> dtype = np.dtype({'names':['monty', 'pithon'],
  1253. ... 'formats':[bool, bool]})
  1254. >>> dtype
  1255. dtype([('monty', '|b1'), ('pithon', '|b1')])
  1256. >>> m = np.array([(True, False), (False, True), (True, False)],
  1257. ... dtype=dtype)
  1258. >>> m
  1259. array([( True, False), (False, True), ( True, False)],
  1260. dtype=[('monty', '?'), ('pithon', '?')])
  1261. >>> ma.is_mask(m)
  1262. False
  1263. """
  1264. try:
  1265. return m.dtype.type is MaskType
  1266. except AttributeError:
  1267. return False
  1268. def _shrink_mask(m):
  1269. """
  1270. Shrink a mask to nomask if possible
  1271. """
  1272. if m.dtype.names is None and not m.any():
  1273. return nomask
  1274. else:
  1275. return m
  1276. def make_mask(m, copy=False, shrink=True, dtype=MaskType):
  1277. """
  1278. Create a boolean mask from an array.
  1279. Return `m` as a boolean mask, creating a copy if necessary or requested.
  1280. The function can accept any sequence that is convertible to integers,
  1281. or ``nomask``. Does not require that contents must be 0s and 1s, values
  1282. of 0 are interpreted as False, everything else as True.
  1283. Parameters
  1284. ----------
  1285. m : array_like
  1286. Potential mask.
  1287. copy : bool, optional
  1288. Whether to return a copy of `m` (True) or `m` itself (False).
  1289. shrink : bool, optional
  1290. Whether to shrink `m` to ``nomask`` if all its values are False.
  1291. dtype : dtype, optional
  1292. Data-type of the output mask. By default, the output mask has a
  1293. dtype of MaskType (bool). If the dtype is flexible, each field has
  1294. a boolean dtype. This is ignored when `m` is ``nomask``, in which
  1295. case ``nomask`` is always returned.
  1296. Returns
  1297. -------
  1298. result : ndarray
  1299. A boolean mask derived from `m`.
  1300. Examples
  1301. --------
  1302. >>> import numpy.ma as ma
  1303. >>> m = [True, False, True, True]
  1304. >>> ma.make_mask(m)
  1305. array([ True, False, True, True])
  1306. >>> m = [1, 0, 1, 1]
  1307. >>> ma.make_mask(m)
  1308. array([ True, False, True, True])
  1309. >>> m = [1, 0, 2, -3]
  1310. >>> ma.make_mask(m)
  1311. array([ True, False, True, True])
  1312. Effect of the `shrink` parameter.
  1313. >>> m = np.zeros(4)
  1314. >>> m
  1315. array([0., 0., 0., 0.])
  1316. >>> ma.make_mask(m)
  1317. False
  1318. >>> ma.make_mask(m, shrink=False)
  1319. array([False, False, False, False])
  1320. Using a flexible `dtype`.
  1321. >>> m = [1, 0, 1, 1]
  1322. >>> n = [0, 1, 0, 0]
  1323. >>> arr = []
  1324. >>> for man, mouse in zip(m, n):
  1325. ... arr.append((man, mouse))
  1326. >>> arr
  1327. [(1, 0), (0, 1), (1, 0), (1, 0)]
  1328. >>> dtype = np.dtype({'names':['man', 'mouse'],
  1329. ... 'formats':[np.int64, np.int64]})
  1330. >>> arr = np.array(arr, dtype=dtype)
  1331. >>> arr
  1332. array([(1, 0), (0, 1), (1, 0), (1, 0)],
  1333. dtype=[('man', '<i8'), ('mouse', '<i8')])
  1334. >>> ma.make_mask(arr, dtype=dtype)
  1335. array([(True, False), (False, True), (True, False), (True, False)],
  1336. dtype=[('man', '|b1'), ('mouse', '|b1')])
  1337. """
  1338. if m is nomask:
  1339. return nomask
  1340. # Make sure the input dtype is valid.
  1341. dtype = make_mask_descr(dtype)
  1342. # legacy boolean special case: "existence of fields implies true"
  1343. if isinstance(m, ndarray) and m.dtype.fields and dtype == np.bool_:
  1344. return np.ones(m.shape, dtype=dtype)
  1345. # Fill the mask in case there are missing data; turn it into an ndarray.
  1346. result = np.array(filled(m, True), copy=copy, dtype=dtype, subok=True)
  1347. # Bas les masques !
  1348. if shrink:
  1349. result = _shrink_mask(result)
  1350. return result
  1351. def make_mask_none(newshape, dtype=None):
  1352. """
  1353. Return a boolean mask of the given shape, filled with False.
  1354. This function returns a boolean ndarray with all entries False, that can
  1355. be used in common mask manipulations. If a complex dtype is specified, the
  1356. type of each field is converted to a boolean type.
  1357. Parameters
  1358. ----------
  1359. newshape : tuple
  1360. A tuple indicating the shape of the mask.
  1361. dtype : {None, dtype}, optional
  1362. If None, use a MaskType instance. Otherwise, use a new datatype with
  1363. the same fields as `dtype`, converted to boolean types.
  1364. Returns
  1365. -------
  1366. result : ndarray
  1367. An ndarray of appropriate shape and dtype, filled with False.
  1368. See Also
  1369. --------
  1370. make_mask : Create a boolean mask from an array.
  1371. make_mask_descr : Construct a dtype description list from a given dtype.
  1372. Examples
  1373. --------
  1374. >>> import numpy.ma as ma
  1375. >>> ma.make_mask_none((3,))
  1376. array([False, False, False])
  1377. Defining a more complex dtype.
  1378. >>> dtype = np.dtype({'names':['foo', 'bar'],
  1379. ... 'formats':[np.float32, np.int64]})
  1380. >>> dtype
  1381. dtype([('foo', '<f4'), ('bar', '<i8')])
  1382. >>> ma.make_mask_none((3,), dtype=dtype)
  1383. array([(False, False), (False, False), (False, False)],
  1384. dtype=[('foo', '|b1'), ('bar', '|b1')])
  1385. """
  1386. if dtype is None:
  1387. result = np.zeros(newshape, dtype=MaskType)
  1388. else:
  1389. result = np.zeros(newshape, dtype=make_mask_descr(dtype))
  1390. return result
  1391. def _recursive_mask_or(m1, m2, newmask):
  1392. names = m1.dtype.names
  1393. for name in names:
  1394. current1 = m1[name]
  1395. if current1.dtype.names is not None:
  1396. _recursive_mask_or(current1, m2[name], newmask[name])
  1397. else:
  1398. umath.logical_or(current1, m2[name], newmask[name])
  1399. def mask_or(m1, m2, copy=False, shrink=True):
  1400. """
  1401. Combine two masks with the ``logical_or`` operator.
  1402. The result may be a view on `m1` or `m2` if the other is `nomask`
  1403. (i.e. False).
  1404. Parameters
  1405. ----------
  1406. m1, m2 : array_like
  1407. Input masks.
  1408. copy : bool, optional
  1409. If copy is False and one of the inputs is `nomask`, return a view
  1410. of the other input mask. Defaults to False.
  1411. shrink : bool, optional
  1412. Whether to shrink the output to `nomask` if all its values are
  1413. False. Defaults to True.
  1414. Returns
  1415. -------
  1416. mask : output mask
  1417. The result masks values that are masked in either `m1` or `m2`.
  1418. Raises
  1419. ------
  1420. ValueError
  1421. If `m1` and `m2` have different flexible dtypes.
  1422. Examples
  1423. --------
  1424. >>> m1 = np.ma.make_mask([0, 1, 1, 0])
  1425. >>> m2 = np.ma.make_mask([1, 0, 0, 0])
  1426. >>> np.ma.mask_or(m1, m2)
  1427. array([ True, True, True, False])
  1428. """
  1429. if (m1 is nomask) or (m1 is False):
  1430. dtype = getattr(m2, 'dtype', MaskType)
  1431. return make_mask(m2, copy=copy, shrink=shrink, dtype=dtype)
  1432. if (m2 is nomask) or (m2 is False):
  1433. dtype = getattr(m1, 'dtype', MaskType)
  1434. return make_mask(m1, copy=copy, shrink=shrink, dtype=dtype)
  1435. if m1 is m2 and is_mask(m1):
  1436. return m1
  1437. (dtype1, dtype2) = (getattr(m1, 'dtype', None), getattr(m2, 'dtype', None))
  1438. if dtype1 != dtype2:
  1439. raise ValueError("Incompatible dtypes '%s'<>'%s'" % (dtype1, dtype2))
  1440. if dtype1.names is not None:
  1441. # Allocate an output mask array with the properly broadcast shape.
  1442. newmask = np.empty(np.broadcast(m1, m2).shape, dtype1)
  1443. _recursive_mask_or(m1, m2, newmask)
  1444. return newmask
  1445. return make_mask(umath.logical_or(m1, m2), copy=copy, shrink=shrink)
  1446. def flatten_mask(mask):
  1447. """
  1448. Returns a completely flattened version of the mask, where nested fields
  1449. are collapsed.
  1450. Parameters
  1451. ----------
  1452. mask : array_like
  1453. Input array, which will be interpreted as booleans.
  1454. Returns
  1455. -------
  1456. flattened_mask : ndarray of bools
  1457. The flattened input.
  1458. Examples
  1459. --------
  1460. >>> mask = np.array([0, 0, 1])
  1461. >>> np.ma.flatten_mask(mask)
  1462. array([False, False, True])
  1463. >>> mask = np.array([(0, 0), (0, 1)], dtype=[('a', bool), ('b', bool)])
  1464. >>> np.ma.flatten_mask(mask)
  1465. array([False, False, False, True])
  1466. >>> mdtype = [('a', bool), ('b', [('ba', bool), ('bb', bool)])]
  1467. >>> mask = np.array([(0, (0, 0)), (0, (0, 1))], dtype=mdtype)
  1468. >>> np.ma.flatten_mask(mask)
  1469. array([False, False, False, False, False, True])
  1470. """
  1471. def _flatmask(mask):
  1472. "Flatten the mask and returns a (maybe nested) sequence of booleans."
  1473. mnames = mask.dtype.names
  1474. if mnames is not None:
  1475. return [flatten_mask(mask[name]) for name in mnames]
  1476. else:
  1477. return mask
  1478. def _flatsequence(sequence):
  1479. "Generates a flattened version of the sequence."
  1480. try:
  1481. for element in sequence:
  1482. if hasattr(element, '__iter__'):
  1483. yield from _flatsequence(element)
  1484. else:
  1485. yield element
  1486. except TypeError:
  1487. yield sequence
  1488. mask = np.asarray(mask)
  1489. flattened = _flatsequence(_flatmask(mask))
  1490. return np.array([_ for _ in flattened], dtype=bool)
  1491. def _check_mask_axis(mask, axis, keepdims=np._NoValue):
  1492. "Check whether there are masked values along the given axis"
  1493. kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
  1494. if mask is not nomask:
  1495. return mask.all(axis=axis, **kwargs)
  1496. return nomask
  1497. ###############################################################################
  1498. # Masking functions #
  1499. ###############################################################################
  1500. def masked_where(condition, a, copy=True):
  1501. """
  1502. Mask an array where a condition is met.
  1503. Return `a` as an array masked where `condition` is True.
  1504. Any masked values of `a` or `condition` are also masked in the output.
  1505. Parameters
  1506. ----------
  1507. condition : array_like
  1508. Masking condition. When `condition` tests floating point values for
  1509. equality, consider using ``masked_values`` instead.
  1510. a : array_like
  1511. Array to mask.
  1512. copy : bool
  1513. If True (default) make a copy of `a` in the result. If False modify
  1514. `a` in place and return a view.
  1515. Returns
  1516. -------
  1517. result : MaskedArray
  1518. The result of masking `a` where `condition` is True.
  1519. See Also
  1520. --------
  1521. masked_values : Mask using floating point equality.
  1522. masked_equal : Mask where equal to a given value.
  1523. masked_not_equal : Mask where `not` equal to a given value.
  1524. masked_less_equal : Mask where less than or equal to a given value.
  1525. masked_greater_equal : Mask where greater than or equal to a given value.
  1526. masked_less : Mask where less than a given value.
  1527. masked_greater : Mask where greater than a given value.
  1528. masked_inside : Mask inside a given interval.
  1529. masked_outside : Mask outside a given interval.
  1530. masked_invalid : Mask invalid values (NaNs or infs).
  1531. Examples
  1532. --------
  1533. >>> import numpy.ma as ma
  1534. >>> a = np.arange(4)
  1535. >>> a
  1536. array([0, 1, 2, 3])
  1537. >>> ma.masked_where(a <= 2, a)
  1538. masked_array(data=[--, --, --, 3],
  1539. mask=[ True, True, True, False],
  1540. fill_value=999999)
  1541. Mask array `b` conditional on `a`.
  1542. >>> b = ['a', 'b', 'c', 'd']
  1543. >>> ma.masked_where(a == 2, b)
  1544. masked_array(data=['a', 'b', --, 'd'],
  1545. mask=[False, False, True, False],
  1546. fill_value='N/A',
  1547. dtype='<U1')
  1548. Effect of the `copy` argument.
  1549. >>> c = ma.masked_where(a <= 2, a)
  1550. >>> c
  1551. masked_array(data=[--, --, --, 3],
  1552. mask=[ True, True, True, False],
  1553. fill_value=999999)
  1554. >>> c[0] = 99
  1555. >>> c
  1556. masked_array(data=[99, --, --, 3],
  1557. mask=[False, True, True, False],
  1558. fill_value=999999)
  1559. >>> a
  1560. array([0, 1, 2, 3])
  1561. >>> c = ma.masked_where(a <= 2, a, copy=False)
  1562. >>> c[0] = 99
  1563. >>> c
  1564. masked_array(data=[99, --, --, 3],
  1565. mask=[False, True, True, False],
  1566. fill_value=999999)
  1567. >>> a
  1568. array([99, 1, 2, 3])
  1569. When `condition` or `a` contain masked values.
  1570. >>> a = np.arange(4)
  1571. >>> a = ma.masked_where(a == 2, a)
  1572. >>> a
  1573. masked_array(data=[0, 1, --, 3],
  1574. mask=[False, False, True, False],
  1575. fill_value=999999)
  1576. >>> b = np.arange(4)
  1577. >>> b = ma.masked_where(b == 0, b)
  1578. >>> b
  1579. masked_array(data=[--, 1, 2, 3],
  1580. mask=[ True, False, False, False],
  1581. fill_value=999999)
  1582. >>> ma.masked_where(a == 3, b)
  1583. masked_array(data=[--, 1, --, --],
  1584. mask=[ True, False, True, True],
  1585. fill_value=999999)
  1586. """
  1587. # Make sure that condition is a valid standard-type mask.
  1588. cond = make_mask(condition, shrink=False)
  1589. a = np.array(a, copy=copy, subok=True)
  1590. (cshape, ashape) = (cond.shape, a.shape)
  1591. if cshape and cshape != ashape:
  1592. raise IndexError("Inconsistent shape between the condition and the input"
  1593. " (got %s and %s)" % (cshape, ashape))
  1594. if hasattr(a, '_mask'):
  1595. cond = mask_or(cond, a._mask)
  1596. cls = type(a)
  1597. else:
  1598. cls = MaskedArray
  1599. result = a.view(cls)
  1600. # Assign to *.mask so that structured masks are handled correctly.
  1601. result.mask = _shrink_mask(cond)
  1602. # There is no view of a boolean so when 'a' is a MaskedArray with nomask
  1603. # the update to the result's mask has no effect.
  1604. if not copy and hasattr(a, '_mask') and getmask(a) is nomask:
  1605. a._mask = result._mask.view()
  1606. return result
  1607. def masked_greater(x, value, copy=True):
  1608. """
  1609. Mask an array where greater than a given value.
  1610. This function is a shortcut to ``masked_where``, with
  1611. `condition` = (x > value).
  1612. See Also
  1613. --------
  1614. masked_where : Mask where a condition is met.
  1615. Examples
  1616. --------
  1617. >>> import numpy.ma as ma
  1618. >>> a = np.arange(4)
  1619. >>> a
  1620. array([0, 1, 2, 3])
  1621. >>> ma.masked_greater(a, 2)
  1622. masked_array(data=[0, 1, 2, --],
  1623. mask=[False, False, False, True],
  1624. fill_value=999999)
  1625. """
  1626. return masked_where(greater(x, value), x, copy=copy)
  1627. def masked_greater_equal(x, value, copy=True):
  1628. """
  1629. Mask an array where greater than or equal to a given value.
  1630. This function is a shortcut to ``masked_where``, with
  1631. `condition` = (x >= value).
  1632. See Also
  1633. --------
  1634. masked_where : Mask where a condition is met.
  1635. Examples
  1636. --------
  1637. >>> import numpy.ma as ma
  1638. >>> a = np.arange(4)
  1639. >>> a
  1640. array([0, 1, 2, 3])
  1641. >>> ma.masked_greater_equal(a, 2)
  1642. masked_array(data=[0, 1, --, --],
  1643. mask=[False, False, True, True],
  1644. fill_value=999999)
  1645. """
  1646. return masked_where(greater_equal(x, value), x, copy=copy)
  1647. def masked_less(x, value, copy=True):
  1648. """
  1649. Mask an array where less than a given value.
  1650. This function is a shortcut to ``masked_where``, with
  1651. `condition` = (x < value).
  1652. See Also
  1653. --------
  1654. masked_where : Mask where a condition is met.
  1655. Examples
  1656. --------
  1657. >>> import numpy.ma as ma
  1658. >>> a = np.arange(4)
  1659. >>> a
  1660. array([0, 1, 2, 3])
  1661. >>> ma.masked_less(a, 2)
  1662. masked_array(data=[--, --, 2, 3],
  1663. mask=[ True, True, False, False],
  1664. fill_value=999999)
  1665. """
  1666. return masked_where(less(x, value), x, copy=copy)
  1667. def masked_less_equal(x, value, copy=True):
  1668. """
  1669. Mask an array where less than or equal to a given value.
  1670. This function is a shortcut to ``masked_where``, with
  1671. `condition` = (x <= value).
  1672. See Also
  1673. --------
  1674. masked_where : Mask where a condition is met.
  1675. Examples
  1676. --------
  1677. >>> import numpy.ma as ma
  1678. >>> a = np.arange(4)
  1679. >>> a
  1680. array([0, 1, 2, 3])
  1681. >>> ma.masked_less_equal(a, 2)
  1682. masked_array(data=[--, --, --, 3],
  1683. mask=[ True, True, True, False],
  1684. fill_value=999999)
  1685. """
  1686. return masked_where(less_equal(x, value), x, copy=copy)
  1687. def masked_not_equal(x, value, copy=True):
  1688. """
  1689. Mask an array where `not` equal to a given value.
  1690. This function is a shortcut to ``masked_where``, with
  1691. `condition` = (x != value).
  1692. See Also
  1693. --------
  1694. masked_where : Mask where a condition is met.
  1695. Examples
  1696. --------
  1697. >>> import numpy.ma as ma
  1698. >>> a = np.arange(4)
  1699. >>> a
  1700. array([0, 1, 2, 3])
  1701. >>> ma.masked_not_equal(a, 2)
  1702. masked_array(data=[--, --, 2, --],
  1703. mask=[ True, True, False, True],
  1704. fill_value=999999)
  1705. """
  1706. return masked_where(not_equal(x, value), x, copy=copy)
  1707. def masked_equal(x, value, copy=True):
  1708. """
  1709. Mask an array where equal to a given value.
  1710. Return a MaskedArray, masked where the data in array `x` are
  1711. equal to `value`. The fill_value of the returned MaskedArray
  1712. is set to `value`.
  1713. For floating point arrays, consider using ``masked_values(x, value)``.
  1714. See Also
  1715. --------
  1716. masked_where : Mask where a condition is met.
  1717. masked_values : Mask using floating point equality.
  1718. Examples
  1719. --------
  1720. >>> import numpy.ma as ma
  1721. >>> a = np.arange(4)
  1722. >>> a
  1723. array([0, 1, 2, 3])
  1724. >>> ma.masked_equal(a, 2)
  1725. masked_array(data=[0, 1, --, 3],
  1726. mask=[False, False, True, False],
  1727. fill_value=2)
  1728. """
  1729. output = masked_where(equal(x, value), x, copy=copy)
  1730. output.fill_value = value
  1731. return output
  1732. def masked_inside(x, v1, v2, copy=True):
  1733. """
  1734. Mask an array inside a given interval.
  1735. Shortcut to ``masked_where``, where `condition` is True for `x` inside
  1736. the interval [v1,v2] (v1 <= x <= v2). The boundaries `v1` and `v2`
  1737. can be given in either order.
  1738. See Also
  1739. --------
  1740. masked_where : Mask where a condition is met.
  1741. Notes
  1742. -----
  1743. The array `x` is prefilled with its filling value.
  1744. Examples
  1745. --------
  1746. >>> import numpy.ma as ma
  1747. >>> x = [0.31, 1.2, 0.01, 0.2, -0.4, -1.1]
  1748. >>> ma.masked_inside(x, -0.3, 0.3)
  1749. masked_array(data=[0.31, 1.2, --, --, -0.4, -1.1],
  1750. mask=[False, False, True, True, False, False],
  1751. fill_value=1e+20)
  1752. The order of `v1` and `v2` doesn't matter.
  1753. >>> ma.masked_inside(x, 0.3, -0.3)
  1754. masked_array(data=[0.31, 1.2, --, --, -0.4, -1.1],
  1755. mask=[False, False, True, True, False, False],
  1756. fill_value=1e+20)
  1757. """
  1758. if v2 < v1:
  1759. (v1, v2) = (v2, v1)
  1760. xf = filled(x)
  1761. condition = (xf >= v1) & (xf <= v2)
  1762. return masked_where(condition, x, copy=copy)
  1763. def masked_outside(x, v1, v2, copy=True):
  1764. """
  1765. Mask an array outside a given interval.
  1766. Shortcut to ``masked_where``, where `condition` is True for `x` outside
  1767. the interval [v1,v2] (x < v1)|(x > v2).
  1768. The boundaries `v1` and `v2` can be given in either order.
  1769. See Also
  1770. --------
  1771. masked_where : Mask where a condition is met.
  1772. Notes
  1773. -----
  1774. The array `x` is prefilled with its filling value.
  1775. Examples
  1776. --------
  1777. >>> import numpy.ma as ma
  1778. >>> x = [0.31, 1.2, 0.01, 0.2, -0.4, -1.1]
  1779. >>> ma.masked_outside(x, -0.3, 0.3)
  1780. masked_array(data=[--, --, 0.01, 0.2, --, --],
  1781. mask=[ True, True, False, False, True, True],
  1782. fill_value=1e+20)
  1783. The order of `v1` and `v2` doesn't matter.
  1784. >>> ma.masked_outside(x, 0.3, -0.3)
  1785. masked_array(data=[--, --, 0.01, 0.2, --, --],
  1786. mask=[ True, True, False, False, True, True],
  1787. fill_value=1e+20)
  1788. """
  1789. if v2 < v1:
  1790. (v1, v2) = (v2, v1)
  1791. xf = filled(x)
  1792. condition = (xf < v1) | (xf > v2)
  1793. return masked_where(condition, x, copy=copy)
  1794. def masked_object(x, value, copy=True, shrink=True):
  1795. """
  1796. Mask the array `x` where the data are exactly equal to value.
  1797. This function is similar to `masked_values`, but only suitable
  1798. for object arrays: for floating point, use `masked_values` instead.
  1799. Parameters
  1800. ----------
  1801. x : array_like
  1802. Array to mask
  1803. value : object
  1804. Comparison value
  1805. copy : {True, False}, optional
  1806. Whether to return a copy of `x`.
  1807. shrink : {True, False}, optional
  1808. Whether to collapse a mask full of False to nomask
  1809. Returns
  1810. -------
  1811. result : MaskedArray
  1812. The result of masking `x` where equal to `value`.
  1813. See Also
  1814. --------
  1815. masked_where : Mask where a condition is met.
  1816. masked_equal : Mask where equal to a given value (integers).
  1817. masked_values : Mask using floating point equality.
  1818. Examples
  1819. --------
  1820. >>> import numpy.ma as ma
  1821. >>> food = np.array(['green_eggs', 'ham'], dtype=object)
  1822. >>> # don't eat spoiled food
  1823. >>> eat = ma.masked_object(food, 'green_eggs')
  1824. >>> eat
  1825. masked_array(data=[--, 'ham'],
  1826. mask=[ True, False],
  1827. fill_value='green_eggs',
  1828. dtype=object)
  1829. >>> # plain ol` ham is boring
  1830. >>> fresh_food = np.array(['cheese', 'ham', 'pineapple'], dtype=object)
  1831. >>> eat = ma.masked_object(fresh_food, 'green_eggs')
  1832. >>> eat
  1833. masked_array(data=['cheese', 'ham', 'pineapple'],
  1834. mask=False,
  1835. fill_value='green_eggs',
  1836. dtype=object)
  1837. Note that `mask` is set to ``nomask`` if possible.
  1838. >>> eat
  1839. masked_array(data=['cheese', 'ham', 'pineapple'],
  1840. mask=False,
  1841. fill_value='green_eggs',
  1842. dtype=object)
  1843. """
  1844. if isMaskedArray(x):
  1845. condition = umath.equal(x._data, value)
  1846. mask = x._mask
  1847. else:
  1848. condition = umath.equal(np.asarray(x), value)
  1849. mask = nomask
  1850. mask = mask_or(mask, make_mask(condition, shrink=shrink))
  1851. return masked_array(x, mask=mask, copy=copy, fill_value=value)
  1852. def masked_values(x, value, rtol=1e-5, atol=1e-8, copy=True, shrink=True):
  1853. """
  1854. Mask using floating point equality.
  1855. Return a MaskedArray, masked where the data in array `x` are approximately
  1856. equal to `value`, determined using `isclose`. The default tolerances for
  1857. `masked_values` are the same as those for `isclose`.
  1858. For integer types, exact equality is used, in the same way as
  1859. `masked_equal`.
  1860. The fill_value is set to `value` and the mask is set to ``nomask`` if
  1861. possible.
  1862. Parameters
  1863. ----------
  1864. x : array_like
  1865. Array to mask.
  1866. value : float
  1867. Masking value.
  1868. rtol, atol : float, optional
  1869. Tolerance parameters passed on to `isclose`
  1870. copy : bool, optional
  1871. Whether to return a copy of `x`.
  1872. shrink : bool, optional
  1873. Whether to collapse a mask full of False to ``nomask``.
  1874. Returns
  1875. -------
  1876. result : MaskedArray
  1877. The result of masking `x` where approximately equal to `value`.
  1878. See Also
  1879. --------
  1880. masked_where : Mask where a condition is met.
  1881. masked_equal : Mask where equal to a given value (integers).
  1882. Examples
  1883. --------
  1884. >>> import numpy.ma as ma
  1885. >>> x = np.array([1, 1.1, 2, 1.1, 3])
  1886. >>> ma.masked_values(x, 1.1)
  1887. masked_array(data=[1.0, --, 2.0, --, 3.0],
  1888. mask=[False, True, False, True, False],
  1889. fill_value=1.1)
  1890. Note that `mask` is set to ``nomask`` if possible.
  1891. >>> ma.masked_values(x, 2.1)
  1892. masked_array(data=[1. , 1.1, 2. , 1.1, 3. ],
  1893. mask=False,
  1894. fill_value=2.1)
  1895. Unlike `masked_equal`, `masked_values` can perform approximate equalities.
  1896. >>> ma.masked_values(x, 2.1, atol=1e-1)
  1897. masked_array(data=[1.0, 1.1, --, 1.1, 3.0],
  1898. mask=[False, False, True, False, False],
  1899. fill_value=2.1)
  1900. """
  1901. xnew = filled(x, value)
  1902. if np.issubdtype(xnew.dtype, np.floating):
  1903. mask = np.isclose(xnew, value, atol=atol, rtol=rtol)
  1904. else:
  1905. mask = umath.equal(xnew, value)
  1906. ret = masked_array(xnew, mask=mask, copy=copy, fill_value=value)
  1907. if shrink:
  1908. ret.shrink_mask()
  1909. return ret
  1910. def masked_invalid(a, copy=True):
  1911. """
  1912. Mask an array where invalid values occur (NaNs or infs).
  1913. This function is a shortcut to ``masked_where``, with
  1914. `condition` = ~(np.isfinite(a)). Any pre-existing mask is conserved.
  1915. Only applies to arrays with a dtype where NaNs or infs make sense
  1916. (i.e. floating point types), but accepts any array_like object.
  1917. See Also
  1918. --------
  1919. masked_where : Mask where a condition is met.
  1920. Examples
  1921. --------
  1922. >>> import numpy.ma as ma
  1923. >>> a = np.arange(5, dtype=float)
  1924. >>> a[2] = np.NaN
  1925. >>> a[3] = np.PINF
  1926. >>> a
  1927. array([ 0., 1., nan, inf, 4.])
  1928. >>> ma.masked_invalid(a)
  1929. masked_array(data=[0.0, 1.0, --, --, 4.0],
  1930. mask=[False, False, True, True, False],
  1931. fill_value=1e+20)
  1932. """
  1933. a = np.array(a, copy=False, subok=True)
  1934. res = masked_where(~(np.isfinite(a)), a, copy=copy)
  1935. # masked_invalid previously never returned nomask as a mask and doing so
  1936. # threw off matplotlib (gh-22842). So use shrink=False:
  1937. if res._mask is nomask:
  1938. res._mask = make_mask_none(res.shape, res.dtype)
  1939. return res
  1940. ###############################################################################
  1941. # Printing options #
  1942. ###############################################################################
  1943. class _MaskedPrintOption:
  1944. """
  1945. Handle the string used to represent missing data in a masked array.
  1946. """
  1947. def __init__(self, display):
  1948. """
  1949. Create the masked_print_option object.
  1950. """
  1951. self._display = display
  1952. self._enabled = True
  1953. def display(self):
  1954. """
  1955. Display the string to print for masked values.
  1956. """
  1957. return self._display
  1958. def set_display(self, s):
  1959. """
  1960. Set the string to print for masked values.
  1961. """
  1962. self._display = s
  1963. def enabled(self):
  1964. """
  1965. Is the use of the display value enabled?
  1966. """
  1967. return self._enabled
  1968. def enable(self, shrink=1):
  1969. """
  1970. Set the enabling shrink to `shrink`.
  1971. """
  1972. self._enabled = shrink
  1973. def __str__(self):
  1974. return str(self._display)
  1975. __repr__ = __str__
  1976. # if you single index into a masked location you get this object.
  1977. masked_print_option = _MaskedPrintOption('--')
  1978. def _recursive_printoption(result, mask, printopt):
  1979. """
  1980. Puts printoptions in result where mask is True.
  1981. Private function allowing for recursion
  1982. """
  1983. names = result.dtype.names
  1984. if names is not None:
  1985. for name in names:
  1986. curdata = result[name]
  1987. curmask = mask[name]
  1988. _recursive_printoption(curdata, curmask, printopt)
  1989. else:
  1990. np.copyto(result, printopt, where=mask)
  1991. return
  1992. # For better or worse, these end in a newline
  1993. _legacy_print_templates = dict(
  1994. long_std=textwrap.dedent("""\
  1995. masked_%(name)s(data =
  1996. %(data)s,
  1997. %(nlen)s mask =
  1998. %(mask)s,
  1999. %(nlen)s fill_value = %(fill)s)
  2000. """),
  2001. long_flx=textwrap.dedent("""\
  2002. masked_%(name)s(data =
  2003. %(data)s,
  2004. %(nlen)s mask =
  2005. %(mask)s,
  2006. %(nlen)s fill_value = %(fill)s,
  2007. %(nlen)s dtype = %(dtype)s)
  2008. """),
  2009. short_std=textwrap.dedent("""\
  2010. masked_%(name)s(data = %(data)s,
  2011. %(nlen)s mask = %(mask)s,
  2012. %(nlen)s fill_value = %(fill)s)
  2013. """),
  2014. short_flx=textwrap.dedent("""\
  2015. masked_%(name)s(data = %(data)s,
  2016. %(nlen)s mask = %(mask)s,
  2017. %(nlen)s fill_value = %(fill)s,
  2018. %(nlen)s dtype = %(dtype)s)
  2019. """)
  2020. )
  2021. ###############################################################################
  2022. # MaskedArray class #
  2023. ###############################################################################
  2024. def _recursive_filled(a, mask, fill_value):
  2025. """
  2026. Recursively fill `a` with `fill_value`.
  2027. """
  2028. names = a.dtype.names
  2029. for name in names:
  2030. current = a[name]
  2031. if current.dtype.names is not None:
  2032. _recursive_filled(current, mask[name], fill_value[name])
  2033. else:
  2034. np.copyto(current, fill_value[name], where=mask[name])
  2035. def flatten_structured_array(a):
  2036. """
  2037. Flatten a structured array.
  2038. The data type of the output is chosen such that it can represent all of the
  2039. (nested) fields.
  2040. Parameters
  2041. ----------
  2042. a : structured array
  2043. Returns
  2044. -------
  2045. output : masked array or ndarray
  2046. A flattened masked array if the input is a masked array, otherwise a
  2047. standard ndarray.
  2048. Examples
  2049. --------
  2050. >>> ndtype = [('a', int), ('b', float)]
  2051. >>> a = np.array([(1, 1), (2, 2)], dtype=ndtype)
  2052. >>> np.ma.flatten_structured_array(a)
  2053. array([[1., 1.],
  2054. [2., 2.]])
  2055. """
  2056. def flatten_sequence(iterable):
  2057. """
  2058. Flattens a compound of nested iterables.
  2059. """
  2060. for elm in iter(iterable):
  2061. if hasattr(elm, '__iter__'):
  2062. yield from flatten_sequence(elm)
  2063. else:
  2064. yield elm
  2065. a = np.asanyarray(a)
  2066. inishape = a.shape
  2067. a = a.ravel()
  2068. if isinstance(a, MaskedArray):
  2069. out = np.array([tuple(flatten_sequence(d.item())) for d in a._data])
  2070. out = out.view(MaskedArray)
  2071. out._mask = np.array([tuple(flatten_sequence(d.item()))
  2072. for d in getmaskarray(a)])
  2073. else:
  2074. out = np.array([tuple(flatten_sequence(d.item())) for d in a])
  2075. if len(inishape) > 1:
  2076. newshape = list(out.shape)
  2077. newshape[0] = inishape
  2078. out.shape = tuple(flatten_sequence(newshape))
  2079. return out
  2080. def _arraymethod(funcname, onmask=True):
  2081. """
  2082. Return a class method wrapper around a basic array method.
  2083. Creates a class method which returns a masked array, where the new
  2084. ``_data`` array is the output of the corresponding basic method called
  2085. on the original ``_data``.
  2086. If `onmask` is True, the new mask is the output of the method called
  2087. on the initial mask. Otherwise, the new mask is just a reference
  2088. to the initial mask.
  2089. Parameters
  2090. ----------
  2091. funcname : str
  2092. Name of the function to apply on data.
  2093. onmask : bool
  2094. Whether the mask must be processed also (True) or left
  2095. alone (False). Default is True. Make available as `_onmask`
  2096. attribute.
  2097. Returns
  2098. -------
  2099. method : instancemethod
  2100. Class method wrapper of the specified basic array method.
  2101. """
  2102. def wrapped_method(self, *args, **params):
  2103. result = getattr(self._data, funcname)(*args, **params)
  2104. result = result.view(type(self))
  2105. result._update_from(self)
  2106. mask = self._mask
  2107. if not onmask:
  2108. result.__setmask__(mask)
  2109. elif mask is not nomask:
  2110. # __setmask__ makes a copy, which we don't want
  2111. result._mask = getattr(mask, funcname)(*args, **params)
  2112. return result
  2113. methdoc = getattr(ndarray, funcname, None) or getattr(np, funcname, None)
  2114. if methdoc is not None:
  2115. wrapped_method.__doc__ = methdoc.__doc__
  2116. wrapped_method.__name__ = funcname
  2117. return wrapped_method
  2118. class MaskedIterator:
  2119. """
  2120. Flat iterator object to iterate over masked arrays.
  2121. A `MaskedIterator` iterator is returned by ``x.flat`` for any masked array
  2122. `x`. It allows iterating over the array as if it were a 1-D array,
  2123. either in a for-loop or by calling its `next` method.
  2124. Iteration is done in C-contiguous style, with the last index varying the
  2125. fastest. The iterator can also be indexed using basic slicing or
  2126. advanced indexing.
  2127. See Also
  2128. --------
  2129. MaskedArray.flat : Return a flat iterator over an array.
  2130. MaskedArray.flatten : Returns a flattened copy of an array.
  2131. Notes
  2132. -----
  2133. `MaskedIterator` is not exported by the `ma` module. Instead of
  2134. instantiating a `MaskedIterator` directly, use `MaskedArray.flat`.
  2135. Examples
  2136. --------
  2137. >>> x = np.ma.array(arange(6).reshape(2, 3))
  2138. >>> fl = x.flat
  2139. >>> type(fl)
  2140. <class 'numpy.ma.core.MaskedIterator'>
  2141. >>> for item in fl:
  2142. ... print(item)
  2143. ...
  2144. 0
  2145. 1
  2146. 2
  2147. 3
  2148. 4
  2149. 5
  2150. Extracting more than a single element b indexing the `MaskedIterator`
  2151. returns a masked array:
  2152. >>> fl[2:4]
  2153. masked_array(data = [2 3],
  2154. mask = False,
  2155. fill_value = 999999)
  2156. """
  2157. def __init__(self, ma):
  2158. self.ma = ma
  2159. self.dataiter = ma._data.flat
  2160. if ma._mask is nomask:
  2161. self.maskiter = None
  2162. else:
  2163. self.maskiter = ma._mask.flat
  2164. def __iter__(self):
  2165. return self
  2166. def __getitem__(self, indx):
  2167. result = self.dataiter.__getitem__(indx).view(type(self.ma))
  2168. if self.maskiter is not None:
  2169. _mask = self.maskiter.__getitem__(indx)
  2170. if isinstance(_mask, ndarray):
  2171. # set shape to match that of data; this is needed for matrices
  2172. _mask.shape = result.shape
  2173. result._mask = _mask
  2174. elif isinstance(_mask, np.void):
  2175. return mvoid(result, mask=_mask, hardmask=self.ma._hardmask)
  2176. elif _mask: # Just a scalar, masked
  2177. return masked
  2178. return result
  2179. # This won't work if ravel makes a copy
  2180. def __setitem__(self, index, value):
  2181. self.dataiter[index] = getdata(value)
  2182. if self.maskiter is not None:
  2183. self.maskiter[index] = getmaskarray(value)
  2184. def __next__(self):
  2185. """
  2186. Return the next value, or raise StopIteration.
  2187. Examples
  2188. --------
  2189. >>> x = np.ma.array([3, 2], mask=[0, 1])
  2190. >>> fl = x.flat
  2191. >>> next(fl)
  2192. 3
  2193. >>> next(fl)
  2194. masked
  2195. >>> next(fl)
  2196. Traceback (most recent call last):
  2197. ...
  2198. StopIteration
  2199. """
  2200. d = next(self.dataiter)
  2201. if self.maskiter is not None:
  2202. m = next(self.maskiter)
  2203. if isinstance(m, np.void):
  2204. return mvoid(d, mask=m, hardmask=self.ma._hardmask)
  2205. elif m: # Just a scalar, masked
  2206. return masked
  2207. return d
  2208. class MaskedArray(ndarray):
  2209. """
  2210. An array class with possibly masked values.
  2211. Masked values of True exclude the corresponding element from any
  2212. computation.
  2213. Construction::
  2214. x = MaskedArray(data, mask=nomask, dtype=None, copy=False, subok=True,
  2215. ndmin=0, fill_value=None, keep_mask=True, hard_mask=None,
  2216. shrink=True, order=None)
  2217. Parameters
  2218. ----------
  2219. data : array_like
  2220. Input data.
  2221. mask : sequence, optional
  2222. Mask. Must be convertible to an array of booleans with the same
  2223. shape as `data`. True indicates a masked (i.e. invalid) data.
  2224. dtype : dtype, optional
  2225. Data type of the output.
  2226. If `dtype` is None, the type of the data argument (``data.dtype``)
  2227. is used. If `dtype` is not None and different from ``data.dtype``,
  2228. a copy is performed.
  2229. copy : bool, optional
  2230. Whether to copy the input data (True), or to use a reference instead.
  2231. Default is False.
  2232. subok : bool, optional
  2233. Whether to return a subclass of `MaskedArray` if possible (True) or a
  2234. plain `MaskedArray`. Default is True.
  2235. ndmin : int, optional
  2236. Minimum number of dimensions. Default is 0.
  2237. fill_value : scalar, optional
  2238. Value used to fill in the masked values when necessary.
  2239. If None, a default based on the data-type is used.
  2240. keep_mask : bool, optional
  2241. Whether to combine `mask` with the mask of the input data, if any
  2242. (True), or to use only `mask` for the output (False). Default is True.
  2243. hard_mask : bool, optional
  2244. Whether to use a hard mask or not. With a hard mask, masked values
  2245. cannot be unmasked. Default is False.
  2246. shrink : bool, optional
  2247. Whether to force compression of an empty mask. Default is True.
  2248. order : {'C', 'F', 'A'}, optional
  2249. Specify the order of the array. If order is 'C', then the array
  2250. will be in C-contiguous order (last-index varies the fastest).
  2251. If order is 'F', then the returned array will be in
  2252. Fortran-contiguous order (first-index varies the fastest).
  2253. If order is 'A' (default), then the returned array may be
  2254. in any order (either C-, Fortran-contiguous, or even discontiguous),
  2255. unless a copy is required, in which case it will be C-contiguous.
  2256. Examples
  2257. --------
  2258. The ``mask`` can be initialized with an array of boolean values
  2259. with the same shape as ``data``.
  2260. >>> data = np.arange(6).reshape((2, 3))
  2261. >>> np.ma.MaskedArray(data, mask=[[False, True, False],
  2262. ... [False, False, True]])
  2263. masked_array(
  2264. data=[[0, --, 2],
  2265. [3, 4, --]],
  2266. mask=[[False, True, False],
  2267. [False, False, True]],
  2268. fill_value=999999)
  2269. Alternatively, the ``mask`` can be initialized to homogeneous boolean
  2270. array with the same shape as ``data`` by passing in a scalar
  2271. boolean value:
  2272. >>> np.ma.MaskedArray(data, mask=False)
  2273. masked_array(
  2274. data=[[0, 1, 2],
  2275. [3, 4, 5]],
  2276. mask=[[False, False, False],
  2277. [False, False, False]],
  2278. fill_value=999999)
  2279. >>> np.ma.MaskedArray(data, mask=True)
  2280. masked_array(
  2281. data=[[--, --, --],
  2282. [--, --, --]],
  2283. mask=[[ True, True, True],
  2284. [ True, True, True]],
  2285. fill_value=999999,
  2286. dtype=int64)
  2287. .. note::
  2288. The recommended practice for initializing ``mask`` with a scalar
  2289. boolean value is to use ``True``/``False`` rather than
  2290. ``np.True_``/``np.False_``. The reason is :attr:`nomask`
  2291. is represented internally as ``np.False_``.
  2292. >>> np.False_ is np.ma.nomask
  2293. True
  2294. """
  2295. __array_priority__ = 15
  2296. _defaultmask = nomask
  2297. _defaulthardmask = False
  2298. _baseclass = ndarray
  2299. # Maximum number of elements per axis used when printing an array. The
  2300. # 1d case is handled separately because we need more values in this case.
  2301. _print_width = 100
  2302. _print_width_1d = 1500
  2303. def __new__(cls, data=None, mask=nomask, dtype=None, copy=False,
  2304. subok=True, ndmin=0, fill_value=None, keep_mask=True,
  2305. hard_mask=None, shrink=True, order=None):
  2306. """
  2307. Create a new masked array from scratch.
  2308. Notes
  2309. -----
  2310. A masked array can also be created by taking a .view(MaskedArray).
  2311. """
  2312. # Process data.
  2313. _data = np.array(data, dtype=dtype, copy=copy,
  2314. order=order, subok=True, ndmin=ndmin)
  2315. _baseclass = getattr(data, '_baseclass', type(_data))
  2316. # Check that we're not erasing the mask.
  2317. if isinstance(data, MaskedArray) and (data.shape != _data.shape):
  2318. copy = True
  2319. # Here, we copy the _view_, so that we can attach new properties to it
  2320. # we must never do .view(MaskedConstant), as that would create a new
  2321. # instance of np.ma.masked, which make identity comparison fail
  2322. if isinstance(data, cls) and subok and not isinstance(data, MaskedConstant):
  2323. _data = ndarray.view(_data, type(data))
  2324. else:
  2325. _data = ndarray.view(_data, cls)
  2326. # Handle the case where data is not a subclass of ndarray, but
  2327. # still has the _mask attribute like MaskedArrays
  2328. if hasattr(data, '_mask') and not isinstance(data, ndarray):
  2329. _data._mask = data._mask
  2330. # FIXME: should we set `_data._sharedmask = True`?
  2331. # Process mask.
  2332. # Type of the mask
  2333. mdtype = make_mask_descr(_data.dtype)
  2334. if mask is nomask:
  2335. # Case 1. : no mask in input.
  2336. # Erase the current mask ?
  2337. if not keep_mask:
  2338. # With a reduced version
  2339. if shrink:
  2340. _data._mask = nomask
  2341. # With full version
  2342. else:
  2343. _data._mask = np.zeros(_data.shape, dtype=mdtype)
  2344. # Check whether we missed something
  2345. elif isinstance(data, (tuple, list)):
  2346. try:
  2347. # If data is a sequence of masked array
  2348. mask = np.array(
  2349. [getmaskarray(np.asanyarray(m, dtype=_data.dtype))
  2350. for m in data], dtype=mdtype)
  2351. except ValueError:
  2352. # If data is nested
  2353. mask = nomask
  2354. # Force shrinking of the mask if needed (and possible)
  2355. if (mdtype == MaskType) and mask.any():
  2356. _data._mask = mask
  2357. _data._sharedmask = False
  2358. else:
  2359. _data._sharedmask = not copy
  2360. if copy:
  2361. _data._mask = _data._mask.copy()
  2362. # Reset the shape of the original mask
  2363. if getmask(data) is not nomask:
  2364. data._mask.shape = data.shape
  2365. else:
  2366. # Case 2. : With a mask in input.
  2367. # If mask is boolean, create an array of True or False
  2368. if mask is True and mdtype == MaskType:
  2369. mask = np.ones(_data.shape, dtype=mdtype)
  2370. elif mask is False and mdtype == MaskType:
  2371. mask = np.zeros(_data.shape, dtype=mdtype)
  2372. else:
  2373. # Read the mask with the current mdtype
  2374. try:
  2375. mask = np.array(mask, copy=copy, dtype=mdtype)
  2376. # Or assume it's a sequence of bool/int
  2377. except TypeError:
  2378. mask = np.array([tuple([m] * len(mdtype)) for m in mask],
  2379. dtype=mdtype)
  2380. # Make sure the mask and the data have the same shape
  2381. if mask.shape != _data.shape:
  2382. (nd, nm) = (_data.size, mask.size)
  2383. if nm == 1:
  2384. mask = np.resize(mask, _data.shape)
  2385. elif nm == nd:
  2386. mask = np.reshape(mask, _data.shape)
  2387. else:
  2388. msg = "Mask and data not compatible: data size is %i, " + \
  2389. "mask size is %i."
  2390. raise MaskError(msg % (nd, nm))
  2391. copy = True
  2392. # Set the mask to the new value
  2393. if _data._mask is nomask:
  2394. _data._mask = mask
  2395. _data._sharedmask = not copy
  2396. else:
  2397. if not keep_mask:
  2398. _data._mask = mask
  2399. _data._sharedmask = not copy
  2400. else:
  2401. if _data.dtype.names is not None:
  2402. def _recursive_or(a, b):
  2403. "do a|=b on each field of a, recursively"
  2404. for name in a.dtype.names:
  2405. (af, bf) = (a[name], b[name])
  2406. if af.dtype.names is not None:
  2407. _recursive_or(af, bf)
  2408. else:
  2409. af |= bf
  2410. _recursive_or(_data._mask, mask)
  2411. else:
  2412. _data._mask = np.logical_or(mask, _data._mask)
  2413. _data._sharedmask = False
  2414. # Update fill_value.
  2415. if fill_value is None:
  2416. fill_value = getattr(data, '_fill_value', None)
  2417. # But don't run the check unless we have something to check.
  2418. if fill_value is not None:
  2419. _data._fill_value = _check_fill_value(fill_value, _data.dtype)
  2420. # Process extra options ..
  2421. if hard_mask is None:
  2422. _data._hardmask = getattr(data, '_hardmask', False)
  2423. else:
  2424. _data._hardmask = hard_mask
  2425. _data._baseclass = _baseclass
  2426. return _data
  2427. def _update_from(self, obj):
  2428. """
  2429. Copies some attributes of obj to self.
  2430. """
  2431. if isinstance(obj, ndarray):
  2432. _baseclass = type(obj)
  2433. else:
  2434. _baseclass = ndarray
  2435. # We need to copy the _basedict to avoid backward propagation
  2436. _optinfo = {}
  2437. _optinfo.update(getattr(obj, '_optinfo', {}))
  2438. _optinfo.update(getattr(obj, '_basedict', {}))
  2439. if not isinstance(obj, MaskedArray):
  2440. _optinfo.update(getattr(obj, '__dict__', {}))
  2441. _dict = dict(_fill_value=getattr(obj, '_fill_value', None),
  2442. _hardmask=getattr(obj, '_hardmask', False),
  2443. _sharedmask=getattr(obj, '_sharedmask', False),
  2444. _isfield=getattr(obj, '_isfield', False),
  2445. _baseclass=getattr(obj, '_baseclass', _baseclass),
  2446. _optinfo=_optinfo,
  2447. _basedict=_optinfo)
  2448. self.__dict__.update(_dict)
  2449. self.__dict__.update(_optinfo)
  2450. return
  2451. def __array_finalize__(self, obj):
  2452. """
  2453. Finalizes the masked array.
  2454. """
  2455. # Get main attributes.
  2456. self._update_from(obj)
  2457. # We have to decide how to initialize self.mask, based on
  2458. # obj.mask. This is very difficult. There might be some
  2459. # correspondence between the elements in the array we are being
  2460. # created from (= obj) and us. Or there might not. This method can
  2461. # be called in all kinds of places for all kinds of reasons -- could
  2462. # be empty_like, could be slicing, could be a ufunc, could be a view.
  2463. # The numpy subclassing interface simply doesn't give us any way
  2464. # to know, which means that at best this method will be based on
  2465. # guesswork and heuristics. To make things worse, there isn't even any
  2466. # clear consensus about what the desired behavior is. For instance,
  2467. # most users think that np.empty_like(marr) -- which goes via this
  2468. # method -- should return a masked array with an empty mask (see
  2469. # gh-3404 and linked discussions), but others disagree, and they have
  2470. # existing code which depends on empty_like returning an array that
  2471. # matches the input mask.
  2472. #
  2473. # Historically our algorithm was: if the template object mask had the
  2474. # same *number of elements* as us, then we used *it's mask object
  2475. # itself* as our mask, so that writes to us would also write to the
  2476. # original array. This is horribly broken in multiple ways.
  2477. #
  2478. # Now what we do instead is, if the template object mask has the same
  2479. # number of elements as us, and we do not have the same base pointer
  2480. # as the template object (b/c views like arr[...] should keep the same
  2481. # mask), then we make a copy of the template object mask and use
  2482. # that. This is also horribly broken but somewhat less so. Maybe.
  2483. if isinstance(obj, ndarray):
  2484. # XX: This looks like a bug -- shouldn't it check self.dtype
  2485. # instead?
  2486. if obj.dtype.names is not None:
  2487. _mask = getmaskarray(obj)
  2488. else:
  2489. _mask = getmask(obj)
  2490. # If self and obj point to exactly the same data, then probably
  2491. # self is a simple view of obj (e.g., self = obj[...]), so they
  2492. # should share the same mask. (This isn't 100% reliable, e.g. self
  2493. # could be the first row of obj, or have strange strides, but as a
  2494. # heuristic it's not bad.) In all other cases, we make a copy of
  2495. # the mask, so that future modifications to 'self' do not end up
  2496. # side-effecting 'obj' as well.
  2497. if (_mask is not nomask and obj.__array_interface__["data"][0]
  2498. != self.__array_interface__["data"][0]):
  2499. # We should make a copy. But we could get here via astype,
  2500. # in which case the mask might need a new dtype as well
  2501. # (e.g., changing to or from a structured dtype), and the
  2502. # order could have changed. So, change the mask type if
  2503. # needed and use astype instead of copy.
  2504. if self.dtype == obj.dtype:
  2505. _mask_dtype = _mask.dtype
  2506. else:
  2507. _mask_dtype = make_mask_descr(self.dtype)
  2508. if self.flags.c_contiguous:
  2509. order = "C"
  2510. elif self.flags.f_contiguous:
  2511. order = "F"
  2512. else:
  2513. order = "K"
  2514. _mask = _mask.astype(_mask_dtype, order)
  2515. else:
  2516. # Take a view so shape changes, etc., do not propagate back.
  2517. _mask = _mask.view()
  2518. else:
  2519. _mask = nomask
  2520. self._mask = _mask
  2521. # Finalize the mask
  2522. if self._mask is not nomask:
  2523. try:
  2524. self._mask.shape = self.shape
  2525. except ValueError:
  2526. self._mask = nomask
  2527. except (TypeError, AttributeError):
  2528. # When _mask.shape is not writable (because it's a void)
  2529. pass
  2530. # Finalize the fill_value
  2531. if self._fill_value is not None:
  2532. self._fill_value = _check_fill_value(self._fill_value, self.dtype)
  2533. elif self.dtype.names is not None:
  2534. # Finalize the default fill_value for structured arrays
  2535. self._fill_value = _check_fill_value(None, self.dtype)
  2536. def __array_wrap__(self, obj, context=None):
  2537. """
  2538. Special hook for ufuncs.
  2539. Wraps the numpy array and sets the mask according to context.
  2540. """
  2541. if obj is self: # for in-place operations
  2542. result = obj
  2543. else:
  2544. result = obj.view(type(self))
  2545. result._update_from(self)
  2546. if context is not None:
  2547. result._mask = result._mask.copy()
  2548. func, args, out_i = context
  2549. # args sometimes contains outputs (gh-10459), which we don't want
  2550. input_args = args[:func.nin]
  2551. m = reduce(mask_or, [getmaskarray(arg) for arg in input_args])
  2552. # Get the domain mask
  2553. domain = ufunc_domain.get(func, None)
  2554. if domain is not None:
  2555. # Take the domain, and make sure it's a ndarray
  2556. with np.errstate(divide='ignore', invalid='ignore'):
  2557. d = filled(domain(*input_args), True)
  2558. if d.any():
  2559. # Fill the result where the domain is wrong
  2560. try:
  2561. # Binary domain: take the last value
  2562. fill_value = ufunc_fills[func][-1]
  2563. except TypeError:
  2564. # Unary domain: just use this one
  2565. fill_value = ufunc_fills[func]
  2566. except KeyError:
  2567. # Domain not recognized, use fill_value instead
  2568. fill_value = self.fill_value
  2569. np.copyto(result, fill_value, where=d)
  2570. # Update the mask
  2571. if m is nomask:
  2572. m = d
  2573. else:
  2574. # Don't modify inplace, we risk back-propagation
  2575. m = (m | d)
  2576. # Make sure the mask has the proper size
  2577. if result is not self and result.shape == () and m:
  2578. return masked
  2579. else:
  2580. result._mask = m
  2581. result._sharedmask = False
  2582. return result
  2583. def view(self, dtype=None, type=None, fill_value=None):
  2584. """
  2585. Return a view of the MaskedArray data.
  2586. Parameters
  2587. ----------
  2588. dtype : data-type or ndarray sub-class, optional
  2589. Data-type descriptor of the returned view, e.g., float32 or int16.
  2590. The default, None, results in the view having the same data-type
  2591. as `a`. As with ``ndarray.view``, dtype can also be specified as
  2592. an ndarray sub-class, which then specifies the type of the
  2593. returned object (this is equivalent to setting the ``type``
  2594. parameter).
  2595. type : Python type, optional
  2596. Type of the returned view, either ndarray or a subclass. The
  2597. default None results in type preservation.
  2598. fill_value : scalar, optional
  2599. The value to use for invalid entries (None by default).
  2600. If None, then this argument is inferred from the passed `dtype`, or
  2601. in its absence the original array, as discussed in the notes below.
  2602. See Also
  2603. --------
  2604. numpy.ndarray.view : Equivalent method on ndarray object.
  2605. Notes
  2606. -----
  2607. ``a.view()`` is used two different ways:
  2608. ``a.view(some_dtype)`` or ``a.view(dtype=some_dtype)`` constructs a view
  2609. of the array's memory with a different data-type. This can cause a
  2610. reinterpretation of the bytes of memory.
  2611. ``a.view(ndarray_subclass)`` or ``a.view(type=ndarray_subclass)`` just
  2612. returns an instance of `ndarray_subclass` that looks at the same array
  2613. (same shape, dtype, etc.) This does not cause a reinterpretation of the
  2614. memory.
  2615. If `fill_value` is not specified, but `dtype` is specified (and is not
  2616. an ndarray sub-class), the `fill_value` of the MaskedArray will be
  2617. reset. If neither `fill_value` nor `dtype` are specified (or if
  2618. `dtype` is an ndarray sub-class), then the fill value is preserved.
  2619. Finally, if `fill_value` is specified, but `dtype` is not, the fill
  2620. value is set to the specified value.
  2621. For ``a.view(some_dtype)``, if ``some_dtype`` has a different number of
  2622. bytes per entry than the previous dtype (for example, converting a
  2623. regular array to a structured array), then the behavior of the view
  2624. cannot be predicted just from the superficial appearance of ``a`` (shown
  2625. by ``print(a)``). It also depends on exactly how ``a`` is stored in
  2626. memory. Therefore if ``a`` is C-ordered versus fortran-ordered, versus
  2627. defined as a slice or transpose, etc., the view may give different
  2628. results.
  2629. """
  2630. if dtype is None:
  2631. if type is None:
  2632. output = ndarray.view(self)
  2633. else:
  2634. output = ndarray.view(self, type)
  2635. elif type is None:
  2636. try:
  2637. if issubclass(dtype, ndarray):
  2638. output = ndarray.view(self, dtype)
  2639. dtype = None
  2640. else:
  2641. output = ndarray.view(self, dtype)
  2642. except TypeError:
  2643. output = ndarray.view(self, dtype)
  2644. else:
  2645. output = ndarray.view(self, dtype, type)
  2646. # also make the mask be a view (so attr changes to the view's
  2647. # mask do no affect original object's mask)
  2648. # (especially important to avoid affecting np.masked singleton)
  2649. if getmask(output) is not nomask:
  2650. output._mask = output._mask.view()
  2651. # Make sure to reset the _fill_value if needed
  2652. if getattr(output, '_fill_value', None) is not None:
  2653. if fill_value is None:
  2654. if dtype is None:
  2655. pass # leave _fill_value as is
  2656. else:
  2657. output._fill_value = None
  2658. else:
  2659. output.fill_value = fill_value
  2660. return output
  2661. def __getitem__(self, indx):
  2662. """
  2663. x.__getitem__(y) <==> x[y]
  2664. Return the item described by i, as a masked array.
  2665. """
  2666. # We could directly use ndarray.__getitem__ on self.
  2667. # But then we would have to modify __array_finalize__ to prevent the
  2668. # mask of being reshaped if it hasn't been set up properly yet
  2669. # So it's easier to stick to the current version
  2670. dout = self.data[indx]
  2671. _mask = self._mask
  2672. def _is_scalar(m):
  2673. return not isinstance(m, np.ndarray)
  2674. def _scalar_heuristic(arr, elem):
  2675. """
  2676. Return whether `elem` is a scalar result of indexing `arr`, or None
  2677. if undecidable without promoting nomask to a full mask
  2678. """
  2679. # obviously a scalar
  2680. if not isinstance(elem, np.ndarray):
  2681. return True
  2682. # object array scalar indexing can return anything
  2683. elif arr.dtype.type is np.object_:
  2684. if arr.dtype is not elem.dtype:
  2685. # elem is an array, but dtypes do not match, so must be
  2686. # an element
  2687. return True
  2688. # well-behaved subclass that only returns 0d arrays when
  2689. # expected - this is not a scalar
  2690. elif type(arr).__getitem__ == ndarray.__getitem__:
  2691. return False
  2692. return None
  2693. if _mask is not nomask:
  2694. # _mask cannot be a subclass, so it tells us whether we should
  2695. # expect a scalar. It also cannot be of dtype object.
  2696. mout = _mask[indx]
  2697. scalar_expected = _is_scalar(mout)
  2698. else:
  2699. # attempt to apply the heuristic to avoid constructing a full mask
  2700. mout = nomask
  2701. scalar_expected = _scalar_heuristic(self.data, dout)
  2702. if scalar_expected is None:
  2703. # heuristics have failed
  2704. # construct a full array, so we can be certain. This is costly.
  2705. # we could also fall back on ndarray.__getitem__(self.data, indx)
  2706. scalar_expected = _is_scalar(getmaskarray(self)[indx])
  2707. # Did we extract a single item?
  2708. if scalar_expected:
  2709. # A record
  2710. if isinstance(dout, np.void):
  2711. # We should always re-cast to mvoid, otherwise users can
  2712. # change masks on rows that already have masked values, but not
  2713. # on rows that have no masked values, which is inconsistent.
  2714. return mvoid(dout, mask=mout, hardmask=self._hardmask)
  2715. # special case introduced in gh-5962
  2716. elif (self.dtype.type is np.object_ and
  2717. isinstance(dout, np.ndarray) and
  2718. dout is not masked):
  2719. # If masked, turn into a MaskedArray, with everything masked.
  2720. if mout:
  2721. return MaskedArray(dout, mask=True)
  2722. else:
  2723. return dout
  2724. # Just a scalar
  2725. else:
  2726. if mout:
  2727. return masked
  2728. else:
  2729. return dout
  2730. else:
  2731. # Force dout to MA
  2732. dout = dout.view(type(self))
  2733. # Inherit attributes from self
  2734. dout._update_from(self)
  2735. # Check the fill_value
  2736. if is_string_or_list_of_strings(indx):
  2737. if self._fill_value is not None:
  2738. dout._fill_value = self._fill_value[indx]
  2739. # Something like gh-15895 has happened if this check fails.
  2740. # _fill_value should always be an ndarray.
  2741. if not isinstance(dout._fill_value, np.ndarray):
  2742. raise RuntimeError('Internal NumPy error.')
  2743. # If we're indexing a multidimensional field in a
  2744. # structured array (such as dtype("(2,)i2,(2,)i1")),
  2745. # dimensionality goes up (M[field].ndim == M.ndim +
  2746. # M.dtype[field].ndim). That's fine for
  2747. # M[field] but problematic for M[field].fill_value
  2748. # which should have shape () to avoid breaking several
  2749. # methods. There is no great way out, so set to
  2750. # first element. See issue #6723.
  2751. if dout._fill_value.ndim > 0:
  2752. if not (dout._fill_value ==
  2753. dout._fill_value.flat[0]).all():
  2754. warnings.warn(
  2755. "Upon accessing multidimensional field "
  2756. f"{indx!s}, need to keep dimensionality "
  2757. "of fill_value at 0. Discarding "
  2758. "heterogeneous fill_value and setting "
  2759. f"all to {dout._fill_value[0]!s}.",
  2760. stacklevel=2)
  2761. # Need to use `.flat[0:1].squeeze(...)` instead of just
  2762. # `.flat[0]` to ensure the result is a 0d array and not
  2763. # a scalar.
  2764. dout._fill_value = dout._fill_value.flat[0:1].squeeze(axis=0)
  2765. dout._isfield = True
  2766. # Update the mask if needed
  2767. if mout is not nomask:
  2768. # set shape to match that of data; this is needed for matrices
  2769. dout._mask = reshape(mout, dout.shape)
  2770. dout._sharedmask = True
  2771. # Note: Don't try to check for m.any(), that'll take too long
  2772. return dout
  2773. # setitem may put NaNs into integer arrays or occasionally overflow a
  2774. # float. But this may happen in masked values, so avoid otherwise
  2775. # correct warnings (as is typical also in masked calculations).
  2776. @np.errstate(over='ignore', invalid='ignore')
  2777. def __setitem__(self, indx, value):
  2778. """
  2779. x.__setitem__(i, y) <==> x[i]=y
  2780. Set item described by index. If value is masked, masks those
  2781. locations.
  2782. """
  2783. if self is masked:
  2784. raise MaskError('Cannot alter the masked element.')
  2785. _data = self._data
  2786. _mask = self._mask
  2787. if isinstance(indx, str):
  2788. _data[indx] = value
  2789. if _mask is nomask:
  2790. self._mask = _mask = make_mask_none(self.shape, self.dtype)
  2791. _mask[indx] = getmask(value)
  2792. return
  2793. _dtype = _data.dtype
  2794. if value is masked:
  2795. # The mask wasn't set: create a full version.
  2796. if _mask is nomask:
  2797. _mask = self._mask = make_mask_none(self.shape, _dtype)
  2798. # Now, set the mask to its value.
  2799. if _dtype.names is not None:
  2800. _mask[indx] = tuple([True] * len(_dtype.names))
  2801. else:
  2802. _mask[indx] = True
  2803. return
  2804. # Get the _data part of the new value
  2805. dval = getattr(value, '_data', value)
  2806. # Get the _mask part of the new value
  2807. mval = getmask(value)
  2808. if _dtype.names is not None and mval is nomask:
  2809. mval = tuple([False] * len(_dtype.names))
  2810. if _mask is nomask:
  2811. # Set the data, then the mask
  2812. _data[indx] = dval
  2813. if mval is not nomask:
  2814. _mask = self._mask = make_mask_none(self.shape, _dtype)
  2815. _mask[indx] = mval
  2816. elif not self._hardmask:
  2817. # Set the data, then the mask
  2818. if (isinstance(indx, masked_array) and
  2819. not isinstance(value, masked_array)):
  2820. _data[indx.data] = dval
  2821. else:
  2822. _data[indx] = dval
  2823. _mask[indx] = mval
  2824. elif hasattr(indx, 'dtype') and (indx.dtype == MaskType):
  2825. indx = indx * umath.logical_not(_mask)
  2826. _data[indx] = dval
  2827. else:
  2828. if _dtype.names is not None:
  2829. err_msg = "Flexible 'hard' masks are not yet supported."
  2830. raise NotImplementedError(err_msg)
  2831. mindx = mask_or(_mask[indx], mval, copy=True)
  2832. dindx = self._data[indx]
  2833. if dindx.size > 1:
  2834. np.copyto(dindx, dval, where=~mindx)
  2835. elif mindx is nomask:
  2836. dindx = dval
  2837. _data[indx] = dindx
  2838. _mask[indx] = mindx
  2839. return
  2840. # Define so that we can overwrite the setter.
  2841. @property
  2842. def dtype(self):
  2843. return super().dtype
  2844. @dtype.setter
  2845. def dtype(self, dtype):
  2846. super(MaskedArray, type(self)).dtype.__set__(self, dtype)
  2847. if self._mask is not nomask:
  2848. self._mask = self._mask.view(make_mask_descr(dtype), ndarray)
  2849. # Try to reset the shape of the mask (if we don't have a void).
  2850. # This raises a ValueError if the dtype change won't work.
  2851. try:
  2852. self._mask.shape = self.shape
  2853. except (AttributeError, TypeError):
  2854. pass
  2855. @property
  2856. def shape(self):
  2857. return super().shape
  2858. @shape.setter
  2859. def shape(self, shape):
  2860. super(MaskedArray, type(self)).shape.__set__(self, shape)
  2861. # Cannot use self._mask, since it may not (yet) exist when a
  2862. # masked matrix sets the shape.
  2863. if getmask(self) is not nomask:
  2864. self._mask.shape = self.shape
  2865. def __setmask__(self, mask, copy=False):
  2866. """
  2867. Set the mask.
  2868. """
  2869. idtype = self.dtype
  2870. current_mask = self._mask
  2871. if mask is masked:
  2872. mask = True
  2873. if current_mask is nomask:
  2874. # Make sure the mask is set
  2875. # Just don't do anything if there's nothing to do.
  2876. if mask is nomask:
  2877. return
  2878. current_mask = self._mask = make_mask_none(self.shape, idtype)
  2879. if idtype.names is None:
  2880. # No named fields.
  2881. # Hardmask: don't unmask the data
  2882. if self._hardmask:
  2883. current_mask |= mask
  2884. # Softmask: set everything to False
  2885. # If it's obviously a compatible scalar, use a quick update
  2886. # method.
  2887. elif isinstance(mask, (int, float, np.bool_, np.number)):
  2888. current_mask[...] = mask
  2889. # Otherwise fall back to the slower, general purpose way.
  2890. else:
  2891. current_mask.flat = mask
  2892. else:
  2893. # Named fields w/
  2894. mdtype = current_mask.dtype
  2895. mask = np.array(mask, copy=False)
  2896. # Mask is a singleton
  2897. if not mask.ndim:
  2898. # It's a boolean : make a record
  2899. if mask.dtype.kind == 'b':
  2900. mask = np.array(tuple([mask.item()] * len(mdtype)),
  2901. dtype=mdtype)
  2902. # It's a record: make sure the dtype is correct
  2903. else:
  2904. mask = mask.astype(mdtype)
  2905. # Mask is a sequence
  2906. else:
  2907. # Make sure the new mask is a ndarray with the proper dtype
  2908. try:
  2909. mask = np.array(mask, copy=copy, dtype=mdtype)
  2910. # Or assume it's a sequence of bool/int
  2911. except TypeError:
  2912. mask = np.array([tuple([m] * len(mdtype)) for m in mask],
  2913. dtype=mdtype)
  2914. # Hardmask: don't unmask the data
  2915. if self._hardmask:
  2916. for n in idtype.names:
  2917. current_mask[n] |= mask[n]
  2918. # Softmask: set everything to False
  2919. # If it's obviously a compatible scalar, use a quick update
  2920. # method.
  2921. elif isinstance(mask, (int, float, np.bool_, np.number)):
  2922. current_mask[...] = mask
  2923. # Otherwise fall back to the slower, general purpose way.
  2924. else:
  2925. current_mask.flat = mask
  2926. # Reshape if needed
  2927. if current_mask.shape:
  2928. current_mask.shape = self.shape
  2929. return
  2930. _set_mask = __setmask__
  2931. @property
  2932. def mask(self):
  2933. """ Current mask. """
  2934. # We could try to force a reshape, but that wouldn't work in some
  2935. # cases.
  2936. # Return a view so that the dtype and shape cannot be changed in place
  2937. # This still preserves nomask by identity
  2938. return self._mask.view()
  2939. @mask.setter
  2940. def mask(self, value):
  2941. self.__setmask__(value)
  2942. @property
  2943. def recordmask(self):
  2944. """
  2945. Get or set the mask of the array if it has no named fields. For
  2946. structured arrays, returns a ndarray of booleans where entries are
  2947. ``True`` if **all** the fields are masked, ``False`` otherwise:
  2948. >>> x = np.ma.array([(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)],
  2949. ... mask=[(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)],
  2950. ... dtype=[('a', int), ('b', int)])
  2951. >>> x.recordmask
  2952. array([False, False, True, False, False])
  2953. """
  2954. _mask = self._mask.view(ndarray)
  2955. if _mask.dtype.names is None:
  2956. return _mask
  2957. return np.all(flatten_structured_array(_mask), axis=-1)
  2958. @recordmask.setter
  2959. def recordmask(self, mask):
  2960. raise NotImplementedError("Coming soon: setting the mask per records!")
  2961. def harden_mask(self):
  2962. """
  2963. Force the mask to hard, preventing unmasking by assignment.
  2964. Whether the mask of a masked array is hard or soft is determined by
  2965. its `~ma.MaskedArray.hardmask` property. `harden_mask` sets
  2966. `~ma.MaskedArray.hardmask` to ``True`` (and returns the modified
  2967. self).
  2968. See Also
  2969. --------
  2970. ma.MaskedArray.hardmask
  2971. ma.MaskedArray.soften_mask
  2972. """
  2973. self._hardmask = True
  2974. return self
  2975. def soften_mask(self):
  2976. """
  2977. Force the mask to soft (default), allowing unmasking by assignment.
  2978. Whether the mask of a masked array is hard or soft is determined by
  2979. its `~ma.MaskedArray.hardmask` property. `soften_mask` sets
  2980. `~ma.MaskedArray.hardmask` to ``False`` (and returns the modified
  2981. self).
  2982. See Also
  2983. --------
  2984. ma.MaskedArray.hardmask
  2985. ma.MaskedArray.harden_mask
  2986. """
  2987. self._hardmask = False
  2988. return self
  2989. @property
  2990. def hardmask(self):
  2991. """
  2992. Specifies whether values can be unmasked through assignments.
  2993. By default, assigning definite values to masked array entries will
  2994. unmask them. When `hardmask` is ``True``, the mask will not change
  2995. through assignments.
  2996. See Also
  2997. --------
  2998. ma.MaskedArray.harden_mask
  2999. ma.MaskedArray.soften_mask
  3000. Examples
  3001. --------
  3002. >>> x = np.arange(10)
  3003. >>> m = np.ma.masked_array(x, x>5)
  3004. >>> assert not m.hardmask
  3005. Since `m` has a soft mask, assigning an element value unmasks that
  3006. element:
  3007. >>> m[8] = 42
  3008. >>> m
  3009. masked_array(data=[0, 1, 2, 3, 4, 5, --, --, 42, --],
  3010. mask=[False, False, False, False, False, False,
  3011. True, True, False, True],
  3012. fill_value=999999)
  3013. After hardening, the mask is not affected by assignments:
  3014. >>> hardened = np.ma.harden_mask(m)
  3015. >>> assert m.hardmask and hardened is m
  3016. >>> m[:] = 23
  3017. >>> m
  3018. masked_array(data=[23, 23, 23, 23, 23, 23, --, --, 23, --],
  3019. mask=[False, False, False, False, False, False,
  3020. True, True, False, True],
  3021. fill_value=999999)
  3022. """
  3023. return self._hardmask
  3024. def unshare_mask(self):
  3025. """
  3026. Copy the mask and set the `sharedmask` flag to ``False``.
  3027. Whether the mask is shared between masked arrays can be seen from
  3028. the `sharedmask` property. `unshare_mask` ensures the mask is not
  3029. shared. A copy of the mask is only made if it was shared.
  3030. See Also
  3031. --------
  3032. sharedmask
  3033. """
  3034. if self._sharedmask:
  3035. self._mask = self._mask.copy()
  3036. self._sharedmask = False
  3037. return self
  3038. @property
  3039. def sharedmask(self):
  3040. """ Share status of the mask (read-only). """
  3041. return self._sharedmask
  3042. def shrink_mask(self):
  3043. """
  3044. Reduce a mask to nomask when possible.
  3045. Parameters
  3046. ----------
  3047. None
  3048. Returns
  3049. -------
  3050. None
  3051. Examples
  3052. --------
  3053. >>> x = np.ma.array([[1,2 ], [3, 4]], mask=[0]*4)
  3054. >>> x.mask
  3055. array([[False, False],
  3056. [False, False]])
  3057. >>> x.shrink_mask()
  3058. masked_array(
  3059. data=[[1, 2],
  3060. [3, 4]],
  3061. mask=False,
  3062. fill_value=999999)
  3063. >>> x.mask
  3064. False
  3065. """
  3066. self._mask = _shrink_mask(self._mask)
  3067. return self
  3068. @property
  3069. def baseclass(self):
  3070. """ Class of the underlying data (read-only). """
  3071. return self._baseclass
  3072. def _get_data(self):
  3073. """
  3074. Returns the underlying data, as a view of the masked array.
  3075. If the underlying data is a subclass of :class:`numpy.ndarray`, it is
  3076. returned as such.
  3077. >>> x = np.ma.array(np.matrix([[1, 2], [3, 4]]), mask=[[0, 1], [1, 0]])
  3078. >>> x.data
  3079. matrix([[1, 2],
  3080. [3, 4]])
  3081. The type of the data can be accessed through the :attr:`baseclass`
  3082. attribute.
  3083. """
  3084. return ndarray.view(self, self._baseclass)
  3085. _data = property(fget=_get_data)
  3086. data = property(fget=_get_data)
  3087. @property
  3088. def flat(self):
  3089. """ Return a flat iterator, or set a flattened version of self to value. """
  3090. return MaskedIterator(self)
  3091. @flat.setter
  3092. def flat(self, value):
  3093. y = self.ravel()
  3094. y[:] = value
  3095. @property
  3096. def fill_value(self):
  3097. """
  3098. The filling value of the masked array is a scalar. When setting, None
  3099. will set to a default based on the data type.
  3100. Examples
  3101. --------
  3102. >>> for dt in [np.int32, np.int64, np.float64, np.complex128]:
  3103. ... np.ma.array([0, 1], dtype=dt).get_fill_value()
  3104. ...
  3105. 999999
  3106. 999999
  3107. 1e+20
  3108. (1e+20+0j)
  3109. >>> x = np.ma.array([0, 1.], fill_value=-np.inf)
  3110. >>> x.fill_value
  3111. -inf
  3112. >>> x.fill_value = np.pi
  3113. >>> x.fill_value
  3114. 3.1415926535897931 # may vary
  3115. Reset to default:
  3116. >>> x.fill_value = None
  3117. >>> x.fill_value
  3118. 1e+20
  3119. """
  3120. if self._fill_value is None:
  3121. self._fill_value = _check_fill_value(None, self.dtype)
  3122. # Temporary workaround to account for the fact that str and bytes
  3123. # scalars cannot be indexed with (), whereas all other numpy
  3124. # scalars can. See issues #7259 and #7267.
  3125. # The if-block can be removed after #7267 has been fixed.
  3126. if isinstance(self._fill_value, ndarray):
  3127. return self._fill_value[()]
  3128. return self._fill_value
  3129. @fill_value.setter
  3130. def fill_value(self, value=None):
  3131. target = _check_fill_value(value, self.dtype)
  3132. if not target.ndim == 0:
  3133. # 2019-11-12, 1.18.0
  3134. warnings.warn(
  3135. "Non-scalar arrays for the fill value are deprecated. Use "
  3136. "arrays with scalar values instead. The filled function "
  3137. "still supports any array as `fill_value`.",
  3138. DeprecationWarning, stacklevel=2)
  3139. _fill_value = self._fill_value
  3140. if _fill_value is None:
  3141. # Create the attribute if it was undefined
  3142. self._fill_value = target
  3143. else:
  3144. # Don't overwrite the attribute, just fill it (for propagation)
  3145. _fill_value[()] = target
  3146. # kept for compatibility
  3147. get_fill_value = fill_value.fget
  3148. set_fill_value = fill_value.fset
  3149. def filled(self, fill_value=None):
  3150. """
  3151. Return a copy of self, with masked values filled with a given value.
  3152. **However**, if there are no masked values to fill, self will be
  3153. returned instead as an ndarray.
  3154. Parameters
  3155. ----------
  3156. fill_value : array_like, optional
  3157. The value to use for invalid entries. Can be scalar or non-scalar.
  3158. If non-scalar, the resulting ndarray must be broadcastable over
  3159. input array. Default is None, in which case, the `fill_value`
  3160. attribute of the array is used instead.
  3161. Returns
  3162. -------
  3163. filled_array : ndarray
  3164. A copy of ``self`` with invalid entries replaced by *fill_value*
  3165. (be it the function argument or the attribute of ``self``), or
  3166. ``self`` itself as an ndarray if there are no invalid entries to
  3167. be replaced.
  3168. Notes
  3169. -----
  3170. The result is **not** a MaskedArray!
  3171. Examples
  3172. --------
  3173. >>> x = np.ma.array([1,2,3,4,5], mask=[0,0,1,0,1], fill_value=-999)
  3174. >>> x.filled()
  3175. array([ 1, 2, -999, 4, -999])
  3176. >>> x.filled(fill_value=1000)
  3177. array([ 1, 2, 1000, 4, 1000])
  3178. >>> type(x.filled())
  3179. <class 'numpy.ndarray'>
  3180. Subclassing is preserved. This means that if, e.g., the data part of
  3181. the masked array is a recarray, `filled` returns a recarray:
  3182. >>> x = np.array([(-1, 2), (-3, 4)], dtype='i8,i8').view(np.recarray)
  3183. >>> m = np.ma.array(x, mask=[(True, False), (False, True)])
  3184. >>> m.filled()
  3185. rec.array([(999999, 2), ( -3, 999999)],
  3186. dtype=[('f0', '<i8'), ('f1', '<i8')])
  3187. """
  3188. m = self._mask
  3189. if m is nomask:
  3190. return self._data
  3191. if fill_value is None:
  3192. fill_value = self.fill_value
  3193. else:
  3194. fill_value = _check_fill_value(fill_value, self.dtype)
  3195. if self is masked_singleton:
  3196. return np.asanyarray(fill_value)
  3197. if m.dtype.names is not None:
  3198. result = self._data.copy('K')
  3199. _recursive_filled(result, self._mask, fill_value)
  3200. elif not m.any():
  3201. return self._data
  3202. else:
  3203. result = self._data.copy('K')
  3204. try:
  3205. np.copyto(result, fill_value, where=m)
  3206. except (TypeError, AttributeError):
  3207. fill_value = narray(fill_value, dtype=object)
  3208. d = result.astype(object)
  3209. result = np.choose(m, (d, fill_value))
  3210. except IndexError:
  3211. # ok, if scalar
  3212. if self._data.shape:
  3213. raise
  3214. elif m:
  3215. result = np.array(fill_value, dtype=self.dtype)
  3216. else:
  3217. result = self._data
  3218. return result
  3219. def compressed(self):
  3220. """
  3221. Return all the non-masked data as a 1-D array.
  3222. Returns
  3223. -------
  3224. data : ndarray
  3225. A new `ndarray` holding the non-masked data is returned.
  3226. Notes
  3227. -----
  3228. The result is **not** a MaskedArray!
  3229. Examples
  3230. --------
  3231. >>> x = np.ma.array(np.arange(5), mask=[0]*2 + [1]*3)
  3232. >>> x.compressed()
  3233. array([0, 1])
  3234. >>> type(x.compressed())
  3235. <class 'numpy.ndarray'>
  3236. """
  3237. data = ndarray.ravel(self._data)
  3238. if self._mask is not nomask:
  3239. data = data.compress(np.logical_not(ndarray.ravel(self._mask)))
  3240. return data
  3241. def compress(self, condition, axis=None, out=None):
  3242. """
  3243. Return `a` where condition is ``True``.
  3244. If condition is a `~ma.MaskedArray`, missing values are considered
  3245. as ``False``.
  3246. Parameters
  3247. ----------
  3248. condition : var
  3249. Boolean 1-d array selecting which entries to return. If len(condition)
  3250. is less than the size of a along the axis, then output is truncated
  3251. to length of condition array.
  3252. axis : {None, int}, optional
  3253. Axis along which the operation must be performed.
  3254. out : {None, ndarray}, optional
  3255. Alternative output array in which to place the result. It must have
  3256. the same shape as the expected output but the type will be cast if
  3257. necessary.
  3258. Returns
  3259. -------
  3260. result : MaskedArray
  3261. A :class:`~ma.MaskedArray` object.
  3262. Notes
  3263. -----
  3264. Please note the difference with :meth:`compressed` !
  3265. The output of :meth:`compress` has a mask, the output of
  3266. :meth:`compressed` does not.
  3267. Examples
  3268. --------
  3269. >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4)
  3270. >>> x
  3271. masked_array(
  3272. data=[[1, --, 3],
  3273. [--, 5, --],
  3274. [7, --, 9]],
  3275. mask=[[False, True, False],
  3276. [ True, False, True],
  3277. [False, True, False]],
  3278. fill_value=999999)
  3279. >>> x.compress([1, 0, 1])
  3280. masked_array(data=[1, 3],
  3281. mask=[False, False],
  3282. fill_value=999999)
  3283. >>> x.compress([1, 0, 1], axis=1)
  3284. masked_array(
  3285. data=[[1, 3],
  3286. [--, --],
  3287. [7, 9]],
  3288. mask=[[False, False],
  3289. [ True, True],
  3290. [False, False]],
  3291. fill_value=999999)
  3292. """
  3293. # Get the basic components
  3294. (_data, _mask) = (self._data, self._mask)
  3295. # Force the condition to a regular ndarray and forget the missing
  3296. # values.
  3297. condition = np.asarray(condition)
  3298. _new = _data.compress(condition, axis=axis, out=out).view(type(self))
  3299. _new._update_from(self)
  3300. if _mask is not nomask:
  3301. _new._mask = _mask.compress(condition, axis=axis)
  3302. return _new
  3303. def _insert_masked_print(self):
  3304. """
  3305. Replace masked values with masked_print_option, casting all innermost
  3306. dtypes to object.
  3307. """
  3308. if masked_print_option.enabled():
  3309. mask = self._mask
  3310. if mask is nomask:
  3311. res = self._data
  3312. else:
  3313. # convert to object array to make filled work
  3314. data = self._data
  3315. # For big arrays, to avoid a costly conversion to the
  3316. # object dtype, extract the corners before the conversion.
  3317. print_width = (self._print_width if self.ndim > 1
  3318. else self._print_width_1d)
  3319. for axis in range(self.ndim):
  3320. if data.shape[axis] > print_width:
  3321. ind = print_width // 2
  3322. arr = np.split(data, (ind, -ind), axis=axis)
  3323. data = np.concatenate((arr[0], arr[2]), axis=axis)
  3324. arr = np.split(mask, (ind, -ind), axis=axis)
  3325. mask = np.concatenate((arr[0], arr[2]), axis=axis)
  3326. rdtype = _replace_dtype_fields(self.dtype, "O")
  3327. res = data.astype(rdtype)
  3328. _recursive_printoption(res, mask, masked_print_option)
  3329. else:
  3330. res = self.filled(self.fill_value)
  3331. return res
  3332. def __str__(self):
  3333. return str(self._insert_masked_print())
  3334. def __repr__(self):
  3335. """
  3336. Literal string representation.
  3337. """
  3338. if self._baseclass is np.ndarray:
  3339. name = 'array'
  3340. else:
  3341. name = self._baseclass.__name__
  3342. # 2016-11-19: Demoted to legacy format
  3343. if np.core.arrayprint._get_legacy_print_mode() <= 113:
  3344. is_long = self.ndim > 1
  3345. parameters = dict(
  3346. name=name,
  3347. nlen=" " * len(name),
  3348. data=str(self),
  3349. mask=str(self._mask),
  3350. fill=str(self.fill_value),
  3351. dtype=str(self.dtype)
  3352. )
  3353. is_structured = bool(self.dtype.names)
  3354. key = '{}_{}'.format(
  3355. 'long' if is_long else 'short',
  3356. 'flx' if is_structured else 'std'
  3357. )
  3358. return _legacy_print_templates[key] % parameters
  3359. prefix = f"masked_{name}("
  3360. dtype_needed = (
  3361. not np.core.arrayprint.dtype_is_implied(self.dtype) or
  3362. np.all(self.mask) or
  3363. self.size == 0
  3364. )
  3365. # determine which keyword args need to be shown
  3366. keys = ['data', 'mask', 'fill_value']
  3367. if dtype_needed:
  3368. keys.append('dtype')
  3369. # array has only one row (non-column)
  3370. is_one_row = builtins.all(dim == 1 for dim in self.shape[:-1])
  3371. # choose what to indent each keyword with
  3372. min_indent = 2
  3373. if is_one_row:
  3374. # first key on the same line as the type, remaining keys
  3375. # aligned by equals
  3376. indents = {}
  3377. indents[keys[0]] = prefix
  3378. for k in keys[1:]:
  3379. n = builtins.max(min_indent, len(prefix + keys[0]) - len(k))
  3380. indents[k] = ' ' * n
  3381. prefix = '' # absorbed into the first indent
  3382. else:
  3383. # each key on its own line, indented by two spaces
  3384. indents = {k: ' ' * min_indent for k in keys}
  3385. prefix = prefix + '\n' # first key on the next line
  3386. # format the field values
  3387. reprs = {}
  3388. reprs['data'] = np.array2string(
  3389. self._insert_masked_print(),
  3390. separator=", ",
  3391. prefix=indents['data'] + 'data=',
  3392. suffix=',')
  3393. reprs['mask'] = np.array2string(
  3394. self._mask,
  3395. separator=", ",
  3396. prefix=indents['mask'] + 'mask=',
  3397. suffix=',')
  3398. reprs['fill_value'] = repr(self.fill_value)
  3399. if dtype_needed:
  3400. reprs['dtype'] = np.core.arrayprint.dtype_short_repr(self.dtype)
  3401. # join keys with values and indentations
  3402. result = ',\n'.join(
  3403. '{}{}={}'.format(indents[k], k, reprs[k])
  3404. for k in keys
  3405. )
  3406. return prefix + result + ')'
  3407. def _delegate_binop(self, other):
  3408. # This emulates the logic in
  3409. # private/binop_override.h:forward_binop_should_defer
  3410. if isinstance(other, type(self)):
  3411. return False
  3412. array_ufunc = getattr(other, "__array_ufunc__", False)
  3413. if array_ufunc is False:
  3414. other_priority = getattr(other, "__array_priority__", -1000000)
  3415. return self.__array_priority__ < other_priority
  3416. else:
  3417. # If array_ufunc is not None, it will be called inside the ufunc;
  3418. # None explicitly tells us to not call the ufunc, i.e., defer.
  3419. return array_ufunc is None
  3420. def _comparison(self, other, compare):
  3421. """Compare self with other using operator.eq or operator.ne.
  3422. When either of the elements is masked, the result is masked as well,
  3423. but the underlying boolean data are still set, with self and other
  3424. considered equal if both are masked, and unequal otherwise.
  3425. For structured arrays, all fields are combined, with masked values
  3426. ignored. The result is masked if all fields were masked, with self
  3427. and other considered equal only if both were fully masked.
  3428. """
  3429. omask = getmask(other)
  3430. smask = self.mask
  3431. mask = mask_or(smask, omask, copy=True)
  3432. odata = getdata(other)
  3433. if mask.dtype.names is not None:
  3434. # only == and != are reasonably defined for structured dtypes,
  3435. # so give up early for all other comparisons:
  3436. if compare not in (operator.eq, operator.ne):
  3437. return NotImplemented
  3438. # For possibly masked structured arrays we need to be careful,
  3439. # since the standard structured array comparison will use all
  3440. # fields, masked or not. To avoid masked fields influencing the
  3441. # outcome, we set all masked fields in self to other, so they'll
  3442. # count as equal. To prepare, we ensure we have the right shape.
  3443. broadcast_shape = np.broadcast(self, odata).shape
  3444. sbroadcast = np.broadcast_to(self, broadcast_shape, subok=True)
  3445. sbroadcast._mask = mask
  3446. sdata = sbroadcast.filled(odata)
  3447. # Now take care of the mask; the merged mask should have an item
  3448. # masked if all fields were masked (in one and/or other).
  3449. mask = (mask == np.ones((), mask.dtype))
  3450. else:
  3451. # For regular arrays, just use the data as they come.
  3452. sdata = self.data
  3453. check = compare(sdata, odata)
  3454. if isinstance(check, (np.bool_, bool)):
  3455. return masked if mask else check
  3456. if mask is not nomask and compare in (operator.eq, operator.ne):
  3457. # Adjust elements that were masked, which should be treated
  3458. # as equal if masked in both, unequal if masked in one.
  3459. # Note that this works automatically for structured arrays too.
  3460. # Ignore this for operations other than `==` and `!=`
  3461. check = np.where(mask, compare(smask, omask), check)
  3462. if mask.shape != check.shape:
  3463. # Guarantee consistency of the shape, making a copy since the
  3464. # the mask may need to get written to later.
  3465. mask = np.broadcast_to(mask, check.shape).copy()
  3466. check = check.view(type(self))
  3467. check._update_from(self)
  3468. check._mask = mask
  3469. # Cast fill value to bool_ if needed. If it cannot be cast, the
  3470. # default boolean fill value is used.
  3471. if check._fill_value is not None:
  3472. try:
  3473. fill = _check_fill_value(check._fill_value, np.bool_)
  3474. except (TypeError, ValueError):
  3475. fill = _check_fill_value(None, np.bool_)
  3476. check._fill_value = fill
  3477. return check
  3478. def __eq__(self, other):
  3479. """Check whether other equals self elementwise.
  3480. When either of the elements is masked, the result is masked as well,
  3481. but the underlying boolean data are still set, with self and other
  3482. considered equal if both are masked, and unequal otherwise.
  3483. For structured arrays, all fields are combined, with masked values
  3484. ignored. The result is masked if all fields were masked, with self
  3485. and other considered equal only if both were fully masked.
  3486. """
  3487. return self._comparison(other, operator.eq)
  3488. def __ne__(self, other):
  3489. """Check whether other does not equal self elementwise.
  3490. When either of the elements is masked, the result is masked as well,
  3491. but the underlying boolean data are still set, with self and other
  3492. considered equal if both are masked, and unequal otherwise.
  3493. For structured arrays, all fields are combined, with masked values
  3494. ignored. The result is masked if all fields were masked, with self
  3495. and other considered equal only if both were fully masked.
  3496. """
  3497. return self._comparison(other, operator.ne)
  3498. # All other comparisons:
  3499. def __le__(self, other):
  3500. return self._comparison(other, operator.le)
  3501. def __lt__(self, other):
  3502. return self._comparison(other, operator.lt)
  3503. def __ge__(self, other):
  3504. return self._comparison(other, operator.ge)
  3505. def __gt__(self, other):
  3506. return self._comparison(other, operator.gt)
  3507. def __add__(self, other):
  3508. """
  3509. Add self to other, and return a new masked array.
  3510. """
  3511. if self._delegate_binop(other):
  3512. return NotImplemented
  3513. return add(self, other)
  3514. def __radd__(self, other):
  3515. """
  3516. Add other to self, and return a new masked array.
  3517. """
  3518. # In analogy with __rsub__ and __rdiv__, use original order:
  3519. # we get here from `other + self`.
  3520. return add(other, self)
  3521. def __sub__(self, other):
  3522. """
  3523. Subtract other from self, and return a new masked array.
  3524. """
  3525. if self._delegate_binop(other):
  3526. return NotImplemented
  3527. return subtract(self, other)
  3528. def __rsub__(self, other):
  3529. """
  3530. Subtract self from other, and return a new masked array.
  3531. """
  3532. return subtract(other, self)
  3533. def __mul__(self, other):
  3534. "Multiply self by other, and return a new masked array."
  3535. if self._delegate_binop(other):
  3536. return NotImplemented
  3537. return multiply(self, other)
  3538. def __rmul__(self, other):
  3539. """
  3540. Multiply other by self, and return a new masked array.
  3541. """
  3542. # In analogy with __rsub__ and __rdiv__, use original order:
  3543. # we get here from `other * self`.
  3544. return multiply(other, self)
  3545. def __div__(self, other):
  3546. """
  3547. Divide other into self, and return a new masked array.
  3548. """
  3549. if self._delegate_binop(other):
  3550. return NotImplemented
  3551. return divide(self, other)
  3552. def __truediv__(self, other):
  3553. """
  3554. Divide other into self, and return a new masked array.
  3555. """
  3556. if self._delegate_binop(other):
  3557. return NotImplemented
  3558. return true_divide(self, other)
  3559. def __rtruediv__(self, other):
  3560. """
  3561. Divide self into other, and return a new masked array.
  3562. """
  3563. return true_divide(other, self)
  3564. def __floordiv__(self, other):
  3565. """
  3566. Divide other into self, and return a new masked array.
  3567. """
  3568. if self._delegate_binop(other):
  3569. return NotImplemented
  3570. return floor_divide(self, other)
  3571. def __rfloordiv__(self, other):
  3572. """
  3573. Divide self into other, and return a new masked array.
  3574. """
  3575. return floor_divide(other, self)
  3576. def __pow__(self, other):
  3577. """
  3578. Raise self to the power other, masking the potential NaNs/Infs
  3579. """
  3580. if self._delegate_binop(other):
  3581. return NotImplemented
  3582. return power(self, other)
  3583. def __rpow__(self, other):
  3584. """
  3585. Raise other to the power self, masking the potential NaNs/Infs
  3586. """
  3587. return power(other, self)
  3588. def __iadd__(self, other):
  3589. """
  3590. Add other to self in-place.
  3591. """
  3592. m = getmask(other)
  3593. if self._mask is nomask:
  3594. if m is not nomask and m.any():
  3595. self._mask = make_mask_none(self.shape, self.dtype)
  3596. self._mask += m
  3597. else:
  3598. if m is not nomask:
  3599. self._mask += m
  3600. other_data = getdata(other)
  3601. other_data = np.where(self._mask, other_data.dtype.type(0), other_data)
  3602. self._data.__iadd__(other_data)
  3603. return self
  3604. def __isub__(self, other):
  3605. """
  3606. Subtract other from self in-place.
  3607. """
  3608. m = getmask(other)
  3609. if self._mask is nomask:
  3610. if m is not nomask and m.any():
  3611. self._mask = make_mask_none(self.shape, self.dtype)
  3612. self._mask += m
  3613. elif m is not nomask:
  3614. self._mask += m
  3615. other_data = getdata(other)
  3616. other_data = np.where(self._mask, other_data.dtype.type(0), other_data)
  3617. self._data.__isub__(other_data)
  3618. return self
  3619. def __imul__(self, other):
  3620. """
  3621. Multiply self by other in-place.
  3622. """
  3623. m = getmask(other)
  3624. if self._mask is nomask:
  3625. if m is not nomask and m.any():
  3626. self._mask = make_mask_none(self.shape, self.dtype)
  3627. self._mask += m
  3628. elif m is not nomask:
  3629. self._mask += m
  3630. other_data = getdata(other)
  3631. other_data = np.where(self._mask, other_data.dtype.type(1), other_data)
  3632. self._data.__imul__(other_data)
  3633. return self
  3634. def __idiv__(self, other):
  3635. """
  3636. Divide self by other in-place.
  3637. """
  3638. other_data = getdata(other)
  3639. dom_mask = _DomainSafeDivide().__call__(self._data, other_data)
  3640. other_mask = getmask(other)
  3641. new_mask = mask_or(other_mask, dom_mask)
  3642. # The following 4 lines control the domain filling
  3643. if dom_mask.any():
  3644. (_, fval) = ufunc_fills[np.divide]
  3645. other_data = np.where(
  3646. dom_mask, other_data.dtype.type(fval), other_data)
  3647. self._mask |= new_mask
  3648. other_data = np.where(self._mask, other_data.dtype.type(1), other_data)
  3649. self._data.__idiv__(other_data)
  3650. return self
  3651. def __ifloordiv__(self, other):
  3652. """
  3653. Floor divide self by other in-place.
  3654. """
  3655. other_data = getdata(other)
  3656. dom_mask = _DomainSafeDivide().__call__(self._data, other_data)
  3657. other_mask = getmask(other)
  3658. new_mask = mask_or(other_mask, dom_mask)
  3659. # The following 3 lines control the domain filling
  3660. if dom_mask.any():
  3661. (_, fval) = ufunc_fills[np.floor_divide]
  3662. other_data = np.where(
  3663. dom_mask, other_data.dtype.type(fval), other_data)
  3664. self._mask |= new_mask
  3665. other_data = np.where(self._mask, other_data.dtype.type(1), other_data)
  3666. self._data.__ifloordiv__(other_data)
  3667. return self
  3668. def __itruediv__(self, other):
  3669. """
  3670. True divide self by other in-place.
  3671. """
  3672. other_data = getdata(other)
  3673. dom_mask = _DomainSafeDivide().__call__(self._data, other_data)
  3674. other_mask = getmask(other)
  3675. new_mask = mask_or(other_mask, dom_mask)
  3676. # The following 3 lines control the domain filling
  3677. if dom_mask.any():
  3678. (_, fval) = ufunc_fills[np.true_divide]
  3679. other_data = np.where(
  3680. dom_mask, other_data.dtype.type(fval), other_data)
  3681. self._mask |= new_mask
  3682. other_data = np.where(self._mask, other_data.dtype.type(1), other_data)
  3683. self._data.__itruediv__(other_data)
  3684. return self
  3685. def __ipow__(self, other):
  3686. """
  3687. Raise self to the power other, in place.
  3688. """
  3689. other_data = getdata(other)
  3690. other_data = np.where(self._mask, other_data.dtype.type(1), other_data)
  3691. other_mask = getmask(other)
  3692. with np.errstate(divide='ignore', invalid='ignore'):
  3693. self._data.__ipow__(other_data)
  3694. invalid = np.logical_not(np.isfinite(self._data))
  3695. if invalid.any():
  3696. if self._mask is not nomask:
  3697. self._mask |= invalid
  3698. else:
  3699. self._mask = invalid
  3700. np.copyto(self._data, self.fill_value, where=invalid)
  3701. new_mask = mask_or(other_mask, invalid)
  3702. self._mask = mask_or(self._mask, new_mask)
  3703. return self
  3704. def __float__(self):
  3705. """
  3706. Convert to float.
  3707. """
  3708. if self.size > 1:
  3709. raise TypeError("Only length-1 arrays can be converted "
  3710. "to Python scalars")
  3711. elif self._mask:
  3712. warnings.warn("Warning: converting a masked element to nan.", stacklevel=2)
  3713. return np.nan
  3714. return float(self.item())
  3715. def __int__(self):
  3716. """
  3717. Convert to int.
  3718. """
  3719. if self.size > 1:
  3720. raise TypeError("Only length-1 arrays can be converted "
  3721. "to Python scalars")
  3722. elif self._mask:
  3723. raise MaskError('Cannot convert masked element to a Python int.')
  3724. return int(self.item())
  3725. @property
  3726. def imag(self):
  3727. """
  3728. The imaginary part of the masked array.
  3729. This property is a view on the imaginary part of this `MaskedArray`.
  3730. See Also
  3731. --------
  3732. real
  3733. Examples
  3734. --------
  3735. >>> x = np.ma.array([1+1.j, -2j, 3.45+1.6j], mask=[False, True, False])
  3736. >>> x.imag
  3737. masked_array(data=[1.0, --, 1.6],
  3738. mask=[False, True, False],
  3739. fill_value=1e+20)
  3740. """
  3741. result = self._data.imag.view(type(self))
  3742. result.__setmask__(self._mask)
  3743. return result
  3744. # kept for compatibility
  3745. get_imag = imag.fget
  3746. @property
  3747. def real(self):
  3748. """
  3749. The real part of the masked array.
  3750. This property is a view on the real part of this `MaskedArray`.
  3751. See Also
  3752. --------
  3753. imag
  3754. Examples
  3755. --------
  3756. >>> x = np.ma.array([1+1.j, -2j, 3.45+1.6j], mask=[False, True, False])
  3757. >>> x.real
  3758. masked_array(data=[1.0, --, 3.45],
  3759. mask=[False, True, False],
  3760. fill_value=1e+20)
  3761. """
  3762. result = self._data.real.view(type(self))
  3763. result.__setmask__(self._mask)
  3764. return result
  3765. # kept for compatibility
  3766. get_real = real.fget
  3767. def count(self, axis=None, keepdims=np._NoValue):
  3768. """
  3769. Count the non-masked elements of the array along the given axis.
  3770. Parameters
  3771. ----------
  3772. axis : None or int or tuple of ints, optional
  3773. Axis or axes along which the count is performed.
  3774. The default, None, performs the count over all
  3775. the dimensions of the input array. `axis` may be negative, in
  3776. which case it counts from the last to the first axis.
  3777. .. versionadded:: 1.10.0
  3778. If this is a tuple of ints, the count is performed on multiple
  3779. axes, instead of a single axis or all the axes as before.
  3780. keepdims : bool, optional
  3781. If this is set to True, the axes which are reduced are left
  3782. in the result as dimensions with size one. With this option,
  3783. the result will broadcast correctly against the array.
  3784. Returns
  3785. -------
  3786. result : ndarray or scalar
  3787. An array with the same shape as the input array, with the specified
  3788. axis removed. If the array is a 0-d array, or if `axis` is None, a
  3789. scalar is returned.
  3790. See Also
  3791. --------
  3792. ma.count_masked : Count masked elements in array or along a given axis.
  3793. Examples
  3794. --------
  3795. >>> import numpy.ma as ma
  3796. >>> a = ma.arange(6).reshape((2, 3))
  3797. >>> a[1, :] = ma.masked
  3798. >>> a
  3799. masked_array(
  3800. data=[[0, 1, 2],
  3801. [--, --, --]],
  3802. mask=[[False, False, False],
  3803. [ True, True, True]],
  3804. fill_value=999999)
  3805. >>> a.count()
  3806. 3
  3807. When the `axis` keyword is specified an array of appropriate size is
  3808. returned.
  3809. >>> a.count(axis=0)
  3810. array([1, 1, 1])
  3811. >>> a.count(axis=1)
  3812. array([3, 0])
  3813. """
  3814. kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
  3815. m = self._mask
  3816. # special case for matrices (we assume no other subclasses modify
  3817. # their dimensions)
  3818. if isinstance(self.data, np.matrix):
  3819. if m is nomask:
  3820. m = np.zeros(self.shape, dtype=np.bool_)
  3821. m = m.view(type(self.data))
  3822. if m is nomask:
  3823. # compare to _count_reduce_items in _methods.py
  3824. if self.shape == ():
  3825. if axis not in (None, 0):
  3826. raise np.AxisError(axis=axis, ndim=self.ndim)
  3827. return 1
  3828. elif axis is None:
  3829. if kwargs.get('keepdims', False):
  3830. return np.array(self.size, dtype=np.intp, ndmin=self.ndim)
  3831. return self.size
  3832. axes = normalize_axis_tuple(axis, self.ndim)
  3833. items = 1
  3834. for ax in axes:
  3835. items *= self.shape[ax]
  3836. if kwargs.get('keepdims', False):
  3837. out_dims = list(self.shape)
  3838. for a in axes:
  3839. out_dims[a] = 1
  3840. else:
  3841. out_dims = [d for n, d in enumerate(self.shape)
  3842. if n not in axes]
  3843. # make sure to return a 0-d array if axis is supplied
  3844. return np.full(out_dims, items, dtype=np.intp)
  3845. # take care of the masked singleton
  3846. if self is masked:
  3847. return 0
  3848. return (~m).sum(axis=axis, dtype=np.intp, **kwargs)
  3849. def ravel(self, order='C'):
  3850. """
  3851. Returns a 1D version of self, as a view.
  3852. Parameters
  3853. ----------
  3854. order : {'C', 'F', 'A', 'K'}, optional
  3855. The elements of `a` are read using this index order. 'C' means to
  3856. index the elements in C-like order, with the last axis index
  3857. changing fastest, back to the first axis index changing slowest.
  3858. 'F' means to index the elements in Fortran-like index order, with
  3859. the first index changing fastest, and the last index changing
  3860. slowest. Note that the 'C' and 'F' options take no account of the
  3861. memory layout of the underlying array, and only refer to the order
  3862. of axis indexing. 'A' means to read the elements in Fortran-like
  3863. index order if `m` is Fortran *contiguous* in memory, C-like order
  3864. otherwise. 'K' means to read the elements in the order they occur
  3865. in memory, except for reversing the data when strides are negative.
  3866. By default, 'C' index order is used.
  3867. (Masked arrays currently use 'A' on the data when 'K' is passed.)
  3868. Returns
  3869. -------
  3870. MaskedArray
  3871. Output view is of shape ``(self.size,)`` (or
  3872. ``(np.ma.product(self.shape),)``).
  3873. Examples
  3874. --------
  3875. >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4)
  3876. >>> x
  3877. masked_array(
  3878. data=[[1, --, 3],
  3879. [--, 5, --],
  3880. [7, --, 9]],
  3881. mask=[[False, True, False],
  3882. [ True, False, True],
  3883. [False, True, False]],
  3884. fill_value=999999)
  3885. >>> x.ravel()
  3886. masked_array(data=[1, --, 3, --, 5, --, 7, --, 9],
  3887. mask=[False, True, False, True, False, True, False, True,
  3888. False],
  3889. fill_value=999999)
  3890. """
  3891. # The order of _data and _mask could be different (it shouldn't be
  3892. # normally). Passing order `K` or `A` would be incorrect.
  3893. # So we ignore the mask memory order.
  3894. # TODO: We don't actually support K, so use A instead. We could
  3895. # try to guess this correct by sorting strides or deprecate.
  3896. if order in "kKaA":
  3897. order = "F" if self._data.flags.fnc else "C"
  3898. r = ndarray.ravel(self._data, order=order).view(type(self))
  3899. r._update_from(self)
  3900. if self._mask is not nomask:
  3901. r._mask = ndarray.ravel(self._mask, order=order).reshape(r.shape)
  3902. else:
  3903. r._mask = nomask
  3904. return r
  3905. def reshape(self, *s, **kwargs):
  3906. """
  3907. Give a new shape to the array without changing its data.
  3908. Returns a masked array containing the same data, but with a new shape.
  3909. The result is a view on the original array; if this is not possible, a
  3910. ValueError is raised.
  3911. Parameters
  3912. ----------
  3913. shape : int or tuple of ints
  3914. The new shape should be compatible with the original shape. If an
  3915. integer is supplied, then the result will be a 1-D array of that
  3916. length.
  3917. order : {'C', 'F'}, optional
  3918. Determines whether the array data should be viewed as in C
  3919. (row-major) or FORTRAN (column-major) order.
  3920. Returns
  3921. -------
  3922. reshaped_array : array
  3923. A new view on the array.
  3924. See Also
  3925. --------
  3926. reshape : Equivalent function in the masked array module.
  3927. numpy.ndarray.reshape : Equivalent method on ndarray object.
  3928. numpy.reshape : Equivalent function in the NumPy module.
  3929. Notes
  3930. -----
  3931. The reshaping operation cannot guarantee that a copy will not be made,
  3932. to modify the shape in place, use ``a.shape = s``
  3933. Examples
  3934. --------
  3935. >>> x = np.ma.array([[1,2],[3,4]], mask=[1,0,0,1])
  3936. >>> x
  3937. masked_array(
  3938. data=[[--, 2],
  3939. [3, --]],
  3940. mask=[[ True, False],
  3941. [False, True]],
  3942. fill_value=999999)
  3943. >>> x = x.reshape((4,1))
  3944. >>> x
  3945. masked_array(
  3946. data=[[--],
  3947. [2],
  3948. [3],
  3949. [--]],
  3950. mask=[[ True],
  3951. [False],
  3952. [False],
  3953. [ True]],
  3954. fill_value=999999)
  3955. """
  3956. kwargs.update(order=kwargs.get('order', 'C'))
  3957. result = self._data.reshape(*s, **kwargs).view(type(self))
  3958. result._update_from(self)
  3959. mask = self._mask
  3960. if mask is not nomask:
  3961. result._mask = mask.reshape(*s, **kwargs)
  3962. return result
  3963. def resize(self, newshape, refcheck=True, order=False):
  3964. """
  3965. .. warning::
  3966. This method does nothing, except raise a ValueError exception. A
  3967. masked array does not own its data and therefore cannot safely be
  3968. resized in place. Use the `numpy.ma.resize` function instead.
  3969. This method is difficult to implement safely and may be deprecated in
  3970. future releases of NumPy.
  3971. """
  3972. # Note : the 'order' keyword looks broken, let's just drop it
  3973. errmsg = "A masked array does not own its data "\
  3974. "and therefore cannot be resized.\n" \
  3975. "Use the numpy.ma.resize function instead."
  3976. raise ValueError(errmsg)
  3977. def put(self, indices, values, mode='raise'):
  3978. """
  3979. Set storage-indexed locations to corresponding values.
  3980. Sets self._data.flat[n] = values[n] for each n in indices.
  3981. If `values` is shorter than `indices` then it will repeat.
  3982. If `values` has some masked values, the initial mask is updated
  3983. in consequence, else the corresponding values are unmasked.
  3984. Parameters
  3985. ----------
  3986. indices : 1-D array_like
  3987. Target indices, interpreted as integers.
  3988. values : array_like
  3989. Values to place in self._data copy at target indices.
  3990. mode : {'raise', 'wrap', 'clip'}, optional
  3991. Specifies how out-of-bounds indices will behave.
  3992. 'raise' : raise an error.
  3993. 'wrap' : wrap around.
  3994. 'clip' : clip to the range.
  3995. Notes
  3996. -----
  3997. `values` can be a scalar or length 1 array.
  3998. Examples
  3999. --------
  4000. >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4)
  4001. >>> x
  4002. masked_array(
  4003. data=[[1, --, 3],
  4004. [--, 5, --],
  4005. [7, --, 9]],
  4006. mask=[[False, True, False],
  4007. [ True, False, True],
  4008. [False, True, False]],
  4009. fill_value=999999)
  4010. >>> x.put([0,4,8],[10,20,30])
  4011. >>> x
  4012. masked_array(
  4013. data=[[10, --, 3],
  4014. [--, 20, --],
  4015. [7, --, 30]],
  4016. mask=[[False, True, False],
  4017. [ True, False, True],
  4018. [False, True, False]],
  4019. fill_value=999999)
  4020. >>> x.put(4,999)
  4021. >>> x
  4022. masked_array(
  4023. data=[[10, --, 3],
  4024. [--, 999, --],
  4025. [7, --, 30]],
  4026. mask=[[False, True, False],
  4027. [ True, False, True],
  4028. [False, True, False]],
  4029. fill_value=999999)
  4030. """
  4031. # Hard mask: Get rid of the values/indices that fall on masked data
  4032. if self._hardmask and self._mask is not nomask:
  4033. mask = self._mask[indices]
  4034. indices = narray(indices, copy=False)
  4035. values = narray(values, copy=False, subok=True)
  4036. values.resize(indices.shape)
  4037. indices = indices[~mask]
  4038. values = values[~mask]
  4039. self._data.put(indices, values, mode=mode)
  4040. # short circuit if neither self nor values are masked
  4041. if self._mask is nomask and getmask(values) is nomask:
  4042. return
  4043. m = getmaskarray(self)
  4044. if getmask(values) is nomask:
  4045. m.put(indices, False, mode=mode)
  4046. else:
  4047. m.put(indices, values._mask, mode=mode)
  4048. m = make_mask(m, copy=False, shrink=True)
  4049. self._mask = m
  4050. return
  4051. def ids(self):
  4052. """
  4053. Return the addresses of the data and mask areas.
  4054. Parameters
  4055. ----------
  4056. None
  4057. Examples
  4058. --------
  4059. >>> x = np.ma.array([1, 2, 3], mask=[0, 1, 1])
  4060. >>> x.ids()
  4061. (166670640, 166659832) # may vary
  4062. If the array has no mask, the address of `nomask` is returned. This address
  4063. is typically not close to the data in memory:
  4064. >>> x = np.ma.array([1, 2, 3])
  4065. >>> x.ids()
  4066. (166691080, 3083169284) # may vary
  4067. """
  4068. if self._mask is nomask:
  4069. return (self.ctypes.data, id(nomask))
  4070. return (self.ctypes.data, self._mask.ctypes.data)
  4071. def iscontiguous(self):
  4072. """
  4073. Return a boolean indicating whether the data is contiguous.
  4074. Parameters
  4075. ----------
  4076. None
  4077. Examples
  4078. --------
  4079. >>> x = np.ma.array([1, 2, 3])
  4080. >>> x.iscontiguous()
  4081. True
  4082. `iscontiguous` returns one of the flags of the masked array:
  4083. >>> x.flags
  4084. C_CONTIGUOUS : True
  4085. F_CONTIGUOUS : True
  4086. OWNDATA : False
  4087. WRITEABLE : True
  4088. ALIGNED : True
  4089. WRITEBACKIFCOPY : False
  4090. """
  4091. return self.flags['CONTIGUOUS']
  4092. def all(self, axis=None, out=None, keepdims=np._NoValue):
  4093. """
  4094. Returns True if all elements evaluate to True.
  4095. The output array is masked where all the values along the given axis
  4096. are masked: if the output would have been a scalar and that all the
  4097. values are masked, then the output is `masked`.
  4098. Refer to `numpy.all` for full documentation.
  4099. See Also
  4100. --------
  4101. numpy.ndarray.all : corresponding function for ndarrays
  4102. numpy.all : equivalent function
  4103. Examples
  4104. --------
  4105. >>> np.ma.array([1,2,3]).all()
  4106. True
  4107. >>> a = np.ma.array([1,2,3], mask=True)
  4108. >>> (a.all() is np.ma.masked)
  4109. True
  4110. """
  4111. kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
  4112. mask = _check_mask_axis(self._mask, axis, **kwargs)
  4113. if out is None:
  4114. d = self.filled(True).all(axis=axis, **kwargs).view(type(self))
  4115. if d.ndim:
  4116. d.__setmask__(mask)
  4117. elif mask:
  4118. return masked
  4119. return d
  4120. self.filled(True).all(axis=axis, out=out, **kwargs)
  4121. if isinstance(out, MaskedArray):
  4122. if out.ndim or mask:
  4123. out.__setmask__(mask)
  4124. return out
  4125. def any(self, axis=None, out=None, keepdims=np._NoValue):
  4126. """
  4127. Returns True if any of the elements of `a` evaluate to True.
  4128. Masked values are considered as False during computation.
  4129. Refer to `numpy.any` for full documentation.
  4130. See Also
  4131. --------
  4132. numpy.ndarray.any : corresponding function for ndarrays
  4133. numpy.any : equivalent function
  4134. """
  4135. kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
  4136. mask = _check_mask_axis(self._mask, axis, **kwargs)
  4137. if out is None:
  4138. d = self.filled(False).any(axis=axis, **kwargs).view(type(self))
  4139. if d.ndim:
  4140. d.__setmask__(mask)
  4141. elif mask:
  4142. d = masked
  4143. return d
  4144. self.filled(False).any(axis=axis, out=out, **kwargs)
  4145. if isinstance(out, MaskedArray):
  4146. if out.ndim or mask:
  4147. out.__setmask__(mask)
  4148. return out
  4149. def nonzero(self):
  4150. """
  4151. Return the indices of unmasked elements that are not zero.
  4152. Returns a tuple of arrays, one for each dimension, containing the
  4153. indices of the non-zero elements in that dimension. The corresponding
  4154. non-zero values can be obtained with::
  4155. a[a.nonzero()]
  4156. To group the indices by element, rather than dimension, use
  4157. instead::
  4158. np.transpose(a.nonzero())
  4159. The result of this is always a 2d array, with a row for each non-zero
  4160. element.
  4161. Parameters
  4162. ----------
  4163. None
  4164. Returns
  4165. -------
  4166. tuple_of_arrays : tuple
  4167. Indices of elements that are non-zero.
  4168. See Also
  4169. --------
  4170. numpy.nonzero :
  4171. Function operating on ndarrays.
  4172. flatnonzero :
  4173. Return indices that are non-zero in the flattened version of the input
  4174. array.
  4175. numpy.ndarray.nonzero :
  4176. Equivalent ndarray method.
  4177. count_nonzero :
  4178. Counts the number of non-zero elements in the input array.
  4179. Examples
  4180. --------
  4181. >>> import numpy.ma as ma
  4182. >>> x = ma.array(np.eye(3))
  4183. >>> x
  4184. masked_array(
  4185. data=[[1., 0., 0.],
  4186. [0., 1., 0.],
  4187. [0., 0., 1.]],
  4188. mask=False,
  4189. fill_value=1e+20)
  4190. >>> x.nonzero()
  4191. (array([0, 1, 2]), array([0, 1, 2]))
  4192. Masked elements are ignored.
  4193. >>> x[1, 1] = ma.masked
  4194. >>> x
  4195. masked_array(
  4196. data=[[1.0, 0.0, 0.0],
  4197. [0.0, --, 0.0],
  4198. [0.0, 0.0, 1.0]],
  4199. mask=[[False, False, False],
  4200. [False, True, False],
  4201. [False, False, False]],
  4202. fill_value=1e+20)
  4203. >>> x.nonzero()
  4204. (array([0, 2]), array([0, 2]))
  4205. Indices can also be grouped by element.
  4206. >>> np.transpose(x.nonzero())
  4207. array([[0, 0],
  4208. [2, 2]])
  4209. A common use for ``nonzero`` is to find the indices of an array, where
  4210. a condition is True. Given an array `a`, the condition `a` > 3 is a
  4211. boolean array and since False is interpreted as 0, ma.nonzero(a > 3)
  4212. yields the indices of the `a` where the condition is true.
  4213. >>> a = ma.array([[1,2,3],[4,5,6],[7,8,9]])
  4214. >>> a > 3
  4215. masked_array(
  4216. data=[[False, False, False],
  4217. [ True, True, True],
  4218. [ True, True, True]],
  4219. mask=False,
  4220. fill_value=True)
  4221. >>> ma.nonzero(a > 3)
  4222. (array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2]))
  4223. The ``nonzero`` method of the condition array can also be called.
  4224. >>> (a > 3).nonzero()
  4225. (array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2]))
  4226. """
  4227. return narray(self.filled(0), copy=False).nonzero()
  4228. def trace(self, offset=0, axis1=0, axis2=1, dtype=None, out=None):
  4229. """
  4230. (this docstring should be overwritten)
  4231. """
  4232. #!!!: implement out + test!
  4233. m = self._mask
  4234. if m is nomask:
  4235. result = super().trace(offset=offset, axis1=axis1, axis2=axis2,
  4236. out=out)
  4237. return result.astype(dtype)
  4238. else:
  4239. D = self.diagonal(offset=offset, axis1=axis1, axis2=axis2)
  4240. return D.astype(dtype).filled(0).sum(axis=-1, out=out)
  4241. trace.__doc__ = ndarray.trace.__doc__
  4242. def dot(self, b, out=None, strict=False):
  4243. """
  4244. a.dot(b, out=None)
  4245. Masked dot product of two arrays. Note that `out` and `strict` are
  4246. located in different positions than in `ma.dot`. In order to
  4247. maintain compatibility with the functional version, it is
  4248. recommended that the optional arguments be treated as keyword only.
  4249. At some point that may be mandatory.
  4250. .. versionadded:: 1.10.0
  4251. Parameters
  4252. ----------
  4253. b : masked_array_like
  4254. Inputs array.
  4255. out : masked_array, optional
  4256. Output argument. This must have the exact kind that would be
  4257. returned if it was not used. In particular, it must have the
  4258. right type, must be C-contiguous, and its dtype must be the
  4259. dtype that would be returned for `ma.dot(a,b)`. This is a
  4260. performance feature. Therefore, if these conditions are not
  4261. met, an exception is raised, instead of attempting to be
  4262. flexible.
  4263. strict : bool, optional
  4264. Whether masked data are propagated (True) or set to 0 (False)
  4265. for the computation. Default is False. Propagating the mask
  4266. means that if a masked value appears in a row or column, the
  4267. whole row or column is considered masked.
  4268. .. versionadded:: 1.10.2
  4269. See Also
  4270. --------
  4271. numpy.ma.dot : equivalent function
  4272. """
  4273. return dot(self, b, out=out, strict=strict)
  4274. def sum(self, axis=None, dtype=None, out=None, keepdims=np._NoValue):
  4275. """
  4276. Return the sum of the array elements over the given axis.
  4277. Masked elements are set to 0 internally.
  4278. Refer to `numpy.sum` for full documentation.
  4279. See Also
  4280. --------
  4281. numpy.ndarray.sum : corresponding function for ndarrays
  4282. numpy.sum : equivalent function
  4283. Examples
  4284. --------
  4285. >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4)
  4286. >>> x
  4287. masked_array(
  4288. data=[[1, --, 3],
  4289. [--, 5, --],
  4290. [7, --, 9]],
  4291. mask=[[False, True, False],
  4292. [ True, False, True],
  4293. [False, True, False]],
  4294. fill_value=999999)
  4295. >>> x.sum()
  4296. 25
  4297. >>> x.sum(axis=1)
  4298. masked_array(data=[4, 5, 16],
  4299. mask=[False, False, False],
  4300. fill_value=999999)
  4301. >>> x.sum(axis=0)
  4302. masked_array(data=[8, 5, 12],
  4303. mask=[False, False, False],
  4304. fill_value=999999)
  4305. >>> print(type(x.sum(axis=0, dtype=np.int64)[0]))
  4306. <class 'numpy.int64'>
  4307. """
  4308. kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
  4309. _mask = self._mask
  4310. newmask = _check_mask_axis(_mask, axis, **kwargs)
  4311. # No explicit output
  4312. if out is None:
  4313. result = self.filled(0).sum(axis, dtype=dtype, **kwargs)
  4314. rndim = getattr(result, 'ndim', 0)
  4315. if rndim:
  4316. result = result.view(type(self))
  4317. result.__setmask__(newmask)
  4318. elif newmask:
  4319. result = masked
  4320. return result
  4321. # Explicit output
  4322. result = self.filled(0).sum(axis, dtype=dtype, out=out, **kwargs)
  4323. if isinstance(out, MaskedArray):
  4324. outmask = getmask(out)
  4325. if outmask is nomask:
  4326. outmask = out._mask = make_mask_none(out.shape)
  4327. outmask.flat = newmask
  4328. return out
  4329. def cumsum(self, axis=None, dtype=None, out=None):
  4330. """
  4331. Return the cumulative sum of the array elements over the given axis.
  4332. Masked values are set to 0 internally during the computation.
  4333. However, their position is saved, and the result will be masked at
  4334. the same locations.
  4335. Refer to `numpy.cumsum` for full documentation.
  4336. Notes
  4337. -----
  4338. The mask is lost if `out` is not a valid :class:`ma.MaskedArray` !
  4339. Arithmetic is modular when using integer types, and no error is
  4340. raised on overflow.
  4341. See Also
  4342. --------
  4343. numpy.ndarray.cumsum : corresponding function for ndarrays
  4344. numpy.cumsum : equivalent function
  4345. Examples
  4346. --------
  4347. >>> marr = np.ma.array(np.arange(10), mask=[0,0,0,1,1,1,0,0,0,0])
  4348. >>> marr.cumsum()
  4349. masked_array(data=[0, 1, 3, --, --, --, 9, 16, 24, 33],
  4350. mask=[False, False, False, True, True, True, False, False,
  4351. False, False],
  4352. fill_value=999999)
  4353. """
  4354. result = self.filled(0).cumsum(axis=axis, dtype=dtype, out=out)
  4355. if out is not None:
  4356. if isinstance(out, MaskedArray):
  4357. out.__setmask__(self.mask)
  4358. return out
  4359. result = result.view(type(self))
  4360. result.__setmask__(self._mask)
  4361. return result
  4362. def prod(self, axis=None, dtype=None, out=None, keepdims=np._NoValue):
  4363. """
  4364. Return the product of the array elements over the given axis.
  4365. Masked elements are set to 1 internally for computation.
  4366. Refer to `numpy.prod` for full documentation.
  4367. Notes
  4368. -----
  4369. Arithmetic is modular when using integer types, and no error is raised
  4370. on overflow.
  4371. See Also
  4372. --------
  4373. numpy.ndarray.prod : corresponding function for ndarrays
  4374. numpy.prod : equivalent function
  4375. """
  4376. kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
  4377. _mask = self._mask
  4378. newmask = _check_mask_axis(_mask, axis, **kwargs)
  4379. # No explicit output
  4380. if out is None:
  4381. result = self.filled(1).prod(axis, dtype=dtype, **kwargs)
  4382. rndim = getattr(result, 'ndim', 0)
  4383. if rndim:
  4384. result = result.view(type(self))
  4385. result.__setmask__(newmask)
  4386. elif newmask:
  4387. result = masked
  4388. return result
  4389. # Explicit output
  4390. result = self.filled(1).prod(axis, dtype=dtype, out=out, **kwargs)
  4391. if isinstance(out, MaskedArray):
  4392. outmask = getmask(out)
  4393. if outmask is nomask:
  4394. outmask = out._mask = make_mask_none(out.shape)
  4395. outmask.flat = newmask
  4396. return out
  4397. product = prod
  4398. def cumprod(self, axis=None, dtype=None, out=None):
  4399. """
  4400. Return the cumulative product of the array elements over the given axis.
  4401. Masked values are set to 1 internally during the computation.
  4402. However, their position is saved, and the result will be masked at
  4403. the same locations.
  4404. Refer to `numpy.cumprod` for full documentation.
  4405. Notes
  4406. -----
  4407. The mask is lost if `out` is not a valid MaskedArray !
  4408. Arithmetic is modular when using integer types, and no error is
  4409. raised on overflow.
  4410. See Also
  4411. --------
  4412. numpy.ndarray.cumprod : corresponding function for ndarrays
  4413. numpy.cumprod : equivalent function
  4414. """
  4415. result = self.filled(1).cumprod(axis=axis, dtype=dtype, out=out)
  4416. if out is not None:
  4417. if isinstance(out, MaskedArray):
  4418. out.__setmask__(self._mask)
  4419. return out
  4420. result = result.view(type(self))
  4421. result.__setmask__(self._mask)
  4422. return result
  4423. def mean(self, axis=None, dtype=None, out=None, keepdims=np._NoValue):
  4424. """
  4425. Returns the average of the array elements along given axis.
  4426. Masked entries are ignored, and result elements which are not
  4427. finite will be masked.
  4428. Refer to `numpy.mean` for full documentation.
  4429. See Also
  4430. --------
  4431. numpy.ndarray.mean : corresponding function for ndarrays
  4432. numpy.mean : Equivalent function
  4433. numpy.ma.average : Weighted average.
  4434. Examples
  4435. --------
  4436. >>> a = np.ma.array([1,2,3], mask=[False, False, True])
  4437. >>> a
  4438. masked_array(data=[1, 2, --],
  4439. mask=[False, False, True],
  4440. fill_value=999999)
  4441. >>> a.mean()
  4442. 1.5
  4443. """
  4444. kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
  4445. if self._mask is nomask:
  4446. result = super().mean(axis=axis, dtype=dtype, **kwargs)[()]
  4447. else:
  4448. is_float16_result = False
  4449. if dtype is None:
  4450. if issubclass(self.dtype.type, (ntypes.integer, ntypes.bool_)):
  4451. dtype = mu.dtype('f8')
  4452. elif issubclass(self.dtype.type, ntypes.float16):
  4453. dtype = mu.dtype('f4')
  4454. is_float16_result = True
  4455. dsum = self.sum(axis=axis, dtype=dtype, **kwargs)
  4456. cnt = self.count(axis=axis, **kwargs)
  4457. if cnt.shape == () and (cnt == 0):
  4458. result = masked
  4459. elif is_float16_result:
  4460. result = self.dtype.type(dsum * 1. / cnt)
  4461. else:
  4462. result = dsum * 1. / cnt
  4463. if out is not None:
  4464. out.flat = result
  4465. if isinstance(out, MaskedArray):
  4466. outmask = getmask(out)
  4467. if outmask is nomask:
  4468. outmask = out._mask = make_mask_none(out.shape)
  4469. outmask.flat = getmask(result)
  4470. return out
  4471. return result
  4472. def anom(self, axis=None, dtype=None):
  4473. """
  4474. Compute the anomalies (deviations from the arithmetic mean)
  4475. along the given axis.
  4476. Returns an array of anomalies, with the same shape as the input and
  4477. where the arithmetic mean is computed along the given axis.
  4478. Parameters
  4479. ----------
  4480. axis : int, optional
  4481. Axis over which the anomalies are taken.
  4482. The default is to use the mean of the flattened array as reference.
  4483. dtype : dtype, optional
  4484. Type to use in computing the variance. For arrays of integer type
  4485. the default is float32; for arrays of float types it is the same as
  4486. the array type.
  4487. See Also
  4488. --------
  4489. mean : Compute the mean of the array.
  4490. Examples
  4491. --------
  4492. >>> a = np.ma.array([1,2,3])
  4493. >>> a.anom()
  4494. masked_array(data=[-1., 0., 1.],
  4495. mask=False,
  4496. fill_value=1e+20)
  4497. """
  4498. m = self.mean(axis, dtype)
  4499. if not axis:
  4500. return self - m
  4501. else:
  4502. return self - expand_dims(m, axis)
  4503. def var(self, axis=None, dtype=None, out=None, ddof=0,
  4504. keepdims=np._NoValue):
  4505. """
  4506. Returns the variance of the array elements along given axis.
  4507. Masked entries are ignored, and result elements which are not
  4508. finite will be masked.
  4509. Refer to `numpy.var` for full documentation.
  4510. See Also
  4511. --------
  4512. numpy.ndarray.var : corresponding function for ndarrays
  4513. numpy.var : Equivalent function
  4514. """
  4515. kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
  4516. # Easy case: nomask, business as usual
  4517. if self._mask is nomask:
  4518. ret = super().var(axis=axis, dtype=dtype, out=out, ddof=ddof,
  4519. **kwargs)[()]
  4520. if out is not None:
  4521. if isinstance(out, MaskedArray):
  4522. out.__setmask__(nomask)
  4523. return out
  4524. return ret
  4525. # Some data are masked, yay!
  4526. cnt = self.count(axis=axis, **kwargs) - ddof
  4527. danom = self - self.mean(axis, dtype, keepdims=True)
  4528. if iscomplexobj(self):
  4529. danom = umath.absolute(danom) ** 2
  4530. else:
  4531. danom *= danom
  4532. dvar = divide(danom.sum(axis, **kwargs), cnt).view(type(self))
  4533. # Apply the mask if it's not a scalar
  4534. if dvar.ndim:
  4535. dvar._mask = mask_or(self._mask.all(axis, **kwargs), (cnt <= 0))
  4536. dvar._update_from(self)
  4537. elif getmask(dvar):
  4538. # Make sure that masked is returned when the scalar is masked.
  4539. dvar = masked
  4540. if out is not None:
  4541. if isinstance(out, MaskedArray):
  4542. out.flat = 0
  4543. out.__setmask__(True)
  4544. elif out.dtype.kind in 'biu':
  4545. errmsg = "Masked data information would be lost in one or "\
  4546. "more location."
  4547. raise MaskError(errmsg)
  4548. else:
  4549. out.flat = np.nan
  4550. return out
  4551. # In case with have an explicit output
  4552. if out is not None:
  4553. # Set the data
  4554. out.flat = dvar
  4555. # Set the mask if needed
  4556. if isinstance(out, MaskedArray):
  4557. out.__setmask__(dvar.mask)
  4558. return out
  4559. return dvar
  4560. var.__doc__ = np.var.__doc__
  4561. def std(self, axis=None, dtype=None, out=None, ddof=0,
  4562. keepdims=np._NoValue):
  4563. """
  4564. Returns the standard deviation of the array elements along given axis.
  4565. Masked entries are ignored.
  4566. Refer to `numpy.std` for full documentation.
  4567. See Also
  4568. --------
  4569. numpy.ndarray.std : corresponding function for ndarrays
  4570. numpy.std : Equivalent function
  4571. """
  4572. kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
  4573. dvar = self.var(axis, dtype, out, ddof, **kwargs)
  4574. if dvar is not masked:
  4575. if out is not None:
  4576. np.power(out, 0.5, out=out, casting='unsafe')
  4577. return out
  4578. dvar = sqrt(dvar)
  4579. return dvar
  4580. def round(self, decimals=0, out=None):
  4581. """
  4582. Return each element rounded to the given number of decimals.
  4583. Refer to `numpy.around` for full documentation.
  4584. See Also
  4585. --------
  4586. numpy.ndarray.round : corresponding function for ndarrays
  4587. numpy.around : equivalent function
  4588. """
  4589. result = self._data.round(decimals=decimals, out=out).view(type(self))
  4590. if result.ndim > 0:
  4591. result._mask = self._mask
  4592. result._update_from(self)
  4593. elif self._mask:
  4594. # Return masked when the scalar is masked
  4595. result = masked
  4596. # No explicit output: we're done
  4597. if out is None:
  4598. return result
  4599. if isinstance(out, MaskedArray):
  4600. out.__setmask__(self._mask)
  4601. return out
  4602. def argsort(self, axis=np._NoValue, kind=None, order=None,
  4603. endwith=True, fill_value=None):
  4604. """
  4605. Return an ndarray of indices that sort the array along the
  4606. specified axis. Masked values are filled beforehand to
  4607. `fill_value`.
  4608. Parameters
  4609. ----------
  4610. axis : int, optional
  4611. Axis along which to sort. If None, the default, the flattened array
  4612. is used.
  4613. .. versionchanged:: 1.13.0
  4614. Previously, the default was documented to be -1, but that was
  4615. in error. At some future date, the default will change to -1, as
  4616. originally intended.
  4617. Until then, the axis should be given explicitly when
  4618. ``arr.ndim > 1``, to avoid a FutureWarning.
  4619. kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional
  4620. The sorting algorithm used.
  4621. order : list, optional
  4622. When `a` is an array with fields defined, this argument specifies
  4623. which fields to compare first, second, etc. Not all fields need be
  4624. specified.
  4625. endwith : {True, False}, optional
  4626. Whether missing values (if any) should be treated as the largest values
  4627. (True) or the smallest values (False)
  4628. When the array contains unmasked values at the same extremes of the
  4629. datatype, the ordering of these values and the masked values is
  4630. undefined.
  4631. fill_value : scalar or None, optional
  4632. Value used internally for the masked values.
  4633. If ``fill_value`` is not None, it supersedes ``endwith``.
  4634. Returns
  4635. -------
  4636. index_array : ndarray, int
  4637. Array of indices that sort `a` along the specified axis.
  4638. In other words, ``a[index_array]`` yields a sorted `a`.
  4639. See Also
  4640. --------
  4641. ma.MaskedArray.sort : Describes sorting algorithms used.
  4642. lexsort : Indirect stable sort with multiple keys.
  4643. numpy.ndarray.sort : Inplace sort.
  4644. Notes
  4645. -----
  4646. See `sort` for notes on the different sorting algorithms.
  4647. Examples
  4648. --------
  4649. >>> a = np.ma.array([3,2,1], mask=[False, False, True])
  4650. >>> a
  4651. masked_array(data=[3, 2, --],
  4652. mask=[False, False, True],
  4653. fill_value=999999)
  4654. >>> a.argsort()
  4655. array([1, 0, 2])
  4656. """
  4657. # 2017-04-11, Numpy 1.13.0, gh-8701: warn on axis default
  4658. if axis is np._NoValue:
  4659. axis = _deprecate_argsort_axis(self)
  4660. if fill_value is None:
  4661. if endwith:
  4662. # nan > inf
  4663. if np.issubdtype(self.dtype, np.floating):
  4664. fill_value = np.nan
  4665. else:
  4666. fill_value = minimum_fill_value(self)
  4667. else:
  4668. fill_value = maximum_fill_value(self)
  4669. filled = self.filled(fill_value)
  4670. return filled.argsort(axis=axis, kind=kind, order=order)
  4671. def argmin(self, axis=None, fill_value=None, out=None, *,
  4672. keepdims=np._NoValue):
  4673. """
  4674. Return array of indices to the minimum values along the given axis.
  4675. Parameters
  4676. ----------
  4677. axis : {None, integer}
  4678. If None, the index is into the flattened array, otherwise along
  4679. the specified axis
  4680. fill_value : scalar or None, optional
  4681. Value used to fill in the masked values. If None, the output of
  4682. minimum_fill_value(self._data) is used instead.
  4683. out : {None, array}, optional
  4684. Array into which the result can be placed. Its type is preserved
  4685. and it must be of the right shape to hold the output.
  4686. Returns
  4687. -------
  4688. ndarray or scalar
  4689. If multi-dimension input, returns a new ndarray of indices to the
  4690. minimum values along the given axis. Otherwise, returns a scalar
  4691. of index to the minimum values along the given axis.
  4692. Examples
  4693. --------
  4694. >>> x = np.ma.array(np.arange(4), mask=[1,1,0,0])
  4695. >>> x.shape = (2,2)
  4696. >>> x
  4697. masked_array(
  4698. data=[[--, --],
  4699. [2, 3]],
  4700. mask=[[ True, True],
  4701. [False, False]],
  4702. fill_value=999999)
  4703. >>> x.argmin(axis=0, fill_value=-1)
  4704. array([0, 0])
  4705. >>> x.argmin(axis=0, fill_value=9)
  4706. array([1, 1])
  4707. """
  4708. if fill_value is None:
  4709. fill_value = minimum_fill_value(self)
  4710. d = self.filled(fill_value).view(ndarray)
  4711. keepdims = False if keepdims is np._NoValue else bool(keepdims)
  4712. return d.argmin(axis, out=out, keepdims=keepdims)
  4713. def argmax(self, axis=None, fill_value=None, out=None, *,
  4714. keepdims=np._NoValue):
  4715. """
  4716. Returns array of indices of the maximum values along the given axis.
  4717. Masked values are treated as if they had the value fill_value.
  4718. Parameters
  4719. ----------
  4720. axis : {None, integer}
  4721. If None, the index is into the flattened array, otherwise along
  4722. the specified axis
  4723. fill_value : scalar or None, optional
  4724. Value used to fill in the masked values. If None, the output of
  4725. maximum_fill_value(self._data) is used instead.
  4726. out : {None, array}, optional
  4727. Array into which the result can be placed. Its type is preserved
  4728. and it must be of the right shape to hold the output.
  4729. Returns
  4730. -------
  4731. index_array : {integer_array}
  4732. Examples
  4733. --------
  4734. >>> a = np.arange(6).reshape(2,3)
  4735. >>> a.argmax()
  4736. 5
  4737. >>> a.argmax(0)
  4738. array([1, 1, 1])
  4739. >>> a.argmax(1)
  4740. array([2, 2])
  4741. """
  4742. if fill_value is None:
  4743. fill_value = maximum_fill_value(self._data)
  4744. d = self.filled(fill_value).view(ndarray)
  4745. keepdims = False if keepdims is np._NoValue else bool(keepdims)
  4746. return d.argmax(axis, out=out, keepdims=keepdims)
  4747. def sort(self, axis=-1, kind=None, order=None,
  4748. endwith=True, fill_value=None):
  4749. """
  4750. Sort the array, in-place
  4751. Parameters
  4752. ----------
  4753. a : array_like
  4754. Array to be sorted.
  4755. axis : int, optional
  4756. Axis along which to sort. If None, the array is flattened before
  4757. sorting. The default is -1, which sorts along the last axis.
  4758. kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional
  4759. The sorting algorithm used.
  4760. order : list, optional
  4761. When `a` is a structured array, this argument specifies which fields
  4762. to compare first, second, and so on. This list does not need to
  4763. include all of the fields.
  4764. endwith : {True, False}, optional
  4765. Whether missing values (if any) should be treated as the largest values
  4766. (True) or the smallest values (False)
  4767. When the array contains unmasked values sorting at the same extremes of the
  4768. datatype, the ordering of these values and the masked values is
  4769. undefined.
  4770. fill_value : scalar or None, optional
  4771. Value used internally for the masked values.
  4772. If ``fill_value`` is not None, it supersedes ``endwith``.
  4773. Returns
  4774. -------
  4775. sorted_array : ndarray
  4776. Array of the same type and shape as `a`.
  4777. See Also
  4778. --------
  4779. numpy.ndarray.sort : Method to sort an array in-place.
  4780. argsort : Indirect sort.
  4781. lexsort : Indirect stable sort on multiple keys.
  4782. searchsorted : Find elements in a sorted array.
  4783. Notes
  4784. -----
  4785. See ``sort`` for notes on the different sorting algorithms.
  4786. Examples
  4787. --------
  4788. >>> a = np.ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0])
  4789. >>> # Default
  4790. >>> a.sort()
  4791. >>> a
  4792. masked_array(data=[1, 3, 5, --, --],
  4793. mask=[False, False, False, True, True],
  4794. fill_value=999999)
  4795. >>> a = np.ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0])
  4796. >>> # Put missing values in the front
  4797. >>> a.sort(endwith=False)
  4798. >>> a
  4799. masked_array(data=[--, --, 1, 3, 5],
  4800. mask=[ True, True, False, False, False],
  4801. fill_value=999999)
  4802. >>> a = np.ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0])
  4803. >>> # fill_value takes over endwith
  4804. >>> a.sort(endwith=False, fill_value=3)
  4805. >>> a
  4806. masked_array(data=[1, --, --, 3, 5],
  4807. mask=[False, True, True, False, False],
  4808. fill_value=999999)
  4809. """
  4810. if self._mask is nomask:
  4811. ndarray.sort(self, axis=axis, kind=kind, order=order)
  4812. return
  4813. if self is masked:
  4814. return
  4815. sidx = self.argsort(axis=axis, kind=kind, order=order,
  4816. fill_value=fill_value, endwith=endwith)
  4817. self[...] = np.take_along_axis(self, sidx, axis=axis)
  4818. def min(self, axis=None, out=None, fill_value=None, keepdims=np._NoValue):
  4819. """
  4820. Return the minimum along a given axis.
  4821. Parameters
  4822. ----------
  4823. axis : None or int or tuple of ints, optional
  4824. Axis along which to operate. By default, ``axis`` is None and the
  4825. flattened input is used.
  4826. .. versionadded:: 1.7.0
  4827. If this is a tuple of ints, the minimum is selected over multiple
  4828. axes, instead of a single axis or all the axes as before.
  4829. out : array_like, optional
  4830. Alternative output array in which to place the result. Must be of
  4831. the same shape and buffer length as the expected output.
  4832. fill_value : scalar or None, optional
  4833. Value used to fill in the masked values.
  4834. If None, use the output of `minimum_fill_value`.
  4835. keepdims : bool, optional
  4836. If this is set to True, the axes which are reduced are left
  4837. in the result as dimensions with size one. With this option,
  4838. the result will broadcast correctly against the array.
  4839. Returns
  4840. -------
  4841. amin : array_like
  4842. New array holding the result.
  4843. If ``out`` was specified, ``out`` is returned.
  4844. See Also
  4845. --------
  4846. ma.minimum_fill_value
  4847. Returns the minimum filling value for a given datatype.
  4848. Examples
  4849. --------
  4850. >>> import numpy.ma as ma
  4851. >>> x = [[1., -2., 3.], [0.2, -0.7, 0.1]]
  4852. >>> mask = [[1, 1, 0], [0, 0, 1]]
  4853. >>> masked_x = ma.masked_array(x, mask)
  4854. >>> masked_x
  4855. masked_array(
  4856. data=[[--, --, 3.0],
  4857. [0.2, -0.7, --]],
  4858. mask=[[ True, True, False],
  4859. [False, False, True]],
  4860. fill_value=1e+20)
  4861. >>> ma.min(masked_x)
  4862. -0.7
  4863. >>> ma.min(masked_x, axis=-1)
  4864. masked_array(data=[3.0, -0.7],
  4865. mask=[False, False],
  4866. fill_value=1e+20)
  4867. >>> ma.min(masked_x, axis=0, keepdims=True)
  4868. masked_array(data=[[0.2, -0.7, 3.0]],
  4869. mask=[[False, False, False]],
  4870. fill_value=1e+20)
  4871. >>> mask = [[1, 1, 1,], [1, 1, 1]]
  4872. >>> masked_x = ma.masked_array(x, mask)
  4873. >>> ma.min(masked_x, axis=0)
  4874. masked_array(data=[--, --, --],
  4875. mask=[ True, True, True],
  4876. fill_value=1e+20,
  4877. dtype=float64)
  4878. """
  4879. kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
  4880. _mask = self._mask
  4881. newmask = _check_mask_axis(_mask, axis, **kwargs)
  4882. if fill_value is None:
  4883. fill_value = minimum_fill_value(self)
  4884. # No explicit output
  4885. if out is None:
  4886. result = self.filled(fill_value).min(
  4887. axis=axis, out=out, **kwargs).view(type(self))
  4888. if result.ndim:
  4889. # Set the mask
  4890. result.__setmask__(newmask)
  4891. # Get rid of Infs
  4892. if newmask.ndim:
  4893. np.copyto(result, result.fill_value, where=newmask)
  4894. elif newmask:
  4895. result = masked
  4896. return result
  4897. # Explicit output
  4898. result = self.filled(fill_value).min(axis=axis, out=out, **kwargs)
  4899. if isinstance(out, MaskedArray):
  4900. outmask = getmask(out)
  4901. if outmask is nomask:
  4902. outmask = out._mask = make_mask_none(out.shape)
  4903. outmask.flat = newmask
  4904. else:
  4905. if out.dtype.kind in 'biu':
  4906. errmsg = "Masked data information would be lost in one or more"\
  4907. " location."
  4908. raise MaskError(errmsg)
  4909. np.copyto(out, np.nan, where=newmask)
  4910. return out
  4911. def max(self, axis=None, out=None, fill_value=None, keepdims=np._NoValue):
  4912. """
  4913. Return the maximum along a given axis.
  4914. Parameters
  4915. ----------
  4916. axis : None or int or tuple of ints, optional
  4917. Axis along which to operate. By default, ``axis`` is None and the
  4918. flattened input is used.
  4919. .. versionadded:: 1.7.0
  4920. If this is a tuple of ints, the maximum is selected over multiple
  4921. axes, instead of a single axis or all the axes as before.
  4922. out : array_like, optional
  4923. Alternative output array in which to place the result. Must
  4924. be of the same shape and buffer length as the expected output.
  4925. fill_value : scalar or None, optional
  4926. Value used to fill in the masked values.
  4927. If None, use the output of maximum_fill_value().
  4928. keepdims : bool, optional
  4929. If this is set to True, the axes which are reduced are left
  4930. in the result as dimensions with size one. With this option,
  4931. the result will broadcast correctly against the array.
  4932. Returns
  4933. -------
  4934. amax : array_like
  4935. New array holding the result.
  4936. If ``out`` was specified, ``out`` is returned.
  4937. See Also
  4938. --------
  4939. ma.maximum_fill_value
  4940. Returns the maximum filling value for a given datatype.
  4941. Examples
  4942. --------
  4943. >>> import numpy.ma as ma
  4944. >>> x = [[-1., 2.5], [4., -2.], [3., 0.]]
  4945. >>> mask = [[0, 0], [1, 0], [1, 0]]
  4946. >>> masked_x = ma.masked_array(x, mask)
  4947. >>> masked_x
  4948. masked_array(
  4949. data=[[-1.0, 2.5],
  4950. [--, -2.0],
  4951. [--, 0.0]],
  4952. mask=[[False, False],
  4953. [ True, False],
  4954. [ True, False]],
  4955. fill_value=1e+20)
  4956. >>> ma.max(masked_x)
  4957. 2.5
  4958. >>> ma.max(masked_x, axis=0)
  4959. masked_array(data=[-1.0, 2.5],
  4960. mask=[False, False],
  4961. fill_value=1e+20)
  4962. >>> ma.max(masked_x, axis=1, keepdims=True)
  4963. masked_array(
  4964. data=[[2.5],
  4965. [-2.0],
  4966. [0.0]],
  4967. mask=[[False],
  4968. [False],
  4969. [False]],
  4970. fill_value=1e+20)
  4971. >>> mask = [[1, 1], [1, 1], [1, 1]]
  4972. >>> masked_x = ma.masked_array(x, mask)
  4973. >>> ma.max(masked_x, axis=1)
  4974. masked_array(data=[--, --, --],
  4975. mask=[ True, True, True],
  4976. fill_value=1e+20,
  4977. dtype=float64)
  4978. """
  4979. kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
  4980. _mask = self._mask
  4981. newmask = _check_mask_axis(_mask, axis, **kwargs)
  4982. if fill_value is None:
  4983. fill_value = maximum_fill_value(self)
  4984. # No explicit output
  4985. if out is None:
  4986. result = self.filled(fill_value).max(
  4987. axis=axis, out=out, **kwargs).view(type(self))
  4988. if result.ndim:
  4989. # Set the mask
  4990. result.__setmask__(newmask)
  4991. # Get rid of Infs
  4992. if newmask.ndim:
  4993. np.copyto(result, result.fill_value, where=newmask)
  4994. elif newmask:
  4995. result = masked
  4996. return result
  4997. # Explicit output
  4998. result = self.filled(fill_value).max(axis=axis, out=out, **kwargs)
  4999. if isinstance(out, MaskedArray):
  5000. outmask = getmask(out)
  5001. if outmask is nomask:
  5002. outmask = out._mask = make_mask_none(out.shape)
  5003. outmask.flat = newmask
  5004. else:
  5005. if out.dtype.kind in 'biu':
  5006. errmsg = "Masked data information would be lost in one or more"\
  5007. " location."
  5008. raise MaskError(errmsg)
  5009. np.copyto(out, np.nan, where=newmask)
  5010. return out
  5011. def ptp(self, axis=None, out=None, fill_value=None, keepdims=False):
  5012. """
  5013. Return (maximum - minimum) along the given dimension
  5014. (i.e. peak-to-peak value).
  5015. .. warning::
  5016. `ptp` preserves the data type of the array. This means the
  5017. return value for an input of signed integers with n bits
  5018. (e.g. `np.int8`, `np.int16`, etc) is also a signed integer
  5019. with n bits. In that case, peak-to-peak values greater than
  5020. ``2**(n-1)-1`` will be returned as negative values. An example
  5021. with a work-around is shown below.
  5022. Parameters
  5023. ----------
  5024. axis : {None, int}, optional
  5025. Axis along which to find the peaks. If None (default) the
  5026. flattened array is used.
  5027. out : {None, array_like}, optional
  5028. Alternative output array in which to place the result. It must
  5029. have the same shape and buffer length as the expected output
  5030. but the type will be cast if necessary.
  5031. fill_value : scalar or None, optional
  5032. Value used to fill in the masked values.
  5033. keepdims : bool, optional
  5034. If this is set to True, the axes which are reduced are left
  5035. in the result as dimensions with size one. With this option,
  5036. the result will broadcast correctly against the array.
  5037. Returns
  5038. -------
  5039. ptp : ndarray.
  5040. A new array holding the result, unless ``out`` was
  5041. specified, in which case a reference to ``out`` is returned.
  5042. Examples
  5043. --------
  5044. >>> x = np.ma.MaskedArray([[4, 9, 2, 10],
  5045. ... [6, 9, 7, 12]])
  5046. >>> x.ptp(axis=1)
  5047. masked_array(data=[8, 6],
  5048. mask=False,
  5049. fill_value=999999)
  5050. >>> x.ptp(axis=0)
  5051. masked_array(data=[2, 0, 5, 2],
  5052. mask=False,
  5053. fill_value=999999)
  5054. >>> x.ptp()
  5055. 10
  5056. This example shows that a negative value can be returned when
  5057. the input is an array of signed integers.
  5058. >>> y = np.ma.MaskedArray([[1, 127],
  5059. ... [0, 127],
  5060. ... [-1, 127],
  5061. ... [-2, 127]], dtype=np.int8)
  5062. >>> y.ptp(axis=1)
  5063. masked_array(data=[ 126, 127, -128, -127],
  5064. mask=False,
  5065. fill_value=999999,
  5066. dtype=int8)
  5067. A work-around is to use the `view()` method to view the result as
  5068. unsigned integers with the same bit width:
  5069. >>> y.ptp(axis=1).view(np.uint8)
  5070. masked_array(data=[126, 127, 128, 129],
  5071. mask=False,
  5072. fill_value=999999,
  5073. dtype=uint8)
  5074. """
  5075. if out is None:
  5076. result = self.max(axis=axis, fill_value=fill_value,
  5077. keepdims=keepdims)
  5078. result -= self.min(axis=axis, fill_value=fill_value,
  5079. keepdims=keepdims)
  5080. return result
  5081. out.flat = self.max(axis=axis, out=out, fill_value=fill_value,
  5082. keepdims=keepdims)
  5083. min_value = self.min(axis=axis, fill_value=fill_value,
  5084. keepdims=keepdims)
  5085. np.subtract(out, min_value, out=out, casting='unsafe')
  5086. return out
  5087. def partition(self, *args, **kwargs):
  5088. warnings.warn("Warning: 'partition' will ignore the 'mask' "
  5089. f"of the {self.__class__.__name__}.",
  5090. stacklevel=2)
  5091. return super().partition(*args, **kwargs)
  5092. def argpartition(self, *args, **kwargs):
  5093. warnings.warn("Warning: 'argpartition' will ignore the 'mask' "
  5094. f"of the {self.__class__.__name__}.",
  5095. stacklevel=2)
  5096. return super().argpartition(*args, **kwargs)
  5097. def take(self, indices, axis=None, out=None, mode='raise'):
  5098. """
  5099. """
  5100. (_data, _mask) = (self._data, self._mask)
  5101. cls = type(self)
  5102. # Make sure the indices are not masked
  5103. maskindices = getmask(indices)
  5104. if maskindices is not nomask:
  5105. indices = indices.filled(0)
  5106. # Get the data, promoting scalars to 0d arrays with [...] so that
  5107. # .view works correctly
  5108. if out is None:
  5109. out = _data.take(indices, axis=axis, mode=mode)[...].view(cls)
  5110. else:
  5111. np.take(_data, indices, axis=axis, mode=mode, out=out)
  5112. # Get the mask
  5113. if isinstance(out, MaskedArray):
  5114. if _mask is nomask:
  5115. outmask = maskindices
  5116. else:
  5117. outmask = _mask.take(indices, axis=axis, mode=mode)
  5118. outmask |= maskindices
  5119. out.__setmask__(outmask)
  5120. # demote 0d arrays back to scalars, for consistency with ndarray.take
  5121. return out[()]
  5122. # Array methods
  5123. copy = _arraymethod('copy')
  5124. diagonal = _arraymethod('diagonal')
  5125. flatten = _arraymethod('flatten')
  5126. repeat = _arraymethod('repeat')
  5127. squeeze = _arraymethod('squeeze')
  5128. swapaxes = _arraymethod('swapaxes')
  5129. T = property(fget=lambda self: self.transpose())
  5130. transpose = _arraymethod('transpose')
  5131. def tolist(self, fill_value=None):
  5132. """
  5133. Return the data portion of the masked array as a hierarchical Python list.
  5134. Data items are converted to the nearest compatible Python type.
  5135. Masked values are converted to `fill_value`. If `fill_value` is None,
  5136. the corresponding entries in the output list will be ``None``.
  5137. Parameters
  5138. ----------
  5139. fill_value : scalar, optional
  5140. The value to use for invalid entries. Default is None.
  5141. Returns
  5142. -------
  5143. result : list
  5144. The Python list representation of the masked array.
  5145. Examples
  5146. --------
  5147. >>> x = np.ma.array([[1,2,3], [4,5,6], [7,8,9]], mask=[0] + [1,0]*4)
  5148. >>> x.tolist()
  5149. [[1, None, 3], [None, 5, None], [7, None, 9]]
  5150. >>> x.tolist(-999)
  5151. [[1, -999, 3], [-999, 5, -999], [7, -999, 9]]
  5152. """
  5153. _mask = self._mask
  5154. # No mask ? Just return .data.tolist ?
  5155. if _mask is nomask:
  5156. return self._data.tolist()
  5157. # Explicit fill_value: fill the array and get the list
  5158. if fill_value is not None:
  5159. return self.filled(fill_value).tolist()
  5160. # Structured array.
  5161. names = self.dtype.names
  5162. if names:
  5163. result = self._data.astype([(_, object) for _ in names])
  5164. for n in names:
  5165. result[n][_mask[n]] = None
  5166. return result.tolist()
  5167. # Standard arrays.
  5168. if _mask is nomask:
  5169. return [None]
  5170. # Set temps to save time when dealing w/ marrays.
  5171. inishape = self.shape
  5172. result = np.array(self._data.ravel(), dtype=object)
  5173. result[_mask.ravel()] = None
  5174. result.shape = inishape
  5175. return result.tolist()
  5176. def tostring(self, fill_value=None, order='C'):
  5177. r"""
  5178. A compatibility alias for `tobytes`, with exactly the same behavior.
  5179. Despite its name, it returns `bytes` not `str`\ s.
  5180. .. deprecated:: 1.19.0
  5181. """
  5182. # 2020-03-30, Numpy 1.19.0
  5183. warnings.warn(
  5184. "tostring() is deprecated. Use tobytes() instead.",
  5185. DeprecationWarning, stacklevel=2)
  5186. return self.tobytes(fill_value, order=order)
  5187. def tobytes(self, fill_value=None, order='C'):
  5188. """
  5189. Return the array data as a string containing the raw bytes in the array.
  5190. The array is filled with a fill value before the string conversion.
  5191. .. versionadded:: 1.9.0
  5192. Parameters
  5193. ----------
  5194. fill_value : scalar, optional
  5195. Value used to fill in the masked values. Default is None, in which
  5196. case `MaskedArray.fill_value` is used.
  5197. order : {'C','F','A'}, optional
  5198. Order of the data item in the copy. Default is 'C'.
  5199. - 'C' -- C order (row major).
  5200. - 'F' -- Fortran order (column major).
  5201. - 'A' -- Any, current order of array.
  5202. - None -- Same as 'A'.
  5203. See Also
  5204. --------
  5205. numpy.ndarray.tobytes
  5206. tolist, tofile
  5207. Notes
  5208. -----
  5209. As for `ndarray.tobytes`, information about the shape, dtype, etc.,
  5210. but also about `fill_value`, will be lost.
  5211. Examples
  5212. --------
  5213. >>> x = np.ma.array(np.array([[1, 2], [3, 4]]), mask=[[0, 1], [1, 0]])
  5214. >>> x.tobytes()
  5215. b'\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00?B\\x0f\\x00\\x00\\x00\\x00\\x00?B\\x0f\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00'
  5216. """
  5217. return self.filled(fill_value).tobytes(order=order)
  5218. def tofile(self, fid, sep="", format="%s"):
  5219. """
  5220. Save a masked array to a file in binary format.
  5221. .. warning::
  5222. This function is not implemented yet.
  5223. Raises
  5224. ------
  5225. NotImplementedError
  5226. When `tofile` is called.
  5227. """
  5228. raise NotImplementedError("MaskedArray.tofile() not implemented yet.")
  5229. def toflex(self):
  5230. """
  5231. Transforms a masked array into a flexible-type array.
  5232. The flexible type array that is returned will have two fields:
  5233. * the ``_data`` field stores the ``_data`` part of the array.
  5234. * the ``_mask`` field stores the ``_mask`` part of the array.
  5235. Parameters
  5236. ----------
  5237. None
  5238. Returns
  5239. -------
  5240. record : ndarray
  5241. A new flexible-type `ndarray` with two fields: the first element
  5242. containing a value, the second element containing the corresponding
  5243. mask boolean. The returned record shape matches self.shape.
  5244. Notes
  5245. -----
  5246. A side-effect of transforming a masked array into a flexible `ndarray` is
  5247. that meta information (``fill_value``, ...) will be lost.
  5248. Examples
  5249. --------
  5250. >>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4)
  5251. >>> x
  5252. masked_array(
  5253. data=[[1, --, 3],
  5254. [--, 5, --],
  5255. [7, --, 9]],
  5256. mask=[[False, True, False],
  5257. [ True, False, True],
  5258. [False, True, False]],
  5259. fill_value=999999)
  5260. >>> x.toflex()
  5261. array([[(1, False), (2, True), (3, False)],
  5262. [(4, True), (5, False), (6, True)],
  5263. [(7, False), (8, True), (9, False)]],
  5264. dtype=[('_data', '<i8'), ('_mask', '?')])
  5265. """
  5266. # Get the basic dtype.
  5267. ddtype = self.dtype
  5268. # Make sure we have a mask
  5269. _mask = self._mask
  5270. if _mask is None:
  5271. _mask = make_mask_none(self.shape, ddtype)
  5272. # And get its dtype
  5273. mdtype = self._mask.dtype
  5274. record = np.ndarray(shape=self.shape,
  5275. dtype=[('_data', ddtype), ('_mask', mdtype)])
  5276. record['_data'] = self._data
  5277. record['_mask'] = self._mask
  5278. return record
  5279. torecords = toflex
  5280. # Pickling
  5281. def __getstate__(self):
  5282. """Return the internal state of the masked array, for pickling
  5283. purposes.
  5284. """
  5285. cf = 'CF'[self.flags.fnc]
  5286. data_state = super().__reduce__()[2]
  5287. return data_state + (getmaskarray(self).tobytes(cf), self._fill_value)
  5288. def __setstate__(self, state):
  5289. """Restore the internal state of the masked array, for
  5290. pickling purposes. ``state`` is typically the output of the
  5291. ``__getstate__`` output, and is a 5-tuple:
  5292. - class name
  5293. - a tuple giving the shape of the data
  5294. - a typecode for the data
  5295. - a binary string for the data
  5296. - a binary string for the mask.
  5297. """
  5298. (_, shp, typ, isf, raw, msk, flv) = state
  5299. super().__setstate__((shp, typ, isf, raw))
  5300. self._mask.__setstate__((shp, make_mask_descr(typ), isf, msk))
  5301. self.fill_value = flv
  5302. def __reduce__(self):
  5303. """Return a 3-tuple for pickling a MaskedArray.
  5304. """
  5305. return (_mareconstruct,
  5306. (self.__class__, self._baseclass, (0,), 'b',),
  5307. self.__getstate__())
  5308. def __deepcopy__(self, memo=None):
  5309. from copy import deepcopy
  5310. copied = MaskedArray.__new__(type(self), self, copy=True)
  5311. if memo is None:
  5312. memo = {}
  5313. memo[id(self)] = copied
  5314. for (k, v) in self.__dict__.items():
  5315. copied.__dict__[k] = deepcopy(v, memo)
  5316. return copied
  5317. def _mareconstruct(subtype, baseclass, baseshape, basetype,):
  5318. """Internal function that builds a new MaskedArray from the
  5319. information stored in a pickle.
  5320. """
  5321. _data = ndarray.__new__(baseclass, baseshape, basetype)
  5322. _mask = ndarray.__new__(ndarray, baseshape, make_mask_descr(basetype))
  5323. return subtype.__new__(subtype, _data, mask=_mask, dtype=basetype,)
  5324. class mvoid(MaskedArray):
  5325. """
  5326. Fake a 'void' object to use for masked array with structured dtypes.
  5327. """
  5328. def __new__(self, data, mask=nomask, dtype=None, fill_value=None,
  5329. hardmask=False, copy=False, subok=True):
  5330. _data = np.array(data, copy=copy, subok=subok, dtype=dtype)
  5331. _data = _data.view(self)
  5332. _data._hardmask = hardmask
  5333. if mask is not nomask:
  5334. if isinstance(mask, np.void):
  5335. _data._mask = mask
  5336. else:
  5337. try:
  5338. # Mask is already a 0D array
  5339. _data._mask = np.void(mask)
  5340. except TypeError:
  5341. # Transform the mask to a void
  5342. mdtype = make_mask_descr(dtype)
  5343. _data._mask = np.array(mask, dtype=mdtype)[()]
  5344. if fill_value is not None:
  5345. _data.fill_value = fill_value
  5346. return _data
  5347. @property
  5348. def _data(self):
  5349. # Make sure that the _data part is a np.void
  5350. return super()._data[()]
  5351. def __getitem__(self, indx):
  5352. """
  5353. Get the index.
  5354. """
  5355. m = self._mask
  5356. if isinstance(m[indx], ndarray):
  5357. # Can happen when indx is a multi-dimensional field:
  5358. # A = ma.masked_array(data=[([0,1],)], mask=[([True,
  5359. # False],)], dtype=[("A", ">i2", (2,))])
  5360. # x = A[0]; y = x["A"]; then y.mask["A"].size==2
  5361. # and we can not say masked/unmasked.
  5362. # The result is no longer mvoid!
  5363. # See also issue #6724.
  5364. return masked_array(
  5365. data=self._data[indx], mask=m[indx],
  5366. fill_value=self._fill_value[indx],
  5367. hard_mask=self._hardmask)
  5368. if m is not nomask and m[indx]:
  5369. return masked
  5370. return self._data[indx]
  5371. def __setitem__(self, indx, value):
  5372. self._data[indx] = value
  5373. if self._hardmask:
  5374. self._mask[indx] |= getattr(value, "_mask", False)
  5375. else:
  5376. self._mask[indx] = getattr(value, "_mask", False)
  5377. def __str__(self):
  5378. m = self._mask
  5379. if m is nomask:
  5380. return str(self._data)
  5381. rdtype = _replace_dtype_fields(self._data.dtype, "O")
  5382. data_arr = super()._data
  5383. res = data_arr.astype(rdtype)
  5384. _recursive_printoption(res, self._mask, masked_print_option)
  5385. return str(res)
  5386. __repr__ = __str__
  5387. def __iter__(self):
  5388. "Defines an iterator for mvoid"
  5389. (_data, _mask) = (self._data, self._mask)
  5390. if _mask is nomask:
  5391. yield from _data
  5392. else:
  5393. for (d, m) in zip(_data, _mask):
  5394. if m:
  5395. yield masked
  5396. else:
  5397. yield d
  5398. def __len__(self):
  5399. return self._data.__len__()
  5400. def filled(self, fill_value=None):
  5401. """
  5402. Return a copy with masked fields filled with a given value.
  5403. Parameters
  5404. ----------
  5405. fill_value : array_like, optional
  5406. The value to use for invalid entries. Can be scalar or
  5407. non-scalar. If latter is the case, the filled array should
  5408. be broadcastable over input array. Default is None, in
  5409. which case the `fill_value` attribute is used instead.
  5410. Returns
  5411. -------
  5412. filled_void
  5413. A `np.void` object
  5414. See Also
  5415. --------
  5416. MaskedArray.filled
  5417. """
  5418. return asarray(self).filled(fill_value)[()]
  5419. def tolist(self):
  5420. """
  5421. Transforms the mvoid object into a tuple.
  5422. Masked fields are replaced by None.
  5423. Returns
  5424. -------
  5425. returned_tuple
  5426. Tuple of fields
  5427. """
  5428. _mask = self._mask
  5429. if _mask is nomask:
  5430. return self._data.tolist()
  5431. result = []
  5432. for (d, m) in zip(self._data, self._mask):
  5433. if m:
  5434. result.append(None)
  5435. else:
  5436. # .item() makes sure we return a standard Python object
  5437. result.append(d.item())
  5438. return tuple(result)
  5439. ##############################################################################
  5440. # Shortcuts #
  5441. ##############################################################################
  5442. def isMaskedArray(x):
  5443. """
  5444. Test whether input is an instance of MaskedArray.
  5445. This function returns True if `x` is an instance of MaskedArray
  5446. and returns False otherwise. Any object is accepted as input.
  5447. Parameters
  5448. ----------
  5449. x : object
  5450. Object to test.
  5451. Returns
  5452. -------
  5453. result : bool
  5454. True if `x` is a MaskedArray.
  5455. See Also
  5456. --------
  5457. isMA : Alias to isMaskedArray.
  5458. isarray : Alias to isMaskedArray.
  5459. Examples
  5460. --------
  5461. >>> import numpy.ma as ma
  5462. >>> a = np.eye(3, 3)
  5463. >>> a
  5464. array([[ 1., 0., 0.],
  5465. [ 0., 1., 0.],
  5466. [ 0., 0., 1.]])
  5467. >>> m = ma.masked_values(a, 0)
  5468. >>> m
  5469. masked_array(
  5470. data=[[1.0, --, --],
  5471. [--, 1.0, --],
  5472. [--, --, 1.0]],
  5473. mask=[[False, True, True],
  5474. [ True, False, True],
  5475. [ True, True, False]],
  5476. fill_value=0.0)
  5477. >>> ma.isMaskedArray(a)
  5478. False
  5479. >>> ma.isMaskedArray(m)
  5480. True
  5481. >>> ma.isMaskedArray([0, 1, 2])
  5482. False
  5483. """
  5484. return isinstance(x, MaskedArray)
  5485. isarray = isMaskedArray
  5486. isMA = isMaskedArray # backward compatibility
  5487. class MaskedConstant(MaskedArray):
  5488. # the lone np.ma.masked instance
  5489. __singleton = None
  5490. @classmethod
  5491. def __has_singleton(cls):
  5492. # second case ensures `cls.__singleton` is not just a view on the
  5493. # superclass singleton
  5494. return cls.__singleton is not None and type(cls.__singleton) is cls
  5495. def __new__(cls):
  5496. if not cls.__has_singleton():
  5497. # We define the masked singleton as a float for higher precedence.
  5498. # Note that it can be tricky sometimes w/ type comparison
  5499. data = np.array(0.)
  5500. mask = np.array(True)
  5501. # prevent any modifications
  5502. data.flags.writeable = False
  5503. mask.flags.writeable = False
  5504. # don't fall back on MaskedArray.__new__(MaskedConstant), since
  5505. # that might confuse it - this way, the construction is entirely
  5506. # within our control
  5507. cls.__singleton = MaskedArray(data, mask=mask).view(cls)
  5508. return cls.__singleton
  5509. def __array_finalize__(self, obj):
  5510. if not self.__has_singleton():
  5511. # this handles the `.view` in __new__, which we want to copy across
  5512. # properties normally
  5513. return super().__array_finalize__(obj)
  5514. elif self is self.__singleton:
  5515. # not clear how this can happen, play it safe
  5516. pass
  5517. else:
  5518. # everywhere else, we want to downcast to MaskedArray, to prevent a
  5519. # duplicate maskedconstant.
  5520. self.__class__ = MaskedArray
  5521. MaskedArray.__array_finalize__(self, obj)
  5522. def __array_prepare__(self, obj, context=None):
  5523. return self.view(MaskedArray).__array_prepare__(obj, context)
  5524. def __array_wrap__(self, obj, context=None):
  5525. return self.view(MaskedArray).__array_wrap__(obj, context)
  5526. def __str__(self):
  5527. return str(masked_print_option._display)
  5528. def __repr__(self):
  5529. if self is MaskedConstant.__singleton:
  5530. return 'masked'
  5531. else:
  5532. # it's a subclass, or something is wrong, make it obvious
  5533. return object.__repr__(self)
  5534. def __format__(self, format_spec):
  5535. # Replace ndarray.__format__ with the default, which supports no format characters.
  5536. # Supporting format characters is unwise here, because we do not know what type
  5537. # the user was expecting - better to not guess.
  5538. try:
  5539. return object.__format__(self, format_spec)
  5540. except TypeError:
  5541. # 2020-03-23, NumPy 1.19.0
  5542. warnings.warn(
  5543. "Format strings passed to MaskedConstant are ignored, but in future may "
  5544. "error or produce different behavior",
  5545. FutureWarning, stacklevel=2
  5546. )
  5547. return object.__format__(self, "")
  5548. def __reduce__(self):
  5549. """Override of MaskedArray's __reduce__.
  5550. """
  5551. return (self.__class__, ())
  5552. # inplace operations have no effect. We have to override them to avoid
  5553. # trying to modify the readonly data and mask arrays
  5554. def __iop__(self, other):
  5555. return self
  5556. __iadd__ = \
  5557. __isub__ = \
  5558. __imul__ = \
  5559. __ifloordiv__ = \
  5560. __itruediv__ = \
  5561. __ipow__ = \
  5562. __iop__
  5563. del __iop__ # don't leave this around
  5564. def copy(self, *args, **kwargs):
  5565. """ Copy is a no-op on the maskedconstant, as it is a scalar """
  5566. # maskedconstant is a scalar, so copy doesn't need to copy. There's
  5567. # precedent for this with `np.bool_` scalars.
  5568. return self
  5569. def __copy__(self):
  5570. return self
  5571. def __deepcopy__(self, memo):
  5572. return self
  5573. def __setattr__(self, attr, value):
  5574. if not self.__has_singleton():
  5575. # allow the singleton to be initialized
  5576. return super().__setattr__(attr, value)
  5577. elif self is self.__singleton:
  5578. raise AttributeError(
  5579. f"attributes of {self!r} are not writeable")
  5580. else:
  5581. # duplicate instance - we can end up here from __array_finalize__,
  5582. # where we set the __class__ attribute
  5583. return super().__setattr__(attr, value)
  5584. masked = masked_singleton = MaskedConstant()
  5585. masked_array = MaskedArray
  5586. def array(data, dtype=None, copy=False, order=None,
  5587. mask=nomask, fill_value=None, keep_mask=True,
  5588. hard_mask=False, shrink=True, subok=True, ndmin=0):
  5589. """
  5590. Shortcut to MaskedArray.
  5591. The options are in a different order for convenience and backwards
  5592. compatibility.
  5593. """
  5594. return MaskedArray(data, mask=mask, dtype=dtype, copy=copy,
  5595. subok=subok, keep_mask=keep_mask,
  5596. hard_mask=hard_mask, fill_value=fill_value,
  5597. ndmin=ndmin, shrink=shrink, order=order)
  5598. array.__doc__ = masked_array.__doc__
  5599. def is_masked(x):
  5600. """
  5601. Determine whether input has masked values.
  5602. Accepts any object as input, but always returns False unless the
  5603. input is a MaskedArray containing masked values.
  5604. Parameters
  5605. ----------
  5606. x : array_like
  5607. Array to check for masked values.
  5608. Returns
  5609. -------
  5610. result : bool
  5611. True if `x` is a MaskedArray with masked values, False otherwise.
  5612. Examples
  5613. --------
  5614. >>> import numpy.ma as ma
  5615. >>> x = ma.masked_equal([0, 1, 0, 2, 3], 0)
  5616. >>> x
  5617. masked_array(data=[--, 1, --, 2, 3],
  5618. mask=[ True, False, True, False, False],
  5619. fill_value=0)
  5620. >>> ma.is_masked(x)
  5621. True
  5622. >>> x = ma.masked_equal([0, 1, 0, 2, 3], 42)
  5623. >>> x
  5624. masked_array(data=[0, 1, 0, 2, 3],
  5625. mask=False,
  5626. fill_value=42)
  5627. >>> ma.is_masked(x)
  5628. False
  5629. Always returns False if `x` isn't a MaskedArray.
  5630. >>> x = [False, True, False]
  5631. >>> ma.is_masked(x)
  5632. False
  5633. >>> x = 'a string'
  5634. >>> ma.is_masked(x)
  5635. False
  5636. """
  5637. m = getmask(x)
  5638. if m is nomask:
  5639. return False
  5640. elif m.any():
  5641. return True
  5642. return False
  5643. ##############################################################################
  5644. # Extrema functions #
  5645. ##############################################################################
  5646. class _extrema_operation(_MaskedUFunc):
  5647. """
  5648. Generic class for maximum/minimum functions.
  5649. .. note::
  5650. This is the base class for `_maximum_operation` and
  5651. `_minimum_operation`.
  5652. """
  5653. def __init__(self, ufunc, compare, fill_value):
  5654. super().__init__(ufunc)
  5655. self.compare = compare
  5656. self.fill_value_func = fill_value
  5657. def __call__(self, a, b):
  5658. "Executes the call behavior."
  5659. return where(self.compare(a, b), a, b)
  5660. def reduce(self, target, axis=np._NoValue):
  5661. "Reduce target along the given axis."
  5662. target = narray(target, copy=False, subok=True)
  5663. m = getmask(target)
  5664. if axis is np._NoValue and target.ndim > 1:
  5665. # 2017-05-06, Numpy 1.13.0: warn on axis default
  5666. warnings.warn(
  5667. f"In the future the default for ma.{self.__name__}.reduce will be axis=0, "
  5668. f"not the current None, to match np.{self.__name__}.reduce. "
  5669. "Explicitly pass 0 or None to silence this warning.",
  5670. MaskedArrayFutureWarning, stacklevel=2)
  5671. axis = None
  5672. if axis is not np._NoValue:
  5673. kwargs = dict(axis=axis)
  5674. else:
  5675. kwargs = dict()
  5676. if m is nomask:
  5677. t = self.f.reduce(target, **kwargs)
  5678. else:
  5679. target = target.filled(
  5680. self.fill_value_func(target)).view(type(target))
  5681. t = self.f.reduce(target, **kwargs)
  5682. m = umath.logical_and.reduce(m, **kwargs)
  5683. if hasattr(t, '_mask'):
  5684. t._mask = m
  5685. elif m:
  5686. t = masked
  5687. return t
  5688. def outer(self, a, b):
  5689. "Return the function applied to the outer product of a and b."
  5690. ma = getmask(a)
  5691. mb = getmask(b)
  5692. if ma is nomask and mb is nomask:
  5693. m = nomask
  5694. else:
  5695. ma = getmaskarray(a)
  5696. mb = getmaskarray(b)
  5697. m = logical_or.outer(ma, mb)
  5698. result = self.f.outer(filled(a), filled(b))
  5699. if not isinstance(result, MaskedArray):
  5700. result = result.view(MaskedArray)
  5701. result._mask = m
  5702. return result
  5703. def min(obj, axis=None, out=None, fill_value=None, keepdims=np._NoValue):
  5704. kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
  5705. try:
  5706. return obj.min(axis=axis, fill_value=fill_value, out=out, **kwargs)
  5707. except (AttributeError, TypeError):
  5708. # If obj doesn't have a min method, or if the method doesn't accept a
  5709. # fill_value argument
  5710. return asanyarray(obj).min(axis=axis, fill_value=fill_value,
  5711. out=out, **kwargs)
  5712. min.__doc__ = MaskedArray.min.__doc__
  5713. def max(obj, axis=None, out=None, fill_value=None, keepdims=np._NoValue):
  5714. kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
  5715. try:
  5716. return obj.max(axis=axis, fill_value=fill_value, out=out, **kwargs)
  5717. except (AttributeError, TypeError):
  5718. # If obj doesn't have a max method, or if the method doesn't accept a
  5719. # fill_value argument
  5720. return asanyarray(obj).max(axis=axis, fill_value=fill_value,
  5721. out=out, **kwargs)
  5722. max.__doc__ = MaskedArray.max.__doc__
  5723. def ptp(obj, axis=None, out=None, fill_value=None, keepdims=np._NoValue):
  5724. kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims}
  5725. try:
  5726. return obj.ptp(axis, out=out, fill_value=fill_value, **kwargs)
  5727. except (AttributeError, TypeError):
  5728. # If obj doesn't have a ptp method or if the method doesn't accept
  5729. # a fill_value argument
  5730. return asanyarray(obj).ptp(axis=axis, fill_value=fill_value,
  5731. out=out, **kwargs)
  5732. ptp.__doc__ = MaskedArray.ptp.__doc__
  5733. ##############################################################################
  5734. # Definition of functions from the corresponding methods #
  5735. ##############################################################################
  5736. class _frommethod:
  5737. """
  5738. Define functions from existing MaskedArray methods.
  5739. Parameters
  5740. ----------
  5741. methodname : str
  5742. Name of the method to transform.
  5743. """
  5744. def __init__(self, methodname, reversed=False):
  5745. self.__name__ = methodname
  5746. self.__doc__ = self.getdoc()
  5747. self.reversed = reversed
  5748. def getdoc(self):
  5749. "Return the doc of the function (from the doc of the method)."
  5750. meth = getattr(MaskedArray, self.__name__, None) or\
  5751. getattr(np, self.__name__, None)
  5752. signature = self.__name__ + get_object_signature(meth)
  5753. if meth is not None:
  5754. doc = """ %s\n%s""" % (
  5755. signature, getattr(meth, '__doc__', None))
  5756. return doc
  5757. def __call__(self, a, *args, **params):
  5758. if self.reversed:
  5759. args = list(args)
  5760. a, args[0] = args[0], a
  5761. marr = asanyarray(a)
  5762. method_name = self.__name__
  5763. method = getattr(type(marr), method_name, None)
  5764. if method is None:
  5765. # use the corresponding np function
  5766. method = getattr(np, method_name)
  5767. return method(marr, *args, **params)
  5768. all = _frommethod('all')
  5769. anomalies = anom = _frommethod('anom')
  5770. any = _frommethod('any')
  5771. compress = _frommethod('compress', reversed=True)
  5772. cumprod = _frommethod('cumprod')
  5773. cumsum = _frommethod('cumsum')
  5774. copy = _frommethod('copy')
  5775. diagonal = _frommethod('diagonal')
  5776. harden_mask = _frommethod('harden_mask')
  5777. ids = _frommethod('ids')
  5778. maximum = _extrema_operation(umath.maximum, greater, maximum_fill_value)
  5779. mean = _frommethod('mean')
  5780. minimum = _extrema_operation(umath.minimum, less, minimum_fill_value)
  5781. nonzero = _frommethod('nonzero')
  5782. prod = _frommethod('prod')
  5783. product = _frommethod('prod')
  5784. ravel = _frommethod('ravel')
  5785. repeat = _frommethod('repeat')
  5786. shrink_mask = _frommethod('shrink_mask')
  5787. soften_mask = _frommethod('soften_mask')
  5788. std = _frommethod('std')
  5789. sum = _frommethod('sum')
  5790. swapaxes = _frommethod('swapaxes')
  5791. #take = _frommethod('take')
  5792. trace = _frommethod('trace')
  5793. var = _frommethod('var')
  5794. count = _frommethod('count')
  5795. def take(a, indices, axis=None, out=None, mode='raise'):
  5796. """
  5797. """
  5798. a = masked_array(a)
  5799. return a.take(indices, axis=axis, out=out, mode=mode)
  5800. def power(a, b, third=None):
  5801. """
  5802. Returns element-wise base array raised to power from second array.
  5803. This is the masked array version of `numpy.power`. For details see
  5804. `numpy.power`.
  5805. See Also
  5806. --------
  5807. numpy.power
  5808. Notes
  5809. -----
  5810. The *out* argument to `numpy.power` is not supported, `third` has to be
  5811. None.
  5812. Examples
  5813. --------
  5814. >>> import numpy.ma as ma
  5815. >>> x = [11.2, -3.973, 0.801, -1.41]
  5816. >>> mask = [0, 0, 0, 1]
  5817. >>> masked_x = ma.masked_array(x, mask)
  5818. >>> masked_x
  5819. masked_array(data=[11.2, -3.973, 0.801, --],
  5820. mask=[False, False, False, True],
  5821. fill_value=1e+20)
  5822. >>> ma.power(masked_x, 2)
  5823. masked_array(data=[125.43999999999998, 15.784728999999999,
  5824. 0.6416010000000001, --],
  5825. mask=[False, False, False, True],
  5826. fill_value=1e+20)
  5827. >>> y = [-0.5, 2, 0, 17]
  5828. >>> masked_y = ma.masked_array(y, mask)
  5829. >>> masked_y
  5830. masked_array(data=[-0.5, 2.0, 0.0, --],
  5831. mask=[False, False, False, True],
  5832. fill_value=1e+20)
  5833. >>> ma.power(masked_x, masked_y)
  5834. masked_array(data=[0.29880715233359845, 15.784728999999999, 1.0, --],
  5835. mask=[False, False, False, True],
  5836. fill_value=1e+20)
  5837. """
  5838. if third is not None:
  5839. raise MaskError("3-argument power not supported.")
  5840. # Get the masks
  5841. ma = getmask(a)
  5842. mb = getmask(b)
  5843. m = mask_or(ma, mb)
  5844. # Get the rawdata
  5845. fa = getdata(a)
  5846. fb = getdata(b)
  5847. # Get the type of the result (so that we preserve subclasses)
  5848. if isinstance(a, MaskedArray):
  5849. basetype = type(a)
  5850. else:
  5851. basetype = MaskedArray
  5852. # Get the result and view it as a (subclass of) MaskedArray
  5853. with np.errstate(divide='ignore', invalid='ignore'):
  5854. result = np.where(m, fa, umath.power(fa, fb)).view(basetype)
  5855. result._update_from(a)
  5856. # Find where we're in trouble w/ NaNs and Infs
  5857. invalid = np.logical_not(np.isfinite(result.view(ndarray)))
  5858. # Add the initial mask
  5859. if m is not nomask:
  5860. if not result.ndim:
  5861. return masked
  5862. result._mask = np.logical_or(m, invalid)
  5863. # Fix the invalid parts
  5864. if invalid.any():
  5865. if not result.ndim:
  5866. return masked
  5867. elif result._mask is nomask:
  5868. result._mask = invalid
  5869. result._data[invalid] = result.fill_value
  5870. return result
  5871. argmin = _frommethod('argmin')
  5872. argmax = _frommethod('argmax')
  5873. def argsort(a, axis=np._NoValue, kind=None, order=None, endwith=True, fill_value=None):
  5874. "Function version of the eponymous method."
  5875. a = np.asanyarray(a)
  5876. # 2017-04-11, Numpy 1.13.0, gh-8701: warn on axis default
  5877. if axis is np._NoValue:
  5878. axis = _deprecate_argsort_axis(a)
  5879. if isinstance(a, MaskedArray):
  5880. return a.argsort(axis=axis, kind=kind, order=order,
  5881. endwith=endwith, fill_value=fill_value)
  5882. else:
  5883. return a.argsort(axis=axis, kind=kind, order=order)
  5884. argsort.__doc__ = MaskedArray.argsort.__doc__
  5885. def sort(a, axis=-1, kind=None, order=None, endwith=True, fill_value=None):
  5886. """
  5887. Return a sorted copy of the masked array.
  5888. Equivalent to creating a copy of the array
  5889. and applying the MaskedArray ``sort()`` method.
  5890. Refer to ``MaskedArray.sort`` for the full documentation
  5891. See Also
  5892. --------
  5893. MaskedArray.sort : equivalent method
  5894. """
  5895. a = np.array(a, copy=True, subok=True)
  5896. if axis is None:
  5897. a = a.flatten()
  5898. axis = 0
  5899. if isinstance(a, MaskedArray):
  5900. a.sort(axis=axis, kind=kind, order=order,
  5901. endwith=endwith, fill_value=fill_value)
  5902. else:
  5903. a.sort(axis=axis, kind=kind, order=order)
  5904. return a
  5905. def compressed(x):
  5906. """
  5907. Return all the non-masked data as a 1-D array.
  5908. This function is equivalent to calling the "compressed" method of a
  5909. `ma.MaskedArray`, see `ma.MaskedArray.compressed` for details.
  5910. See Also
  5911. --------
  5912. ma.MaskedArray.compressed : Equivalent method.
  5913. """
  5914. return asanyarray(x).compressed()
  5915. def concatenate(arrays, axis=0):
  5916. """
  5917. Concatenate a sequence of arrays along the given axis.
  5918. Parameters
  5919. ----------
  5920. arrays : sequence of array_like
  5921. The arrays must have the same shape, except in the dimension
  5922. corresponding to `axis` (the first, by default).
  5923. axis : int, optional
  5924. The axis along which the arrays will be joined. Default is 0.
  5925. Returns
  5926. -------
  5927. result : MaskedArray
  5928. The concatenated array with any masked entries preserved.
  5929. See Also
  5930. --------
  5931. numpy.concatenate : Equivalent function in the top-level NumPy module.
  5932. Examples
  5933. --------
  5934. >>> import numpy.ma as ma
  5935. >>> a = ma.arange(3)
  5936. >>> a[1] = ma.masked
  5937. >>> b = ma.arange(2, 5)
  5938. >>> a
  5939. masked_array(data=[0, --, 2],
  5940. mask=[False, True, False],
  5941. fill_value=999999)
  5942. >>> b
  5943. masked_array(data=[2, 3, 4],
  5944. mask=False,
  5945. fill_value=999999)
  5946. >>> ma.concatenate([a, b])
  5947. masked_array(data=[0, --, 2, 2, 3, 4],
  5948. mask=[False, True, False, False, False, False],
  5949. fill_value=999999)
  5950. """
  5951. d = np.concatenate([getdata(a) for a in arrays], axis)
  5952. rcls = get_masked_subclass(*arrays)
  5953. data = d.view(rcls)
  5954. # Check whether one of the arrays has a non-empty mask.
  5955. for x in arrays:
  5956. if getmask(x) is not nomask:
  5957. break
  5958. else:
  5959. return data
  5960. # OK, so we have to concatenate the masks
  5961. dm = np.concatenate([getmaskarray(a) for a in arrays], axis)
  5962. dm = dm.reshape(d.shape)
  5963. # If we decide to keep a '_shrinkmask' option, we want to check that
  5964. # all of them are True, and then check for dm.any()
  5965. data._mask = _shrink_mask(dm)
  5966. return data
  5967. def diag(v, k=0):
  5968. """
  5969. Extract a diagonal or construct a diagonal array.
  5970. This function is the equivalent of `numpy.diag` that takes masked
  5971. values into account, see `numpy.diag` for details.
  5972. See Also
  5973. --------
  5974. numpy.diag : Equivalent function for ndarrays.
  5975. """
  5976. output = np.diag(v, k).view(MaskedArray)
  5977. if getmask(v) is not nomask:
  5978. output._mask = np.diag(v._mask, k)
  5979. return output
  5980. def left_shift(a, n):
  5981. """
  5982. Shift the bits of an integer to the left.
  5983. This is the masked array version of `numpy.left_shift`, for details
  5984. see that function.
  5985. See Also
  5986. --------
  5987. numpy.left_shift
  5988. """
  5989. m = getmask(a)
  5990. if m is nomask:
  5991. d = umath.left_shift(filled(a), n)
  5992. return masked_array(d)
  5993. else:
  5994. d = umath.left_shift(filled(a, 0), n)
  5995. return masked_array(d, mask=m)
  5996. def right_shift(a, n):
  5997. """
  5998. Shift the bits of an integer to the right.
  5999. This is the masked array version of `numpy.right_shift`, for details
  6000. see that function.
  6001. See Also
  6002. --------
  6003. numpy.right_shift
  6004. """
  6005. m = getmask(a)
  6006. if m is nomask:
  6007. d = umath.right_shift(filled(a), n)
  6008. return masked_array(d)
  6009. else:
  6010. d = umath.right_shift(filled(a, 0), n)
  6011. return masked_array(d, mask=m)
  6012. def put(a, indices, values, mode='raise'):
  6013. """
  6014. Set storage-indexed locations to corresponding values.
  6015. This function is equivalent to `MaskedArray.put`, see that method
  6016. for details.
  6017. See Also
  6018. --------
  6019. MaskedArray.put
  6020. """
  6021. # We can't use 'frommethod', the order of arguments is different
  6022. try:
  6023. return a.put(indices, values, mode=mode)
  6024. except AttributeError:
  6025. return narray(a, copy=False).put(indices, values, mode=mode)
  6026. def putmask(a, mask, values): # , mode='raise'):
  6027. """
  6028. Changes elements of an array based on conditional and input values.
  6029. This is the masked array version of `numpy.putmask`, for details see
  6030. `numpy.putmask`.
  6031. See Also
  6032. --------
  6033. numpy.putmask
  6034. Notes
  6035. -----
  6036. Using a masked array as `values` will **not** transform a `ndarray` into
  6037. a `MaskedArray`.
  6038. """
  6039. # We can't use 'frommethod', the order of arguments is different
  6040. if not isinstance(a, MaskedArray):
  6041. a = a.view(MaskedArray)
  6042. (valdata, valmask) = (getdata(values), getmask(values))
  6043. if getmask(a) is nomask:
  6044. if valmask is not nomask:
  6045. a._sharedmask = True
  6046. a._mask = make_mask_none(a.shape, a.dtype)
  6047. np.copyto(a._mask, valmask, where=mask)
  6048. elif a._hardmask:
  6049. if valmask is not nomask:
  6050. m = a._mask.copy()
  6051. np.copyto(m, valmask, where=mask)
  6052. a.mask |= m
  6053. else:
  6054. if valmask is nomask:
  6055. valmask = getmaskarray(values)
  6056. np.copyto(a._mask, valmask, where=mask)
  6057. np.copyto(a._data, valdata, where=mask)
  6058. return
  6059. def transpose(a, axes=None):
  6060. """
  6061. Permute the dimensions of an array.
  6062. This function is exactly equivalent to `numpy.transpose`.
  6063. See Also
  6064. --------
  6065. numpy.transpose : Equivalent function in top-level NumPy module.
  6066. Examples
  6067. --------
  6068. >>> import numpy.ma as ma
  6069. >>> x = ma.arange(4).reshape((2,2))
  6070. >>> x[1, 1] = ma.masked
  6071. >>> x
  6072. masked_array(
  6073. data=[[0, 1],
  6074. [2, --]],
  6075. mask=[[False, False],
  6076. [False, True]],
  6077. fill_value=999999)
  6078. >>> ma.transpose(x)
  6079. masked_array(
  6080. data=[[0, 2],
  6081. [1, --]],
  6082. mask=[[False, False],
  6083. [False, True]],
  6084. fill_value=999999)
  6085. """
  6086. # We can't use 'frommethod', as 'transpose' doesn't take keywords
  6087. try:
  6088. return a.transpose(axes)
  6089. except AttributeError:
  6090. return narray(a, copy=False).transpose(axes).view(MaskedArray)
  6091. def reshape(a, new_shape, order='C'):
  6092. """
  6093. Returns an array containing the same data with a new shape.
  6094. Refer to `MaskedArray.reshape` for full documentation.
  6095. See Also
  6096. --------
  6097. MaskedArray.reshape : equivalent function
  6098. """
  6099. # We can't use 'frommethod', it whine about some parameters. Dmmit.
  6100. try:
  6101. return a.reshape(new_shape, order=order)
  6102. except AttributeError:
  6103. _tmp = narray(a, copy=False).reshape(new_shape, order=order)
  6104. return _tmp.view(MaskedArray)
  6105. def resize(x, new_shape):
  6106. """
  6107. Return a new masked array with the specified size and shape.
  6108. This is the masked equivalent of the `numpy.resize` function. The new
  6109. array is filled with repeated copies of `x` (in the order that the
  6110. data are stored in memory). If `x` is masked, the new array will be
  6111. masked, and the new mask will be a repetition of the old one.
  6112. See Also
  6113. --------
  6114. numpy.resize : Equivalent function in the top level NumPy module.
  6115. Examples
  6116. --------
  6117. >>> import numpy.ma as ma
  6118. >>> a = ma.array([[1, 2] ,[3, 4]])
  6119. >>> a[0, 1] = ma.masked
  6120. >>> a
  6121. masked_array(
  6122. data=[[1, --],
  6123. [3, 4]],
  6124. mask=[[False, True],
  6125. [False, False]],
  6126. fill_value=999999)
  6127. >>> np.resize(a, (3, 3))
  6128. masked_array(
  6129. data=[[1, 2, 3],
  6130. [4, 1, 2],
  6131. [3, 4, 1]],
  6132. mask=False,
  6133. fill_value=999999)
  6134. >>> ma.resize(a, (3, 3))
  6135. masked_array(
  6136. data=[[1, --, 3],
  6137. [4, 1, --],
  6138. [3, 4, 1]],
  6139. mask=[[False, True, False],
  6140. [False, False, True],
  6141. [False, False, False]],
  6142. fill_value=999999)
  6143. A MaskedArray is always returned, regardless of the input type.
  6144. >>> a = np.array([[1, 2] ,[3, 4]])
  6145. >>> ma.resize(a, (3, 3))
  6146. masked_array(
  6147. data=[[1, 2, 3],
  6148. [4, 1, 2],
  6149. [3, 4, 1]],
  6150. mask=False,
  6151. fill_value=999999)
  6152. """
  6153. # We can't use _frommethods here, as N.resize is notoriously whiny.
  6154. m = getmask(x)
  6155. if m is not nomask:
  6156. m = np.resize(m, new_shape)
  6157. result = np.resize(x, new_shape).view(get_masked_subclass(x))
  6158. if result.ndim:
  6159. result._mask = m
  6160. return result
  6161. def ndim(obj):
  6162. """
  6163. maskedarray version of the numpy function.
  6164. """
  6165. return np.ndim(getdata(obj))
  6166. ndim.__doc__ = np.ndim.__doc__
  6167. def shape(obj):
  6168. "maskedarray version of the numpy function."
  6169. return np.shape(getdata(obj))
  6170. shape.__doc__ = np.shape.__doc__
  6171. def size(obj, axis=None):
  6172. "maskedarray version of the numpy function."
  6173. return np.size(getdata(obj), axis)
  6174. size.__doc__ = np.size.__doc__
  6175. ##############################################################################
  6176. # Extra functions #
  6177. ##############################################################################
  6178. def where(condition, x=_NoValue, y=_NoValue):
  6179. """
  6180. Return a masked array with elements from `x` or `y`, depending on condition.
  6181. .. note::
  6182. When only `condition` is provided, this function is identical to
  6183. `nonzero`. The rest of this documentation covers only the case where
  6184. all three arguments are provided.
  6185. Parameters
  6186. ----------
  6187. condition : array_like, bool
  6188. Where True, yield `x`, otherwise yield `y`.
  6189. x, y : array_like, optional
  6190. Values from which to choose. `x`, `y` and `condition` need to be
  6191. broadcastable to some shape.
  6192. Returns
  6193. -------
  6194. out : MaskedArray
  6195. An masked array with `masked` elements where the condition is masked,
  6196. elements from `x` where `condition` is True, and elements from `y`
  6197. elsewhere.
  6198. See Also
  6199. --------
  6200. numpy.where : Equivalent function in the top-level NumPy module.
  6201. nonzero : The function that is called when x and y are omitted
  6202. Examples
  6203. --------
  6204. >>> x = np.ma.array(np.arange(9.).reshape(3, 3), mask=[[0, 1, 0],
  6205. ... [1, 0, 1],
  6206. ... [0, 1, 0]])
  6207. >>> x
  6208. masked_array(
  6209. data=[[0.0, --, 2.0],
  6210. [--, 4.0, --],
  6211. [6.0, --, 8.0]],
  6212. mask=[[False, True, False],
  6213. [ True, False, True],
  6214. [False, True, False]],
  6215. fill_value=1e+20)
  6216. >>> np.ma.where(x > 5, x, -3.1416)
  6217. masked_array(
  6218. data=[[-3.1416, --, -3.1416],
  6219. [--, -3.1416, --],
  6220. [6.0, --, 8.0]],
  6221. mask=[[False, True, False],
  6222. [ True, False, True],
  6223. [False, True, False]],
  6224. fill_value=1e+20)
  6225. """
  6226. # handle the single-argument case
  6227. missing = (x is _NoValue, y is _NoValue).count(True)
  6228. if missing == 1:
  6229. raise ValueError("Must provide both 'x' and 'y' or neither.")
  6230. if missing == 2:
  6231. return nonzero(condition)
  6232. # we only care if the condition is true - false or masked pick y
  6233. cf = filled(condition, False)
  6234. xd = getdata(x)
  6235. yd = getdata(y)
  6236. # we need the full arrays here for correct final dimensions
  6237. cm = getmaskarray(condition)
  6238. xm = getmaskarray(x)
  6239. ym = getmaskarray(y)
  6240. # deal with the fact that masked.dtype == float64, but we don't actually
  6241. # want to treat it as that.
  6242. if x is masked and y is not masked:
  6243. xd = np.zeros((), dtype=yd.dtype)
  6244. xm = np.ones((), dtype=ym.dtype)
  6245. elif y is masked and x is not masked:
  6246. yd = np.zeros((), dtype=xd.dtype)
  6247. ym = np.ones((), dtype=xm.dtype)
  6248. data = np.where(cf, xd, yd)
  6249. mask = np.where(cf, xm, ym)
  6250. mask = np.where(cm, np.ones((), dtype=mask.dtype), mask)
  6251. # collapse the mask, for backwards compatibility
  6252. mask = _shrink_mask(mask)
  6253. return masked_array(data, mask=mask)
  6254. def choose(indices, choices, out=None, mode='raise'):
  6255. """
  6256. Use an index array to construct a new array from a list of choices.
  6257. Given an array of integers and a list of n choice arrays, this method
  6258. will create a new array that merges each of the choice arrays. Where a
  6259. value in `index` is i, the new array will have the value that choices[i]
  6260. contains in the same place.
  6261. Parameters
  6262. ----------
  6263. indices : ndarray of ints
  6264. This array must contain integers in ``[0, n-1]``, where n is the
  6265. number of choices.
  6266. choices : sequence of arrays
  6267. Choice arrays. The index array and all of the choices should be
  6268. broadcastable to the same shape.
  6269. out : array, optional
  6270. If provided, the result will be inserted into this array. It should
  6271. be of the appropriate shape and `dtype`.
  6272. mode : {'raise', 'wrap', 'clip'}, optional
  6273. Specifies how out-of-bounds indices will behave.
  6274. * 'raise' : raise an error
  6275. * 'wrap' : wrap around
  6276. * 'clip' : clip to the range
  6277. Returns
  6278. -------
  6279. merged_array : array
  6280. See Also
  6281. --------
  6282. choose : equivalent function
  6283. Examples
  6284. --------
  6285. >>> choice = np.array([[1,1,1], [2,2,2], [3,3,3]])
  6286. >>> a = np.array([2, 1, 0])
  6287. >>> np.ma.choose(a, choice)
  6288. masked_array(data=[3, 2, 1],
  6289. mask=False,
  6290. fill_value=999999)
  6291. """
  6292. def fmask(x):
  6293. "Returns the filled array, or True if masked."
  6294. if x is masked:
  6295. return True
  6296. return filled(x)
  6297. def nmask(x):
  6298. "Returns the mask, True if ``masked``, False if ``nomask``."
  6299. if x is masked:
  6300. return True
  6301. return getmask(x)
  6302. # Get the indices.
  6303. c = filled(indices, 0)
  6304. # Get the masks.
  6305. masks = [nmask(x) for x in choices]
  6306. data = [fmask(x) for x in choices]
  6307. # Construct the mask
  6308. outputmask = np.choose(c, masks, mode=mode)
  6309. outputmask = make_mask(mask_or(outputmask, getmask(indices)),
  6310. copy=False, shrink=True)
  6311. # Get the choices.
  6312. d = np.choose(c, data, mode=mode, out=out).view(MaskedArray)
  6313. if out is not None:
  6314. if isinstance(out, MaskedArray):
  6315. out.__setmask__(outputmask)
  6316. return out
  6317. d.__setmask__(outputmask)
  6318. return d
  6319. def round_(a, decimals=0, out=None):
  6320. """
  6321. Return a copy of a, rounded to 'decimals' places.
  6322. When 'decimals' is negative, it specifies the number of positions
  6323. to the left of the decimal point. The real and imaginary parts of
  6324. complex numbers are rounded separately. Nothing is done if the
  6325. array is not of float type and 'decimals' is greater than or equal
  6326. to 0.
  6327. Parameters
  6328. ----------
  6329. decimals : int
  6330. Number of decimals to round to. May be negative.
  6331. out : array_like
  6332. Existing array to use for output.
  6333. If not given, returns a default copy of a.
  6334. Notes
  6335. -----
  6336. If out is given and does not have a mask attribute, the mask of a
  6337. is lost!
  6338. Examples
  6339. --------
  6340. >>> import numpy.ma as ma
  6341. >>> x = [11.2, -3.973, 0.801, -1.41]
  6342. >>> mask = [0, 0, 0, 1]
  6343. >>> masked_x = ma.masked_array(x, mask)
  6344. >>> masked_x
  6345. masked_array(data=[11.2, -3.973, 0.801, --],
  6346. mask=[False, False, False, True],
  6347. fill_value=1e+20)
  6348. >>> ma.round_(masked_x)
  6349. masked_array(data=[11.0, -4.0, 1.0, --],
  6350. mask=[False, False, False, True],
  6351. fill_value=1e+20)
  6352. >>> ma.round(masked_x, decimals=1)
  6353. masked_array(data=[11.2, -4.0, 0.8, --],
  6354. mask=[False, False, False, True],
  6355. fill_value=1e+20)
  6356. >>> ma.round_(masked_x, decimals=-1)
  6357. masked_array(data=[10.0, -0.0, 0.0, --],
  6358. mask=[False, False, False, True],
  6359. fill_value=1e+20)
  6360. """
  6361. if out is None:
  6362. return np.round_(a, decimals, out)
  6363. else:
  6364. np.round_(getdata(a), decimals, out)
  6365. if hasattr(out, '_mask'):
  6366. out._mask = getmask(a)
  6367. return out
  6368. round = round_
  6369. # Needed by dot, so move here from extras.py. It will still be exported
  6370. # from extras.py for compatibility.
  6371. def mask_rowcols(a, axis=None):
  6372. """
  6373. Mask rows and/or columns of a 2D array that contain masked values.
  6374. Mask whole rows and/or columns of a 2D array that contain
  6375. masked values. The masking behavior is selected using the
  6376. `axis` parameter.
  6377. - If `axis` is None, rows *and* columns are masked.
  6378. - If `axis` is 0, only rows are masked.
  6379. - If `axis` is 1 or -1, only columns are masked.
  6380. Parameters
  6381. ----------
  6382. a : array_like, MaskedArray
  6383. The array to mask. If not a MaskedArray instance (or if no array
  6384. elements are masked). The result is a MaskedArray with `mask` set
  6385. to `nomask` (False). Must be a 2D array.
  6386. axis : int, optional
  6387. Axis along which to perform the operation. If None, applies to a
  6388. flattened version of the array.
  6389. Returns
  6390. -------
  6391. a : MaskedArray
  6392. A modified version of the input array, masked depending on the value
  6393. of the `axis` parameter.
  6394. Raises
  6395. ------
  6396. NotImplementedError
  6397. If input array `a` is not 2D.
  6398. See Also
  6399. --------
  6400. mask_rows : Mask rows of a 2D array that contain masked values.
  6401. mask_cols : Mask cols of a 2D array that contain masked values.
  6402. masked_where : Mask where a condition is met.
  6403. Notes
  6404. -----
  6405. The input array's mask is modified by this function.
  6406. Examples
  6407. --------
  6408. >>> import numpy.ma as ma
  6409. >>> a = np.zeros((3, 3), dtype=int)
  6410. >>> a[1, 1] = 1
  6411. >>> a
  6412. array([[0, 0, 0],
  6413. [0, 1, 0],
  6414. [0, 0, 0]])
  6415. >>> a = ma.masked_equal(a, 1)
  6416. >>> a
  6417. masked_array(
  6418. data=[[0, 0, 0],
  6419. [0, --, 0],
  6420. [0, 0, 0]],
  6421. mask=[[False, False, False],
  6422. [False, True, False],
  6423. [False, False, False]],
  6424. fill_value=1)
  6425. >>> ma.mask_rowcols(a)
  6426. masked_array(
  6427. data=[[0, --, 0],
  6428. [--, --, --],
  6429. [0, --, 0]],
  6430. mask=[[False, True, False],
  6431. [ True, True, True],
  6432. [False, True, False]],
  6433. fill_value=1)
  6434. """
  6435. a = array(a, subok=False)
  6436. if a.ndim != 2:
  6437. raise NotImplementedError("mask_rowcols works for 2D arrays only.")
  6438. m = getmask(a)
  6439. # Nothing is masked: return a
  6440. if m is nomask or not m.any():
  6441. return a
  6442. maskedval = m.nonzero()
  6443. a._mask = a._mask.copy()
  6444. if not axis:
  6445. a[np.unique(maskedval[0])] = masked
  6446. if axis in [None, 1, -1]:
  6447. a[:, np.unique(maskedval[1])] = masked
  6448. return a
  6449. # Include masked dot here to avoid import problems in getting it from
  6450. # extras.py. Note that it is not included in __all__, but rather exported
  6451. # from extras in order to avoid backward compatibility problems.
  6452. def dot(a, b, strict=False, out=None):
  6453. """
  6454. Return the dot product of two arrays.
  6455. This function is the equivalent of `numpy.dot` that takes masked values
  6456. into account. Note that `strict` and `out` are in different position
  6457. than in the method version. In order to maintain compatibility with the
  6458. corresponding method, it is recommended that the optional arguments be
  6459. treated as keyword only. At some point that may be mandatory.
  6460. .. note::
  6461. Works only with 2-D arrays at the moment.
  6462. Parameters
  6463. ----------
  6464. a, b : masked_array_like
  6465. Inputs arrays.
  6466. strict : bool, optional
  6467. Whether masked data are propagated (True) or set to 0 (False) for
  6468. the computation. Default is False. Propagating the mask means that
  6469. if a masked value appears in a row or column, the whole row or
  6470. column is considered masked.
  6471. out : masked_array, optional
  6472. Output argument. This must have the exact kind that would be returned
  6473. if it was not used. In particular, it must have the right type, must be
  6474. C-contiguous, and its dtype must be the dtype that would be returned
  6475. for `dot(a,b)`. This is a performance feature. Therefore, if these
  6476. conditions are not met, an exception is raised, instead of attempting
  6477. to be flexible.
  6478. .. versionadded:: 1.10.2
  6479. See Also
  6480. --------
  6481. numpy.dot : Equivalent function for ndarrays.
  6482. Examples
  6483. --------
  6484. >>> a = np.ma.array([[1, 2, 3], [4, 5, 6]], mask=[[1, 0, 0], [0, 0, 0]])
  6485. >>> b = np.ma.array([[1, 2], [3, 4], [5, 6]], mask=[[1, 0], [0, 0], [0, 0]])
  6486. >>> np.ma.dot(a, b)
  6487. masked_array(
  6488. data=[[21, 26],
  6489. [45, 64]],
  6490. mask=[[False, False],
  6491. [False, False]],
  6492. fill_value=999999)
  6493. >>> np.ma.dot(a, b, strict=True)
  6494. masked_array(
  6495. data=[[--, --],
  6496. [--, 64]],
  6497. mask=[[ True, True],
  6498. [ True, False]],
  6499. fill_value=999999)
  6500. """
  6501. # !!!: Works only with 2D arrays. There should be a way to get it to run
  6502. # with higher dimension
  6503. if strict and (a.ndim == 2) and (b.ndim == 2):
  6504. a = mask_rowcols(a, 0)
  6505. b = mask_rowcols(b, 1)
  6506. am = ~getmaskarray(a)
  6507. bm = ~getmaskarray(b)
  6508. if out is None:
  6509. d = np.dot(filled(a, 0), filled(b, 0))
  6510. m = ~np.dot(am, bm)
  6511. if d.ndim == 0:
  6512. d = np.asarray(d)
  6513. r = d.view(get_masked_subclass(a, b))
  6514. r.__setmask__(m)
  6515. return r
  6516. else:
  6517. d = np.dot(filled(a, 0), filled(b, 0), out._data)
  6518. if out.mask.shape != d.shape:
  6519. out._mask = np.empty(d.shape, MaskType)
  6520. np.dot(am, bm, out._mask)
  6521. np.logical_not(out._mask, out._mask)
  6522. return out
  6523. def inner(a, b):
  6524. """
  6525. Returns the inner product of a and b for arrays of floating point types.
  6526. Like the generic NumPy equivalent the product sum is over the last dimension
  6527. of a and b. The first argument is not conjugated.
  6528. """
  6529. fa = filled(a, 0)
  6530. fb = filled(b, 0)
  6531. if fa.ndim == 0:
  6532. fa.shape = (1,)
  6533. if fb.ndim == 0:
  6534. fb.shape = (1,)
  6535. return np.inner(fa, fb).view(MaskedArray)
  6536. inner.__doc__ = doc_note(np.inner.__doc__,
  6537. "Masked values are replaced by 0.")
  6538. innerproduct = inner
  6539. def outer(a, b):
  6540. "maskedarray version of the numpy function."
  6541. fa = filled(a, 0).ravel()
  6542. fb = filled(b, 0).ravel()
  6543. d = np.outer(fa, fb)
  6544. ma = getmask(a)
  6545. mb = getmask(b)
  6546. if ma is nomask and mb is nomask:
  6547. return masked_array(d)
  6548. ma = getmaskarray(a)
  6549. mb = getmaskarray(b)
  6550. m = make_mask(1 - np.outer(1 - ma, 1 - mb), copy=False)
  6551. return masked_array(d, mask=m)
  6552. outer.__doc__ = doc_note(np.outer.__doc__,
  6553. "Masked values are replaced by 0.")
  6554. outerproduct = outer
  6555. def _convolve_or_correlate(f, a, v, mode, propagate_mask):
  6556. """
  6557. Helper function for ma.correlate and ma.convolve
  6558. """
  6559. if propagate_mask:
  6560. # results which are contributed to by either item in any pair being invalid
  6561. mask = (
  6562. f(getmaskarray(a), np.ones(np.shape(v), dtype=bool), mode=mode)
  6563. | f(np.ones(np.shape(a), dtype=bool), getmaskarray(v), mode=mode)
  6564. )
  6565. data = f(getdata(a), getdata(v), mode=mode)
  6566. else:
  6567. # results which are not contributed to by any pair of valid elements
  6568. mask = ~f(~getmaskarray(a), ~getmaskarray(v))
  6569. data = f(filled(a, 0), filled(v, 0), mode=mode)
  6570. return masked_array(data, mask=mask)
  6571. def correlate(a, v, mode='valid', propagate_mask=True):
  6572. """
  6573. Cross-correlation of two 1-dimensional sequences.
  6574. Parameters
  6575. ----------
  6576. a, v : array_like
  6577. Input sequences.
  6578. mode : {'valid', 'same', 'full'}, optional
  6579. Refer to the `np.convolve` docstring. Note that the default
  6580. is 'valid', unlike `convolve`, which uses 'full'.
  6581. propagate_mask : bool
  6582. If True, then a result element is masked if any masked element contributes towards it.
  6583. If False, then a result element is only masked if no non-masked element
  6584. contribute towards it
  6585. Returns
  6586. -------
  6587. out : MaskedArray
  6588. Discrete cross-correlation of `a` and `v`.
  6589. See Also
  6590. --------
  6591. numpy.correlate : Equivalent function in the top-level NumPy module.
  6592. """
  6593. return _convolve_or_correlate(np.correlate, a, v, mode, propagate_mask)
  6594. def convolve(a, v, mode='full', propagate_mask=True):
  6595. """
  6596. Returns the discrete, linear convolution of two one-dimensional sequences.
  6597. Parameters
  6598. ----------
  6599. a, v : array_like
  6600. Input sequences.
  6601. mode : {'valid', 'same', 'full'}, optional
  6602. Refer to the `np.convolve` docstring.
  6603. propagate_mask : bool
  6604. If True, then if any masked element is included in the sum for a result
  6605. element, then the result is masked.
  6606. If False, then the result element is only masked if no non-masked cells
  6607. contribute towards it
  6608. Returns
  6609. -------
  6610. out : MaskedArray
  6611. Discrete, linear convolution of `a` and `v`.
  6612. See Also
  6613. --------
  6614. numpy.convolve : Equivalent function in the top-level NumPy module.
  6615. """
  6616. return _convolve_or_correlate(np.convolve, a, v, mode, propagate_mask)
  6617. def allequal(a, b, fill_value=True):
  6618. """
  6619. Return True if all entries of a and b are equal, using
  6620. fill_value as a truth value where either or both are masked.
  6621. Parameters
  6622. ----------
  6623. a, b : array_like
  6624. Input arrays to compare.
  6625. fill_value : bool, optional
  6626. Whether masked values in a or b are considered equal (True) or not
  6627. (False).
  6628. Returns
  6629. -------
  6630. y : bool
  6631. Returns True if the two arrays are equal within the given
  6632. tolerance, False otherwise. If either array contains NaN,
  6633. then False is returned.
  6634. See Also
  6635. --------
  6636. all, any
  6637. numpy.ma.allclose
  6638. Examples
  6639. --------
  6640. >>> a = np.ma.array([1e10, 1e-7, 42.0], mask=[0, 0, 1])
  6641. >>> a
  6642. masked_array(data=[10000000000.0, 1e-07, --],
  6643. mask=[False, False, True],
  6644. fill_value=1e+20)
  6645. >>> b = np.array([1e10, 1e-7, -42.0])
  6646. >>> b
  6647. array([ 1.00000000e+10, 1.00000000e-07, -4.20000000e+01])
  6648. >>> np.ma.allequal(a, b, fill_value=False)
  6649. False
  6650. >>> np.ma.allequal(a, b)
  6651. True
  6652. """
  6653. m = mask_or(getmask(a), getmask(b))
  6654. if m is nomask:
  6655. x = getdata(a)
  6656. y = getdata(b)
  6657. d = umath.equal(x, y)
  6658. return d.all()
  6659. elif fill_value:
  6660. x = getdata(a)
  6661. y = getdata(b)
  6662. d = umath.equal(x, y)
  6663. dm = array(d, mask=m, copy=False)
  6664. return dm.filled(True).all(None)
  6665. else:
  6666. return False
  6667. def allclose(a, b, masked_equal=True, rtol=1e-5, atol=1e-8):
  6668. """
  6669. Returns True if two arrays are element-wise equal within a tolerance.
  6670. This function is equivalent to `allclose` except that masked values
  6671. are treated as equal (default) or unequal, depending on the `masked_equal`
  6672. argument.
  6673. Parameters
  6674. ----------
  6675. a, b : array_like
  6676. Input arrays to compare.
  6677. masked_equal : bool, optional
  6678. Whether masked values in `a` and `b` are considered equal (True) or not
  6679. (False). They are considered equal by default.
  6680. rtol : float, optional
  6681. Relative tolerance. The relative difference is equal to ``rtol * b``.
  6682. Default is 1e-5.
  6683. atol : float, optional
  6684. Absolute tolerance. The absolute difference is equal to `atol`.
  6685. Default is 1e-8.
  6686. Returns
  6687. -------
  6688. y : bool
  6689. Returns True if the two arrays are equal within the given
  6690. tolerance, False otherwise. If either array contains NaN, then
  6691. False is returned.
  6692. See Also
  6693. --------
  6694. all, any
  6695. numpy.allclose : the non-masked `allclose`.
  6696. Notes
  6697. -----
  6698. If the following equation is element-wise True, then `allclose` returns
  6699. True::
  6700. absolute(`a` - `b`) <= (`atol` + `rtol` * absolute(`b`))
  6701. Return True if all elements of `a` and `b` are equal subject to
  6702. given tolerances.
  6703. Examples
  6704. --------
  6705. >>> a = np.ma.array([1e10, 1e-7, 42.0], mask=[0, 0, 1])
  6706. >>> a
  6707. masked_array(data=[10000000000.0, 1e-07, --],
  6708. mask=[False, False, True],
  6709. fill_value=1e+20)
  6710. >>> b = np.ma.array([1e10, 1e-8, -42.0], mask=[0, 0, 1])
  6711. >>> np.ma.allclose(a, b)
  6712. False
  6713. >>> a = np.ma.array([1e10, 1e-8, 42.0], mask=[0, 0, 1])
  6714. >>> b = np.ma.array([1.00001e10, 1e-9, -42.0], mask=[0, 0, 1])
  6715. >>> np.ma.allclose(a, b)
  6716. True
  6717. >>> np.ma.allclose(a, b, masked_equal=False)
  6718. False
  6719. Masked values are not compared directly.
  6720. >>> a = np.ma.array([1e10, 1e-8, 42.0], mask=[0, 0, 1])
  6721. >>> b = np.ma.array([1.00001e10, 1e-9, 42.0], mask=[0, 0, 1])
  6722. >>> np.ma.allclose(a, b)
  6723. True
  6724. >>> np.ma.allclose(a, b, masked_equal=False)
  6725. False
  6726. """
  6727. x = masked_array(a, copy=False)
  6728. y = masked_array(b, copy=False)
  6729. # make sure y is an inexact type to avoid abs(MIN_INT); will cause
  6730. # casting of x later.
  6731. # NOTE: We explicitly allow timedelta, which used to work. This could
  6732. # possibly be deprecated. See also gh-18286.
  6733. # timedelta works if `atol` is an integer or also a timedelta.
  6734. # Although, the default tolerances are unlikely to be useful
  6735. if y.dtype.kind != "m":
  6736. dtype = np.result_type(y, 1.)
  6737. if y.dtype != dtype:
  6738. y = masked_array(y, dtype=dtype, copy=False)
  6739. m = mask_or(getmask(x), getmask(y))
  6740. xinf = np.isinf(masked_array(x, copy=False, mask=m)).filled(False)
  6741. # If we have some infs, they should fall at the same place.
  6742. if not np.all(xinf == filled(np.isinf(y), False)):
  6743. return False
  6744. # No infs at all
  6745. if not np.any(xinf):
  6746. d = filled(less_equal(absolute(x - y), atol + rtol * absolute(y)),
  6747. masked_equal)
  6748. return np.all(d)
  6749. if not np.all(filled(x[xinf] == y[xinf], masked_equal)):
  6750. return False
  6751. x = x[~xinf]
  6752. y = y[~xinf]
  6753. d = filled(less_equal(absolute(x - y), atol + rtol * absolute(y)),
  6754. masked_equal)
  6755. return np.all(d)
  6756. def asarray(a, dtype=None, order=None):
  6757. """
  6758. Convert the input to a masked array of the given data-type.
  6759. No copy is performed if the input is already an `ndarray`. If `a` is
  6760. a subclass of `MaskedArray`, a base class `MaskedArray` is returned.
  6761. Parameters
  6762. ----------
  6763. a : array_like
  6764. Input data, in any form that can be converted to a masked array. This
  6765. includes lists, lists of tuples, tuples, tuples of tuples, tuples
  6766. of lists, ndarrays and masked arrays.
  6767. dtype : dtype, optional
  6768. By default, the data-type is inferred from the input data.
  6769. order : {'C', 'F'}, optional
  6770. Whether to use row-major ('C') or column-major ('FORTRAN') memory
  6771. representation. Default is 'C'.
  6772. Returns
  6773. -------
  6774. out : MaskedArray
  6775. Masked array interpretation of `a`.
  6776. See Also
  6777. --------
  6778. asanyarray : Similar to `asarray`, but conserves subclasses.
  6779. Examples
  6780. --------
  6781. >>> x = np.arange(10.).reshape(2, 5)
  6782. >>> x
  6783. array([[0., 1., 2., 3., 4.],
  6784. [5., 6., 7., 8., 9.]])
  6785. >>> np.ma.asarray(x)
  6786. masked_array(
  6787. data=[[0., 1., 2., 3., 4.],
  6788. [5., 6., 7., 8., 9.]],
  6789. mask=False,
  6790. fill_value=1e+20)
  6791. >>> type(np.ma.asarray(x))
  6792. <class 'numpy.ma.core.MaskedArray'>
  6793. """
  6794. order = order or 'C'
  6795. return masked_array(a, dtype=dtype, copy=False, keep_mask=True,
  6796. subok=False, order=order)
  6797. def asanyarray(a, dtype=None):
  6798. """
  6799. Convert the input to a masked array, conserving subclasses.
  6800. If `a` is a subclass of `MaskedArray`, its class is conserved.
  6801. No copy is performed if the input is already an `ndarray`.
  6802. Parameters
  6803. ----------
  6804. a : array_like
  6805. Input data, in any form that can be converted to an array.
  6806. dtype : dtype, optional
  6807. By default, the data-type is inferred from the input data.
  6808. order : {'C', 'F'}, optional
  6809. Whether to use row-major ('C') or column-major ('FORTRAN') memory
  6810. representation. Default is 'C'.
  6811. Returns
  6812. -------
  6813. out : MaskedArray
  6814. MaskedArray interpretation of `a`.
  6815. See Also
  6816. --------
  6817. asarray : Similar to `asanyarray`, but does not conserve subclass.
  6818. Examples
  6819. --------
  6820. >>> x = np.arange(10.).reshape(2, 5)
  6821. >>> x
  6822. array([[0., 1., 2., 3., 4.],
  6823. [5., 6., 7., 8., 9.]])
  6824. >>> np.ma.asanyarray(x)
  6825. masked_array(
  6826. data=[[0., 1., 2., 3., 4.],
  6827. [5., 6., 7., 8., 9.]],
  6828. mask=False,
  6829. fill_value=1e+20)
  6830. >>> type(np.ma.asanyarray(x))
  6831. <class 'numpy.ma.core.MaskedArray'>
  6832. """
  6833. # workaround for #8666, to preserve identity. Ideally the bottom line
  6834. # would handle this for us.
  6835. if isinstance(a, MaskedArray) and (dtype is None or dtype == a.dtype):
  6836. return a
  6837. return masked_array(a, dtype=dtype, copy=False, keep_mask=True, subok=True)
  6838. ##############################################################################
  6839. # Pickling #
  6840. ##############################################################################
  6841. def fromfile(file, dtype=float, count=-1, sep=''):
  6842. raise NotImplementedError(
  6843. "fromfile() not yet implemented for a MaskedArray.")
  6844. def fromflex(fxarray):
  6845. """
  6846. Build a masked array from a suitable flexible-type array.
  6847. The input array has to have a data-type with ``_data`` and ``_mask``
  6848. fields. This type of array is output by `MaskedArray.toflex`.
  6849. Parameters
  6850. ----------
  6851. fxarray : ndarray
  6852. The structured input array, containing ``_data`` and ``_mask``
  6853. fields. If present, other fields are discarded.
  6854. Returns
  6855. -------
  6856. result : MaskedArray
  6857. The constructed masked array.
  6858. See Also
  6859. --------
  6860. MaskedArray.toflex : Build a flexible-type array from a masked array.
  6861. Examples
  6862. --------
  6863. >>> x = np.ma.array(np.arange(9).reshape(3, 3), mask=[0] + [1, 0] * 4)
  6864. >>> rec = x.toflex()
  6865. >>> rec
  6866. array([[(0, False), (1, True), (2, False)],
  6867. [(3, True), (4, False), (5, True)],
  6868. [(6, False), (7, True), (8, False)]],
  6869. dtype=[('_data', '<i8'), ('_mask', '?')])
  6870. >>> x2 = np.ma.fromflex(rec)
  6871. >>> x2
  6872. masked_array(
  6873. data=[[0, --, 2],
  6874. [--, 4, --],
  6875. [6, --, 8]],
  6876. mask=[[False, True, False],
  6877. [ True, False, True],
  6878. [False, True, False]],
  6879. fill_value=999999)
  6880. Extra fields can be present in the structured array but are discarded:
  6881. >>> dt = [('_data', '<i4'), ('_mask', '|b1'), ('field3', '<f4')]
  6882. >>> rec2 = np.zeros((2, 2), dtype=dt)
  6883. >>> rec2
  6884. array([[(0, False, 0.), (0, False, 0.)],
  6885. [(0, False, 0.), (0, False, 0.)]],
  6886. dtype=[('_data', '<i4'), ('_mask', '?'), ('field3', '<f4')])
  6887. >>> y = np.ma.fromflex(rec2)
  6888. >>> y
  6889. masked_array(
  6890. data=[[0, 0],
  6891. [0, 0]],
  6892. mask=[[False, False],
  6893. [False, False]],
  6894. fill_value=999999,
  6895. dtype=int32)
  6896. """
  6897. return masked_array(fxarray['_data'], mask=fxarray['_mask'])
  6898. class _convert2ma:
  6899. """
  6900. Convert functions from numpy to numpy.ma.
  6901. Parameters
  6902. ----------
  6903. _methodname : string
  6904. Name of the method to transform.
  6905. """
  6906. __doc__ = None
  6907. def __init__(self, funcname, np_ret, np_ma_ret, params=None):
  6908. self._func = getattr(np, funcname)
  6909. self.__doc__ = self.getdoc(np_ret, np_ma_ret)
  6910. self._extras = params or {}
  6911. def getdoc(self, np_ret, np_ma_ret):
  6912. "Return the doc of the function (from the doc of the method)."
  6913. doc = getattr(self._func, '__doc__', None)
  6914. sig = get_object_signature(self._func)
  6915. if doc:
  6916. doc = self._replace_return_type(doc, np_ret, np_ma_ret)
  6917. # Add the signature of the function at the beginning of the doc
  6918. if sig:
  6919. sig = "%s%s\n" % (self._func.__name__, sig)
  6920. doc = sig + doc
  6921. return doc
  6922. def _replace_return_type(self, doc, np_ret, np_ma_ret):
  6923. """
  6924. Replace documentation of ``np`` function's return type.
  6925. Replaces it with the proper type for the ``np.ma`` function.
  6926. Parameters
  6927. ----------
  6928. doc : str
  6929. The documentation of the ``np`` method.
  6930. np_ret : str
  6931. The return type string of the ``np`` method that we want to
  6932. replace. (e.g. "out : ndarray")
  6933. np_ma_ret : str
  6934. The return type string of the ``np.ma`` method.
  6935. (e.g. "out : MaskedArray")
  6936. """
  6937. if np_ret not in doc:
  6938. raise RuntimeError(
  6939. f"Failed to replace `{np_ret}` with `{np_ma_ret}`. "
  6940. f"The documentation string for return type, {np_ret}, is not "
  6941. f"found in the docstring for `np.{self._func.__name__}`. "
  6942. f"Fix the docstring for `np.{self._func.__name__}` or "
  6943. "update the expected string for return type."
  6944. )
  6945. return doc.replace(np_ret, np_ma_ret)
  6946. def __call__(self, *args, **params):
  6947. # Find the common parameters to the call and the definition
  6948. _extras = self._extras
  6949. common_params = set(params).intersection(_extras)
  6950. # Drop the common parameters from the call
  6951. for p in common_params:
  6952. _extras[p] = params.pop(p)
  6953. # Get the result
  6954. result = self._func.__call__(*args, **params).view(MaskedArray)
  6955. if "fill_value" in common_params:
  6956. result.fill_value = _extras.get("fill_value", None)
  6957. if "hardmask" in common_params:
  6958. result._hardmask = bool(_extras.get("hard_mask", False))
  6959. return result
  6960. arange = _convert2ma(
  6961. 'arange',
  6962. params=dict(fill_value=None, hardmask=False),
  6963. np_ret='arange : ndarray',
  6964. np_ma_ret='arange : MaskedArray',
  6965. )
  6966. clip = _convert2ma(
  6967. 'clip',
  6968. params=dict(fill_value=None, hardmask=False),
  6969. np_ret='clipped_array : ndarray',
  6970. np_ma_ret='clipped_array : MaskedArray',
  6971. )
  6972. diff = _convert2ma(
  6973. 'diff',
  6974. params=dict(fill_value=None, hardmask=False),
  6975. np_ret='diff : ndarray',
  6976. np_ma_ret='diff : MaskedArray',
  6977. )
  6978. empty = _convert2ma(
  6979. 'empty',
  6980. params=dict(fill_value=None, hardmask=False),
  6981. np_ret='out : ndarray',
  6982. np_ma_ret='out : MaskedArray',
  6983. )
  6984. empty_like = _convert2ma(
  6985. 'empty_like',
  6986. np_ret='out : ndarray',
  6987. np_ma_ret='out : MaskedArray',
  6988. )
  6989. frombuffer = _convert2ma(
  6990. 'frombuffer',
  6991. np_ret='out : ndarray',
  6992. np_ma_ret='out: MaskedArray',
  6993. )
  6994. fromfunction = _convert2ma(
  6995. 'fromfunction',
  6996. np_ret='fromfunction : any',
  6997. np_ma_ret='fromfunction: MaskedArray',
  6998. )
  6999. identity = _convert2ma(
  7000. 'identity',
  7001. params=dict(fill_value=None, hardmask=False),
  7002. np_ret='out : ndarray',
  7003. np_ma_ret='out : MaskedArray',
  7004. )
  7005. indices = _convert2ma(
  7006. 'indices',
  7007. params=dict(fill_value=None, hardmask=False),
  7008. np_ret='grid : one ndarray or tuple of ndarrays',
  7009. np_ma_ret='grid : one MaskedArray or tuple of MaskedArrays',
  7010. )
  7011. ones = _convert2ma(
  7012. 'ones',
  7013. params=dict(fill_value=None, hardmask=False),
  7014. np_ret='out : ndarray',
  7015. np_ma_ret='out : MaskedArray',
  7016. )
  7017. ones_like = _convert2ma(
  7018. 'ones_like',
  7019. np_ret='out : ndarray',
  7020. np_ma_ret='out : MaskedArray',
  7021. )
  7022. squeeze = _convert2ma(
  7023. 'squeeze',
  7024. params=dict(fill_value=None, hardmask=False),
  7025. np_ret='squeezed : ndarray',
  7026. np_ma_ret='squeezed : MaskedArray',
  7027. )
  7028. zeros = _convert2ma(
  7029. 'zeros',
  7030. params=dict(fill_value=None, hardmask=False),
  7031. np_ret='out : ndarray',
  7032. np_ma_ret='out : MaskedArray',
  7033. )
  7034. zeros_like = _convert2ma(
  7035. 'zeros_like',
  7036. np_ret='out : ndarray',
  7037. np_ma_ret='out : MaskedArray',
  7038. )
  7039. def append(a, b, axis=None):
  7040. """Append values to the end of an array.
  7041. .. versionadded:: 1.9.0
  7042. Parameters
  7043. ----------
  7044. a : array_like
  7045. Values are appended to a copy of this array.
  7046. b : array_like
  7047. These values are appended to a copy of `a`. It must be of the
  7048. correct shape (the same shape as `a`, excluding `axis`). If `axis`
  7049. is not specified, `b` can be any shape and will be flattened
  7050. before use.
  7051. axis : int, optional
  7052. The axis along which `v` are appended. If `axis` is not given,
  7053. both `a` and `b` are flattened before use.
  7054. Returns
  7055. -------
  7056. append : MaskedArray
  7057. A copy of `a` with `b` appended to `axis`. Note that `append`
  7058. does not occur in-place: a new array is allocated and filled. If
  7059. `axis` is None, the result is a flattened array.
  7060. See Also
  7061. --------
  7062. numpy.append : Equivalent function in the top-level NumPy module.
  7063. Examples
  7064. --------
  7065. >>> import numpy.ma as ma
  7066. >>> a = ma.masked_values([1, 2, 3], 2)
  7067. >>> b = ma.masked_values([[4, 5, 6], [7, 8, 9]], 7)
  7068. >>> ma.append(a, b)
  7069. masked_array(data=[1, --, 3, 4, 5, 6, --, 8, 9],
  7070. mask=[False, True, False, False, False, False, True, False,
  7071. False],
  7072. fill_value=999999)
  7073. """
  7074. return concatenate([a, b], axis)