core.py 250 KB

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