1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399

400

401

402

403

404

405

406

407

408

409

410

411

412

413

414

415

416

417

418

419

420

421

422

423

424

425

426

427

428

429

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

445

446

447

448

449

450

451

452

453

454

455

456

457

458

459

460

461

462

463

464

465

466

467

468

469

470

471

472

473

474

475

476

477

478

479

480

481

482

483

484

485

486

487

488

489

490

491

492

493

494

495

496

497

498

499

500

501

502

503

504

505

506

507

508

509

510

511

512

513

514

515

516

517

518

519

520

521

522

523

524

525

526

527

528

529

530

531

532

533

534

535

536

537

538

539

540

541

542

543

544

545

546

547

548

549

550

551

552

553

554

555

556

557

558

559

560

561

562

563

564

565

566

567

568

569

570

571

572

573

574

575

576

577

578

579

580

581

582

583

584

585

586

587

588

589

590

591

592

593

594

595

596

597

598

599

600

601

602

603

604

605

606

607

608

609

610

611

612

613

614

615

616

617

618

619

620

621

622

623

624

625

626

627

628

629

630

631

632

633

634

635

636

637

638

639

640

641

642

643

644

645

646

647

648

649

650

651

652

653

654

655

656

657

658

659

660

661

662

663

664

665

666

667

668

669

670

671

672

673

674

675

676

677

678

679

680

681

682

683

684

685

686

687

688

689

690

691

692

693

694

695

696

697

698

699

700

701

702

703

704

705

706

707

708

709

710

711

712

713

714

715

716

717

718

719

720

721

722

723

724

725

726

727

728

729

730

731

732

733

734

735

736

737

738

739

740

741

742

743

744

745

746

747

748

749

750

751

752

753

754

755

756

757

758

759

760

761

762

763

764

765

766

767

768

769

770

771

772

773

774

775

776

777

778

779

780

781

782

783

784

785

786

787

788

789

790

791

792

793

794

795

796

797

798

799

800

801

802

803

804

805

806

807

808

809

810

811

812

813

814

815

816

817

818

819

820

821

822

823

824

825

826

827

828

829

830

831

832

833

834

835

836

837

838

839

840

841

842

843

844

845

846

847

848

849

850

851

852

853

854

855

856

857

858

859

860

861

862

863

864

865

866

867

868

869

870

871

872

873

874

875

876

877

878

879

880

881

882

883

884

885

886

887

888

889

890

891

892

893

894

895

896

897

898

899

900

901

902

903

904

905

906

907

908

909

910

911

912

913

914

915

916

917

918

919

920

921

922

923

924

925

926

927

928

929

930

931

932

933

934

935

936

937

938

939

940

941

942

943

944

945

946

947

948

949

950

951

952

953

954

955

956

957

958

959

960

961

962

963

964

965

966

967

968

969

970

971

972

973

974

975

976

977

978

979

980

981

982

983

984

985

986

987

988

989

990

991

992

993

994

995

996

997

998

999

1000

1001

1002

1003

1004

1005

1006

1007

1008

1009

1010

1011

1012

1013

1014

1015

1016

1017

1018

1019

1020

1021

1022

1023

1024

1025

1026

1027

1028

1029

1030

1031

1032

1033

1034

1035

1036

1037

1038

1039

1040

1041

1042

1043

1044

1045

1046

1047

1048

1049

1050

1051

1052

1053

1054

1055

1056

1057

1058

1059

1060

1061

1062

1063

1064

1065

1066

1067

1068

1069

1070

1071

1072

1073

1074

1075

1076

1077

1078

1079

1080

1081

1082

1083

1084

1085

1086

1087

1088

1089

1090

1091

1092

1093

1094

1095

1096

1097

1098

1099

1100

1101

1102

1103

1104

1105

1106

1107

1108

1109

1110

1111

1112

1113

1114

1115

1116

1117

1118

1119

1120

1121

1122

1123

1124

1125

1126

1127

1128

1129

1130

1131

1132

1133

1134

1135

1136

1137

1138

1139

1140

1141

1142

1143

1144

1145

1146

1147

1148

1149

1150

1151

1152

1153

1154

1155

1156

1157

1158

1159

1160

1161

1162

1163

1164

1165

1166

1167

1168

1169

1170

1171

1172

1173

1174

1175

1176

1177

1178

1179

1180

1181

1182

1183

1184

1185

1186

1187

1188

1189

1190

1191

1192

1193

1194

1195

1196

1197

1198

1199

1200

1201

1202

1203

1204

1205

1206

1207

1208

1209

1210

1211

1212

1213

1214

1215

1216

1217

1218

1219

1220

1221

1222

1223

1224

1225

1226

1227

1228

1229

1230

1231

1232

1233

1234

1235

1236

1237

1238

1239

1240

1241

1242

1243

1244

1245

1246

1247

1248

1249

1250

1251

1252

1253

1254

1255

1256

1257

1258

1259

1260

1261

1262

1263

1264

1265

1266

1267

1268

1269

1270

1271

1272

1273

1274

1275

1276

1277

1278

1279

1280

1281

1282

1283

1284

1285

1286

1287

1288

1289

1290

1291

1292

1293

1294

1295

1296

1297

1298

1299

1300

1301

1302

1303

1304

1305

1306

1307

1308

1309

1310

1311

1312

1313

1314

1315

1316

1317

1318

1319

1320

1321

1322

1323

1324

1325

1326

1327

1328

1329

1330

1331

1332

1333

1334

1335

1336

1337

1338

1339

1340

1341

1342

1343

1344

1345

1346

1347

1348

1349

1350

1351

1352

1353

1354

1355

1356

1357

1358

1359

1360

1361

1362

1363

1364

1365

1366

1367

1368

1369

1370

1371

1372

1373

1374

1375

1376

1377

1378

1379

1380

1381

1382

1383

1384

1385

1386

1387

1388

1389

1390

1391

1392

1393

1394

1395

1396

1397

1398

1399

1400

1401

1402

1403

1404

1405

1406

1407

1408

1409

1410

1411

1412

1413

1414

1415

1416

1417

1418

1419

1420

1421

1422

1423

1424

1425

1426

1427

1428

1429

1430

1431

1432

1433

1434

1435

1436

1437

1438

1439

1440

1441

1442

1443

1444

1445

1446

1447

1448

1449

1450

1451

1452

1453

1454

1455

1456

1457

1458

1459

1460

1461

1462

1463

1464

1465

1466

1467

1468

1469

1470

1471

1472

1473

1474

1475

1476

1477

1478

1479

1480

1481

1482

1483

1484

1485

1486

1487

1488

1489

1490

1491

1492

1493

1494

1495

1496

1497

1498

1499

1500

1501

1502

1503

1504

1505

1506

1507

1508

1509

1510

1511

1512

1513

1514

1515

1516

1517

1518

1519

1520

1521

1522

1523

1524

1525

1526

1527

1528

1529

1530

1531

1532

1533

1534

1535

1536

1537

1538

1539

1540

1541

1542

1543

1544

1545

1546

1547

1548

1549

1550

1551

1552

1553

1554

1555

1556

1557

1558

1559

1560

1561

1562

1563

1564

1565

1566

1567

1568

1569

1570

1571

1572

1573

1574

1575

1576

1577

1578

1579

1580

1581

1582

1583

1584

1585

1586

1587

1588

1589

1590

1591

1592

1593

1594

1595

1596

1597

1598

1599

1600

1601

1602

1603

1604

1605

1606

1607

1608

1609

1610

1611

1612

1613

1614

1615

1616

1617

1618

1619

1620

1621

1622

1623

1624

1625

1626

1627

1628

1629

1630

1631

1632

1633

1634

1635

1636

1637

1638

1639

1640

1641

1642

1643

1644

1645

1646

1647

1648

1649

1650

1651

1652

1653

1654

1655

1656

1657

1658

1659

1660

1661

1662

1663

1664

1665

1666

1667

1668

1669

1670

1671

1672

1673

1674

1675

1676

1677

1678

1679

1680

1681

1682

1683

1684

1685

1686

1687

1688

1689

1690

1691

1692

1693

1694

1695

1696

1697

1698

1699

1700

1701

1702

1703

1704

1705

1706

1707

1708

1709

1710

1711

1712

1713

1714

1715

1716

1717

1718

1719

1720

1721

1722

1723

1724

1725

1726

1727

1728

1729

1730

1731

1732

1733

1734

1735

1736

1737

1738

1739

1740

1741

1742

1743

1744

1745

1746

1747

1748

1749

1750

1751

1752

1753

1754

1755

1756

1757

1758

1759

1760

1761

1762

1763

1764

1765

1766

1767

1768

1769

1770

1771

1772

1773

1774

1775

1776

1777

1778

1779

1780

1781

1782

1783

1784

1785

1786

1787

1788

1789

1790

1791

1792

1793

1794

1795

1796

1797

1798

1799

1800

1801

1802

1803

1804

1805

1806

1807

1808

1809

1810

1811

1812

1813

1814

1815

1816

1817

1818

1819

1820

1821

1822

1823

1824

1825

1826

1827

1828

1829

1830

1831

1832

1833

1834

1835

1836

1837

1838

1839

1840

1841

1842

1843

1844

1845

1846

1847

1848

1849

1850

1851

1852

1853

1854

1855

1856

1857

1858

1859

1860

1861

1862

1863

1864

1865

1866

1867

1868

1869

1870

1871

1872

1873

1874

1875

1876

1877

1878

1879

1880

1881

1882

1883

1884

1885

1886

1887

1888

1889

1890

1891

1892

1893

1894

1895

1896

1897

1898

1899

1900

1901

1902

1903

1904

1905

1906

1907

1908

1909

1910

1911

1912

1913

1914

1915

1916

1917

1918

1919

1920

1921

1922

1923

1924

1925

1926

1927

1928

1929

1930

1931

1932

1933

1934

1935

1936

1937

1938

1939

1940

1941

1942

1943

1944

1945

1946

1947

1948

1949

1950

1951

1952

1953

1954

1955

1956

1957

1958

1959

1960

1961

1962

1963

1964

1965

1966

1967

1968

1969

1970

1971

1972

1973

1974

1975

1976

1977

1978

1979

1980

1981

1982

1983

1984

1985

1986

1987

1988

1989

1990

1991

1992

1993

1994

1995

1996

1997

1998

1999

2000

2001

2002

2003

2004

2005

2006

2007

2008

2009

2010

2011

2012

2013

2014

2015

2016

2017

2018

2019

2020

2021

2022

2023

2024

2025

2026

2027

2028

2029

2030

2031

2032

2033

2034

2035

2036

2037

2038

2039

2040

2041

2042

2043

2044

2045

2046

2047

2048

2049

2050

2051

2052

2053

2054

2055

2056

2057

2058

2059

2060

2061

2062

2063

2064

2065

2066

2067

2068

2069

2070

2071

2072

2073

2074

2075

2076

2077

2078

2079

2080

2081

2082

2083

2084

2085

2086

2087

2088

2089

2090

2091

2092

2093

2094

2095

2096

2097

2098

2099

2100

2101

2102

2103

2104

2105

2106

2107

2108

2109

2110

2111

2112

2113

2114

2115

2116

2117

2118

2119

2120

2121

2122

2123

2124

2125

2126

2127

2128

2129

2130

2131

2132

2133

2134

2135

2136

2137

2138

2139

2140

2141

2142

2143

2144

2145

2146

2147

2148

2149

2150

2151

2152

2153

2154

2155

2156

2157

2158

2159

2160

2161

2162

2163

2164

2165

2166

2167

2168

2169

2170

2171

2172

2173

2174

2175

2176

2177

2178

2179

2180

2181

2182

2183

2184

2185

2186

2187

2188

2189

2190

2191

2192

2193

2194

2195

2196

2197

2198

2199

2200

2201

2202

2203

2204

2205

2206

2207

2208

2209

2210

2211

2212

2213

2214

2215

2216

2217

2218

2219

2220

2221

2222

2223

2224

2225

2226

2227

2228

2229

2230

2231

2232

2233

2234

2235

2236

2237

2238

2239

2240

2241

2242

2243

2244

2245

2246

2247

2248

2249

2250

2251

2252

2253

2254

2255

2256

2257

2258

2259

2260

2261

2262

2263

2264

2265

2266

2267

2268

2269

2270

2271

2272

2273

2274

2275

2276

2277

2278

2279

2280

2281

2282

2283

2284

2285

2286

2287

2288

2289

2290

2291

2292

2293

2294

2295

2296

2297

2298

2299

2300

2301

2302

2303

2304

2305

2306

2307

2308

2309

2310

2311

2312

2313

2314

2315

2316

2317

2318

2319

2320

2321

2322

2323

2324

2325

2326

2327

2328

2329

2330

2331

2332

2333

2334

2335

2336

2337

2338

2339

2340

2341

2342

2343

2344

2345

2346

2347

2348

2349

2350

2351

2352

2353

2354

2355

2356

2357

2358

2359

2360

2361

2362

2363

2364

2365

2366

2367

2368

2369

2370

2371

2372

2373

2374

2375

2376

2377

2378

2379

2380

2381

2382

2383

2384

2385

2386

2387

2388

2389

2390

2391

2392

2393

2394

2395

2396

2397

2398

2399

2400

2401

2402

2403

2404

2405

2406

2407

2408

2409

2410

2411

2412

2413

2414

2415

2416

2417

2418

2419

2420

2421

2422

2423

2424

2425

2426

2427

2428

2429

2430

2431

2432

2433

2434

2435

2436

2437

2438

2439

2440

2441

2442

2443

2444

2445

2446

2447

2448

2449

2450

2451

2452

2453

2454

2455

2456

2457

2458

2459

2460

2461

2462

2463

2464

2465

2466

2467

2468

2469

2470

2471

2472

2473

2474

2475

2476

2477

2478

2479

2480

2481

2482

2483

2484

2485

2486

2487

2488

2489

2490

2491

2492

2493

2494

2495

2496

2497

2498

2499

2500

2501

2502

2503

2504

2505

2506

2507

2508

2509

2510

2511

2512

2513

2514

2515

2516

2517

2518

2519

2520

2521

2522

2523

2524

2525

2526

2527

2528

2529

2530

2531

2532

2533

2534

2535

2536

2537

2538

2539

2540

2541

2542

2543

2544

2545

2546

2547

2548

2549

2550

2551

2552

2553

2554

2555

2556

2557

2558

2559

2560

2561

2562

2563

2564

2565

2566

2567

2568

2569

2570

2571

2572

2573

2574

2575

2576

2577

2578

2579

2580

2581

2582

2583

2584

2585

2586

2587

2588

2589

2590

2591

2592

2593

2594

2595

2596

2597

2598

2599

2600

2601

2602

2603

2604

2605

2606

2607

2608

2609

2610

2611

2612

2613

2614

2615

2616

2617

2618

2619

2620

2621

2622

2623

2624

2625

2626

2627

2628

2629

2630

2631

2632

2633

2634

2635

2636

2637

2638

2639

2640

2641

2642

2643

2644

2645

2646

2647

2648

2649

2650

2651

2652

2653

2654

2655

2656

2657

2658

2659

2660

2661

2662

2663

2664

2665

2666

2667

2668

2669

2670

2671

2672

2673

2674

2675

2676

2677

2678

2679

2680

2681

2682

2683

2684

2685

2686

2687

2688

2689

2690

2691

2692

2693

2694

2695

2696

2697

2698

2699

2700

2701

2702

2703

2704

2705

2706

2707

2708

2709

2710

2711

2712

2713

2714

2715

2716

2717

2718

2719

2720

2721

2722

2723

2724

2725

2726

2727

2728

2729

2730

2731

2732

2733

2734

2735

2736

2737

2738

2739

2740

2741

2742

2743

2744

2745

2746

2747

2748

2749

2750

2751

2752

2753

2754

2755

2756

2757

2758

2759

2760

2761

2762

2763

2764

2765

2766

2767

2768

2769

2770

2771

2772

2773

2774

2775

2776

2777

2778

2779

2780

2781

2782

2783

2784

2785

2786

2787

2788

2789

2790

2791

2792

2793

2794

2795

2796

2797

2798

2799

2800

2801

2802

2803

2804

2805

2806

2807

2808

2809

2810

2811

2812

2813

2814

2815

2816

2817

2818

2819

2820

2821

2822

2823

2824

2825

2826

2827

2828

2829

2830

2831

2832

2833

2834

2835

2836

2837

2838

2839

2840

2841

2842

2843

2844

2845

2846

2847

2848

2849

2850

2851

2852

2853

2854

2855

2856

2857

2858

2859

2860

2861

2862

2863

2864

2865

2866

2867

2868

2869

2870

2871

2872

2873

2874

2875

2876

2877

2878

2879

2880

2881

2882

2883

2884

2885

2886

2887

2888

2889

2890

2891

2892

2893

2894

2895

2896

2897

2898

2899

2900

2901

2902

2903

2904

2905

2906

2907

2908

2909

2910

2911

2912

2913

2914

2915

2916

2917

2918

2919

2920

2921

2922

2923

2924

2925

2926

2927

2928

2929

2930

2931

2932

2933

2934

2935

2936

2937

2938

2939

2940

2941

2942

2943

2944

2945

2946

2947

2948

2949

2950

2951

2952

2953

2954

2955

2956

2957

2958

2959

2960

2961

2962

2963

2964

2965

2966

2967

2968

2969

2970

2971

2972

2973

2974

2975

2976

2977

2978

2979

2980

2981

2982

2983

2984

2985

2986

2987

2988

2989

2990

2991

2992

2993

2994

2995

2996

2997

2998

2999

3000

3001

3002

3003

3004

3005

3006

3007

3008

3009

3010

3011

3012

3013

3014

3015

3016

3017

3018

3019

3020

3021

3022

3023

3024

3025

3026

3027

3028

3029

3030

3031

3032

3033

3034

3035

3036

3037

3038

3039

3040

3041

3042

3043

3044

3045

3046

3047

3048

3049

3050

3051

3052

3053

3054

3055

3056

3057

3058

3059

3060

3061

3062

3063

3064

3065

3066

3067

3068

3069

3070

3071

3072

3073

3074

3075

3076

3077

3078

3079

3080

3081

3082

3083

3084

3085

3086

3087

3088

3089

3090

3091

3092

3093

3094

3095

3096

3097

3098

3099

3100

3101

3102

3103

3104

3105

3106

3107

3108

3109

3110

3111

3112

3113

3114

3115

3116

3117

3118

3119

3120

3121

3122

3123

3124

3125

3126

3127

3128

3129

3130

3131

3132

3133

3134

3135

3136

3137

3138

3139

3140

3141

3142

3143

3144

3145

3146

3147

3148

3149

3150

3151

3152

3153

3154

3155

3156

3157

3158

3159

3160

3161

3162

3163

3164

3165

3166

3167

3168

3169

3170

3171

3172

3173

3174

3175

3176

3177

3178

3179

3180

3181

3182

3183

3184

3185

3186

3187

3188

3189

3190

3191

3192

3193

3194

3195

3196

3197

3198

3199

3200

3201

3202

3203

3204

3205

3206

3207

3208

3209

3210

3211

3212

3213

3214

3215

3216

3217

3218

3219

3220

3221

3222

3223

3224

3225

3226

3227

3228

3229

3230

3231

3232

3233

3234

3235

3236

3237

3238

3239

3240

3241

3242

3243

3244

3245

3246

3247

3248

3249

3250

3251

3252

3253

3254

3255

3256

3257

3258

3259

3260

3261

3262

3263

3264

3265

3266

3267

3268

3269

3270

3271

3272

3273

3274

3275

3276

3277

3278

3279

3280

3281

3282

3283

3284

3285

3286

3287

3288

3289

3290

3291

3292

3293

3294

3295

3296

3297

3298

3299

3300

3301

3302

3303

3304

3305

3306

3307

3308

3309

3310

3311

3312

3313

3314

3315

3316

3317

3318

3319

3320

3321

3322

3323

3324

3325

3326

3327

3328

3329

3330

3331

3332

3333

3334

3335

3336

3337

3338

3339

3340

3341

3342

3343

3344

3345

3346

3347

3348

3349

3350

3351

3352

3353

3354

3355

3356

3357

3358

3359

3360

3361

3362

3363

3364

3365

3366

3367

3368

3369

3370

3371

3372

3373

3374

3375

3376

3377

3378

3379

3380

3381

3382

3383

3384

3385

3386

3387

3388

3389

3390

3391

3392

3393

3394

3395

3396

3397

3398

3399

3400

3401

3402

3403

3404

3405

3406

3407

3408

3409

3410

3411

3412

3413

3414

3415

3416

3417

3418

3419

3420

3421

3422

3423

3424

3425

3426

3427

3428

3429

3430

3431

3432

3433

3434

3435

3436

3437

3438

3439

3440

3441

3442

3443

3444

3445

3446

3447

3448

3449

3450

3451

3452

3453

3454

3455

3456

3457

3458

3459

3460

3461

3462

3463

3464

3465

3466

3467

3468

3469

3470

3471

3472

3473

3474

3475

3476

3477

3478

3479

3480

3481

3482

3483

3484

3485

3486

3487

3488

3489

3490

3491

3492

3493

3494

3495

3496

3497

3498

3499

3500

3501

3502

3503

3504

3505

3506

3507

3508

3509

3510

3511

3512

3513

3514

3515

3516

3517

3518

3519

3520

3521

3522

3523

3524

3525

3526

3527

3528

3529

3530

3531

3532

3533

3534

3535

3536

3537

3538

3539

3540

3541

3542

3543

3544

3545

3546

3547

3548

3549

3550

3551

3552

3553

3554

3555

3556

3557

3558

3559

3560

3561

3562

3563

3564

3565

3566

3567

3568

3569

3570

3571

3572

3573

3574

3575

3576

3577

3578

3579

3580

3581

3582

3583

3584

3585

3586

3587

3588

3589

3590

3591

3592

3593

3594

3595

3596

3597

3598

3599

3600

3601

3602

3603

3604

3605

3606

3607

3608

3609

3610

3611

3612

3613

3614

3615

3616

3617

3618

3619

3620

3621

3622

3623

3624

3625

3626

3627

3628

3629

3630

3631

3632

3633

3634

3635

3636

3637

3638

3639

3640

3641

3642

3643

3644

3645

3646

3647

3648

3649

3650

3651

3652

3653

3654

3655

3656

3657

3658

3659

3660

3661

3662

3663

3664

3665

3666

3667

3668

3669

3670

3671

3672

3673

3674

3675

3676

3677

3678

3679

3680

3681

3682

3683

3684

3685

3686

3687

3688

3689

3690

3691

3692

3693

3694

3695

3696

3697

3698

3699

3700

3701

3702

3703

3704

3705

3706

3707

3708

3709

3710

3711

3712

3713

3714

3715

3716

3717

3718

3719

3720

3721

3722

3723

3724

3725

3726

3727

3728

3729

3730

3731

3732

3733

3734

3735

3736

3737

3738

3739

3740

3741

3742

3743

3744

3745

3746

3747

3748

3749

3750

3751

3752

3753

3754

3755

3756

3757

3758

3759

3760

3761

3762

3763

3764

3765

3766

3767

3768

3769

3770

3771

3772

3773

3774

3775

3776

3777

3778

3779

3780

3781

3782

3783

3784

3785

3786

3787

3788

3789

3790

3791

3792

3793

3794

3795

3796

3797

3798

3799

3800

3801

3802

3803

3804

3805

3806

3807

3808

3809

3810

3811

3812

3813

3814

3815

3816

3817

3818

3819

3820

3821

3822

3823

3824

3825

3826

3827

3828

3829

3830

3831

3832

3833

3834

3835

3836

3837

3838

3839

3840

3841

3842

3843

3844

3845

3846

3847

3848

3849

3850

3851

3852

3853

3854

3855

3856

3857

3858

3859

3860

3861

3862

3863

3864

3865

3866

3867

3868

3869

3870

3871

3872

3873

3874

3875

3876

3877

3878

3879

3880

3881

3882

3883

3884

3885

3886

3887

3888

3889

3890

3891

3892

3893

3894

3895

3896

3897

3898

3899

3900

3901

3902

3903

3904

3905

3906

3907

3908

3909

3910

3911

3912

3913

3914

3915

3916

3917

3918

3919

3920

3921

3922

3923

3924

3925

3926

3927

3928

3929

3930

3931

3932

3933

3934

3935

3936

3937

3938

3939

3940

3941

3942

3943

3944

3945

3946

3947

3948

3949

3950

3951

3952

3953

3954

3955

3956

3957

3958

3959

3960

3961

3962

3963

3964

3965

3966

3967

3968

3969

3970

3971

3972

3973

3974

3975

3976

3977

3978

3979

3980

3981

3982

3983

3984

3985

3986

3987

3988

3989

3990

3991

3992

3993

3994

3995

3996

3997

3998

3999

4000

4001

4002

4003

4004

4005

4006

4007

4008

4009

4010

4011

4012

4013

4014

4015

4016

4017

4018

4019

4020

4021

4022

4023

4024

4025

4026

4027

4028

4029

4030

4031

4032

4033

4034

4035

4036

4037

4038

4039

4040

4041

4042

4043

4044

4045

4046

4047

4048

4049

4050

4051

4052

4053

4054

4055

4056

4057

4058

4059

4060

4061

4062

4063

4064

4065

4066

4067

4068

4069

4070

4071

4072

4073

4074

4075

4076

4077

4078

4079

4080

4081

4082

4083

4084

4085

4086

4087

4088

4089

4090

4091

4092

4093

4094

4095

4096

4097

4098

4099

4100

4101

4102

4103

4104

4105

4106

4107

4108

4109

4110

4111

4112

4113

4114

4115

4116

4117

4118

4119

4120

4121

4122

4123

4124

4125

4126

4127

4128

4129

4130

4131

4132

4133

4134

4135

4136

4137

4138

4139

4140

4141

4142

4143

4144

4145

4146

4147

4148

4149

4150

4151

4152

4153

4154

4155

4156

4157

4158

4159

4160

4161

4162

4163

4164

4165

4166

4167

4168

4169

4170

4171

4172

4173

4174

4175

4176

4177

4178

4179

4180

4181

4182

4183

4184

4185

4186

4187

4188

4189

4190

4191

4192

4193

4194

4195

4196

4197

4198

4199

4200

4201

4202

4203

4204

4205

4206

4207

4208

4209

4210

4211

4212

4213

4214

4215

4216

4217

4218

4219

4220

4221

4222

4223

4224

4225

4226

4227

4228

4229

4230

4231

4232

4233

4234

4235

4236

4237

4238

4239

4240

4241

4242

4243

4244

4245

4246

4247

4248

4249

4250

4251

4252

4253

4254

4255

4256

4257

4258

4259

4260

4261

4262

4263

4264

4265

4266

4267

4268

4269

4270

4271

4272

4273

4274

4275

4276

4277

4278

4279

4280

4281

4282

4283

4284

4285

4286

4287

4288

4289

4290

4291

4292

4293

4294

4295

4296

4297

4298

4299

4300

4301

4302

4303

4304

4305

4306

4307

4308

4309

4310

4311

4312

4313

4314

4315

4316

4317

4318

4319

4320

4321

4322

4323

4324

4325

4326

4327

4328

4329

4330

4331

4332

4333

4334

4335

4336

4337

4338

4339

4340

4341

4342

4343

4344

4345

4346

4347

4348

4349

4350

4351

4352

4353

4354

4355

4356

4357

4358

4359

4360

4361

4362

4363

4364

4365

4366

4367

4368

4369

4370

4371

4372

4373

4374

4375

4376

4377

4378

4379

4380

4381

4382

4383

4384

4385

4386

4387

4388

4389

4390

4391

4392

4393

4394

4395

4396

4397

4398

4399

4400

4401

4402

4403

4404

4405

4406

4407

4408

4409

4410

4411

4412

4413

4414

4415

4416

4417

4418

4419

4420

4421

4422

4423

4424

4425

4426

4427

4428

4429

4430

4431

4432

4433

4434

4435

4436

4437

4438

4439

4440

4441

4442

4443

4444

4445

4446

4447

4448

4449

4450

4451

4452

4453

4454

4455

4456

4457

4458

4459

4460

4461

4462

4463

4464

4465

4466

4467

4468

4469

4470

4471

4472

4473

4474

4475

4476

4477

4478

4479

4480

4481

4482

4483

4484

4485

4486

4487

4488

4489

4490

4491

4492

4493

4494

4495

4496

4497

4498

4499

4500

4501

4502

4503

4504

4505

4506

4507

4508

4509

4510

4511

4512

4513

4514

4515

4516

4517

4518

4519

4520

4521

4522

4523

4524

4525

4526

4527

4528

4529

4530

4531

4532

4533

4534

4535

4536

4537

4538

4539

4540

4541

4542

4543

4544

4545

4546

4547

4548

4549

4550

4551

4552

4553

4554

4555

4556

4557

4558

4559

4560

4561

4562

4563

4564

4565

4566

4567

4568

4569

4570

4571

4572

4573

4574

4575

4576

4577

4578

4579

4580

4581

4582

4583

4584

4585

4586

4587

4588

4589

4590

4591

4592

4593

4594

4595

4596

4597

4598

4599

4600

4601

4602

4603

4604

4605

4606

4607

4608

4609

4610

4611

4612

4613

4614

4615

4616

4617

4618

4619

4620

4621

4622

4623

4624

4625

4626

4627

4628

4629

4630

4631

4632

4633

4634

4635

4636

4637

4638

4639

4640

4641

4642

4643

4644

4645

4646

4647

4648

4649

4650

4651

4652

4653

4654

4655

4656

4657

4658

4659

4660

4661

4662

4663

4664

4665

4666

4667

4668

4669

4670

4671

4672

4673

4674

4675

4676

4677

4678

4679

4680

4681

4682

4683

4684

4685

4686

4687

4688

4689

4690

4691

4692

4693

4694

4695

4696

4697

4698

4699

4700

4701

4702

4703

4704

4705

4706

4707

4708

4709

4710

4711

4712

4713

4714

4715

4716

4717

4718

4719

4720

4721

4722

4723

4724

4725

4726

4727

4728

4729

4730

4731

4732

4733

4734

4735

4736

4737

4738

4739

4740

4741

4742

4743

4744

4745

4746

4747

4748

4749

4750

4751

4752

4753

4754

4755

4756

4757

4758

4759

4760

4761

4762

4763

4764

4765

4766

4767

4768

4769

4770

4771

4772

4773

4774

4775

4776

4777

4778

4779

4780

4781

4782

4783

4784

4785

4786

4787

4788

4789

4790

4791

4792

4793

4794

4795

4796

4797

4798

4799

4800

4801

4802

4803

4804

4805

4806

4807

4808

4809

4810

4811

4812

4813

4814

4815

4816

4817

4818

4819

4820

4821

4822

4823

4824

4825

4826

4827

4828

4829

4830

4831

4832

4833

4834

4835

4836

4837

4838

4839

4840

4841

4842

4843

4844

4845

4846

4847

4848

4849

4850

4851

4852

4853

4854

4855

4856

4857

4858

4859

4860

4861

4862

4863

4864

4865

4866

4867

4868

4869

4870

4871

4872

4873

4874

4875

4876

4877

4878

4879

4880

4881

4882

4883

4884

4885

4886

4887

4888

4889

4890

4891

4892

4893

4894

4895

4896

4897

4898

4899

4900

4901

4902

4903

4904

4905

4906

4907

4908

4909

4910

4911

4912

4913

4914

4915

4916

4917

4918

4919

4920

4921

4922

4923

4924

4925

4926

4927

4928

4929

4930

4931

4932

4933

4934

4935

4936

4937

4938

4939

4940

4941

4942

4943

4944

4945

4946

4947

4948

4949

4950

4951

4952

4953

4954

4955

4956

4957

4958

4959

4960

4961

4962

4963

4964

4965

4966

4967

4968

4969

4970

4971

4972

4973

4974

4975

4976

4977

4978

4979

4980

4981

4982

4983

4984

4985

4986

4987

4988

4989

4990

4991

4992

4993

4994

4995

4996

4997

4998

4999

5000

5001

5002

5003

5004

5005

5006

5007

5008

5009

5010

5011

5012

5013

5014

5015

5016

5017

5018

5019

5020

5021

5022

5023

5024

5025

5026

5027

5028

5029

5030

5031

5032

5033

5034

5035

5036

5037

5038

5039

5040

5041

5042

5043

5044

5045

5046

5047

5048

5049

5050

5051

5052

5053

5054

5055

5056

5057

5058

5059

5060

5061

5062

5063

5064

5065

5066

5067

5068

5069

5070

5071

5072

5073

5074

5075

5076

5077

5078

5079

5080

5081

5082

5083

5084

5085

5086

5087

5088

5089

5090

5091

5092

5093

5094

5095

5096

5097

5098

5099

5100

5101

5102

5103

5104

5105

5106

5107

5108

5109

5110

5111

5112

5113

5114

5115

5116

5117

5118

5119

5120

5121

5122

5123

5124

5125

5126

5127

5128

5129

5130

5131

5132

5133

5134

5135

5136

5137

5138

5139

5140

5141

5142

5143

5144

5145

5146

5147

5148

5149

5150

5151

5152

5153

5154

5155

5156

5157

5158

5159

5160

5161

5162

5163

5164

5165

5166

5167

5168

5169

5170

5171

5172

5173

5174

5175

5176

5177

5178

5179

5180

5181

5182

5183

5184

5185

5186

5187

5188

5189

5190

5191

5192

5193

5194

5195

5196

5197

5198

5199

5200

5201

5202

5203

5204

5205

5206

5207

5208

5209

5210

5211

5212

5213

5214

5215

5216

5217

5218

5219

5220

5221

5222

5223

5224

5225

5226

5227

5228

5229

5230

5231

5232

5233

5234

5235

5236

5237

5238

5239

5240

5241

5242

5243

5244

5245

5246

5247

5248

5249

5250

5251

5252

5253

5254

5255

5256

5257

5258

5259

5260

5261

5262

5263

5264

5265

5266

5267

5268

5269

5270

5271

5272

5273

5274

5275

5276

5277

5278

5279

5280

5281

5282

5283

5284

5285

5286

5287

5288

5289

5290

5291

5292

5293

5294

5295

5296

5297

5298

5299

5300

5301

5302

5303

5304

5305

5306

5307

5308

5309

5310

5311

5312

5313

5314

5315

5316

5317

5318

5319

5320

5321

5322

5323

5324

5325

5326

5327

5328

5329

5330

5331

5332

5333

5334

5335

5336

5337

5338

5339

5340

5341

5342

5343

5344

5345

5346

5347

5348

5349

5350

5351

5352

5353

5354

5355

5356

5357

5358

5359

5360

5361

5362

5363

5364

5365

5366

5367

5368

5369

5370

5371

5372

5373

5374

5375

5376

5377

5378

5379

5380

5381

5382

5383

5384

5385

5386

5387

5388

5389

5390

5391

5392

5393

5394

5395

5396

5397

5398

5399

5400

5401

5402

5403

5404

5405

5406

5407

5408

5409

5410

5411

5412

5413

5414

5415

5416

5417

5418

5419

5420

5421

5422

5423

5424

5425

5426

5427

5428

5429

5430

5431

5432

5433

5434

5435

5436

5437

5438

5439

5440

5441

5442

5443

5444

5445

5446

5447

5448

5449

5450

5451

5452

5453

5454

5455

5456

5457

5458

5459

5460

5461

5462

5463

5464

5465

5466

5467

5468

5469

5470

5471

5472

5473

5474

5475

5476

5477

5478

5479

5480

5481

5482

5483

5484

5485

5486

5487

5488

5489

5490

5491

5492

5493

5494

5495

5496

5497

5498

5499

5500

5501

5502

5503

5504

5505

5506

5507

5508

5509

5510

5511

5512

5513

5514

5515

5516

5517

5518

5519

5520

5521

5522

5523

5524

5525

5526

5527

5528

5529

5530

5531

5532

5533

5534

5535

5536

5537

5538

5539

5540

5541

5542

5543

5544

5545

5546

5547

5548

5549

5550

5551

5552

5553

5554

5555

5556

5557

5558

5559

5560

5561

5562

5563

5564

5565

5566

5567

5568

5569

5570

5571

5572

5573

5574

5575

5576

5577

5578

5579

5580

5581

5582

5583

5584

5585

5586

5587

5588

5589

5590

5591

5592

5593

5594

5595

5596

5597

5598

5599

5600

5601

5602

5603

5604

5605

5606

5607

5608

5609

5610

5611

5612

5613

5614

5615

5616

5617

5618

5619

5620

5621

5622

5623

5624

5625

5626

5627

5628

5629

5630

5631

5632

5633

5634

5635

5636

5637

5638

5639

5640

5641

5642

5643

5644

5645

5646

5647

5648

5649

5650

5651

5652

5653

5654

5655

5656

5657

5658

5659

5660

5661

5662

5663

5664

5665

5666

5667

5668

5669

5670

5671

5672

5673

5674

5675

5676

5677

5678

5679

5680

5681

5682

5683

5684

5685

5686

5687

5688

5689

5690

5691

5692

5693

5694

5695

5696

5697

5698

5699

5700

5701

5702

5703

5704

5705

5706

5707

5708

5709

5710

5711

5712

5713

5714

5715

5716

5717

5718

5719

5720

5721

5722

5723

5724

5725

5726

5727

5728

5729

5730

5731

5732

5733

5734

5735

5736

5737

5738

5739

5740

5741

5742

5743

5744

5745

5746

5747

5748

5749

5750

5751

5752

5753

5754

5755

5756

5757

5758

5759

5760

5761

5762

5763

5764

5765

5766

5767

5768

5769

5770

5771

5772

5773

5774

5775

5776

5777

5778

5779

5780

5781

5782

5783

5784

5785

5786

5787

5788

5789

5790

5791

5792

5793

5794

5795

5796

5797

5798

5799

5800

5801

5802

5803

5804

5805

5806

5807

5808

5809

5810

5811

5812

5813

5814

5815

5816

5817

5818

5819

5820

5821

5822

5823

5824

5825

5826

5827

5828

5829

5830

5831

5832

5833

5834

5835

5836

5837

5838

5839

5840

5841

5842

5843

5844

5845

5846

5847

5848

5849

5850

5851

5852

5853

5854

5855

5856

5857

5858

5859

5860

5861

5862

5863

5864

5865

5866

5867

5868

5869

5870

5871

5872

5873

5874

5875

5876

5877

5878

5879

5880

5881

5882

5883

5884

5885

5886

5887

5888

5889

5890

5891

5892

5893

5894

5895

5896

5897

5898

5899

5900

5901

5902

5903

5904

5905

5906

5907

5908

5909

5910

5911

5912

5913

5914

5915

5916

5917

5918

5919

5920

5921

5922

5923

5924

5925

5926

5927

5928

5929

5930

5931

5932

5933

5934

5935

5936

5937

5938

5939

5940

5941

5942

5943

5944

5945

5946

5947

5948

5949

5950

5951

5952

5953

5954

5955

5956

5957

5958

5959

5960

5961

5962

5963

5964

5965

5966

5967

5968

5969

5970

5971

5972

5973

5974

5975

5976

5977

5978

5979

5980

5981

5982

5983

5984

5985

5986

5987

5988

5989

5990

5991

5992

5993

5994

5995

5996

5997

5998

5999

6000

6001

6002

6003

6004

6005

6006

6007

6008

6009

6010

6011

6012

6013

6014

6015

6016

6017

6018

6019

6020

6021

6022

6023

6024

6025

6026

6027

6028

6029

6030

6031

6032

6033

6034

6035

6036

6037

6038

6039

6040

6041

6042

6043

6044

6045

6046

6047

6048

6049

6050

6051

6052

6053

6054

6055

6056

6057

6058

6059

6060

6061

6062

6063

6064

6065

6066

6067

6068

6069

6070

6071

6072

6073

6074

6075

6076

6077

6078

6079

6080

6081

6082

6083

6084

6085

6086

6087

6088

6089

6090

6091

6092

6093

6094

6095

6096

6097

6098

6099

6100

6101

6102

6103

6104

6105

6106

6107

6108

6109

6110

6111

6112

6113

6114

6115

6116

6117

6118

6119

6120

6121

6122

6123

6124

6125

6126

6127

6128

6129

6130

6131

6132

6133

6134

6135

6136

6137

6138

6139

6140

6141

6142

6143

6144

6145

6146

6147

6148

6149

6150

6151

6152

6153

6154

6155

6156

6157

6158

6159

6160

6161

6162

6163

6164

6165

6166

6167

6168

6169

6170

6171

6172

6173

6174

6175

6176

6177

6178

6179

6180

6181

6182

6183

6184

6185

6186

6187

6188

6189

6190

6191

6192

6193

6194

6195

6196

6197

6198

6199

6200

6201

6202

6203

6204

6205

6206

6207

6208

6209

6210

6211

6212

6213

6214

6215

6216

6217

6218

6219

6220

6221

6222

6223

6224

6225

6226

6227

6228

6229

6230

6231

6232

6233

6234

6235

6236

6237

6238

6239

6240

6241

6242

6243

6244

6245

6246

6247

6248

6249

6250

6251

6252

6253

6254

6255

6256

6257

6258

6259

6260

6261

6262

6263

6264

6265

6266

6267

6268

6269

6270

6271

6272

6273

6274

6275

6276

6277

6278

6279

6280

6281

6282

6283

6284

6285

6286

6287

6288

6289

6290

6291

6292

6293

6294

6295

6296

6297

6298

6299

6300

6301

6302

6303

6304

6305

6306

6307

6308

6309

6310

6311

6312

6313

6314

6315

6316

6317

6318

6319

6320

6321

6322

6323

6324

6325

6326

6327

6328

6329

6330

6331

6332

6333

6334

6335

6336

6337

6338

6339

6340

6341

6342

6343

6344

6345

6346

6347

6348

6349

6350

6351

6352

6353

6354

6355

6356

6357

6358

6359

6360

6361

6362

6363

6364

6365

6366

6367

6368

6369

6370

6371

6372

6373

6374

6375

6376

6377

6378

6379

6380

6381

6382

6383

6384

6385

6386

6387

6388

6389

6390

6391

6392

6393

6394

6395

6396

6397

6398

6399

6400

6401

6402

6403

6404

6405

6406

6407

6408

6409

6410

6411

6412

6413

6414

6415

6416

6417

6418

6419

6420

6421

6422

6423

6424

6425

6426

6427

6428

6429

6430

6431

6432

6433

6434

6435

6436

6437

6438

6439

6440

6441

6442

6443

6444

6445

6446

6447

6448

6449

6450

6451

6452

6453

6454

6455

6456

6457

6458

6459

6460

6461

6462

6463

6464

6465

6466

6467

6468

6469

6470

6471

6472

6473

6474

6475

6476

6477

6478

6479

6480

6481

6482

6483

6484

6485

6486

6487

6488

6489

6490

6491

6492

6493

6494

6495

6496

6497

6498

6499

6500

6501

6502

6503

6504

6505

6506

6507

6508

6509

6510

6511

6512

6513

6514

6515

6516

6517

6518

6519

6520

6521

6522

6523

6524

6525

6526

6527

6528

6529

6530

6531

6532

6533

6534

6535

6536

6537

6538

6539

6540

6541

6542

6543

6544

6545

6546

6547

6548

6549

6550

6551

6552

6553

6554

6555

6556

6557

6558

6559

6560

6561

6562

6563

6564

6565

6566

6567

6568

6569

6570

6571

6572

6573

6574

6575

6576

6577

6578

6579

6580

6581

6582

6583

6584

6585

6586

6587

6588

6589

6590

6591

6592

6593

6594

6595

6596

6597

6598

6599

6600

6601

6602

6603

6604

6605

6606

6607

6608

6609

6610

6611

6612

6613

6614

6615

6616

6617

6618

6619

6620

6621

6622

6623

6624

6625

6626

6627

6628

6629

6630

6631

6632

6633

6634

6635

6636

6637

6638

6639

6640

6641

6642

6643

6644

6645

6646

6647

6648

6649

6650

6651

6652

6653

6654

6655

6656

6657

6658

6659

6660

6661

6662

6663

6664

6665

6666

6667

6668

6669

6670

6671

6672

6673

6674

6675

6676

6677

6678

6679

6680

6681

6682

6683

6684

6685

6686

6687

6688

6689

6690

6691

6692

6693

6694

6695

6696

6697

6698

6699

6700

6701

6702

6703

6704

6705

6706

6707

6708

6709

6710

6711

6712

6713

6714

6715

6716

6717

6718

6719

6720

6721

6722

6723

6724

6725

6726

6727

6728

6729

6730

6731

6732

6733

6734

6735

6736

6737

6738

6739

6740

6741

6742

6743

6744

6745

6746

6747

6748

6749

6750

6751

6752

6753

6754

6755

6756

6757

6758

6759

6760

6761

6762

6763

6764

6765

6766

6767

6768

6769

6770

6771

6772

6773

6774

6775

6776

6777

6778

6779

6780

6781

6782

6783

6784

6785

6786

6787

6788

6789

6790

6791

6792

6793

6794

6795

6796

6797

6798

6799

6800

6801

6802

6803

6804

6805

6806

6807

6808

6809

6810

6811

6812

6813

6814

6815

6816

6817

6818

6819

6820

6821

6822

6823

6824

6825

6826

6827

6828

6829

6830

6831

6832

6833

6834

6835

6836

6837

6838

6839

6840

6841

6842

6843

6844

6845

6846

6847

6848

6849

6850

6851

6852

6853

6854

6855

6856

6857

6858

6859

6860

6861

6862

6863

6864

6865

6866

6867

6868

6869

6870

6871

6872

6873

6874

6875

6876

6877

6878

6879

6880

6881

6882

6883

6884

6885

6886

6887

6888

6889

6890

6891

6892

6893

6894

6895

6896

6897

6898

6899

6900

6901

6902

6903

6904

6905

6906

6907

6908

6909

6910

6911

6912

6913

6914

6915

6916

6917

6918

6919

6920

6921

6922

6923

6924

6925

6926

6927

6928

6929

6930

6931

6932

6933

6934

6935

6936

6937

6938

6939

6940

6941

6942

6943

6944

6945

6946

6947

6948

6949

6950

6951

6952

6953

6954

6955

6956

6957

6958

6959

6960

6961

6962

6963

6964

6965

6966

6967

6968

6969

6970

6971

6972

6973

6974

6975

6976

6977

6978

6979

6980

6981

6982

6983

6984

6985

6986

6987

6988

6989

6990

6991

6992

6993

6994

6995

6996

6997

6998

6999

7000

7001

7002

7003

7004

7005

7006

7007

7008

7009

7010

7011

7012

7013

7014

7015

7016

7017

7018

7019

7020

7021

7022

7023

7024

7025

7026

7027

7028

7029

7030

7031

7032

7033

7034

7035

7036

7037

7038

7039

7040

7041

7042

7043

7044

7045

7046

7047

7048

7049

7050

7051

7052

7053

7054

7055

7056

7057

7058

7059

7060

7061

7062

7063

7064

7065

7066

7067

7068

7069

7070

7071

7072

7073

7074

7075

7076

7077

7078

7079

7080

7081

7082

7083

7084

7085

7086

7087

7088

7089

7090

7091

7092

7093

7094

7095

7096

7097

7098

7099

7100

7101

7102

7103

7104

7105

7106

7107

7108

7109

7110

7111

7112

7113

7114

7115

7116

7117

7118

7119

7120

7121

7122

7123

7124

7125

7126

7127

7128

7129

7130

7131

7132

7133

7134

7135

7136

7137

7138

7139

7140

7141

7142

7143

7144

7145

7146

7147

7148

7149

7150

7151

7152

7153

7154

7155

7156

7157

7158

7159

7160

7161

7162

7163

7164

7165

7166

7167

7168

7169

7170

7171

7172

7173

7174

7175

7176

7177

7178

7179

7180

7181

7182

7183

7184

7185

7186

7187

7188

7189

7190

7191

7192

7193

7194

7195

7196

7197

7198

7199

7200

7201

7202

7203

7204

7205

7206

7207

7208

7209

7210

7211

7212

7213

7214

7215

7216

7217

7218

7219

7220

7221

7222

7223

7224

7225

7226

7227

7228

7229

7230

7231

7232

7233

7234

7235

7236

7237

7238

7239

7240

7241

7242

7243

7244

7245

7246

7247

7248

7249

7250

7251

7252

7253

7254

7255

7256

7257

7258

7259

7260

7261

7262

7263

7264

7265

7266

7267

7268

7269

7270

7271

7272

7273

7274

7275

7276

7277

7278

7279

7280

7281

7282

7283

7284

7285

7286

7287

7288

7289

7290

7291

7292

7293

7294

7295

7296

7297

7298

7299

7300

7301

7302

7303

7304

7305

7306

7307

7308

7309

7310

7311

7312

7313

7314

7315

7316

7317

7318

7319

7320

7321

7322

7323

7324

7325

7326

7327

7328

7329

7330

7331

7332

7333

7334

7335

7336

7337

7338

7339

7340

7341

7342

7343

7344

7345

7346

7347

7348

7349

7350

7351

7352

7353

7354

7355

7356

7357

7358

7359

7360

7361

7362

7363

7364

7365

7366

7367

7368

7369

7370

7371

7372

7373

7374

7375

7376

7377

7378

7379

7380

7381

7382

7383

7384

7385

7386

7387

7388

7389

7390

7391

7392

7393

7394

7395

7396

7397

7398

7399

7400

7401

7402

7403

7404

7405

7406

7407

7408

7409

7410

7411

7412

7413

7414

7415

7416

7417

7418

7419

7420

7421

7422

7423

7424

7425

7426

7427

7428

7429

7430

7431

7432

7433

7434

7435

7436

7437

7438

7439

7440

7441

7442

7443

7444

7445

7446

7447

7448

7449

7450

7451

7452

7453

7454

7455

7456

7457

7458

7459

7460

7461

7462

7463

7464

7465

7466

7467

7468

7469

7470

7471

7472

7473

7474

7475

7476

7477

7478

7479

7480

7481

7482

7483

7484

7485

7486

7487

7488

7489

7490

7491

7492

7493

7494

7495

7496

7497

7498

7499

7500

7501

7502

7503

7504

7505

7506

7507

7508

7509

7510

7511

7512

7513

7514

7515

7516

7517

7518

7519

7520

7521

7522

7523

7524

7525

7526

7527

7528

7529

7530

7531

7532

7533

7534

7535

7536

7537

7538

7539

7540

7541

7542

7543

7544

7545

7546

7547

7548

7549

7550

7551

7552

7553

7554

7555

7556

7557

7558

7559

7560

7561

7562

7563

7564

7565

7566

7567

7568

7569

7570

7571

7572

7573

7574

7575

7576

7577

7578

7579

7580

7581

7582

7583

7584

7585

7586

7587

7588

7589

7590

7591

7592

7593

7594

7595

7596

7597

7598

7599

7600

7601

7602

7603

7604

7605

7606

7607

7608

7609

7610

7611

7612

7613

7614

7615

7616

7617

7618

7619

7620

7621

7622

7623

7624

7625

7626

7627

7628

7629

7630

7631

7632

7633

7634

7635

7636

7637

7638

7639

7640

7641

7642

7643

7644

7645

7646

7647

7648

7649

7650

7651

7652

7653

7654

7655

7656

7657

7658

7659

7660

7661

7662

7663

7664

7665

7666

7667

7668

7669

7670

7671

7672

7673

7674

7675

7676

7677

7678

7679

7680

7681

7682

7683

7684

7685

7686

7687

7688

7689

7690

7691

7692

7693

7694

7695

7696

7697

7698

7699

7700

7701

7702

7703

7704

7705

7706

7707

7708

7709

7710

7711

7712

7713

7714

7715

7716

7717

7718

7719

7720

7721

7722

7723

7724

7725

7726

7727

7728

7729

7730

7731

7732

7733

7734

7735

7736

7737

7738

7739

7740

7741

7742

7743

7744

7745

7746

7747

7748

7749

7750

7751

7752

7753

7754

7755

7756

7757

7758

7759

7760

7761

7762

7763

7764

7765

7766

7767

7768

7769

7770

7771

7772

7773

7774

7775

7776

7777

7778

7779

7780

7781

7782

7783

7784

7785

7786

7787

7788

7789

7790

7791

7792

7793

7794

7795

7796

7797

7798

7799

7800

7801

7802

7803

7804

7805

7806

7807

7808

7809

7810

7811

7812

7813

7814

7815

7816

7817

7818

7819

7820

7821

7822

7823

7824

7825

7826

7827

7828

7829

7830

7831

7832

7833

7834

7835

7836

7837

7838

7839

7840

7841

7842

7843

7844

7845

7846

7847

7848

7849

7850

7851

7852

7853

7854

7855

7856

7857

7858

7859

7860

7861

7862

7863

7864

7865

7866

7867

7868

7869

7870

7871

7872

7873

7874

7875

7876

7877

7878

7879

7880

7881

7882

7883

7884

7885

7886

7887

7888

7889

7890

7891

7892

7893

7894

7895

7896

7897

7898

7899

7900

7901

7902

7903

7904

7905

7906

7907

7908

7909

7910

7911

7912

7913

7914

7915

7916

7917

7918

7919

7920

7921

7922

7923

7924

7925

7926

7927

7928

7929

7930

7931

7932

7933

7934

7935

7936

7937

7938

7939

7940

7941

7942

7943

7944

7945

7946

7947

7948

7949

7950

7951

7952

7953

7954

7955

7956

7957

7958

7959

7960

7961

7962

7963

7964

7965

7966

7967

7968

7969

7970

7971

7972

7973

7974

7975

7976

7977

7978

7979

7980

7981

7982

7983

7984

7985

7986

7987

7988

7989

7990

7991

7992

7993

7994

7995

7996

7997

7998

7999

8000

8001

8002

8003

8004

8005

8006

8007

8008

8009

8010

8011

8012

8013

8014

8015

8016

8017

8018

8019

8020

8021

8022

8023

8024

8025

8026

8027

8028

8029

8030

8031

8032

8033

8034

8035

8036

8037

8038

8039

8040

8041

8042

8043

8044

8045

8046

8047

8048

8049

8050

8051

8052

8053

8054

8055

8056

8057

8058

8059

8060

8061

8062

8063

8064

8065

8066

8067

8068

8069

8070

8071

8072

8073

8074

8075

8076

8077

8078

8079

8080

8081

8082

8083

8084

8085

8086

8087

8088

8089

8090

8091

8092

""" 

numpy.ma : a package to handle missing or invalid values. 

 

This package was initially written for numarray by Paul F. Dubois 

at Lawrence Livermore National Laboratory. 

In 2006, the package was completely rewritten by Pierre Gerard-Marchant 

(University of Georgia) to make the MaskedArray class a subclass of ndarray, 

and to improve support of structured arrays. 

 

 

Copyright 1999, 2000, 2001 Regents of the University of California. 

Released for unlimited redistribution. 

 

* Adapted for numpy_core 2005 by Travis Oliphant and (mainly) Paul Dubois. 

* Subclassing of the base `ndarray` 2006 by Pierre Gerard-Marchant 

(pgmdevlist_AT_gmail_DOT_com) 

* Improvements suggested by Reggie Dugard (reggie_AT_merfinllc_DOT_com) 

 

.. moduleauthor:: Pierre Gerard-Marchant 

 

""" 

# pylint: disable-msg=E1002 

from __future__ import division, absolute_import, print_function 

 

import sys 

import operator 

import warnings 

import textwrap 

import re 

from functools import reduce 

 

if sys.version_info[0] >= 3: 

import builtins 

else: 

import __builtin__ as builtins 

 

import numpy as np 

import numpy.core.umath as umath 

import numpy.core.numerictypes as ntypes 

from numpy import ndarray, amax, amin, iscomplexobj, bool_, _NoValue 

from numpy import array as narray 

from numpy.lib.function_base import angle 

from numpy.compat import ( 

getargspec, formatargspec, long, basestring, unicode, bytes 

) 

from numpy import expand_dims 

from numpy.core.multiarray import normalize_axis_index 

from numpy.core.numeric import normalize_axis_tuple 

from numpy.core._internal import recursive 

from numpy.core.numeric import pickle 

 

 

__all__ = [ 

'MAError', 'MaskError', 'MaskType', 'MaskedArray', 'abs', 'absolute', 

'add', 'all', 'allclose', 'allequal', 'alltrue', 'amax', 'amin', 

'angle', 'anom', 'anomalies', 'any', 'append', 'arange', 'arccos', 

'arccosh', 'arcsin', 'arcsinh', 'arctan', 'arctan2', 'arctanh', 

'argmax', 'argmin', 'argsort', 'around', 'array', 'asanyarray', 

'asarray', 'bitwise_and', 'bitwise_or', 'bitwise_xor', 'bool_', 'ceil', 

'choose', 'clip', 'common_fill_value', 'compress', 'compressed', 

'concatenate', 'conjugate', 'convolve', 'copy', 'correlate', 'cos', 'cosh', 

'count', 'cumprod', 'cumsum', 'default_fill_value', 'diag', 'diagonal', 

'diff', 'divide', 'dump', 'dumps', 'empty', 'empty_like', 'equal', 'exp', 

'expand_dims', 'fabs', 'filled', 'fix_invalid', 'flatten_mask', 

'flatten_structured_array', 'floor', 'floor_divide', 'fmod', 

'frombuffer', 'fromflex', 'fromfunction', 'getdata', 'getmask', 

'getmaskarray', 'greater', 'greater_equal', 'harden_mask', 'hypot', 

'identity', 'ids', 'indices', 'inner', 'innerproduct', 'isMA', 

'isMaskedArray', 'is_mask', 'is_masked', 'isarray', 'left_shift', 

'less', 'less_equal', 'load', 'loads', 'log', 'log10', 'log2', 

'logical_and', 'logical_not', 'logical_or', 'logical_xor', 'make_mask', 

'make_mask_descr', 'make_mask_none', 'mask_or', 'masked', 

'masked_array', 'masked_equal', 'masked_greater', 

'masked_greater_equal', 'masked_inside', 'masked_invalid', 

'masked_less', 'masked_less_equal', 'masked_not_equal', 

'masked_object', 'masked_outside', 'masked_print_option', 

'masked_singleton', 'masked_values', 'masked_where', 'max', 'maximum', 

'maximum_fill_value', 'mean', 'min', 'minimum', 'minimum_fill_value', 

'mod', 'multiply', 'mvoid', 'ndim', 'negative', 'nomask', 'nonzero', 

'not_equal', 'ones', 'outer', 'outerproduct', 'power', 'prod', 

'product', 'ptp', 'put', 'putmask', 'rank', 'ravel', 'remainder', 

'repeat', 'reshape', 'resize', 'right_shift', 'round', 'round_', 

'set_fill_value', 'shape', 'sin', 'sinh', 'size', 'soften_mask', 

'sometrue', 'sort', 'sqrt', 'squeeze', 'std', 'subtract', 'sum', 

'swapaxes', 'take', 'tan', 'tanh', 'trace', 'transpose', 'true_divide', 

'var', 'where', 'zeros', 

] 

 

MaskType = np.bool_ 

nomask = MaskType(0) 

 

class MaskedArrayFutureWarning(FutureWarning): 

pass 

 

def _deprecate_argsort_axis(arr): 

""" 

Adjust the axis passed to argsort, warning if necessary 

 

Parameters 

---------- 

arr 

The array which argsort was called on 

 

np.ma.argsort has a long-term bug where the default of the axis argument 

is wrong (gh-8701), which now must be kept for backwards compatibiity. 

Thankfully, this only makes a difference when arrays are 2- or more- 

dimensional, so we only need a warning then. 

""" 

if arr.ndim <= 1: 

# no warning needed - but switch to -1 anyway, to avoid surprising 

# subclasses, which are more likely to implement scalar axes. 

return -1 

else: 

# 2017-04-11, Numpy 1.13.0, gh-8701: warn on axis default 

warnings.warn( 

"In the future the default for argsort will be axis=-1, not the " 

"current None, to match its documentation and np.argsort. " 

"Explicitly pass -1 or None to silence this warning.", 

MaskedArrayFutureWarning, stacklevel=3) 

return None 

 

 

def doc_note(initialdoc, note): 

""" 

Adds a Notes section to an existing docstring. 

 

""" 

if initialdoc is None: 

return 

if note is None: 

return initialdoc 

 

notesplit = re.split(r'\n\s*?Notes\n\s*?-----', initialdoc) 

 

notedoc = """\ 

Notes 

----- 

%s""" % note 

 

if len(notesplit) > 1: 

notedoc = '\n\n ' + notedoc + '\n' 

 

return ''.join(notesplit[:1] + [notedoc] + notesplit[1:]) 

 

 

def get_object_signature(obj): 

""" 

Get the signature from obj 

 

""" 

try: 

sig = formatargspec(*getargspec(obj)) 

except TypeError: 

sig = '' 

return sig 

 

 

############################################################################### 

# Exceptions # 

############################################################################### 

 

 

class MAError(Exception): 

""" 

Class for masked array related errors. 

 

""" 

pass 

 

 

class MaskError(MAError): 

""" 

Class for mask related errors. 

 

""" 

pass 

 

 

############################################################################### 

# Filling options # 

############################################################################### 

 

 

# b: boolean - c: complex - f: floats - i: integer - O: object - S: string 

default_filler = {'b': True, 

'c': 1.e20 + 0.0j, 

'f': 1.e20, 

'i': 999999, 

'O': '?', 

'S': b'N/A', 

'u': 999999, 

'V': b'???', 

'U': u'N/A' 

} 

 

# Add datetime64 and timedelta64 types 

for v in ["Y", "M", "W", "D", "h", "m", "s", "ms", "us", "ns", "ps", 

"fs", "as"]: 

default_filler["M8[" + v + "]"] = np.datetime64("NaT", v) 

default_filler["m8[" + v + "]"] = np.timedelta64("NaT", v) 

 

max_filler = ntypes._minvals 

max_filler.update([(k, -np.inf) for k in [np.float32, np.float64]]) 

min_filler = ntypes._maxvals 

min_filler.update([(k, +np.inf) for k in [np.float32, np.float64]]) 

if 'float128' in ntypes.typeDict: 

max_filler.update([(np.float128, -np.inf)]) 

min_filler.update([(np.float128, +np.inf)]) 

 

 

def _recursive_fill_value(dtype, f): 

""" 

Recursively produce a fill value for `dtype`, calling f on scalar dtypes 

""" 

if dtype.names is not None: 

vals = tuple(_recursive_fill_value(dtype[name], f) for name in dtype.names) 

return np.array(vals, dtype=dtype)[()] # decay to void scalar from 0d 

elif dtype.subdtype: 

subtype, shape = dtype.subdtype 

subval = _recursive_fill_value(subtype, f) 

return np.full(shape, subval) 

else: 

return f(dtype) 

 

 

def _get_dtype_of(obj): 

""" Convert the argument for *_fill_value into a dtype """ 

if isinstance(obj, np.dtype): 

return obj 

elif hasattr(obj, 'dtype'): 

return obj.dtype 

else: 

return np.asanyarray(obj).dtype 

 

 

def default_fill_value(obj): 

""" 

Return the default fill value for the argument object. 

 

The default filling value depends on the datatype of the input 

array or the type of the input scalar: 

 

======== ======== 

datatype default 

======== ======== 

bool True 

int 999999 

float 1.e20 

complex 1.e20+0j 

object '?' 

string 'N/A' 

======== ======== 

 

For structured types, a structured scalar is returned, with each field the 

default fill value for its type. 

 

For subarray types, the fill value is an array of the same size containing 

the default scalar fill value. 

 

Parameters 

---------- 

obj : ndarray, dtype or scalar 

The array data-type or scalar for which the default fill value 

is returned. 

 

Returns 

------- 

fill_value : scalar 

The default fill value. 

 

Examples 

-------- 

>>> np.ma.default_fill_value(1) 

999999 

>>> np.ma.default_fill_value(np.array([1.1, 2., np.pi])) 

1e+20 

>>> np.ma.default_fill_value(np.dtype(complex)) 

(1e+20+0j) 

 

""" 

def _scalar_fill_value(dtype): 

if dtype.kind in 'Mm': 

return default_filler.get(dtype.str[1:], '?') 

else: 

return default_filler.get(dtype.kind, '?') 

 

dtype = _get_dtype_of(obj) 

return _recursive_fill_value(dtype, _scalar_fill_value) 

 

 

def _extremum_fill_value(obj, extremum, extremum_name): 

 

def _scalar_fill_value(dtype): 

try: 

return extremum[dtype] 

except KeyError: 

raise TypeError( 

"Unsuitable type {} for calculating {}." 

.format(dtype, extremum_name) 

) 

 

dtype = _get_dtype_of(obj) 

return _recursive_fill_value(dtype, _scalar_fill_value) 

 

 

def minimum_fill_value(obj): 

""" 

Return the maximum value that can be represented by the dtype of an object. 

 

This function is useful for calculating a fill value suitable for 

taking the minimum of an array with a given dtype. 

 

Parameters 

---------- 

obj : ndarray, dtype or scalar 

An object that can be queried for it's numeric type. 

 

Returns 

------- 

val : scalar 

The maximum representable value. 

 

Raises 

------ 

TypeError 

If `obj` isn't a suitable numeric type. 

 

See Also 

-------- 

maximum_fill_value : The inverse function. 

set_fill_value : Set the filling value of a masked array. 

MaskedArray.fill_value : Return current fill value. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> a = np.int8() 

>>> ma.minimum_fill_value(a) 

127 

>>> a = np.int32() 

>>> ma.minimum_fill_value(a) 

2147483647 

 

An array of numeric data can also be passed. 

 

>>> a = np.array([1, 2, 3], dtype=np.int8) 

>>> ma.minimum_fill_value(a) 

127 

>>> a = np.array([1, 2, 3], dtype=np.float32) 

>>> ma.minimum_fill_value(a) 

inf 

 

""" 

return _extremum_fill_value(obj, min_filler, "minimum") 

 

 

def maximum_fill_value(obj): 

""" 

Return the minimum value that can be represented by the dtype of an object. 

 

This function is useful for calculating a fill value suitable for 

taking the maximum of an array with a given dtype. 

 

Parameters 

---------- 

obj : ndarray, dtype or scalar 

An object that can be queried for it's numeric type. 

 

Returns 

------- 

val : scalar 

The minimum representable value. 

 

Raises 

------ 

TypeError 

If `obj` isn't a suitable numeric type. 

 

See Also 

-------- 

minimum_fill_value : The inverse function. 

set_fill_value : Set the filling value of a masked array. 

MaskedArray.fill_value : Return current fill value. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> a = np.int8() 

>>> ma.maximum_fill_value(a) 

-128 

>>> a = np.int32() 

>>> ma.maximum_fill_value(a) 

-2147483648 

 

An array of numeric data can also be passed. 

 

>>> a = np.array([1, 2, 3], dtype=np.int8) 

>>> ma.maximum_fill_value(a) 

-128 

>>> a = np.array([1, 2, 3], dtype=np.float32) 

>>> ma.maximum_fill_value(a) 

-inf 

 

""" 

return _extremum_fill_value(obj, max_filler, "maximum") 

 

 

def _recursive_set_fill_value(fillvalue, dt): 

""" 

Create a fill value for a structured dtype. 

 

Parameters 

---------- 

fillvalue: scalar or array_like 

Scalar or array representing the fill value. If it is of shorter 

length than the number of fields in dt, it will be resized. 

dt: dtype 

The structured dtype for which to create the fill value. 

 

Returns 

------- 

val: tuple 

A tuple of values corresponding to the structured fill value. 

 

""" 

fillvalue = np.resize(fillvalue, len(dt.names)) 

output_value = [] 

for (fval, name) in zip(fillvalue, dt.names): 

cdtype = dt[name] 

if cdtype.subdtype: 

cdtype = cdtype.subdtype[0] 

 

if cdtype.names is not None: 

output_value.append(tuple(_recursive_set_fill_value(fval, cdtype))) 

else: 

output_value.append(np.array(fval, dtype=cdtype).item()) 

return tuple(output_value) 

 

 

def _check_fill_value(fill_value, ndtype): 

""" 

Private function validating the given `fill_value` for the given dtype. 

 

If fill_value is None, it is set to the default corresponding to the dtype. 

 

If fill_value is not None, its value is forced to the given dtype. 

 

The result is always a 0d array. 

 

""" 

ndtype = np.dtype(ndtype) 

if fill_value is None: 

fill_value = default_fill_value(ndtype) 

elif ndtype.names is not None: 

if isinstance(fill_value, (ndarray, np.void)): 

try: 

fill_value = np.array(fill_value, copy=False, dtype=ndtype) 

except ValueError: 

err_msg = "Unable to transform %s to dtype %s" 

raise ValueError(err_msg % (fill_value, ndtype)) 

else: 

fill_value = np.asarray(fill_value, dtype=object) 

fill_value = np.array(_recursive_set_fill_value(fill_value, ndtype), 

dtype=ndtype) 

else: 

if isinstance(fill_value, basestring) and (ndtype.char not in 'OSVU'): 

# Note this check doesn't work if fill_value is not a scalar 

err_msg = "Cannot set fill value of string with array of dtype %s" 

raise TypeError(err_msg % ndtype) 

else: 

# In case we want to convert 1e20 to int. 

# Also in case of converting string arrays. 

try: 

fill_value = np.array(fill_value, copy=False, dtype=ndtype) 

except (OverflowError, ValueError): 

# Raise TypeError instead of OverflowError or ValueError. 

# OverflowError is seldom used, and the real problem here is 

# that the passed fill_value is not compatible with the ndtype. 

err_msg = "Cannot convert fill_value %s to dtype %s" 

raise TypeError(err_msg % (fill_value, ndtype)) 

return np.array(fill_value) 

 

 

def set_fill_value(a, fill_value): 

""" 

Set the filling value of a, if a is a masked array. 

 

This function changes the fill value of the masked array `a` in place. 

If `a` is not a masked array, the function returns silently, without 

doing anything. 

 

Parameters 

---------- 

a : array_like 

Input array. 

fill_value : dtype 

Filling value. A consistency test is performed to make sure 

the value is compatible with the dtype of `a`. 

 

Returns 

------- 

None 

Nothing returned by this function. 

 

See Also 

-------- 

maximum_fill_value : Return the default fill value for a dtype. 

MaskedArray.fill_value : Return current fill value. 

MaskedArray.set_fill_value : Equivalent method. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> a = np.arange(5) 

>>> a 

array([0, 1, 2, 3, 4]) 

>>> a = ma.masked_where(a < 3, a) 

>>> a 

masked_array(data = [-- -- -- 3 4], 

mask = [ True True True False False], 

fill_value=999999) 

>>> ma.set_fill_value(a, -999) 

>>> a 

masked_array(data = [-- -- -- 3 4], 

mask = [ True True True False False], 

fill_value=-999) 

 

Nothing happens if `a` is not a masked array. 

 

>>> a = range(5) 

>>> a 

[0, 1, 2, 3, 4] 

>>> ma.set_fill_value(a, 100) 

>>> a 

[0, 1, 2, 3, 4] 

>>> a = np.arange(5) 

>>> a 

array([0, 1, 2, 3, 4]) 

>>> ma.set_fill_value(a, 100) 

>>> a 

array([0, 1, 2, 3, 4]) 

 

""" 

if isinstance(a, MaskedArray): 

a.set_fill_value(fill_value) 

return 

 

 

def get_fill_value(a): 

""" 

Return the filling value of a, if any. Otherwise, returns the 

default filling value for that type. 

 

""" 

if isinstance(a, MaskedArray): 

result = a.fill_value 

else: 

result = default_fill_value(a) 

return result 

 

 

def common_fill_value(a, b): 

""" 

Return the common filling value of two masked arrays, if any. 

 

If ``a.fill_value == b.fill_value``, return the fill value, 

otherwise return None. 

 

Parameters 

---------- 

a, b : MaskedArray 

The masked arrays for which to compare fill values. 

 

Returns 

------- 

fill_value : scalar or None 

The common fill value, or None. 

 

Examples 

-------- 

>>> x = np.ma.array([0, 1.], fill_value=3) 

>>> y = np.ma.array([0, 1.], fill_value=3) 

>>> np.ma.common_fill_value(x, y) 

3.0 

 

""" 

t1 = get_fill_value(a) 

t2 = get_fill_value(b) 

if t1 == t2: 

return t1 

return None 

 

 

def filled(a, fill_value=None): 

""" 

Return input as an array with masked data replaced by a fill value. 

 

If `a` is not a `MaskedArray`, `a` itself is returned. 

If `a` is a `MaskedArray` and `fill_value` is None, `fill_value` is set to 

``a.fill_value``. 

 

Parameters 

---------- 

a : MaskedArray or array_like 

An input object. 

fill_value : scalar, optional 

Filling value. Default is None. 

 

Returns 

------- 

a : ndarray 

The filled array. 

 

See Also 

-------- 

compressed 

 

Examples 

-------- 

>>> x = np.ma.array(np.arange(9).reshape(3, 3), mask=[[1, 0, 0], 

... [1, 0, 0], 

... [0, 0, 0]]) 

>>> x.filled() 

array([[999999, 1, 2], 

[999999, 4, 5], 

[ 6, 7, 8]]) 

 

""" 

if hasattr(a, 'filled'): 

return a.filled(fill_value) 

elif isinstance(a, ndarray): 

# Should we check for contiguity ? and a.flags['CONTIGUOUS']: 

return a 

elif isinstance(a, dict): 

return np.array(a, 'O') 

else: 

return np.array(a) 

 

 

def get_masked_subclass(*arrays): 

""" 

Return the youngest subclass of MaskedArray from a list of (masked) arrays. 

 

In case of siblings, the first listed takes over. 

 

""" 

if len(arrays) == 1: 

arr = arrays[0] 

if isinstance(arr, MaskedArray): 

rcls = type(arr) 

else: 

rcls = MaskedArray 

else: 

arrcls = [type(a) for a in arrays] 

rcls = arrcls[0] 

if not issubclass(rcls, MaskedArray): 

rcls = MaskedArray 

for cls in arrcls[1:]: 

if issubclass(cls, rcls): 

rcls = cls 

# Don't return MaskedConstant as result: revert to MaskedArray 

if rcls.__name__ == 'MaskedConstant': 

return MaskedArray 

return rcls 

 

 

def getdata(a, subok=True): 

""" 

Return the data of a masked array as an ndarray. 

 

Return the data of `a` (if any) as an ndarray if `a` is a ``MaskedArray``, 

else return `a` as a ndarray or subclass (depending on `subok`) if not. 

 

Parameters 

---------- 

a : array_like 

Input ``MaskedArray``, alternatively a ndarray or a subclass thereof. 

subok : bool 

Whether to force the output to be a `pure` ndarray (False) or to 

return a subclass of ndarray if appropriate (True, default). 

 

See Also 

-------- 

getmask : Return the mask of a masked array, or nomask. 

getmaskarray : Return the mask of a masked array, or full array of False. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> a = ma.masked_equal([[1,2],[3,4]], 2) 

>>> a 

masked_array(data = 

[[1 --] 

[3 4]], 

mask = 

[[False True] 

[False False]], 

fill_value=999999) 

>>> ma.getdata(a) 

array([[1, 2], 

[3, 4]]) 

 

Equivalently use the ``MaskedArray`` `data` attribute. 

 

>>> a.data 

array([[1, 2], 

[3, 4]]) 

 

""" 

try: 

data = a._data 

except AttributeError: 

data = np.array(a, copy=False, subok=subok) 

if not subok: 

return data.view(ndarray) 

return data 

 

 

get_data = getdata 

 

 

def fix_invalid(a, mask=nomask, copy=True, fill_value=None): 

""" 

Return input with invalid data masked and replaced by a fill value. 

 

Invalid data means values of `nan`, `inf`, etc. 

 

Parameters 

---------- 

a : array_like 

Input array, a (subclass of) ndarray. 

mask : sequence, optional 

Mask. Must be convertible to an array of booleans with the same 

shape as `data`. True indicates a masked (i.e. invalid) data. 

copy : bool, optional 

Whether to use a copy of `a` (True) or to fix `a` in place (False). 

Default is True. 

fill_value : scalar, optional 

Value used for fixing invalid data. Default is None, in which case 

the ``a.fill_value`` is used. 

 

Returns 

------- 

b : MaskedArray 

The input array with invalid entries fixed. 

 

Notes 

----- 

A copy is performed by default. 

 

Examples 

-------- 

>>> x = np.ma.array([1., -1, np.nan, np.inf], mask=[1] + [0]*3) 

>>> x 

masked_array(data = [-- -1.0 nan inf], 

mask = [ True False False False], 

fill_value = 1e+20) 

>>> np.ma.fix_invalid(x) 

masked_array(data = [-- -1.0 -- --], 

mask = [ True False True True], 

fill_value = 1e+20) 

 

>>> fixed = np.ma.fix_invalid(x) 

>>> fixed.data 

array([ 1.00000000e+00, -1.00000000e+00, 1.00000000e+20, 

1.00000000e+20]) 

>>> x.data 

array([ 1., -1., NaN, Inf]) 

 

""" 

a = masked_array(a, copy=copy, mask=mask, subok=True) 

invalid = np.logical_not(np.isfinite(a._data)) 

if not invalid.any(): 

return a 

a._mask |= invalid 

if fill_value is None: 

fill_value = a.fill_value 

a._data[invalid] = fill_value 

return a 

 

def is_string_or_list_of_strings(val): 

return (isinstance(val, basestring) or 

(isinstance(val, list) and val and 

builtins.all(isinstance(s, basestring) for s in val))) 

 

############################################################################### 

# Ufuncs # 

############################################################################### 

 

 

ufunc_domain = {} 

ufunc_fills = {} 

 

 

class _DomainCheckInterval(object): 

""" 

Define a valid interval, so that : 

 

``domain_check_interval(a,b)(x) == True`` where 

``x < a`` or ``x > b``. 

 

""" 

 

def __init__(self, a, b): 

"domain_check_interval(a,b)(x) = true where x < a or y > b" 

if (a > b): 

(a, b) = (b, a) 

self.a = a 

self.b = b 

 

def __call__(self, x): 

"Execute the call behavior." 

# nans at masked positions cause RuntimeWarnings, even though 

# they are masked. To avoid this we suppress warnings. 

with np.errstate(invalid='ignore'): 

return umath.logical_or(umath.greater(x, self.b), 

umath.less(x, self.a)) 

 

 

class _DomainTan(object): 

""" 

Define a valid interval for the `tan` function, so that: 

 

``domain_tan(eps) = True`` where ``abs(cos(x)) < eps`` 

 

""" 

 

def __init__(self, eps): 

"domain_tan(eps) = true where abs(cos(x)) < eps)" 

self.eps = eps 

 

def __call__(self, x): 

"Executes the call behavior." 

with np.errstate(invalid='ignore'): 

return umath.less(umath.absolute(umath.cos(x)), self.eps) 

 

 

class _DomainSafeDivide(object): 

""" 

Define a domain for safe division. 

 

""" 

 

def __init__(self, tolerance=None): 

self.tolerance = tolerance 

 

def __call__(self, a, b): 

# Delay the selection of the tolerance to here in order to reduce numpy 

# import times. The calculation of these parameters is a substantial 

# component of numpy's import time. 

if self.tolerance is None: 

self.tolerance = np.finfo(float).tiny 

# don't call ma ufuncs from __array_wrap__ which would fail for scalars 

a, b = np.asarray(a), np.asarray(b) 

with np.errstate(invalid='ignore'): 

return umath.absolute(a) * self.tolerance >= umath.absolute(b) 

 

 

class _DomainGreater(object): 

""" 

DomainGreater(v)(x) is True where x <= v. 

 

""" 

 

def __init__(self, critical_value): 

"DomainGreater(v)(x) = true where x <= v" 

self.critical_value = critical_value 

 

def __call__(self, x): 

"Executes the call behavior." 

with np.errstate(invalid='ignore'): 

return umath.less_equal(x, self.critical_value) 

 

 

class _DomainGreaterEqual(object): 

""" 

DomainGreaterEqual(v)(x) is True where x < v. 

 

""" 

 

def __init__(self, critical_value): 

"DomainGreaterEqual(v)(x) = true where x < v" 

self.critical_value = critical_value 

 

def __call__(self, x): 

"Executes the call behavior." 

with np.errstate(invalid='ignore'): 

return umath.less(x, self.critical_value) 

 

 

class _MaskedUFunc(object): 

def __init__(self, ufunc): 

self.f = ufunc 

self.__doc__ = ufunc.__doc__ 

self.__name__ = ufunc.__name__ 

 

def __str__(self): 

return "Masked version of {}".format(self.f) 

 

 

class _MaskedUnaryOperation(_MaskedUFunc): 

""" 

Defines masked version of unary operations, where invalid values are 

pre-masked. 

 

Parameters 

---------- 

mufunc : callable 

The function for which to define a masked version. Made available 

as ``_MaskedUnaryOperation.f``. 

fill : scalar, optional 

Filling value, default is 0. 

domain : class instance 

Domain for the function. Should be one of the ``_Domain*`` 

classes. Default is None. 

 

""" 

 

def __init__(self, mufunc, fill=0, domain=None): 

super(_MaskedUnaryOperation, self).__init__(mufunc) 

self.fill = fill 

self.domain = domain 

ufunc_domain[mufunc] = domain 

ufunc_fills[mufunc] = fill 

 

def __call__(self, a, *args, **kwargs): 

""" 

Execute the call behavior. 

 

""" 

d = getdata(a) 

# Deal with domain 

if self.domain is not None: 

# Case 1.1. : Domained function 

# nans at masked positions cause RuntimeWarnings, even though 

# they are masked. To avoid this we suppress warnings. 

with np.errstate(divide='ignore', invalid='ignore'): 

result = self.f(d, *args, **kwargs) 

# Make a mask 

m = ~umath.isfinite(result) 

m |= self.domain(d) 

m |= getmask(a) 

else: 

# Case 1.2. : Function without a domain 

# Get the result and the mask 

with np.errstate(divide='ignore', invalid='ignore'): 

result = self.f(d, *args, **kwargs) 

m = getmask(a) 

 

if not result.ndim: 

# Case 2.1. : The result is scalarscalar 

if m: 

return masked 

return result 

 

if m is not nomask: 

# Case 2.2. The result is an array 

# We need to fill the invalid data back w/ the input Now, 

# that's plain silly: in C, we would just skip the element and 

# keep the original, but we do have to do it that way in Python 

 

# In case result has a lower dtype than the inputs (as in 

# equal) 

try: 

np.copyto(result, d, where=m) 

except TypeError: 

pass 

# Transform to 

masked_result = result.view(get_masked_subclass(a)) 

masked_result._mask = m 

masked_result._update_from(a) 

return masked_result 

 

 

class _MaskedBinaryOperation(_MaskedUFunc): 

""" 

Define masked version of binary operations, where invalid 

values are pre-masked. 

 

Parameters 

---------- 

mbfunc : function 

The function for which to define a masked version. Made available 

as ``_MaskedBinaryOperation.f``. 

domain : class instance 

Default domain for the function. Should be one of the ``_Domain*`` 

classes. Default is None. 

fillx : scalar, optional 

Filling value for the first argument, default is 0. 

filly : scalar, optional 

Filling value for the second argument, default is 0. 

 

""" 

 

def __init__(self, mbfunc, fillx=0, filly=0): 

""" 

abfunc(fillx, filly) must be defined. 

 

abfunc(x, filly) = x for all x to enable reduce. 

 

""" 

super(_MaskedBinaryOperation, self).__init__(mbfunc) 

self.fillx = fillx 

self.filly = filly 

ufunc_domain[mbfunc] = None 

ufunc_fills[mbfunc] = (fillx, filly) 

 

def __call__(self, a, b, *args, **kwargs): 

""" 

Execute the call behavior. 

 

""" 

# Get the data, as ndarray 

(da, db) = (getdata(a), getdata(b)) 

# Get the result 

with np.errstate(): 

np.seterr(divide='ignore', invalid='ignore') 

result = self.f(da, db, *args, **kwargs) 

# Get the mask for the result 

(ma, mb) = (getmask(a), getmask(b)) 

if ma is nomask: 

if mb is nomask: 

m = nomask 

else: 

m = umath.logical_or(getmaskarray(a), mb) 

elif mb is nomask: 

m = umath.logical_or(ma, getmaskarray(b)) 

else: 

m = umath.logical_or(ma, mb) 

 

# Case 1. : scalar 

if not result.ndim: 

if m: 

return masked 

return result 

 

# Case 2. : array 

# Revert result to da where masked 

if m is not nomask and m.any(): 

# any errors, just abort; impossible to guarantee masked values 

try: 

np.copyto(result, da, casting='unsafe', where=m) 

except Exception: 

pass 

 

# Transforms to a (subclass of) MaskedArray 

masked_result = result.view(get_masked_subclass(a, b)) 

masked_result._mask = m 

if isinstance(a, MaskedArray): 

masked_result._update_from(a) 

elif isinstance(b, MaskedArray): 

masked_result._update_from(b) 

return masked_result 

 

def reduce(self, target, axis=0, dtype=None): 

""" 

Reduce `target` along the given `axis`. 

 

""" 

tclass = get_masked_subclass(target) 

m = getmask(target) 

t = filled(target, self.filly) 

if t.shape == (): 

t = t.reshape(1) 

if m is not nomask: 

m = make_mask(m, copy=1) 

m.shape = (1,) 

 

if m is nomask: 

tr = self.f.reduce(t, axis) 

mr = nomask 

else: 

tr = self.f.reduce(t, axis, dtype=dtype or t.dtype) 

mr = umath.logical_and.reduce(m, axis) 

 

if not tr.shape: 

if mr: 

return masked 

else: 

return tr 

masked_tr = tr.view(tclass) 

masked_tr._mask = mr 

return masked_tr 

 

def outer(self, a, b): 

""" 

Return the function applied to the outer product of a and b. 

 

""" 

(da, db) = (getdata(a), getdata(b)) 

d = self.f.outer(da, db) 

ma = getmask(a) 

mb = getmask(b) 

if ma is nomask and mb is nomask: 

m = nomask 

else: 

ma = getmaskarray(a) 

mb = getmaskarray(b) 

m = umath.logical_or.outer(ma, mb) 

if (not m.ndim) and m: 

return masked 

if m is not nomask: 

np.copyto(d, da, where=m) 

if not d.shape: 

return d 

masked_d = d.view(get_masked_subclass(a, b)) 

masked_d._mask = m 

return masked_d 

 

def accumulate(self, target, axis=0): 

"""Accumulate `target` along `axis` after filling with y fill 

value. 

 

""" 

tclass = get_masked_subclass(target) 

t = filled(target, self.filly) 

result = self.f.accumulate(t, axis) 

masked_result = result.view(tclass) 

return masked_result 

 

 

 

class _DomainedBinaryOperation(_MaskedUFunc): 

""" 

Define binary operations that have a domain, like divide. 

 

They have no reduce, outer or accumulate. 

 

Parameters 

---------- 

mbfunc : function 

The function for which to define a masked version. Made available 

as ``_DomainedBinaryOperation.f``. 

domain : class instance 

Default domain for the function. Should be one of the ``_Domain*`` 

classes. 

fillx : scalar, optional 

Filling value for the first argument, default is 0. 

filly : scalar, optional 

Filling value for the second argument, default is 0. 

 

""" 

 

def __init__(self, dbfunc, domain, fillx=0, filly=0): 

"""abfunc(fillx, filly) must be defined. 

abfunc(x, filly) = x for all x to enable reduce. 

""" 

super(_DomainedBinaryOperation, self).__init__(dbfunc) 

self.domain = domain 

self.fillx = fillx 

self.filly = filly 

ufunc_domain[dbfunc] = domain 

ufunc_fills[dbfunc] = (fillx, filly) 

 

def __call__(self, a, b, *args, **kwargs): 

"Execute the call behavior." 

# Get the data 

(da, db) = (getdata(a), getdata(b)) 

# Get the result 

with np.errstate(divide='ignore', invalid='ignore'): 

result = self.f(da, db, *args, **kwargs) 

# Get the mask as a combination of the source masks and invalid 

m = ~umath.isfinite(result) 

m |= getmask(a) 

m |= getmask(b) 

# Apply the domain 

domain = ufunc_domain.get(self.f, None) 

if domain is not None: 

m |= domain(da, db) 

# Take care of the scalar case first 

if (not m.ndim): 

if m: 

return masked 

else: 

return result 

# When the mask is True, put back da if possible 

# any errors, just abort; impossible to guarantee masked values 

try: 

np.copyto(result, 0, casting='unsafe', where=m) 

# avoid using "*" since this may be overlaid 

masked_da = umath.multiply(m, da) 

# only add back if it can be cast safely 

if np.can_cast(masked_da.dtype, result.dtype, casting='safe'): 

result += masked_da 

except Exception: 

pass 

 

# Transforms to a (subclass of) MaskedArray 

masked_result = result.view(get_masked_subclass(a, b)) 

masked_result._mask = m 

if isinstance(a, MaskedArray): 

masked_result._update_from(a) 

elif isinstance(b, MaskedArray): 

masked_result._update_from(b) 

return masked_result 

 

 

# Unary ufuncs 

exp = _MaskedUnaryOperation(umath.exp) 

conjugate = _MaskedUnaryOperation(umath.conjugate) 

sin = _MaskedUnaryOperation(umath.sin) 

cos = _MaskedUnaryOperation(umath.cos) 

tan = _MaskedUnaryOperation(umath.tan) 

arctan = _MaskedUnaryOperation(umath.arctan) 

arcsinh = _MaskedUnaryOperation(umath.arcsinh) 

sinh = _MaskedUnaryOperation(umath.sinh) 

cosh = _MaskedUnaryOperation(umath.cosh) 

tanh = _MaskedUnaryOperation(umath.tanh) 

abs = absolute = _MaskedUnaryOperation(umath.absolute) 

angle = _MaskedUnaryOperation(angle) # from numpy.lib.function_base 

fabs = _MaskedUnaryOperation(umath.fabs) 

negative = _MaskedUnaryOperation(umath.negative) 

floor = _MaskedUnaryOperation(umath.floor) 

ceil = _MaskedUnaryOperation(umath.ceil) 

around = _MaskedUnaryOperation(np.round_) 

logical_not = _MaskedUnaryOperation(umath.logical_not) 

 

# Domained unary ufuncs 

sqrt = _MaskedUnaryOperation(umath.sqrt, 0.0, 

_DomainGreaterEqual(0.0)) 

log = _MaskedUnaryOperation(umath.log, 1.0, 

_DomainGreater(0.0)) 

log2 = _MaskedUnaryOperation(umath.log2, 1.0, 

_DomainGreater(0.0)) 

log10 = _MaskedUnaryOperation(umath.log10, 1.0, 

_DomainGreater(0.0)) 

tan = _MaskedUnaryOperation(umath.tan, 0.0, 

_DomainTan(1e-35)) 

arcsin = _MaskedUnaryOperation(umath.arcsin, 0.0, 

_DomainCheckInterval(-1.0, 1.0)) 

arccos = _MaskedUnaryOperation(umath.arccos, 0.0, 

_DomainCheckInterval(-1.0, 1.0)) 

arccosh = _MaskedUnaryOperation(umath.arccosh, 1.0, 

_DomainGreaterEqual(1.0)) 

arctanh = _MaskedUnaryOperation(umath.arctanh, 0.0, 

_DomainCheckInterval(-1.0 + 1e-15, 1.0 - 1e-15)) 

 

# Binary ufuncs 

add = _MaskedBinaryOperation(umath.add) 

subtract = _MaskedBinaryOperation(umath.subtract) 

multiply = _MaskedBinaryOperation(umath.multiply, 1, 1) 

arctan2 = _MaskedBinaryOperation(umath.arctan2, 0.0, 1.0) 

equal = _MaskedBinaryOperation(umath.equal) 

equal.reduce = None 

not_equal = _MaskedBinaryOperation(umath.not_equal) 

not_equal.reduce = None 

less_equal = _MaskedBinaryOperation(umath.less_equal) 

less_equal.reduce = None 

greater_equal = _MaskedBinaryOperation(umath.greater_equal) 

greater_equal.reduce = None 

less = _MaskedBinaryOperation(umath.less) 

less.reduce = None 

greater = _MaskedBinaryOperation(umath.greater) 

greater.reduce = None 

logical_and = _MaskedBinaryOperation(umath.logical_and) 

alltrue = _MaskedBinaryOperation(umath.logical_and, 1, 1).reduce 

logical_or = _MaskedBinaryOperation(umath.logical_or) 

sometrue = logical_or.reduce 

logical_xor = _MaskedBinaryOperation(umath.logical_xor) 

bitwise_and = _MaskedBinaryOperation(umath.bitwise_and) 

bitwise_or = _MaskedBinaryOperation(umath.bitwise_or) 

bitwise_xor = _MaskedBinaryOperation(umath.bitwise_xor) 

hypot = _MaskedBinaryOperation(umath.hypot) 

 

# Domained binary ufuncs 

divide = _DomainedBinaryOperation(umath.divide, _DomainSafeDivide(), 0, 1) 

true_divide = _DomainedBinaryOperation(umath.true_divide, 

_DomainSafeDivide(), 0, 1) 

floor_divide = _DomainedBinaryOperation(umath.floor_divide, 

_DomainSafeDivide(), 0, 1) 

remainder = _DomainedBinaryOperation(umath.remainder, 

_DomainSafeDivide(), 0, 1) 

fmod = _DomainedBinaryOperation(umath.fmod, _DomainSafeDivide(), 0, 1) 

mod = _DomainedBinaryOperation(umath.mod, _DomainSafeDivide(), 0, 1) 

 

 

############################################################################### 

# Mask creation functions # 

############################################################################### 

 

 

def _replace_dtype_fields_recursive(dtype, primitive_dtype): 

"Private function allowing recursion in _replace_dtype_fields." 

_recurse = _replace_dtype_fields_recursive 

 

# Do we have some name fields ? 

if dtype.names is not None: 

descr = [] 

for name in dtype.names: 

field = dtype.fields[name] 

if len(field) == 3: 

# Prepend the title to the name 

name = (field[-1], name) 

descr.append((name, _recurse(field[0], primitive_dtype))) 

new_dtype = np.dtype(descr) 

 

# Is this some kind of composite a la (float,2) 

elif dtype.subdtype: 

descr = list(dtype.subdtype) 

descr[0] = _recurse(dtype.subdtype[0], primitive_dtype) 

new_dtype = np.dtype(tuple(descr)) 

 

# this is a primitive type, so do a direct replacement 

else: 

new_dtype = primitive_dtype 

 

# preserve identity of dtypes 

if new_dtype == dtype: 

new_dtype = dtype 

 

return new_dtype 

 

 

def _replace_dtype_fields(dtype, primitive_dtype): 

""" 

Construct a dtype description list from a given dtype. 

 

Returns a new dtype object, with all fields and subtypes in the given type 

recursively replaced with `primitive_dtype`. 

 

Arguments are coerced to dtypes first. 

""" 

dtype = np.dtype(dtype) 

primitive_dtype = np.dtype(primitive_dtype) 

return _replace_dtype_fields_recursive(dtype, primitive_dtype) 

 

 

def make_mask_descr(ndtype): 

""" 

Construct a dtype description list from a given dtype. 

 

Returns a new dtype object, with the type of all fields in `ndtype` to a 

boolean type. Field names are not altered. 

 

Parameters 

---------- 

ndtype : dtype 

The dtype to convert. 

 

Returns 

------- 

result : dtype 

A dtype that looks like `ndtype`, the type of all fields is boolean. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> dtype = np.dtype({'names':['foo', 'bar'], 

'formats':[np.float32, int]}) 

>>> dtype 

dtype([('foo', '<f4'), ('bar', '<i4')]) 

>>> ma.make_mask_descr(dtype) 

dtype([('foo', '|b1'), ('bar', '|b1')]) 

>>> ma.make_mask_descr(np.float32) 

dtype('bool') 

 

""" 

return _replace_dtype_fields(ndtype, MaskType) 

 

 

def getmask(a): 

""" 

Return the mask of a masked array, or nomask. 

 

Return the mask of `a` as an ndarray if `a` is a `MaskedArray` and the 

mask is not `nomask`, else return `nomask`. To guarantee a full array 

of booleans of the same shape as a, use `getmaskarray`. 

 

Parameters 

---------- 

a : array_like 

Input `MaskedArray` for which the mask is required. 

 

See Also 

-------- 

getdata : Return the data of a masked array as an ndarray. 

getmaskarray : Return the mask of a masked array, or full array of False. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> a = ma.masked_equal([[1,2],[3,4]], 2) 

>>> a 

masked_array(data = 

[[1 --] 

[3 4]], 

mask = 

[[False True] 

[False False]], 

fill_value=999999) 

>>> ma.getmask(a) 

array([[False, True], 

[False, False]]) 

 

Equivalently use the `MaskedArray` `mask` attribute. 

 

>>> a.mask 

array([[False, True], 

[False, False]]) 

 

Result when mask == `nomask` 

 

>>> b = ma.masked_array([[1,2],[3,4]]) 

>>> b 

masked_array(data = 

[[1 2] 

[3 4]], 

mask = 

False, 

fill_value=999999) 

>>> ma.nomask 

False 

>>> ma.getmask(b) == ma.nomask 

True 

>>> b.mask == ma.nomask 

True 

 

""" 

return getattr(a, '_mask', nomask) 

 

 

get_mask = getmask 

 

 

def getmaskarray(arr): 

""" 

Return the mask of a masked array, or full boolean array of False. 

 

Return the mask of `arr` as an ndarray if `arr` is a `MaskedArray` and 

the mask is not `nomask`, else return a full boolean array of False of 

the same shape as `arr`. 

 

Parameters 

---------- 

arr : array_like 

Input `MaskedArray` for which the mask is required. 

 

See Also 

-------- 

getmask : Return the mask of a masked array, or nomask. 

getdata : Return the data of a masked array as an ndarray. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> a = ma.masked_equal([[1,2],[3,4]], 2) 

>>> a 

masked_array(data = 

[[1 --] 

[3 4]], 

mask = 

[[False True] 

[False False]], 

fill_value=999999) 

>>> ma.getmaskarray(a) 

array([[False, True], 

[False, False]]) 

 

Result when mask == ``nomask`` 

 

>>> b = ma.masked_array([[1,2],[3,4]]) 

>>> b 

masked_array(data = 

[[1 2] 

[3 4]], 

mask = 

False, 

fill_value=999999) 

>>> >ma.getmaskarray(b) 

array([[False, False], 

[False, False]]) 

 

""" 

mask = getmask(arr) 

if mask is nomask: 

mask = make_mask_none(np.shape(arr), getattr(arr, 'dtype', None)) 

return mask 

 

 

def is_mask(m): 

""" 

Return True if m is a valid, standard mask. 

 

This function does not check the contents of the input, only that the 

type is MaskType. In particular, this function returns False if the 

mask has a flexible dtype. 

 

Parameters 

---------- 

m : array_like 

Array to test. 

 

Returns 

------- 

result : bool 

True if `m.dtype.type` is MaskType, False otherwise. 

 

See Also 

-------- 

isMaskedArray : Test whether input is an instance of MaskedArray. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> m = ma.masked_equal([0, 1, 0, 2, 3], 0) 

>>> m 

masked_array(data = [-- 1 -- 2 3], 

mask = [ True False True False False], 

fill_value=999999) 

>>> ma.is_mask(m) 

False 

>>> ma.is_mask(m.mask) 

True 

 

Input must be an ndarray (or have similar attributes) 

for it to be considered a valid mask. 

 

>>> m = [False, True, False] 

>>> ma.is_mask(m) 

False 

>>> m = np.array([False, True, False]) 

>>> m 

array([False, True, False]) 

>>> ma.is_mask(m) 

True 

 

Arrays with complex dtypes don't return True. 

 

>>> dtype = np.dtype({'names':['monty', 'pithon'], 

'formats':[bool, bool]}) 

>>> dtype 

dtype([('monty', '|b1'), ('pithon', '|b1')]) 

>>> m = np.array([(True, False), (False, True), (True, False)], 

dtype=dtype) 

>>> m 

array([(True, False), (False, True), (True, False)], 

dtype=[('monty', '|b1'), ('pithon', '|b1')]) 

>>> ma.is_mask(m) 

False 

 

""" 

try: 

return m.dtype.type is MaskType 

except AttributeError: 

return False 

 

 

def _shrink_mask(m): 

""" 

Shrink a mask to nomask if possible 

""" 

if m.dtype.names is None and not m.any(): 

return nomask 

else: 

return m 

 

 

def make_mask(m, copy=False, shrink=True, dtype=MaskType): 

""" 

Create a boolean mask from an array. 

 

Return `m` as a boolean mask, creating a copy if necessary or requested. 

The function can accept any sequence that is convertible to integers, 

or ``nomask``. Does not require that contents must be 0s and 1s, values 

of 0 are interepreted as False, everything else as True. 

 

Parameters 

---------- 

m : array_like 

Potential mask. 

copy : bool, optional 

Whether to return a copy of `m` (True) or `m` itself (False). 

shrink : bool, optional 

Whether to shrink `m` to ``nomask`` if all its values are False. 

dtype : dtype, optional 

Data-type of the output mask. By default, the output mask has a 

dtype of MaskType (bool). If the dtype is flexible, each field has 

a boolean dtype. This is ignored when `m` is ``nomask``, in which 

case ``nomask`` is always returned. 

 

Returns 

------- 

result : ndarray 

A boolean mask derived from `m`. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> m = [True, False, True, True] 

>>> ma.make_mask(m) 

array([ True, False, True, True]) 

>>> m = [1, 0, 1, 1] 

>>> ma.make_mask(m) 

array([ True, False, True, True]) 

>>> m = [1, 0, 2, -3] 

>>> ma.make_mask(m) 

array([ True, False, True, True]) 

 

Effect of the `shrink` parameter. 

 

>>> m = np.zeros(4) 

>>> m 

array([ 0., 0., 0., 0.]) 

>>> ma.make_mask(m) 

False 

>>> ma.make_mask(m, shrink=False) 

array([False, False, False, False]) 

 

Using a flexible `dtype`. 

 

>>> m = [1, 0, 1, 1] 

>>> n = [0, 1, 0, 0] 

>>> arr = [] 

>>> for man, mouse in zip(m, n): 

... arr.append((man, mouse)) 

>>> arr 

[(1, 0), (0, 1), (1, 0), (1, 0)] 

>>> dtype = np.dtype({'names':['man', 'mouse'], 

'formats':[int, int]}) 

>>> arr = np.array(arr, dtype=dtype) 

>>> arr 

array([(1, 0), (0, 1), (1, 0), (1, 0)], 

dtype=[('man', '<i4'), ('mouse', '<i4')]) 

>>> ma.make_mask(arr, dtype=dtype) 

array([(True, False), (False, True), (True, False), (True, False)], 

dtype=[('man', '|b1'), ('mouse', '|b1')]) 

 

""" 

if m is nomask: 

return nomask 

 

# Make sure the input dtype is valid. 

dtype = make_mask_descr(dtype) 

 

# legacy boolean special case: "existence of fields implies true" 

if isinstance(m, ndarray) and m.dtype.fields and dtype == np.bool_: 

return np.ones(m.shape, dtype=dtype) 

 

# Fill the mask in case there are missing data; turn it into an ndarray. 

result = np.array(filled(m, True), copy=copy, dtype=dtype, subok=True) 

# Bas les masques ! 

if shrink: 

result = _shrink_mask(result) 

return result 

 

 

def make_mask_none(newshape, dtype=None): 

""" 

Return a boolean mask of the given shape, filled with False. 

 

This function returns a boolean ndarray with all entries False, that can 

be used in common mask manipulations. If a complex dtype is specified, the 

type of each field is converted to a boolean type. 

 

Parameters 

---------- 

newshape : tuple 

A tuple indicating the shape of the mask. 

dtype : {None, dtype}, optional 

If None, use a MaskType instance. Otherwise, use a new datatype with 

the same fields as `dtype`, converted to boolean types. 

 

Returns 

------- 

result : ndarray 

An ndarray of appropriate shape and dtype, filled with False. 

 

See Also 

-------- 

make_mask : Create a boolean mask from an array. 

make_mask_descr : Construct a dtype description list from a given dtype. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> ma.make_mask_none((3,)) 

array([False, False, False]) 

 

Defining a more complex dtype. 

 

>>> dtype = np.dtype({'names':['foo', 'bar'], 

'formats':[np.float32, int]}) 

>>> dtype 

dtype([('foo', '<f4'), ('bar', '<i4')]) 

>>> ma.make_mask_none((3,), dtype=dtype) 

array([(False, False), (False, False), (False, False)], 

dtype=[('foo', '|b1'), ('bar', '|b1')]) 

 

""" 

if dtype is None: 

result = np.zeros(newshape, dtype=MaskType) 

else: 

result = np.zeros(newshape, dtype=make_mask_descr(dtype)) 

return result 

 

 

def mask_or(m1, m2, copy=False, shrink=True): 

""" 

Combine two masks with the ``logical_or`` operator. 

 

The result may be a view on `m1` or `m2` if the other is `nomask` 

(i.e. False). 

 

Parameters 

---------- 

m1, m2 : array_like 

Input masks. 

copy : bool, optional 

If copy is False and one of the inputs is `nomask`, return a view 

of the other input mask. Defaults to False. 

shrink : bool, optional 

Whether to shrink the output to `nomask` if all its values are 

False. Defaults to True. 

 

Returns 

------- 

mask : output mask 

The result masks values that are masked in either `m1` or `m2`. 

 

Raises 

------ 

ValueError 

If `m1` and `m2` have different flexible dtypes. 

 

Examples 

-------- 

>>> m1 = np.ma.make_mask([0, 1, 1, 0]) 

>>> m2 = np.ma.make_mask([1, 0, 0, 0]) 

>>> np.ma.mask_or(m1, m2) 

array([ True, True, True, False]) 

 

""" 

 

@recursive 

def _recursive_mask_or(self, m1, m2, newmask): 

names = m1.dtype.names 

for name in names: 

current1 = m1[name] 

if current1.dtype.names is not None: 

self(current1, m2[name], newmask[name]) 

else: 

umath.logical_or(current1, m2[name], newmask[name]) 

return 

 

if (m1 is nomask) or (m1 is False): 

dtype = getattr(m2, 'dtype', MaskType) 

return make_mask(m2, copy=copy, shrink=shrink, dtype=dtype) 

if (m2 is nomask) or (m2 is False): 

dtype = getattr(m1, 'dtype', MaskType) 

return make_mask(m1, copy=copy, shrink=shrink, dtype=dtype) 

if m1 is m2 and is_mask(m1): 

return m1 

(dtype1, dtype2) = (getattr(m1, 'dtype', None), getattr(m2, 'dtype', None)) 

if (dtype1 != dtype2): 

raise ValueError("Incompatible dtypes '%s'<>'%s'" % (dtype1, dtype2)) 

if dtype1.names is not None: 

# Allocate an output mask array with the properly broadcast shape. 

newmask = np.empty(np.broadcast(m1, m2).shape, dtype1) 

_recursive_mask_or(m1, m2, newmask) 

return newmask 

return make_mask(umath.logical_or(m1, m2), copy=copy, shrink=shrink) 

 

 

def flatten_mask(mask): 

""" 

Returns a completely flattened version of the mask, where nested fields 

are collapsed. 

 

Parameters 

---------- 

mask : array_like 

Input array, which will be interpreted as booleans. 

 

Returns 

------- 

flattened_mask : ndarray of bools 

The flattened input. 

 

Examples 

-------- 

>>> mask = np.array([0, 0, 1]) 

>>> flatten_mask(mask) 

array([False, False, True]) 

 

>>> mask = np.array([(0, 0), (0, 1)], dtype=[('a', bool), ('b', bool)]) 

>>> flatten_mask(mask) 

array([False, False, False, True]) 

 

>>> mdtype = [('a', bool), ('b', [('ba', bool), ('bb', bool)])] 

>>> mask = np.array([(0, (0, 0)), (0, (0, 1))], dtype=mdtype) 

>>> flatten_mask(mask) 

array([False, False, False, False, False, True]) 

 

""" 

 

def _flatmask(mask): 

"Flatten the mask and returns a (maybe nested) sequence of booleans." 

mnames = mask.dtype.names 

if mnames is not None: 

return [flatten_mask(mask[name]) for name in mnames] 

else: 

return mask 

 

def _flatsequence(sequence): 

"Generates a flattened version of the sequence." 

try: 

for element in sequence: 

if hasattr(element, '__iter__'): 

for f in _flatsequence(element): 

yield f 

else: 

yield element 

except TypeError: 

yield sequence 

 

mask = np.asarray(mask) 

flattened = _flatsequence(_flatmask(mask)) 

return np.array([_ for _ in flattened], dtype=bool) 

 

 

def _check_mask_axis(mask, axis, keepdims=np._NoValue): 

"Check whether there are masked values along the given axis" 

kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

if mask is not nomask: 

return mask.all(axis=axis, **kwargs) 

return nomask 

 

 

############################################################################### 

# Masking functions # 

############################################################################### 

 

def masked_where(condition, a, copy=True): 

""" 

Mask an array where a condition is met. 

 

Return `a` as an array masked where `condition` is True. 

Any masked values of `a` or `condition` are also masked in the output. 

 

Parameters 

---------- 

condition : array_like 

Masking condition. When `condition` tests floating point values for 

equality, consider using ``masked_values`` instead. 

a : array_like 

Array to mask. 

copy : bool 

If True (default) make a copy of `a` in the result. If False modify 

`a` in place and return a view. 

 

Returns 

------- 

result : MaskedArray 

The result of masking `a` where `condition` is True. 

 

See Also 

-------- 

masked_values : Mask using floating point equality. 

masked_equal : Mask where equal to a given value. 

masked_not_equal : Mask where `not` equal to a given value. 

masked_less_equal : Mask where less than or equal to a given value. 

masked_greater_equal : Mask where greater than or equal to a given value. 

masked_less : Mask where less than a given value. 

masked_greater : Mask where greater than a given value. 

masked_inside : Mask inside a given interval. 

masked_outside : Mask outside a given interval. 

masked_invalid : Mask invalid values (NaNs or infs). 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> a = np.arange(4) 

>>> a 

array([0, 1, 2, 3]) 

>>> ma.masked_where(a <= 2, a) 

masked_array(data = [-- -- -- 3], 

mask = [ True True True False], 

fill_value=999999) 

 

Mask array `b` conditional on `a`. 

 

>>> b = ['a', 'b', 'c', 'd'] 

>>> ma.masked_where(a == 2, b) 

masked_array(data = [a b -- d], 

mask = [False False True False], 

fill_value=N/A) 

 

Effect of the `copy` argument. 

 

>>> c = ma.masked_where(a <= 2, a) 

>>> c 

masked_array(data = [-- -- -- 3], 

mask = [ True True True False], 

fill_value=999999) 

>>> c[0] = 99 

>>> c 

masked_array(data = [99 -- -- 3], 

mask = [False True True False], 

fill_value=999999) 

>>> a 

array([0, 1, 2, 3]) 

>>> c = ma.masked_where(a <= 2, a, copy=False) 

>>> c[0] = 99 

>>> c 

masked_array(data = [99 -- -- 3], 

mask = [False True True False], 

fill_value=999999) 

>>> a 

array([99, 1, 2, 3]) 

 

When `condition` or `a` contain masked values. 

 

>>> a = np.arange(4) 

>>> a = ma.masked_where(a == 2, a) 

>>> a 

masked_array(data = [0 1 -- 3], 

mask = [False False True False], 

fill_value=999999) 

>>> b = np.arange(4) 

>>> b = ma.masked_where(b == 0, b) 

>>> b 

masked_array(data = [-- 1 2 3], 

mask = [ True False False False], 

fill_value=999999) 

>>> ma.masked_where(a == 3, b) 

masked_array(data = [-- 1 -- --], 

mask = [ True False True True], 

fill_value=999999) 

 

""" 

# Make sure that condition is a valid standard-type mask. 

cond = make_mask(condition, shrink=False) 

a = np.array(a, copy=copy, subok=True) 

 

(cshape, ashape) = (cond.shape, a.shape) 

if cshape and cshape != ashape: 

raise IndexError("Inconsistent shape between the condition and the input" 

" (got %s and %s)" % (cshape, ashape)) 

if hasattr(a, '_mask'): 

cond = mask_or(cond, a._mask) 

cls = type(a) 

else: 

cls = MaskedArray 

result = a.view(cls) 

# Assign to *.mask so that structured masks are handled correctly. 

result.mask = _shrink_mask(cond) 

return result 

 

 

def masked_greater(x, value, copy=True): 

""" 

Mask an array where greater than a given value. 

 

This function is a shortcut to ``masked_where``, with 

`condition` = (x > value). 

 

See Also 

-------- 

masked_where : Mask where a condition is met. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> a = np.arange(4) 

>>> a 

array([0, 1, 2, 3]) 

>>> ma.masked_greater(a, 2) 

masked_array(data = [0 1 2 --], 

mask = [False False False True], 

fill_value=999999) 

 

""" 

return masked_where(greater(x, value), x, copy=copy) 

 

 

def masked_greater_equal(x, value, copy=True): 

""" 

Mask an array where greater than or equal to a given value. 

 

This function is a shortcut to ``masked_where``, with 

`condition` = (x >= value). 

 

See Also 

-------- 

masked_where : Mask where a condition is met. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> a = np.arange(4) 

>>> a 

array([0, 1, 2, 3]) 

>>> ma.masked_greater_equal(a, 2) 

masked_array(data = [0 1 -- --], 

mask = [False False True True], 

fill_value=999999) 

 

""" 

return masked_where(greater_equal(x, value), x, copy=copy) 

 

 

def masked_less(x, value, copy=True): 

""" 

Mask an array where less than a given value. 

 

This function is a shortcut to ``masked_where``, with 

`condition` = (x < value). 

 

See Also 

-------- 

masked_where : Mask where a condition is met. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> a = np.arange(4) 

>>> a 

array([0, 1, 2, 3]) 

>>> ma.masked_less(a, 2) 

masked_array(data = [-- -- 2 3], 

mask = [ True True False False], 

fill_value=999999) 

 

""" 

return masked_where(less(x, value), x, copy=copy) 

 

 

def masked_less_equal(x, value, copy=True): 

""" 

Mask an array where less than or equal to a given value. 

 

This function is a shortcut to ``masked_where``, with 

`condition` = (x <= value). 

 

See Also 

-------- 

masked_where : Mask where a condition is met. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> a = np.arange(4) 

>>> a 

array([0, 1, 2, 3]) 

>>> ma.masked_less_equal(a, 2) 

masked_array(data = [-- -- -- 3], 

mask = [ True True True False], 

fill_value=999999) 

 

""" 

return masked_where(less_equal(x, value), x, copy=copy) 

 

 

def masked_not_equal(x, value, copy=True): 

""" 

Mask an array where `not` equal to a given value. 

 

This function is a shortcut to ``masked_where``, with 

`condition` = (x != value). 

 

See Also 

-------- 

masked_where : Mask where a condition is met. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> a = np.arange(4) 

>>> a 

array([0, 1, 2, 3]) 

>>> ma.masked_not_equal(a, 2) 

masked_array(data = [-- -- 2 --], 

mask = [ True True False True], 

fill_value=999999) 

 

""" 

return masked_where(not_equal(x, value), x, copy=copy) 

 

 

def masked_equal(x, value, copy=True): 

""" 

Mask an array where equal to a given value. 

 

This function is a shortcut to ``masked_where``, with 

`condition` = (x == value). For floating point arrays, 

consider using ``masked_values(x, value)``. 

 

See Also 

-------- 

masked_where : Mask where a condition is met. 

masked_values : Mask using floating point equality. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> a = np.arange(4) 

>>> a 

array([0, 1, 2, 3]) 

>>> ma.masked_equal(a, 2) 

masked_array(data = [0 1 -- 3], 

mask = [False False True False], 

fill_value=999999) 

 

""" 

output = masked_where(equal(x, value), x, copy=copy) 

output.fill_value = value 

return output 

 

 

def masked_inside(x, v1, v2, copy=True): 

""" 

Mask an array inside a given interval. 

 

Shortcut to ``masked_where``, where `condition` is True for `x` inside 

the interval [v1,v2] (v1 <= x <= v2). The boundaries `v1` and `v2` 

can be given in either order. 

 

See Also 

-------- 

masked_where : Mask where a condition is met. 

 

Notes 

----- 

The array `x` is prefilled with its filling value. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> x = [0.31, 1.2, 0.01, 0.2, -0.4, -1.1] 

>>> ma.masked_inside(x, -0.3, 0.3) 

masked_array(data = [0.31 1.2 -- -- -0.4 -1.1], 

mask = [False False True True False False], 

fill_value=1e+20) 

 

The order of `v1` and `v2` doesn't matter. 

 

>>> ma.masked_inside(x, 0.3, -0.3) 

masked_array(data = [0.31 1.2 -- -- -0.4 -1.1], 

mask = [False False True True False False], 

fill_value=1e+20) 

 

""" 

if v2 < v1: 

(v1, v2) = (v2, v1) 

xf = filled(x) 

condition = (xf >= v1) & (xf <= v2) 

return masked_where(condition, x, copy=copy) 

 

 

def masked_outside(x, v1, v2, copy=True): 

""" 

Mask an array outside a given interval. 

 

Shortcut to ``masked_where``, where `condition` is True for `x` outside 

the interval [v1,v2] (x < v1)|(x > v2). 

The boundaries `v1` and `v2` can be given in either order. 

 

See Also 

-------- 

masked_where : Mask where a condition is met. 

 

Notes 

----- 

The array `x` is prefilled with its filling value. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> x = [0.31, 1.2, 0.01, 0.2, -0.4, -1.1] 

>>> ma.masked_outside(x, -0.3, 0.3) 

masked_array(data = [-- -- 0.01 0.2 -- --], 

mask = [ True True False False True True], 

fill_value=1e+20) 

 

The order of `v1` and `v2` doesn't matter. 

 

>>> ma.masked_outside(x, 0.3, -0.3) 

masked_array(data = [-- -- 0.01 0.2 -- --], 

mask = [ True True False False True True], 

fill_value=1e+20) 

 

""" 

if v2 < v1: 

(v1, v2) = (v2, v1) 

xf = filled(x) 

condition = (xf < v1) | (xf > v2) 

return masked_where(condition, x, copy=copy) 

 

 

def masked_object(x, value, copy=True, shrink=True): 

""" 

Mask the array `x` where the data are exactly equal to value. 

 

This function is similar to `masked_values`, but only suitable 

for object arrays: for floating point, use `masked_values` instead. 

 

Parameters 

---------- 

x : array_like 

Array to mask 

value : object 

Comparison value 

copy : {True, False}, optional 

Whether to return a copy of `x`. 

shrink : {True, False}, optional 

Whether to collapse a mask full of False to nomask 

 

Returns 

------- 

result : MaskedArray 

The result of masking `x` where equal to `value`. 

 

See Also 

-------- 

masked_where : Mask where a condition is met. 

masked_equal : Mask where equal to a given value (integers). 

masked_values : Mask using floating point equality. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> food = np.array(['green_eggs', 'ham'], dtype=object) 

>>> # don't eat spoiled food 

>>> eat = ma.masked_object(food, 'green_eggs') 

>>> print(eat) 

[-- ham] 

>>> # plain ol` ham is boring 

>>> fresh_food = np.array(['cheese', 'ham', 'pineapple'], dtype=object) 

>>> eat = ma.masked_object(fresh_food, 'green_eggs') 

>>> print(eat) 

[cheese ham pineapple] 

 

Note that `mask` is set to ``nomask`` if possible. 

 

>>> eat 

masked_array(data = [cheese ham pineapple], 

mask = False, 

fill_value=?) 

 

""" 

if isMaskedArray(x): 

condition = umath.equal(x._data, value) 

mask = x._mask 

else: 

condition = umath.equal(np.asarray(x), value) 

mask = nomask 

mask = mask_or(mask, make_mask(condition, shrink=shrink)) 

return masked_array(x, mask=mask, copy=copy, fill_value=value) 

 

 

def masked_values(x, value, rtol=1e-5, atol=1e-8, copy=True, shrink=True): 

""" 

Mask using floating point equality. 

 

Return a MaskedArray, masked where the data in array `x` are approximately 

equal to `value`, determined using `isclose`. The default tolerances for 

`masked_values` are the same as those for `isclose`. 

 

For integer types, exact equality is used, in the same way as 

`masked_equal`. 

 

The fill_value is set to `value` and the mask is set to ``nomask`` if 

possible. 

 

Parameters 

---------- 

x : array_like 

Array to mask. 

value : float 

Masking value. 

rtol, atol : float, optional 

Tolerance parameters passed on to `isclose` 

copy : bool, optional 

Whether to return a copy of `x`. 

shrink : bool, optional 

Whether to collapse a mask full of False to ``nomask``. 

 

Returns 

------- 

result : MaskedArray 

The result of masking `x` where approximately equal to `value`. 

 

See Also 

-------- 

masked_where : Mask where a condition is met. 

masked_equal : Mask where equal to a given value (integers). 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> x = np.array([1, 1.1, 2, 1.1, 3]) 

>>> ma.masked_values(x, 1.1) 

masked_array(data = [1.0 -- 2.0 -- 3.0], 

mask = [False True False True False], 

fill_value=1.1) 

 

Note that `mask` is set to ``nomask`` if possible. 

 

>>> ma.masked_values(x, 1.5) 

masked_array(data = [ 1. 1.1 2. 1.1 3. ], 

mask = False, 

fill_value=1.5) 

 

For integers, the fill value will be different in general to the 

result of ``masked_equal``. 

 

>>> x = np.arange(5) 

>>> x 

array([0, 1, 2, 3, 4]) 

>>> ma.masked_values(x, 2) 

masked_array(data = [0 1 -- 3 4], 

mask = [False False True False False], 

fill_value=2) 

>>> ma.masked_equal(x, 2) 

masked_array(data = [0 1 -- 3 4], 

mask = [False False True False False], 

fill_value=999999) 

 

""" 

xnew = filled(x, value) 

if np.issubdtype(xnew.dtype, np.floating): 

mask = np.isclose(xnew, value, atol=atol, rtol=rtol) 

else: 

mask = umath.equal(xnew, value) 

ret = masked_array(xnew, mask=mask, copy=copy, fill_value=value) 

if shrink: 

ret.shrink_mask() 

return ret 

 

 

def masked_invalid(a, copy=True): 

""" 

Mask an array where invalid values occur (NaNs or infs). 

 

This function is a shortcut to ``masked_where``, with 

`condition` = ~(np.isfinite(a)). Any pre-existing mask is conserved. 

Only applies to arrays with a dtype where NaNs or infs make sense 

(i.e. floating point types), but accepts any array_like object. 

 

See Also 

-------- 

masked_where : Mask where a condition is met. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> a = np.arange(5, dtype=float) 

>>> a[2] = np.NaN 

>>> a[3] = np.PINF 

>>> a 

array([ 0., 1., NaN, Inf, 4.]) 

>>> ma.masked_invalid(a) 

masked_array(data = [0.0 1.0 -- -- 4.0], 

mask = [False False True True False], 

fill_value=1e+20) 

 

""" 

a = np.array(a, copy=copy, subok=True) 

mask = getattr(a, '_mask', None) 

if mask is not None: 

condition = ~(np.isfinite(getdata(a))) 

if mask is not nomask: 

condition |= mask 

cls = type(a) 

else: 

condition = ~(np.isfinite(a)) 

cls = MaskedArray 

result = a.view(cls) 

result._mask = condition 

return result 

 

 

############################################################################### 

# Printing options # 

############################################################################### 

 

 

class _MaskedPrintOption(object): 

""" 

Handle the string used to represent missing data in a masked array. 

 

""" 

 

def __init__(self, display): 

""" 

Create the masked_print_option object. 

 

""" 

self._display = display 

self._enabled = True 

 

def display(self): 

""" 

Display the string to print for masked values. 

 

""" 

return self._display 

 

def set_display(self, s): 

""" 

Set the string to print for masked values. 

 

""" 

self._display = s 

 

def enabled(self): 

""" 

Is the use of the display value enabled? 

 

""" 

return self._enabled 

 

def enable(self, shrink=1): 

""" 

Set the enabling shrink to `shrink`. 

 

""" 

self._enabled = shrink 

 

def __str__(self): 

return str(self._display) 

 

__repr__ = __str__ 

 

# if you single index into a masked location you get this object. 

masked_print_option = _MaskedPrintOption('--') 

 

 

def _recursive_printoption(result, mask, printopt): 

""" 

Puts printoptions in result where mask is True. 

 

Private function allowing for recursion 

 

""" 

names = result.dtype.names 

if names is not None: 

for name in names: 

curdata = result[name] 

curmask = mask[name] 

_recursive_printoption(curdata, curmask, printopt) 

else: 

np.copyto(result, printopt, where=mask) 

return 

 

# For better or worse, these end in a newline 

_legacy_print_templates = dict( 

long_std=textwrap.dedent("""\ 

masked_%(name)s(data = 

%(data)s, 

%(nlen)s mask = 

%(mask)s, 

%(nlen)s fill_value = %(fill)s) 

"""), 

long_flx=textwrap.dedent("""\ 

masked_%(name)s(data = 

%(data)s, 

%(nlen)s mask = 

%(mask)s, 

%(nlen)s fill_value = %(fill)s, 

%(nlen)s dtype = %(dtype)s) 

"""), 

short_std=textwrap.dedent("""\ 

masked_%(name)s(data = %(data)s, 

%(nlen)s mask = %(mask)s, 

%(nlen)s fill_value = %(fill)s) 

"""), 

short_flx=textwrap.dedent("""\ 

masked_%(name)s(data = %(data)s, 

%(nlen)s mask = %(mask)s, 

%(nlen)s fill_value = %(fill)s, 

%(nlen)s dtype = %(dtype)s) 

""") 

) 

 

############################################################################### 

# MaskedArray class # 

############################################################################### 

 

 

def _recursive_filled(a, mask, fill_value): 

""" 

Recursively fill `a` with `fill_value`. 

 

""" 

names = a.dtype.names 

for name in names: 

current = a[name] 

if current.dtype.names is not None: 

_recursive_filled(current, mask[name], fill_value[name]) 

else: 

np.copyto(current, fill_value[name], where=mask[name]) 

 

 

def flatten_structured_array(a): 

""" 

Flatten a structured array. 

 

The data type of the output is chosen such that it can represent all of the 

(nested) fields. 

 

Parameters 

---------- 

a : structured array 

 

Returns 

------- 

output : masked array or ndarray 

A flattened masked array if the input is a masked array, otherwise a 

standard ndarray. 

 

Examples 

-------- 

>>> ndtype = [('a', int), ('b', float)] 

>>> a = np.array([(1, 1), (2, 2)], dtype=ndtype) 

>>> flatten_structured_array(a) 

array([[1., 1.], 

[2., 2.]]) 

 

""" 

 

def flatten_sequence(iterable): 

""" 

Flattens a compound of nested iterables. 

 

""" 

for elm in iter(iterable): 

if hasattr(elm, '__iter__'): 

for f in flatten_sequence(elm): 

yield f 

else: 

yield elm 

 

a = np.asanyarray(a) 

inishape = a.shape 

a = a.ravel() 

if isinstance(a, MaskedArray): 

out = np.array([tuple(flatten_sequence(d.item())) for d in a._data]) 

out = out.view(MaskedArray) 

out._mask = np.array([tuple(flatten_sequence(d.item())) 

for d in getmaskarray(a)]) 

else: 

out = np.array([tuple(flatten_sequence(d.item())) for d in a]) 

if len(inishape) > 1: 

newshape = list(out.shape) 

newshape[0] = inishape 

out.shape = tuple(flatten_sequence(newshape)) 

return out 

 

 

def _arraymethod(funcname, onmask=True): 

""" 

Return a class method wrapper around a basic array method. 

 

Creates a class method which returns a masked array, where the new 

``_data`` array is the output of the corresponding basic method called 

on the original ``_data``. 

 

If `onmask` is True, the new mask is the output of the method called 

on the initial mask. Otherwise, the new mask is just a reference 

to the initial mask. 

 

Parameters 

---------- 

funcname : str 

Name of the function to apply on data. 

onmask : bool 

Whether the mask must be processed also (True) or left 

alone (False). Default is True. Make available as `_onmask` 

attribute. 

 

Returns 

------- 

method : instancemethod 

Class method wrapper of the specified basic array method. 

 

""" 

def wrapped_method(self, *args, **params): 

result = getattr(self._data, funcname)(*args, **params) 

result = result.view(type(self)) 

result._update_from(self) 

mask = self._mask 

if not onmask: 

result.__setmask__(mask) 

elif mask is not nomask: 

# __setmask__ makes a copy, which we don't want 

result._mask = getattr(mask, funcname)(*args, **params) 

return result 

methdoc = getattr(ndarray, funcname, None) or getattr(np, funcname, None) 

if methdoc is not None: 

wrapped_method.__doc__ = methdoc.__doc__ 

wrapped_method.__name__ = funcname 

return wrapped_method 

 

 

class MaskedIterator(object): 

""" 

Flat iterator object to iterate over masked arrays. 

 

A `MaskedIterator` iterator is returned by ``x.flat`` for any masked array 

`x`. It allows iterating over the array as if it were a 1-D array, 

either in a for-loop or by calling its `next` method. 

 

Iteration is done in C-contiguous style, with the last index varying the 

fastest. The iterator can also be indexed using basic slicing or 

advanced indexing. 

 

See Also 

-------- 

MaskedArray.flat : Return a flat iterator over an array. 

MaskedArray.flatten : Returns a flattened copy of an array. 

 

Notes 

----- 

`MaskedIterator` is not exported by the `ma` module. Instead of 

instantiating a `MaskedIterator` directly, use `MaskedArray.flat`. 

 

Examples 

-------- 

>>> x = np.ma.array(arange(6).reshape(2, 3)) 

>>> fl = x.flat 

>>> type(fl) 

<class 'numpy.ma.core.MaskedIterator'> 

>>> for item in fl: 

... print(item) 

... 

0 

1 

2 

3 

4 

5 

 

Extracting more than a single element b indexing the `MaskedIterator` 

returns a masked array: 

 

>>> fl[2:4] 

masked_array(data = [2 3], 

mask = False, 

fill_value = 999999) 

 

""" 

 

def __init__(self, ma): 

self.ma = ma 

self.dataiter = ma._data.flat 

 

if ma._mask is nomask: 

self.maskiter = None 

else: 

self.maskiter = ma._mask.flat 

 

def __iter__(self): 

return self 

 

def __getitem__(self, indx): 

result = self.dataiter.__getitem__(indx).view(type(self.ma)) 

if self.maskiter is not None: 

_mask = self.maskiter.__getitem__(indx) 

if isinstance(_mask, ndarray): 

# set shape to match that of data; this is needed for matrices 

_mask.shape = result.shape 

result._mask = _mask 

elif isinstance(_mask, np.void): 

return mvoid(result, mask=_mask, hardmask=self.ma._hardmask) 

elif _mask: # Just a scalar, masked 

return masked 

return result 

 

# This won't work if ravel makes a copy 

def __setitem__(self, index, value): 

self.dataiter[index] = getdata(value) 

if self.maskiter is not None: 

self.maskiter[index] = getmaskarray(value) 

 

def __next__(self): 

""" 

Return the next value, or raise StopIteration. 

 

Examples 

-------- 

>>> x = np.ma.array([3, 2], mask=[0, 1]) 

>>> fl = x.flat 

>>> fl.next() 

3 

>>> fl.next() 

masked_array(data = --, 

mask = True, 

fill_value = 1e+20) 

>>> fl.next() 

Traceback (most recent call last): 

File "<stdin>", line 1, in <module> 

File "/home/ralf/python/numpy/numpy/ma/core.py", line 2243, in next 

d = self.dataiter.next() 

StopIteration 

 

""" 

d = next(self.dataiter) 

if self.maskiter is not None: 

m = next(self.maskiter) 

if isinstance(m, np.void): 

return mvoid(d, mask=m, hardmask=self.ma._hardmask) 

elif m: # Just a scalar, masked 

return masked 

return d 

 

next = __next__ 

 

 

class MaskedArray(ndarray): 

""" 

An array class with possibly masked values. 

 

Masked values of True exclude the corresponding element from any 

computation. 

 

Construction:: 

 

x = MaskedArray(data, mask=nomask, dtype=None, copy=False, subok=True, 

ndmin=0, fill_value=None, keep_mask=True, hard_mask=None, 

shrink=True, order=None) 

 

Parameters 

---------- 

data : array_like 

Input data. 

mask : sequence, optional 

Mask. Must be convertible to an array of booleans with the same 

shape as `data`. True indicates a masked (i.e. invalid) data. 

dtype : dtype, optional 

Data type of the output. 

If `dtype` is None, the type of the data argument (``data.dtype``) 

is used. If `dtype` is not None and different from ``data.dtype``, 

a copy is performed. 

copy : bool, optional 

Whether to copy the input data (True), or to use a reference instead. 

Default is False. 

subok : bool, optional 

Whether to return a subclass of `MaskedArray` if possible (True) or a 

plain `MaskedArray`. Default is True. 

ndmin : int, optional 

Minimum number of dimensions. Default is 0. 

fill_value : scalar, optional 

Value used to fill in the masked values when necessary. 

If None, a default based on the data-type is used. 

keep_mask : bool, optional 

Whether to combine `mask` with the mask of the input data, if any 

(True), or to use only `mask` for the output (False). Default is True. 

hard_mask : bool, optional 

Whether to use a hard mask or not. With a hard mask, masked values 

cannot be unmasked. Default is False. 

shrink : bool, optional 

Whether to force compression of an empty mask. Default is True. 

order : {'C', 'F', 'A'}, optional 

Specify the order of the array. If order is 'C', then the array 

will be in C-contiguous order (last-index varies the fastest). 

If order is 'F', then the returned array will be in 

Fortran-contiguous order (first-index varies the fastest). 

If order is 'A' (default), then the returned array may be 

in any order (either C-, Fortran-contiguous, or even discontiguous), 

unless a copy is required, in which case it will be C-contiguous. 

 

""" 

 

__array_priority__ = 15 

_defaultmask = nomask 

_defaulthardmask = False 

_baseclass = ndarray 

 

# Maximum number of elements per axis used when printing an array. The 

# 1d case is handled separately because we need more values in this case. 

_print_width = 100 

_print_width_1d = 1500 

 

def __new__(cls, data=None, mask=nomask, dtype=None, copy=False, 

subok=True, ndmin=0, fill_value=None, keep_mask=True, 

hard_mask=None, shrink=True, order=None, **options): 

""" 

Create a new masked array from scratch. 

 

Notes 

----- 

A masked array can also be created by taking a .view(MaskedArray). 

 

""" 

# Process data. 

_data = np.array(data, dtype=dtype, copy=copy, 

order=order, subok=True, ndmin=ndmin) 

_baseclass = getattr(data, '_baseclass', type(_data)) 

# Check that we're not erasing the mask. 

if isinstance(data, MaskedArray) and (data.shape != _data.shape): 

copy = True 

 

# Here, we copy the _view_, so that we can attach new properties to it 

# we must never do .view(MaskedConstant), as that would create a new 

# instance of np.ma.masked, which make identity comparison fail 

if isinstance(data, cls) and subok and not isinstance(data, MaskedConstant): 

_data = ndarray.view(_data, type(data)) 

else: 

_data = ndarray.view(_data, cls) 

# Backwards compatibility w/ numpy.core.ma. 

if hasattr(data, '_mask') and not isinstance(data, ndarray): 

_data._mask = data._mask 

# FIXME _sharedmask is never used. 

_sharedmask = True 

# Process mask. 

# Type of the mask 

mdtype = make_mask_descr(_data.dtype) 

 

if mask is nomask: 

# Case 1. : no mask in input. 

# Erase the current mask ? 

if not keep_mask: 

# With a reduced version 

if shrink: 

_data._mask = nomask 

# With full version 

else: 

_data._mask = np.zeros(_data.shape, dtype=mdtype) 

# Check whether we missed something 

elif isinstance(data, (tuple, list)): 

try: 

# If data is a sequence of masked array 

mask = np.array([getmaskarray(m) for m in data], 

dtype=mdtype) 

except ValueError: 

# If data is nested 

mask = nomask 

# Force shrinking of the mask if needed (and possible) 

if (mdtype == MaskType) and mask.any(): 

_data._mask = mask 

_data._sharedmask = False 

else: 

_data._sharedmask = not copy 

if copy: 

_data._mask = _data._mask.copy() 

# Reset the shape of the original mask 

if getmask(data) is not nomask: 

data._mask.shape = data.shape 

else: 

# Case 2. : With a mask in input. 

# If mask is boolean, create an array of True or False 

if mask is True and mdtype == MaskType: 

mask = np.ones(_data.shape, dtype=mdtype) 

elif mask is False and mdtype == MaskType: 

mask = np.zeros(_data.shape, dtype=mdtype) 

else: 

# Read the mask with the current mdtype 

try: 

mask = np.array(mask, copy=copy, dtype=mdtype) 

# Or assume it's a sequence of bool/int 

except TypeError: 

mask = np.array([tuple([m] * len(mdtype)) for m in mask], 

dtype=mdtype) 

# Make sure the mask and the data have the same shape 

if mask.shape != _data.shape: 

(nd, nm) = (_data.size, mask.size) 

if nm == 1: 

mask = np.resize(mask, _data.shape) 

elif nm == nd: 

mask = np.reshape(mask, _data.shape) 

else: 

msg = "Mask and data not compatible: data size is %i, " + \ 

"mask size is %i." 

raise MaskError(msg % (nd, nm)) 

copy = True 

# Set the mask to the new value 

if _data._mask is nomask: 

_data._mask = mask 

_data._sharedmask = not copy 

else: 

if not keep_mask: 

_data._mask = mask 

_data._sharedmask = not copy 

else: 

if _data.dtype.names is not None: 

def _recursive_or(a, b): 

"do a|=b on each field of a, recursively" 

for name in a.dtype.names: 

(af, bf) = (a[name], b[name]) 

if af.dtype.names is not None: 

_recursive_or(af, bf) 

else: 

af |= bf 

 

_recursive_or(_data._mask, mask) 

else: 

_data._mask = np.logical_or(mask, _data._mask) 

_data._sharedmask = False 

# Update fill_value. 

if fill_value is None: 

fill_value = getattr(data, '_fill_value', None) 

# But don't run the check unless we have something to check. 

if fill_value is not None: 

_data._fill_value = _check_fill_value(fill_value, _data.dtype) 

# Process extra options .. 

if hard_mask is None: 

_data._hardmask = getattr(data, '_hardmask', False) 

else: 

_data._hardmask = hard_mask 

_data._baseclass = _baseclass 

return _data 

 

 

def _update_from(self, obj): 

""" 

Copies some attributes of obj to self. 

 

""" 

if isinstance(obj, ndarray): 

_baseclass = type(obj) 

else: 

_baseclass = ndarray 

# We need to copy the _basedict to avoid backward propagation 

_optinfo = {} 

_optinfo.update(getattr(obj, '_optinfo', {})) 

_optinfo.update(getattr(obj, '_basedict', {})) 

if not isinstance(obj, MaskedArray): 

_optinfo.update(getattr(obj, '__dict__', {})) 

_dict = dict(_fill_value=getattr(obj, '_fill_value', None), 

_hardmask=getattr(obj, '_hardmask', False), 

_sharedmask=getattr(obj, '_sharedmask', False), 

_isfield=getattr(obj, '_isfield', False), 

_baseclass=getattr(obj, '_baseclass', _baseclass), 

_optinfo=_optinfo, 

_basedict=_optinfo) 

self.__dict__.update(_dict) 

self.__dict__.update(_optinfo) 

return 

 

def __array_finalize__(self, obj): 

""" 

Finalizes the masked array. 

 

""" 

# Get main attributes. 

self._update_from(obj) 

 

# We have to decide how to initialize self.mask, based on 

# obj.mask. This is very difficult. There might be some 

# correspondence between the elements in the array we are being 

# created from (= obj) and us. Or there might not. This method can 

# be called in all kinds of places for all kinds of reasons -- could 

# be empty_like, could be slicing, could be a ufunc, could be a view. 

# The numpy subclassing interface simply doesn't give us any way 

# to know, which means that at best this method will be based on 

# guesswork and heuristics. To make things worse, there isn't even any 

# clear consensus about what the desired behavior is. For instance, 

# most users think that np.empty_like(marr) -- which goes via this 

# method -- should return a masked array with an empty mask (see 

# gh-3404 and linked discussions), but others disagree, and they have 

# existing code which depends on empty_like returning an array that 

# matches the input mask. 

# 

# Historically our algorithm was: if the template object mask had the 

# same *number of elements* as us, then we used *it's mask object 

# itself* as our mask, so that writes to us would also write to the 

# original array. This is horribly broken in multiple ways. 

# 

# Now what we do instead is, if the template object mask has the same 

# number of elements as us, and we do not have the same base pointer 

# as the template object (b/c views like arr[...] should keep the same 

# mask), then we make a copy of the template object mask and use 

# that. This is also horribly broken but somewhat less so. Maybe. 

if isinstance(obj, ndarray): 

# XX: This looks like a bug -- shouldn't it check self.dtype 

# instead? 

if obj.dtype.names is not None: 

_mask = getmaskarray(obj) 

else: 

_mask = getmask(obj) 

 

# If self and obj point to exactly the same data, then probably 

# self is a simple view of obj (e.g., self = obj[...]), so they 

# should share the same mask. (This isn't 100% reliable, e.g. self 

# could be the first row of obj, or have strange strides, but as a 

# heuristic it's not bad.) In all other cases, we make a copy of 

# the mask, so that future modifications to 'self' do not end up 

# side-effecting 'obj' as well. 

if (_mask is not nomask and obj.__array_interface__["data"][0] 

!= self.__array_interface__["data"][0]): 

# We should make a copy. But we could get here via astype, 

# in which case the mask might need a new dtype as well 

# (e.g., changing to or from a structured dtype), and the 

# order could have changed. So, change the mask type if 

# needed and use astype instead of copy. 

if self.dtype == obj.dtype: 

_mask_dtype = _mask.dtype 

else: 

_mask_dtype = make_mask_descr(self.dtype) 

 

if self.flags.c_contiguous: 

order = "C" 

elif self.flags.f_contiguous: 

order = "F" 

else: 

order = "K" 

 

_mask = _mask.astype(_mask_dtype, order) 

else: 

# Take a view so shape changes, etc., do not propagate back. 

_mask = _mask.view() 

else: 

_mask = nomask 

 

self._mask = _mask 

# Finalize the mask 

if self._mask is not nomask: 

try: 

self._mask.shape = self.shape 

except ValueError: 

self._mask = nomask 

except (TypeError, AttributeError): 

# When _mask.shape is not writable (because it's a void) 

pass 

 

# Finalize the fill_value 

if self._fill_value is not None: 

self._fill_value = _check_fill_value(self._fill_value, self.dtype) 

elif self.dtype.names is not None: 

# Finalize the default fill_value for structured arrays 

self._fill_value = _check_fill_value(None, self.dtype) 

 

def __array_wrap__(self, obj, context=None): 

""" 

Special hook for ufuncs. 

 

Wraps the numpy array and sets the mask according to context. 

 

""" 

if obj is self: # for in-place operations 

result = obj 

else: 

result = obj.view(type(self)) 

result._update_from(self) 

 

if context is not None: 

result._mask = result._mask.copy() 

func, args, out_i = context 

# args sometimes contains outputs (gh-10459), which we don't want 

input_args = args[:func.nin] 

m = reduce(mask_or, [getmaskarray(arg) for arg in input_args]) 

# Get the domain mask 

domain = ufunc_domain.get(func, None) 

if domain is not None: 

# Take the domain, and make sure it's a ndarray 

with np.errstate(divide='ignore', invalid='ignore'): 

d = filled(domain(*input_args), True) 

 

if d.any(): 

# Fill the result where the domain is wrong 

try: 

# Binary domain: take the last value 

fill_value = ufunc_fills[func][-1] 

except TypeError: 

# Unary domain: just use this one 

fill_value = ufunc_fills[func] 

except KeyError: 

# Domain not recognized, use fill_value instead 

fill_value = self.fill_value 

 

np.copyto(result, fill_value, where=d) 

 

# Update the mask 

if m is nomask: 

m = d 

else: 

# Don't modify inplace, we risk back-propagation 

m = (m | d) 

 

# Make sure the mask has the proper size 

if result is not self and result.shape == () and m: 

return masked 

else: 

result._mask = m 

result._sharedmask = False 

 

return result 

 

def view(self, dtype=None, type=None, fill_value=None): 

""" 

Return a view of the MaskedArray data 

 

Parameters 

---------- 

dtype : data-type or ndarray sub-class, optional 

Data-type descriptor of the returned view, e.g., float32 or int16. 

The default, None, results in the view having the same data-type 

as `a`. As with ``ndarray.view``, dtype can also be specified as 

an ndarray sub-class, which then specifies the type of the 

returned object (this is equivalent to setting the ``type`` 

parameter). 

type : Python type, optional 

Type of the returned view, either ndarray or a subclass. The 

default None results in type preservation. 

 

Notes 

----- 

 

``a.view()`` is used two different ways: 

 

``a.view(some_dtype)`` or ``a.view(dtype=some_dtype)`` constructs a view 

of the array's memory with a different data-type. This can cause a 

reinterpretation of the bytes of memory. 

 

``a.view(ndarray_subclass)`` or ``a.view(type=ndarray_subclass)`` just 

returns an instance of `ndarray_subclass` that looks at the same array 

(same shape, dtype, etc.) This does not cause a reinterpretation of the 

memory. 

 

If `fill_value` is not specified, but `dtype` is specified (and is not 

an ndarray sub-class), the `fill_value` of the MaskedArray will be 

reset. If neither `fill_value` nor `dtype` are specified (or if 

`dtype` is an ndarray sub-class), then the fill value is preserved. 

Finally, if `fill_value` is specified, but `dtype` is not, the fill 

value is set to the specified value. 

 

For ``a.view(some_dtype)``, if ``some_dtype`` has a different number of 

bytes per entry than the previous dtype (for example, converting a 

regular array to a structured array), then the behavior of the view 

cannot be predicted just from the superficial appearance of ``a`` (shown 

by ``print(a)``). It also depends on exactly how ``a`` is stored in 

memory. Therefore if ``a`` is C-ordered versus fortran-ordered, versus 

defined as a slice or transpose, etc., the view may give different 

results. 

""" 

 

if dtype is None: 

if type is None: 

output = ndarray.view(self) 

else: 

output = ndarray.view(self, type) 

elif type is None: 

try: 

if issubclass(dtype, ndarray): 

output = ndarray.view(self, dtype) 

dtype = None 

else: 

output = ndarray.view(self, dtype) 

except TypeError: 

output = ndarray.view(self, dtype) 

else: 

output = ndarray.view(self, dtype, type) 

 

# also make the mask be a view (so attr changes to the view's 

# mask do no affect original object's mask) 

# (especially important to avoid affecting np.masked singleton) 

if (getmask(output) is not nomask): 

output._mask = output._mask.view() 

 

# Make sure to reset the _fill_value if needed 

if getattr(output, '_fill_value', None) is not None: 

if fill_value is None: 

if dtype is None: 

pass # leave _fill_value as is 

else: 

output._fill_value = None 

else: 

output.fill_value = fill_value 

return output 

view.__doc__ = ndarray.view.__doc__ 

 

def __getitem__(self, indx): 

""" 

x.__getitem__(y) <==> x[y] 

 

Return the item described by i, as a masked array. 

 

""" 

# We could directly use ndarray.__getitem__ on self. 

# But then we would have to modify __array_finalize__ to prevent the 

# mask of being reshaped if it hasn't been set up properly yet 

# So it's easier to stick to the current version 

dout = self.data[indx] 

_mask = self._mask 

 

def _is_scalar(m): 

return not isinstance(m, np.ndarray) 

 

def _scalar_heuristic(arr, elem): 

""" 

Return whether `elem` is a scalar result of indexing `arr`, or None 

if undecidable without promoting nomask to a full mask 

""" 

# obviously a scalar 

if not isinstance(elem, np.ndarray): 

return True 

 

# object array scalar indexing can return anything 

elif arr.dtype.type is np.object_: 

if arr.dtype is not elem.dtype: 

# elem is an array, but dtypes do not match, so must be 

# an element 

return True 

 

# well-behaved subclass that only returns 0d arrays when 

# expected - this is not a scalar 

elif type(arr).__getitem__ == ndarray.__getitem__: 

return False 

 

return None 

 

if _mask is not nomask: 

# _mask cannot be a subclass, so it tells us whether we should 

# expect a scalar. It also cannot be of dtype object. 

mout = _mask[indx] 

scalar_expected = _is_scalar(mout) 

 

else: 

# attempt to apply the heuristic to avoid constructing a full mask 

mout = nomask 

scalar_expected = _scalar_heuristic(self.data, dout) 

if scalar_expected is None: 

# heuristics have failed 

# construct a full array, so we can be certain. This is costly. 

# we could also fall back on ndarray.__getitem__(self.data, indx) 

scalar_expected = _is_scalar(getmaskarray(self)[indx]) 

 

# Did we extract a single item? 

if scalar_expected: 

# A record 

if isinstance(dout, np.void): 

# We should always re-cast to mvoid, otherwise users can 

# change masks on rows that already have masked values, but not 

# on rows that have no masked values, which is inconsistent. 

return mvoid(dout, mask=mout, hardmask=self._hardmask) 

 

# special case introduced in gh-5962 

elif (self.dtype.type is np.object_ and 

isinstance(dout, np.ndarray) and 

dout is not masked): 

# If masked, turn into a MaskedArray, with everything masked. 

if mout: 

return MaskedArray(dout, mask=True) 

else: 

return dout 

 

# Just a scalar 

else: 

if mout: 

return masked 

else: 

return dout 

else: 

# Force dout to MA 

dout = dout.view(type(self)) 

# Inherit attributes from self 

dout._update_from(self) 

# Check the fill_value 

if is_string_or_list_of_strings(indx): 

if self._fill_value is not None: 

dout._fill_value = self._fill_value[indx] 

 

# If we're indexing a multidimensional field in a 

# structured array (such as dtype("(2,)i2,(2,)i1")), 

# dimensionality goes up (M[field].ndim == M.ndim + 

# M.dtype[field].ndim). That's fine for 

# M[field] but problematic for M[field].fill_value 

# which should have shape () to avoid breaking several 

# methods. There is no great way out, so set to 

# first element. See issue #6723. 

if dout._fill_value.ndim > 0: 

if not (dout._fill_value == 

dout._fill_value.flat[0]).all(): 

warnings.warn( 

"Upon accessing multidimensional field " 

"{indx:s}, need to keep dimensionality " 

"of fill_value at 0. Discarding " 

"heterogeneous fill_value and setting " 

"all to {fv!s}.".format(indx=indx, 

fv=dout._fill_value[0]), 

stacklevel=2) 

dout._fill_value = dout._fill_value.flat[0] 

dout._isfield = True 

# Update the mask if needed 

if mout is not nomask: 

# set shape to match that of data; this is needed for matrices 

dout._mask = reshape(mout, dout.shape) 

dout._sharedmask = True 

# Note: Don't try to check for m.any(), that'll take too long 

return dout 

 

def __setitem__(self, indx, value): 

""" 

x.__setitem__(i, y) <==> x[i]=y 

 

Set item described by index. If value is masked, masks those 

locations. 

 

""" 

if self is masked: 

raise MaskError('Cannot alter the masked element.') 

_data = self._data 

_mask = self._mask 

if isinstance(indx, basestring): 

_data[indx] = value 

if _mask is nomask: 

self._mask = _mask = make_mask_none(self.shape, self.dtype) 

_mask[indx] = getmask(value) 

return 

 

_dtype = _data.dtype 

 

if value is masked: 

# The mask wasn't set: create a full version. 

if _mask is nomask: 

_mask = self._mask = make_mask_none(self.shape, _dtype) 

# Now, set the mask to its value. 

if _dtype.names is not None: 

_mask[indx] = tuple([True] * len(_dtype.names)) 

else: 

_mask[indx] = True 

return 

 

# Get the _data part of the new value 

dval = getattr(value, '_data', value) 

# Get the _mask part of the new value 

mval = getmask(value) 

if _dtype.names is not None and mval is nomask: 

mval = tuple([False] * len(_dtype.names)) 

if _mask is nomask: 

# Set the data, then the mask 

_data[indx] = dval 

if mval is not nomask: 

_mask = self._mask = make_mask_none(self.shape, _dtype) 

_mask[indx] = mval 

elif not self._hardmask: 

# Set the data, then the mask 

_data[indx] = dval 

_mask[indx] = mval 

elif hasattr(indx, 'dtype') and (indx.dtype == MaskType): 

indx = indx * umath.logical_not(_mask) 

_data[indx] = dval 

else: 

if _dtype.names is not None: 

err_msg = "Flexible 'hard' masks are not yet supported." 

raise NotImplementedError(err_msg) 

mindx = mask_or(_mask[indx], mval, copy=True) 

dindx = self._data[indx] 

if dindx.size > 1: 

np.copyto(dindx, dval, where=~mindx) 

elif mindx is nomask: 

dindx = dval 

_data[indx] = dindx 

_mask[indx] = mindx 

return 

 

# Define so that we can overwrite the setter. 

@property 

def dtype(self): 

return super(MaskedArray, self).dtype 

 

@dtype.setter 

def dtype(self, dtype): 

super(MaskedArray, type(self)).dtype.__set__(self, dtype) 

if self._mask is not nomask: 

self._mask = self._mask.view(make_mask_descr(dtype), ndarray) 

# Try to reset the shape of the mask (if we don't have a void). 

# This raises a ValueError if the dtype change won't work. 

try: 

self._mask.shape = self.shape 

except (AttributeError, TypeError): 

pass 

 

@property 

def shape(self): 

return super(MaskedArray, self).shape 

 

@shape.setter 

def shape(self, shape): 

super(MaskedArray, type(self)).shape.__set__(self, shape) 

# Cannot use self._mask, since it may not (yet) exist when a 

# masked matrix sets the shape. 

if getmask(self) is not nomask: 

self._mask.shape = self.shape 

 

def __setmask__(self, mask, copy=False): 

""" 

Set the mask. 

 

""" 

idtype = self.dtype 

current_mask = self._mask 

if mask is masked: 

mask = True 

 

if (current_mask is nomask): 

# Make sure the mask is set 

# Just don't do anything if there's nothing to do. 

if mask is nomask: 

return 

current_mask = self._mask = make_mask_none(self.shape, idtype) 

 

if idtype.names is None: 

# No named fields. 

# Hardmask: don't unmask the data 

if self._hardmask: 

current_mask |= mask 

# Softmask: set everything to False 

# If it's obviously a compatible scalar, use a quick update 

# method. 

elif isinstance(mask, (int, float, np.bool_, np.number)): 

current_mask[...] = mask 

# Otherwise fall back to the slower, general purpose way. 

else: 

current_mask.flat = mask 

else: 

# Named fields w/ 

mdtype = current_mask.dtype 

mask = np.array(mask, copy=False) 

# Mask is a singleton 

if not mask.ndim: 

# It's a boolean : make a record 

if mask.dtype.kind == 'b': 

mask = np.array(tuple([mask.item()] * len(mdtype)), 

dtype=mdtype) 

# It's a record: make sure the dtype is correct 

else: 

mask = mask.astype(mdtype) 

# Mask is a sequence 

else: 

# Make sure the new mask is a ndarray with the proper dtype 

try: 

mask = np.array(mask, copy=copy, dtype=mdtype) 

# Or assume it's a sequence of bool/int 

except TypeError: 

mask = np.array([tuple([m] * len(mdtype)) for m in mask], 

dtype=mdtype) 

# Hardmask: don't unmask the data 

if self._hardmask: 

for n in idtype.names: 

current_mask[n] |= mask[n] 

# Softmask: set everything to False 

# If it's obviously a compatible scalar, use a quick update 

# method. 

elif isinstance(mask, (int, float, np.bool_, np.number)): 

current_mask[...] = mask 

# Otherwise fall back to the slower, general purpose way. 

else: 

current_mask.flat = mask 

# Reshape if needed 

if current_mask.shape: 

current_mask.shape = self.shape 

return 

 

_set_mask = __setmask__ 

 

def _get_mask(self): 

"""Return the current mask. 

 

""" 

# We could try to force a reshape, but that wouldn't work in some 

# cases. 

return self._mask 

 

mask = property(fget=_get_mask, fset=__setmask__, doc="Mask") 

 

def _get_recordmask(self): 

""" 

Return the mask of the records. 

 

A record is masked when all the fields are masked. 

 

""" 

_mask = self._mask.view(ndarray) 

if _mask.dtype.names is None: 

return _mask 

return np.all(flatten_structured_array(_mask), axis=-1) 

 

def _set_recordmask(self): 

""" 

Return the mask of the records. 

 

A record is masked when all the fields are masked. 

 

""" 

raise NotImplementedError("Coming soon: setting the mask per records!") 

 

recordmask = property(fget=_get_recordmask) 

 

def harden_mask(self): 

""" 

Force the mask to hard. 

 

Whether the mask of a masked array is hard or soft is determined by 

its `hardmask` property. `harden_mask` sets `hardmask` to True. 

 

See Also 

-------- 

hardmask 

 

""" 

self._hardmask = True 

return self 

 

def soften_mask(self): 

""" 

Force the mask to soft. 

 

Whether the mask of a masked array is hard or soft is determined by 

its `hardmask` property. `soften_mask` sets `hardmask` to False. 

 

See Also 

-------- 

hardmask 

 

""" 

self._hardmask = False 

return self 

 

hardmask = property(fget=lambda self: self._hardmask, 

doc="Hardness of the mask") 

 

def unshare_mask(self): 

""" 

Copy the mask and set the sharedmask flag to False. 

 

Whether the mask is shared between masked arrays can be seen from 

the `sharedmask` property. `unshare_mask` ensures the mask is not shared. 

A copy of the mask is only made if it was shared. 

 

See Also 

-------- 

sharedmask 

 

""" 

if self._sharedmask: 

self._mask = self._mask.copy() 

self._sharedmask = False 

return self 

 

sharedmask = property(fget=lambda self: self._sharedmask, 

doc="Share status of the mask (read-only).") 

 

def shrink_mask(self): 

""" 

Reduce a mask to nomask when possible. 

 

Parameters 

---------- 

None 

 

Returns 

------- 

None 

 

Examples 

-------- 

>>> x = np.ma.array([[1,2 ], [3, 4]], mask=[0]*4) 

>>> x.mask 

array([[False, False], 

[False, False]]) 

>>> x.shrink_mask() 

>>> x.mask 

False 

 

""" 

self._mask = _shrink_mask(self._mask) 

return self 

 

baseclass = property(fget=lambda self: self._baseclass, 

doc="Class of the underlying data (read-only).") 

 

def _get_data(self): 

"""Return the current data, as a view of the original 

underlying data. 

 

""" 

return ndarray.view(self, self._baseclass) 

 

_data = property(fget=_get_data) 

data = property(fget=_get_data) 

 

def _get_flat(self): 

"Return a flat iterator." 

return MaskedIterator(self) 

 

def _set_flat(self, value): 

"Set a flattened version of self to value." 

y = self.ravel() 

y[:] = value 

 

flat = property(fget=_get_flat, fset=_set_flat, 

doc="Flat version of the array.") 

 

def get_fill_value(self): 

""" 

Return the filling value of the masked array. 

 

Returns 

------- 

fill_value : scalar 

The filling value. 

 

Examples 

-------- 

>>> for dt in [np.int32, np.int64, np.float64, np.complex128]: 

... np.ma.array([0, 1], dtype=dt).get_fill_value() 

... 

999999 

999999 

1e+20 

(1e+20+0j) 

 

>>> x = np.ma.array([0, 1.], fill_value=-np.inf) 

>>> x.get_fill_value() 

-inf 

 

""" 

if self._fill_value is None: 

self._fill_value = _check_fill_value(None, self.dtype) 

 

# Temporary workaround to account for the fact that str and bytes 

# scalars cannot be indexed with (), whereas all other numpy 

# scalars can. See issues #7259 and #7267. 

# The if-block can be removed after #7267 has been fixed. 

if isinstance(self._fill_value, ndarray): 

return self._fill_value[()] 

return self._fill_value 

 

def set_fill_value(self, value=None): 

""" 

Set the filling value of the masked array. 

 

Parameters 

---------- 

value : scalar, optional 

The new filling value. Default is None, in which case a default 

based on the data type is used. 

 

See Also 

-------- 

ma.set_fill_value : Equivalent function. 

 

Examples 

-------- 

>>> x = np.ma.array([0, 1.], fill_value=-np.inf) 

>>> x.fill_value 

-inf 

>>> x.set_fill_value(np.pi) 

>>> x.fill_value 

3.1415926535897931 

 

Reset to default: 

 

>>> x.set_fill_value() 

>>> x.fill_value 

1e+20 

 

""" 

target = _check_fill_value(value, self.dtype) 

_fill_value = self._fill_value 

if _fill_value is None: 

# Create the attribute if it was undefined 

self._fill_value = target 

else: 

# Don't overwrite the attribute, just fill it (for propagation) 

_fill_value[()] = target 

 

fill_value = property(fget=get_fill_value, fset=set_fill_value, 

doc="Filling value.") 

 

def filled(self, fill_value=None): 

""" 

Return a copy of self, with masked values filled with a given value. 

**However**, if there are no masked values to fill, self will be 

returned instead as an ndarray. 

 

Parameters 

---------- 

fill_value : scalar, optional 

The value to use for invalid entries (None by default). 

If None, the `fill_value` attribute of the array is used instead. 

 

Returns 

------- 

filled_array : ndarray 

A copy of ``self`` with invalid entries replaced by *fill_value* 

(be it the function argument or the attribute of ``self``), or 

``self`` itself as an ndarray if there are no invalid entries to 

be replaced. 

 

Notes 

----- 

The result is **not** a MaskedArray! 

 

Examples 

-------- 

>>> x = np.ma.array([1,2,3,4,5], mask=[0,0,1,0,1], fill_value=-999) 

>>> x.filled() 

array([1, 2, -999, 4, -999]) 

>>> type(x.filled()) 

<type 'numpy.ndarray'> 

 

Subclassing is preserved. This means that if, e.g., the data part of 

the masked array is a recarray, `filled` returns a recarray: 

 

>>> x = np.array([(-1, 2), (-3, 4)], dtype='i8,i8').view(np.recarray) 

>>> m = np.ma.array(x, mask=[(True, False), (False, True)]) 

>>> m.filled() 

rec.array([(999999, 2), ( -3, 999999)], 

dtype=[('f0', '<i8'), ('f1', '<i8')]) 

""" 

m = self._mask 

if m is nomask: 

return self._data 

 

if fill_value is None: 

fill_value = self.fill_value 

else: 

fill_value = _check_fill_value(fill_value, self.dtype) 

 

if self is masked_singleton: 

return np.asanyarray(fill_value) 

 

if m.dtype.names is not None: 

result = self._data.copy('K') 

_recursive_filled(result, self._mask, fill_value) 

elif not m.any(): 

return self._data 

else: 

result = self._data.copy('K') 

try: 

np.copyto(result, fill_value, where=m) 

except (TypeError, AttributeError): 

fill_value = narray(fill_value, dtype=object) 

d = result.astype(object) 

result = np.choose(m, (d, fill_value)) 

except IndexError: 

# ok, if scalar 

if self._data.shape: 

raise 

elif m: 

result = np.array(fill_value, dtype=self.dtype) 

else: 

result = self._data 

return result 

 

def compressed(self): 

""" 

Return all the non-masked data as a 1-D array. 

 

Returns 

------- 

data : ndarray 

A new `ndarray` holding the non-masked data is returned. 

 

Notes 

----- 

The result is **not** a MaskedArray! 

 

Examples 

-------- 

>>> x = np.ma.array(np.arange(5), mask=[0]*2 + [1]*3) 

>>> x.compressed() 

array([0, 1]) 

>>> type(x.compressed()) 

<type 'numpy.ndarray'> 

 

""" 

data = ndarray.ravel(self._data) 

if self._mask is not nomask: 

data = data.compress(np.logical_not(ndarray.ravel(self._mask))) 

return data 

 

def compress(self, condition, axis=None, out=None): 

""" 

Return `a` where condition is ``True``. 

 

If condition is a `MaskedArray`, missing values are considered 

as ``False``. 

 

Parameters 

---------- 

condition : var 

Boolean 1-d array selecting which entries to return. If len(condition) 

is less than the size of a along the axis, then output is truncated 

to length of condition array. 

axis : {None, int}, optional 

Axis along which the operation must be performed. 

out : {None, ndarray}, optional 

Alternative output array in which to place the result. It must have 

the same shape as the expected output but the type will be cast if 

necessary. 

 

Returns 

------- 

result : MaskedArray 

A :class:`MaskedArray` object. 

 

Notes 

----- 

Please note the difference with :meth:`compressed` ! 

The output of :meth:`compress` has a mask, the output of 

:meth:`compressed` does not. 

 

Examples 

-------- 

>>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

>>> print(x) 

[[1 -- 3] 

[-- 5 --] 

[7 -- 9]] 

>>> x.compress([1, 0, 1]) 

masked_array(data = [1 3], 

mask = [False False], 

fill_value=999999) 

 

>>> x.compress([1, 0, 1], axis=1) 

masked_array(data = 

[[1 3] 

[-- --] 

[7 9]], 

mask = 

[[False False] 

[ True True] 

[False False]], 

fill_value=999999) 

 

""" 

# Get the basic components 

(_data, _mask) = (self._data, self._mask) 

 

# Force the condition to a regular ndarray and forget the missing 

# values. 

condition = np.array(condition, copy=False, subok=False) 

 

_new = _data.compress(condition, axis=axis, out=out).view(type(self)) 

_new._update_from(self) 

if _mask is not nomask: 

_new._mask = _mask.compress(condition, axis=axis) 

return _new 

 

def _insert_masked_print(self): 

""" 

Replace masked values with masked_print_option, casting all innermost 

dtypes to object. 

""" 

if masked_print_option.enabled(): 

mask = self._mask 

if mask is nomask: 

res = self._data 

else: 

# convert to object array to make filled work 

data = self._data 

# For big arrays, to avoid a costly conversion to the 

# object dtype, extract the corners before the conversion. 

print_width = (self._print_width if self.ndim > 1 

else self._print_width_1d) 

for axis in range(self.ndim): 

if data.shape[axis] > print_width: 

ind = print_width // 2 

arr = np.split(data, (ind, -ind), axis=axis) 

data = np.concatenate((arr[0], arr[2]), axis=axis) 

arr = np.split(mask, (ind, -ind), axis=axis) 

mask = np.concatenate((arr[0], arr[2]), axis=axis) 

 

rdtype = _replace_dtype_fields(self.dtype, "O") 

res = data.astype(rdtype) 

_recursive_printoption(res, mask, masked_print_option) 

else: 

res = self.filled(self.fill_value) 

return res 

 

def __str__(self): 

return str(self._insert_masked_print()) 

 

if sys.version_info.major < 3: 

def __unicode__(self): 

return unicode(self._insert_masked_print()) 

 

def __repr__(self): 

""" 

Literal string representation. 

 

""" 

if self._baseclass is np.ndarray: 

name = 'array' 

else: 

name = self._baseclass.__name__ 

 

 

# 2016-11-19: Demoted to legacy format 

if np.get_printoptions()['legacy'] == '1.13': 

is_long = self.ndim > 1 

parameters = dict( 

name=name, 

nlen=" " * len(name), 

data=str(self), 

mask=str(self._mask), 

fill=str(self.fill_value), 

dtype=str(self.dtype) 

) 

is_structured = bool(self.dtype.names) 

key = '{}_{}'.format( 

'long' if is_long else 'short', 

'flx' if is_structured else 'std' 

) 

return _legacy_print_templates[key] % parameters 

 

prefix = 'masked_{}('.format(name) 

 

dtype_needed = ( 

not np.core.arrayprint.dtype_is_implied(self.dtype) or 

np.all(self.mask) or 

self.size == 0 

) 

 

# determine which keyword args need to be shown 

keys = ['data', 'mask', 'fill_value'] 

if dtype_needed: 

keys.append('dtype') 

 

# array has only one row (non-column) 

is_one_row = builtins.all(dim == 1 for dim in self.shape[:-1]) 

 

# choose what to indent each keyword with 

min_indent = 2 

if is_one_row: 

# first key on the same line as the type, remaining keys 

# aligned by equals 

indents = {} 

indents[keys[0]] = prefix 

for k in keys[1:]: 

n = builtins.max(min_indent, len(prefix + keys[0]) - len(k)) 

indents[k] = ' ' * n 

prefix = '' # absorbed into the first indent 

else: 

# each key on its own line, indented by two spaces 

indents = {k: ' ' * min_indent for k in keys} 

prefix = prefix + '\n' # first key on the next line 

 

# format the field values 

reprs = {} 

reprs['data'] = np.array2string( 

self._insert_masked_print(), 

separator=", ", 

prefix=indents['data'] + 'data=', 

suffix=',') 

reprs['mask'] = np.array2string( 

self._mask, 

separator=", ", 

prefix=indents['mask'] + 'mask=', 

suffix=',') 

reprs['fill_value'] = repr(self.fill_value) 

if dtype_needed: 

reprs['dtype'] = np.core.arrayprint.dtype_short_repr(self.dtype) 

 

# join keys with values and indentations 

result = ',\n'.join( 

'{}{}={}'.format(indents[k], k, reprs[k]) 

for k in keys 

) 

return prefix + result + ')' 

 

def _delegate_binop(self, other): 

# This emulates the logic in 

# private/binop_override.h:forward_binop_should_defer 

if isinstance(other, type(self)): 

return False 

array_ufunc = getattr(other, "__array_ufunc__", False) 

if array_ufunc is False: 

other_priority = getattr(other, "__array_priority__", -1000000) 

return self.__array_priority__ < other_priority 

else: 

# If array_ufunc is not None, it will be called inside the ufunc; 

# None explicitly tells us to not call the ufunc, i.e., defer. 

return array_ufunc is None 

 

def _comparison(self, other, compare): 

"""Compare self with other using operator.eq or operator.ne. 

 

When either of the elements is masked, the result is masked as well, 

but the underlying boolean data are still set, with self and other 

considered equal if both are masked, and unequal otherwise. 

 

For structured arrays, all fields are combined, with masked values 

ignored. The result is masked if all fields were masked, with self 

and other considered equal only if both were fully masked. 

""" 

omask = getmask(other) 

smask = self.mask 

mask = mask_or(smask, omask, copy=True) 

 

odata = getdata(other) 

if mask.dtype.names is not None: 

# For possibly masked structured arrays we need to be careful, 

# since the standard structured array comparison will use all 

# fields, masked or not. To avoid masked fields influencing the 

# outcome, we set all masked fields in self to other, so they'll 

# count as equal. To prepare, we ensure we have the right shape. 

broadcast_shape = np.broadcast(self, odata).shape 

sbroadcast = np.broadcast_to(self, broadcast_shape, subok=True) 

sbroadcast._mask = mask 

sdata = sbroadcast.filled(odata) 

# Now take care of the mask; the merged mask should have an item 

# masked if all fields were masked (in one and/or other). 

mask = (mask == np.ones((), mask.dtype)) 

 

else: 

# For regular arrays, just use the data as they come. 

sdata = self.data 

 

check = compare(sdata, odata) 

 

if isinstance(check, (np.bool_, bool)): 

return masked if mask else check 

 

if mask is not nomask: 

# Adjust elements that were masked, which should be treated 

# as equal if masked in both, unequal if masked in one. 

# Note that this works automatically for structured arrays too. 

check = np.where(mask, compare(smask, omask), check) 

if mask.shape != check.shape: 

# Guarantee consistency of the shape, making a copy since the 

# the mask may need to get written to later. 

mask = np.broadcast_to(mask, check.shape).copy() 

 

check = check.view(type(self)) 

check._update_from(self) 

check._mask = mask 

 

# Cast fill value to bool_ if needed. If it cannot be cast, the 

# default boolean fill value is used. 

if check._fill_value is not None: 

try: 

fill = _check_fill_value(check._fill_value, np.bool_) 

except (TypeError, ValueError): 

fill = _check_fill_value(None, np.bool_) 

check._fill_value = fill 

 

return check 

 

def __eq__(self, other): 

"""Check whether other equals self elementwise. 

 

When either of the elements is masked, the result is masked as well, 

but the underlying boolean data are still set, with self and other 

considered equal if both are masked, and unequal otherwise. 

 

For structured arrays, all fields are combined, with masked values 

ignored. The result is masked if all fields were masked, with self 

and other considered equal only if both were fully masked. 

""" 

return self._comparison(other, operator.eq) 

 

def __ne__(self, other): 

"""Check whether other does not equal self elementwise. 

 

When either of the elements is masked, the result is masked as well, 

but the underlying boolean data are still set, with self and other 

considered equal if both are masked, and unequal otherwise. 

 

For structured arrays, all fields are combined, with masked values 

ignored. The result is masked if all fields were masked, with self 

and other considered equal only if both were fully masked. 

""" 

return self._comparison(other, operator.ne) 

 

def __add__(self, other): 

""" 

Add self to other, and return a new masked array. 

 

""" 

if self._delegate_binop(other): 

return NotImplemented 

return add(self, other) 

 

def __radd__(self, other): 

""" 

Add other to self, and return a new masked array. 

 

""" 

# In analogy with __rsub__ and __rdiv__, use original order: 

# we get here from `other + self`. 

return add(other, self) 

 

def __sub__(self, other): 

""" 

Subtract other from self, and return a new masked array. 

 

""" 

if self._delegate_binop(other): 

return NotImplemented 

return subtract(self, other) 

 

def __rsub__(self, other): 

""" 

Subtract self from other, and return a new masked array. 

 

""" 

return subtract(other, self) 

 

def __mul__(self, other): 

"Multiply self by other, and return a new masked array." 

if self._delegate_binop(other): 

return NotImplemented 

return multiply(self, other) 

 

def __rmul__(self, other): 

""" 

Multiply other by self, and return a new masked array. 

 

""" 

# In analogy with __rsub__ and __rdiv__, use original order: 

# we get here from `other * self`. 

return multiply(other, self) 

 

def __div__(self, other): 

""" 

Divide other into self, and return a new masked array. 

 

""" 

if self._delegate_binop(other): 

return NotImplemented 

return divide(self, other) 

 

def __truediv__(self, other): 

""" 

Divide other into self, and return a new masked array. 

 

""" 

if self._delegate_binop(other): 

return NotImplemented 

return true_divide(self, other) 

 

def __rtruediv__(self, other): 

""" 

Divide self into other, and return a new masked array. 

 

""" 

return true_divide(other, self) 

 

def __floordiv__(self, other): 

""" 

Divide other into self, and return a new masked array. 

 

""" 

if self._delegate_binop(other): 

return NotImplemented 

return floor_divide(self, other) 

 

def __rfloordiv__(self, other): 

""" 

Divide self into other, and return a new masked array. 

 

""" 

return floor_divide(other, self) 

 

def __pow__(self, other): 

""" 

Raise self to the power other, masking the potential NaNs/Infs 

 

""" 

if self._delegate_binop(other): 

return NotImplemented 

return power(self, other) 

 

def __rpow__(self, other): 

""" 

Raise other to the power self, masking the potential NaNs/Infs 

 

""" 

return power(other, self) 

 

def __iadd__(self, other): 

""" 

Add other to self in-place. 

 

""" 

m = getmask(other) 

if self._mask is nomask: 

if m is not nomask and m.any(): 

self._mask = make_mask_none(self.shape, self.dtype) 

self._mask += m 

else: 

if m is not nomask: 

self._mask += m 

self._data.__iadd__(np.where(self._mask, self.dtype.type(0), 

getdata(other))) 

return self 

 

def __isub__(self, other): 

""" 

Subtract other from self in-place. 

 

""" 

m = getmask(other) 

if self._mask is nomask: 

if m is not nomask and m.any(): 

self._mask = make_mask_none(self.shape, self.dtype) 

self._mask += m 

elif m is not nomask: 

self._mask += m 

self._data.__isub__(np.where(self._mask, self.dtype.type(0), 

getdata(other))) 

return self 

 

def __imul__(self, other): 

""" 

Multiply self by other in-place. 

 

""" 

m = getmask(other) 

if self._mask is nomask: 

if m is not nomask and m.any(): 

self._mask = make_mask_none(self.shape, self.dtype) 

self._mask += m 

elif m is not nomask: 

self._mask += m 

self._data.__imul__(np.where(self._mask, self.dtype.type(1), 

getdata(other))) 

return self 

 

def __idiv__(self, other): 

""" 

Divide self by other in-place. 

 

""" 

other_data = getdata(other) 

dom_mask = _DomainSafeDivide().__call__(self._data, other_data) 

other_mask = getmask(other) 

new_mask = mask_or(other_mask, dom_mask) 

# The following 3 lines control the domain filling 

if dom_mask.any(): 

(_, fval) = ufunc_fills[np.divide] 

other_data = np.where(dom_mask, fval, other_data) 

self._mask |= new_mask 

self._data.__idiv__(np.where(self._mask, self.dtype.type(1), 

other_data)) 

return self 

 

def __ifloordiv__(self, other): 

""" 

Floor divide self by other in-place. 

 

""" 

other_data = getdata(other) 

dom_mask = _DomainSafeDivide().__call__(self._data, other_data) 

other_mask = getmask(other) 

new_mask = mask_or(other_mask, dom_mask) 

# The following 3 lines control the domain filling 

if dom_mask.any(): 

(_, fval) = ufunc_fills[np.floor_divide] 

other_data = np.where(dom_mask, fval, other_data) 

self._mask |= new_mask 

self._data.__ifloordiv__(np.where(self._mask, self.dtype.type(1), 

other_data)) 

return self 

 

def __itruediv__(self, other): 

""" 

True divide self by other in-place. 

 

""" 

other_data = getdata(other) 

dom_mask = _DomainSafeDivide().__call__(self._data, other_data) 

other_mask = getmask(other) 

new_mask = mask_or(other_mask, dom_mask) 

# The following 3 lines control the domain filling 

if dom_mask.any(): 

(_, fval) = ufunc_fills[np.true_divide] 

other_data = np.where(dom_mask, fval, other_data) 

self._mask |= new_mask 

self._data.__itruediv__(np.where(self._mask, self.dtype.type(1), 

other_data)) 

return self 

 

def __ipow__(self, other): 

""" 

Raise self to the power other, in place. 

 

""" 

other_data = getdata(other) 

other_mask = getmask(other) 

with np.errstate(divide='ignore', invalid='ignore'): 

self._data.__ipow__(np.where(self._mask, self.dtype.type(1), 

other_data)) 

invalid = np.logical_not(np.isfinite(self._data)) 

if invalid.any(): 

if self._mask is not nomask: 

self._mask |= invalid 

else: 

self._mask = invalid 

np.copyto(self._data, self.fill_value, where=invalid) 

new_mask = mask_or(other_mask, invalid) 

self._mask = mask_or(self._mask, new_mask) 

return self 

 

def __float__(self): 

""" 

Convert to float. 

 

""" 

if self.size > 1: 

raise TypeError("Only length-1 arrays can be converted " 

"to Python scalars") 

elif self._mask: 

warnings.warn("Warning: converting a masked element to nan.", stacklevel=2) 

return np.nan 

return float(self.item()) 

 

def __int__(self): 

""" 

Convert to int. 

 

""" 

if self.size > 1: 

raise TypeError("Only length-1 arrays can be converted " 

"to Python scalars") 

elif self._mask: 

raise MaskError('Cannot convert masked element to a Python int.') 

return int(self.item()) 

 

def __long__(self): 

""" 

Convert to long. 

""" 

if self.size > 1: 

raise TypeError("Only length-1 arrays can be converted " 

"to Python scalars") 

elif self._mask: 

raise MaskError('Cannot convert masked element to a Python long.') 

return long(self.item()) 

 

 

def get_imag(self): 

""" 

Return the imaginary part of the masked array. 

 

The returned array is a view on the imaginary part of the `MaskedArray` 

whose `get_imag` method is called. 

 

Parameters 

---------- 

None 

 

Returns 

------- 

result : MaskedArray 

The imaginary part of the masked array. 

 

See Also 

-------- 

get_real, real, imag 

 

Examples 

-------- 

>>> x = np.ma.array([1+1.j, -2j, 3.45+1.6j], mask=[False, True, False]) 

>>> x.get_imag() 

masked_array(data = [1.0 -- 1.6], 

mask = [False True False], 

fill_value = 1e+20) 

 

""" 

result = self._data.imag.view(type(self)) 

result.__setmask__(self._mask) 

return result 

 

imag = property(fget=get_imag, doc="Imaginary part.") 

 

def get_real(self): 

""" 

Return the real part of the masked array. 

 

The returned array is a view on the real part of the `MaskedArray` 

whose `get_real` method is called. 

 

Parameters 

---------- 

None 

 

Returns 

------- 

result : MaskedArray 

The real part of the masked array. 

 

See Also 

-------- 

get_imag, real, imag 

 

Examples 

-------- 

>>> x = np.ma.array([1+1.j, -2j, 3.45+1.6j], mask=[False, True, False]) 

>>> x.get_real() 

masked_array(data = [1.0 -- 3.45], 

mask = [False True False], 

fill_value = 1e+20) 

 

""" 

result = self._data.real.view(type(self)) 

result.__setmask__(self._mask) 

return result 

real = property(fget=get_real, doc="Real part") 

 

def count(self, axis=None, keepdims=np._NoValue): 

""" 

Count the non-masked elements of the array along the given axis. 

 

Parameters 

---------- 

axis : None or int or tuple of ints, optional 

Axis or axes along which the count is performed. 

The default (`axis` = `None`) performs the count over all 

the dimensions of the input array. `axis` may be negative, in 

which case it counts from the last to the first axis. 

 

.. versionadded:: 1.10.0 

 

If this is a tuple of ints, the count is performed on multiple 

axes, instead of a single axis or all the axes as before. 

keepdims : bool, optional 

If this is set to True, the axes which are reduced are left 

in the result as dimensions with size one. With this option, 

the result will broadcast correctly against the array. 

 

Returns 

------- 

result : ndarray or scalar 

An array with the same shape as the input array, with the specified 

axis removed. If the array is a 0-d array, or if `axis` is None, a 

scalar is returned. 

 

See Also 

-------- 

count_masked : Count masked elements in array or along a given axis. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> a = ma.arange(6).reshape((2, 3)) 

>>> a[1, :] = ma.masked 

>>> a 

masked_array(data = 

[[0 1 2] 

[-- -- --]], 

mask = 

[[False False False] 

[ True True True]], 

fill_value = 999999) 

>>> a.count() 

3 

 

When the `axis` keyword is specified an array of appropriate size is 

returned. 

 

>>> a.count(axis=0) 

array([1, 1, 1]) 

>>> a.count(axis=1) 

array([3, 0]) 

 

""" 

kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

 

m = self._mask 

# special case for matrices (we assume no other subclasses modify 

# their dimensions) 

if isinstance(self.data, np.matrix): 

if m is nomask: 

m = np.zeros(self.shape, dtype=np.bool_) 

m = m.view(type(self.data)) 

 

if m is nomask: 

# compare to _count_reduce_items in _methods.py 

 

if self.shape is (): 

if axis not in (None, 0): 

raise np.AxisError(axis=axis, ndim=self.ndim) 

return 1 

elif axis is None: 

if kwargs.get('keepdims', False): 

return np.array(self.size, dtype=np.intp, ndmin=self.ndim) 

return self.size 

 

axes = normalize_axis_tuple(axis, self.ndim) 

items = 1 

for ax in axes: 

items *= self.shape[ax] 

 

if kwargs.get('keepdims', False): 

out_dims = list(self.shape) 

for a in axes: 

out_dims[a] = 1 

else: 

out_dims = [d for n, d in enumerate(self.shape) 

if n not in axes] 

# make sure to return a 0-d array if axis is supplied 

return np.full(out_dims, items, dtype=np.intp) 

 

# take care of the masked singleton 

if self is masked: 

return 0 

 

return (~m).sum(axis=axis, dtype=np.intp, **kwargs) 

 

def ravel(self, order='C'): 

""" 

Returns a 1D version of self, as a view. 

 

Parameters 

---------- 

order : {'C', 'F', 'A', 'K'}, optional 

The elements of `a` are read using this index order. 'C' means to 

index the elements in C-like order, with the last axis index 

changing fastest, back to the first axis index changing slowest. 

'F' means to index the elements in Fortran-like index order, with 

the first index changing fastest, and the last index changing 

slowest. Note that the 'C' and 'F' options take no account of the 

memory layout of the underlying array, and only refer to the order 

of axis indexing. 'A' means to read the elements in Fortran-like 

index order if `m` is Fortran *contiguous* in memory, C-like order 

otherwise. 'K' means to read the elements in the order they occur 

in memory, except for reversing the data when strides are negative. 

By default, 'C' index order is used. 

 

Returns 

------- 

MaskedArray 

Output view is of shape ``(self.size,)`` (or 

``(np.ma.product(self.shape),)``). 

 

Examples 

-------- 

>>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

>>> print(x) 

[[1 -- 3] 

[-- 5 --] 

[7 -- 9]] 

>>> print(x.ravel()) 

[1 -- 3 -- 5 -- 7 -- 9] 

 

""" 

r = ndarray.ravel(self._data, order=order).view(type(self)) 

r._update_from(self) 

if self._mask is not nomask: 

r._mask = ndarray.ravel(self._mask, order=order).reshape(r.shape) 

else: 

r._mask = nomask 

return r 

 

 

def reshape(self, *s, **kwargs): 

""" 

Give a new shape to the array without changing its data. 

 

Returns a masked array containing the same data, but with a new shape. 

The result is a view on the original array; if this is not possible, a 

ValueError is raised. 

 

Parameters 

---------- 

shape : int or tuple of ints 

The new shape should be compatible with the original shape. If an 

integer is supplied, then the result will be a 1-D array of that 

length. 

order : {'C', 'F'}, optional 

Determines whether the array data should be viewed as in C 

(row-major) or FORTRAN (column-major) order. 

 

Returns 

------- 

reshaped_array : array 

A new view on the array. 

 

See Also 

-------- 

reshape : Equivalent function in the masked array module. 

numpy.ndarray.reshape : Equivalent method on ndarray object. 

numpy.reshape : Equivalent function in the NumPy module. 

 

Notes 

----- 

The reshaping operation cannot guarantee that a copy will not be made, 

to modify the shape in place, use ``a.shape = s`` 

 

Examples 

-------- 

>>> x = np.ma.array([[1,2],[3,4]], mask=[1,0,0,1]) 

>>> print(x) 

[[-- 2] 

[3 --]] 

>>> x = x.reshape((4,1)) 

>>> print(x) 

[[--] 

[2] 

[3] 

[--]] 

 

""" 

kwargs.update(order=kwargs.get('order', 'C')) 

result = self._data.reshape(*s, **kwargs).view(type(self)) 

result._update_from(self) 

mask = self._mask 

if mask is not nomask: 

result._mask = mask.reshape(*s, **kwargs) 

return result 

 

def resize(self, newshape, refcheck=True, order=False): 

""" 

.. warning:: 

 

This method does nothing, except raise a ValueError exception. A 

masked array does not own its data and therefore cannot safely be 

resized in place. Use the `numpy.ma.resize` function instead. 

 

This method is difficult to implement safely and may be deprecated in 

future releases of NumPy. 

 

""" 

# Note : the 'order' keyword looks broken, let's just drop it 

errmsg = "A masked array does not own its data "\ 

"and therefore cannot be resized.\n" \ 

"Use the numpy.ma.resize function instead." 

raise ValueError(errmsg) 

 

def put(self, indices, values, mode='raise'): 

""" 

Set storage-indexed locations to corresponding values. 

 

Sets self._data.flat[n] = values[n] for each n in indices. 

If `values` is shorter than `indices` then it will repeat. 

If `values` has some masked values, the initial mask is updated 

in consequence, else the corresponding values are unmasked. 

 

Parameters 

---------- 

indices : 1-D array_like 

Target indices, interpreted as integers. 

values : array_like 

Values to place in self._data copy at target indices. 

mode : {'raise', 'wrap', 'clip'}, optional 

Specifies how out-of-bounds indices will behave. 

'raise' : raise an error. 

'wrap' : wrap around. 

'clip' : clip to the range. 

 

Notes 

----- 

`values` can be a scalar or length 1 array. 

 

Examples 

-------- 

>>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

>>> print(x) 

[[1 -- 3] 

[-- 5 --] 

[7 -- 9]] 

>>> x.put([0,4,8],[10,20,30]) 

>>> print(x) 

[[10 -- 3] 

[-- 20 --] 

[7 -- 30]] 

 

>>> x.put(4,999) 

>>> print(x) 

[[10 -- 3] 

[-- 999 --] 

[7 -- 30]] 

 

""" 

# Hard mask: Get rid of the values/indices that fall on masked data 

if self._hardmask and self._mask is not nomask: 

mask = self._mask[indices] 

indices = narray(indices, copy=False) 

values = narray(values, copy=False, subok=True) 

values.resize(indices.shape) 

indices = indices[~mask] 

values = values[~mask] 

 

self._data.put(indices, values, mode=mode) 

 

# short circuit if neither self nor values are masked 

if self._mask is nomask and getmask(values) is nomask: 

return 

 

m = getmaskarray(self) 

 

if getmask(values) is nomask: 

m.put(indices, False, mode=mode) 

else: 

m.put(indices, values._mask, mode=mode) 

m = make_mask(m, copy=False, shrink=True) 

self._mask = m 

return 

 

def ids(self): 

""" 

Return the addresses of the data and mask areas. 

 

Parameters 

---------- 

None 

 

Examples 

-------- 

>>> x = np.ma.array([1, 2, 3], mask=[0, 1, 1]) 

>>> x.ids() 

(166670640, 166659832) 

 

If the array has no mask, the address of `nomask` is returned. This address 

is typically not close to the data in memory: 

 

>>> x = np.ma.array([1, 2, 3]) 

>>> x.ids() 

(166691080, 3083169284L) 

 

""" 

if self._mask is nomask: 

return (self.ctypes.data, id(nomask)) 

return (self.ctypes.data, self._mask.ctypes.data) 

 

def iscontiguous(self): 

""" 

Return a boolean indicating whether the data is contiguous. 

 

Parameters 

---------- 

None 

 

Examples 

-------- 

>>> x = np.ma.array([1, 2, 3]) 

>>> x.iscontiguous() 

True 

 

`iscontiguous` returns one of the flags of the masked array: 

 

>>> x.flags 

C_CONTIGUOUS : True 

F_CONTIGUOUS : True 

OWNDATA : False 

WRITEABLE : True 

ALIGNED : True 

WRITEBACKIFCOPY : False 

UPDATEIFCOPY : False 

 

""" 

return self.flags['CONTIGUOUS'] 

 

def all(self, axis=None, out=None, keepdims=np._NoValue): 

""" 

Returns True if all elements evaluate to True. 

 

The output array is masked where all the values along the given axis 

are masked: if the output would have been a scalar and that all the 

values are masked, then the output is `masked`. 

 

Refer to `numpy.all` for full documentation. 

 

See Also 

-------- 

ndarray.all : corresponding function for ndarrays 

numpy.all : equivalent function 

 

Examples 

-------- 

>>> np.ma.array([1,2,3]).all() 

True 

>>> a = np.ma.array([1,2,3], mask=True) 

>>> (a.all() is np.ma.masked) 

True 

 

""" 

kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

 

mask = _check_mask_axis(self._mask, axis, **kwargs) 

if out is None: 

d = self.filled(True).all(axis=axis, **kwargs).view(type(self)) 

if d.ndim: 

d.__setmask__(mask) 

elif mask: 

return masked 

return d 

self.filled(True).all(axis=axis, out=out, **kwargs) 

if isinstance(out, MaskedArray): 

if out.ndim or mask: 

out.__setmask__(mask) 

return out 

 

def any(self, axis=None, out=None, keepdims=np._NoValue): 

""" 

Returns True if any of the elements of `a` evaluate to True. 

 

Masked values are considered as False during computation. 

 

Refer to `numpy.any` for full documentation. 

 

See Also 

-------- 

ndarray.any : corresponding function for ndarrays 

numpy.any : equivalent function 

 

""" 

kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

 

mask = _check_mask_axis(self._mask, axis, **kwargs) 

if out is None: 

d = self.filled(False).any(axis=axis, **kwargs).view(type(self)) 

if d.ndim: 

d.__setmask__(mask) 

elif mask: 

d = masked 

return d 

self.filled(False).any(axis=axis, out=out, **kwargs) 

if isinstance(out, MaskedArray): 

if out.ndim or mask: 

out.__setmask__(mask) 

return out 

 

def nonzero(self): 

""" 

Return the indices of unmasked elements that are not zero. 

 

Returns a tuple of arrays, one for each dimension, containing the 

indices of the non-zero elements in that dimension. The corresponding 

non-zero values can be obtained with:: 

 

a[a.nonzero()] 

 

To group the indices by element, rather than dimension, use 

instead:: 

 

np.transpose(a.nonzero()) 

 

The result of this is always a 2d array, with a row for each non-zero 

element. 

 

Parameters 

---------- 

None 

 

Returns 

------- 

tuple_of_arrays : tuple 

Indices of elements that are non-zero. 

 

See Also 

-------- 

numpy.nonzero : 

Function operating on ndarrays. 

flatnonzero : 

Return indices that are non-zero in the flattened version of the input 

array. 

ndarray.nonzero : 

Equivalent ndarray method. 

count_nonzero : 

Counts the number of non-zero elements in the input array. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> x = ma.array(np.eye(3)) 

>>> x 

masked_array(data = 

[[ 1. 0. 0.] 

[ 0. 1. 0.] 

[ 0. 0. 1.]], 

mask = 

False, 

fill_value=1e+20) 

>>> x.nonzero() 

(array([0, 1, 2]), array([0, 1, 2])) 

 

Masked elements are ignored. 

 

>>> x[1, 1] = ma.masked 

>>> x 

masked_array(data = 

[[1.0 0.0 0.0] 

[0.0 -- 0.0] 

[0.0 0.0 1.0]], 

mask = 

[[False False False] 

[False True False] 

[False False False]], 

fill_value=1e+20) 

>>> x.nonzero() 

(array([0, 2]), array([0, 2])) 

 

Indices can also be grouped by element. 

 

>>> np.transpose(x.nonzero()) 

array([[0, 0], 

[2, 2]]) 

 

A common use for ``nonzero`` is to find the indices of an array, where 

a condition is True. Given an array `a`, the condition `a` > 3 is a 

boolean array and since False is interpreted as 0, ma.nonzero(a > 3) 

yields the indices of the `a` where the condition is true. 

 

>>> a = ma.array([[1,2,3],[4,5,6],[7,8,9]]) 

>>> a > 3 

masked_array(data = 

[[False False False] 

[ True True True] 

[ True True True]], 

mask = 

False, 

fill_value=999999) 

>>> ma.nonzero(a > 3) 

(array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2])) 

 

The ``nonzero`` method of the condition array can also be called. 

 

>>> (a > 3).nonzero() 

(array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2])) 

 

""" 

return narray(self.filled(0), copy=False).nonzero() 

 

def trace(self, offset=0, axis1=0, axis2=1, dtype=None, out=None): 

""" 

(this docstring should be overwritten) 

""" 

#!!!: implement out + test! 

m = self._mask 

if m is nomask: 

result = super(MaskedArray, self).trace(offset=offset, axis1=axis1, 

axis2=axis2, out=out) 

return result.astype(dtype) 

else: 

D = self.diagonal(offset=offset, axis1=axis1, axis2=axis2) 

return D.astype(dtype).filled(0).sum(axis=-1, out=out) 

trace.__doc__ = ndarray.trace.__doc__ 

 

def dot(self, b, out=None, strict=False): 

""" 

a.dot(b, out=None) 

 

Masked dot product of two arrays. Note that `out` and `strict` are 

located in different positions than in `ma.dot`. In order to 

maintain compatibility with the functional version, it is 

recommended that the optional arguments be treated as keyword only. 

At some point that may be mandatory. 

 

.. versionadded:: 1.10.0 

 

Parameters 

---------- 

b : masked_array_like 

Inputs array. 

out : masked_array, optional 

Output argument. This must have the exact kind that would be 

returned if it was not used. In particular, it must have the 

right type, must be C-contiguous, and its dtype must be the 

dtype that would be returned for `ma.dot(a,b)`. This is a 

performance feature. Therefore, if these conditions are not 

met, an exception is raised, instead of attempting to be 

flexible. 

strict : bool, optional 

Whether masked data are propagated (True) or set to 0 (False) 

for the computation. Default is False. Propagating the mask 

means that if a masked value appears in a row or column, the 

whole row or column is considered masked. 

 

.. versionadded:: 1.10.2 

 

See Also 

-------- 

numpy.ma.dot : equivalent function 

 

""" 

return dot(self, b, out=out, strict=strict) 

 

def sum(self, axis=None, dtype=None, out=None, keepdims=np._NoValue): 

""" 

Return the sum of the array elements over the given axis. 

 

Masked elements are set to 0 internally. 

 

Refer to `numpy.sum` for full documentation. 

 

See Also 

-------- 

ndarray.sum : corresponding function for ndarrays 

numpy.sum : equivalent function 

 

Examples 

-------- 

>>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

>>> print(x) 

[[1 -- 3] 

[-- 5 --] 

[7 -- 9]] 

>>> print(x.sum()) 

25 

>>> print(x.sum(axis=1)) 

[4 5 16] 

>>> print(x.sum(axis=0)) 

[8 5 12] 

>>> print(type(x.sum(axis=0, dtype=np.int64)[0])) 

<type 'numpy.int64'> 

 

""" 

kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

 

_mask = self._mask 

newmask = _check_mask_axis(_mask, axis, **kwargs) 

# No explicit output 

if out is None: 

result = self.filled(0).sum(axis, dtype=dtype, **kwargs) 

rndim = getattr(result, 'ndim', 0) 

if rndim: 

result = result.view(type(self)) 

result.__setmask__(newmask) 

elif newmask: 

result = masked 

return result 

# Explicit output 

result = self.filled(0).sum(axis, dtype=dtype, out=out, **kwargs) 

if isinstance(out, MaskedArray): 

outmask = getmask(out) 

if (outmask is nomask): 

outmask = out._mask = make_mask_none(out.shape) 

outmask.flat = newmask 

return out 

 

def cumsum(self, axis=None, dtype=None, out=None): 

""" 

Return the cumulative sum of the array elements over the given axis. 

 

Masked values are set to 0 internally during the computation. 

However, their position is saved, and the result will be masked at 

the same locations. 

 

Refer to `numpy.cumsum` for full documentation. 

 

Notes 

----- 

The mask is lost if `out` is not a valid :class:`MaskedArray` ! 

 

Arithmetic is modular when using integer types, and no error is 

raised on overflow. 

 

See Also 

-------- 

ndarray.cumsum : corresponding function for ndarrays 

numpy.cumsum : equivalent function 

 

Examples 

-------- 

>>> marr = np.ma.array(np.arange(10), mask=[0,0,0,1,1,1,0,0,0,0]) 

>>> print(marr.cumsum()) 

[0 1 3 -- -- -- 9 16 24 33] 

 

""" 

result = self.filled(0).cumsum(axis=axis, dtype=dtype, out=out) 

if out is not None: 

if isinstance(out, MaskedArray): 

out.__setmask__(self.mask) 

return out 

result = result.view(type(self)) 

result.__setmask__(self._mask) 

return result 

 

def prod(self, axis=None, dtype=None, out=None, keepdims=np._NoValue): 

""" 

Return the product of the array elements over the given axis. 

 

Masked elements are set to 1 internally for computation. 

 

Refer to `numpy.prod` for full documentation. 

 

Notes 

----- 

Arithmetic is modular when using integer types, and no error is raised 

on overflow. 

 

See Also 

-------- 

ndarray.prod : corresponding function for ndarrays 

numpy.prod : equivalent function 

""" 

kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

 

_mask = self._mask 

newmask = _check_mask_axis(_mask, axis, **kwargs) 

# No explicit output 

if out is None: 

result = self.filled(1).prod(axis, dtype=dtype, **kwargs) 

rndim = getattr(result, 'ndim', 0) 

if rndim: 

result = result.view(type(self)) 

result.__setmask__(newmask) 

elif newmask: 

result = masked 

return result 

# Explicit output 

result = self.filled(1).prod(axis, dtype=dtype, out=out, **kwargs) 

if isinstance(out, MaskedArray): 

outmask = getmask(out) 

if (outmask is nomask): 

outmask = out._mask = make_mask_none(out.shape) 

outmask.flat = newmask 

return out 

product = prod 

 

def cumprod(self, axis=None, dtype=None, out=None): 

""" 

Return the cumulative product of the array elements over the given axis. 

 

Masked values are set to 1 internally during the computation. 

However, their position is saved, and the result will be masked at 

the same locations. 

 

Refer to `numpy.cumprod` for full documentation. 

 

Notes 

----- 

The mask is lost if `out` is not a valid MaskedArray ! 

 

Arithmetic is modular when using integer types, and no error is 

raised on overflow. 

 

See Also 

-------- 

ndarray.cumprod : corresponding function for ndarrays 

numpy.cumprod : equivalent function 

""" 

result = self.filled(1).cumprod(axis=axis, dtype=dtype, out=out) 

if out is not None: 

if isinstance(out, MaskedArray): 

out.__setmask__(self._mask) 

return out 

result = result.view(type(self)) 

result.__setmask__(self._mask) 

return result 

 

def mean(self, axis=None, dtype=None, out=None, keepdims=np._NoValue): 

""" 

Returns the average of the array elements along given axis. 

 

Masked entries are ignored, and result elements which are not 

finite will be masked. 

 

Refer to `numpy.mean` for full documentation. 

 

See Also 

-------- 

ndarray.mean : corresponding function for ndarrays 

numpy.mean : Equivalent function 

numpy.ma.average: Weighted average. 

 

Examples 

-------- 

>>> a = np.ma.array([1,2,3], mask=[False, False, True]) 

>>> a 

masked_array(data = [1 2 --], 

mask = [False False True], 

fill_value = 999999) 

>>> a.mean() 

1.5 

 

""" 

kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

 

if self._mask is nomask: 

result = super(MaskedArray, self).mean(axis=axis, 

dtype=dtype, **kwargs)[()] 

else: 

dsum = self.sum(axis=axis, dtype=dtype, **kwargs) 

cnt = self.count(axis=axis, **kwargs) 

if cnt.shape == () and (cnt == 0): 

result = masked 

else: 

result = dsum * 1. / cnt 

if out is not None: 

out.flat = result 

if isinstance(out, MaskedArray): 

outmask = getmask(out) 

if (outmask is nomask): 

outmask = out._mask = make_mask_none(out.shape) 

outmask.flat = getmask(result) 

return out 

return result 

 

def anom(self, axis=None, dtype=None): 

""" 

Compute the anomalies (deviations from the arithmetic mean) 

along the given axis. 

 

Returns an array of anomalies, with the same shape as the input and 

where the arithmetic mean is computed along the given axis. 

 

Parameters 

---------- 

axis : int, optional 

Axis over which the anomalies are taken. 

The default is to use the mean of the flattened array as reference. 

dtype : dtype, optional 

Type to use in computing the variance. For arrays of integer type 

the default is float32; for arrays of float types it is the same as 

the array type. 

 

See Also 

-------- 

mean : Compute the mean of the array. 

 

Examples 

-------- 

>>> a = np.ma.array([1,2,3]) 

>>> a.anom() 

masked_array(data = [-1. 0. 1.], 

mask = False, 

fill_value = 1e+20) 

 

""" 

m = self.mean(axis, dtype) 

if m is masked: 

return m 

 

if not axis: 

return (self - m) 

else: 

return (self - expand_dims(m, axis)) 

 

def var(self, axis=None, dtype=None, out=None, ddof=0, 

keepdims=np._NoValue): 

""" 

Returns the variance of the array elements along given axis. 

 

Masked entries are ignored, and result elements which are not 

finite will be masked. 

 

Refer to `numpy.var` for full documentation. 

 

See Also 

-------- 

ndarray.var : corresponding function for ndarrays 

numpy.var : Equivalent function 

""" 

kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

 

# Easy case: nomask, business as usual 

if self._mask is nomask: 

ret = super(MaskedArray, self).var(axis=axis, dtype=dtype, out=out, 

ddof=ddof, **kwargs)[()] 

if out is not None: 

if isinstance(out, MaskedArray): 

out.__setmask__(nomask) 

return out 

return ret 

 

# Some data are masked, yay! 

cnt = self.count(axis=axis, **kwargs) - ddof 

danom = self - self.mean(axis, dtype, keepdims=True) 

if iscomplexobj(self): 

danom = umath.absolute(danom) ** 2 

else: 

danom *= danom 

dvar = divide(danom.sum(axis, **kwargs), cnt).view(type(self)) 

# Apply the mask if it's not a scalar 

if dvar.ndim: 

dvar._mask = mask_or(self._mask.all(axis, **kwargs), (cnt <= 0)) 

dvar._update_from(self) 

elif getmask(dvar): 

# Make sure that masked is returned when the scalar is masked. 

dvar = masked 

if out is not None: 

if isinstance(out, MaskedArray): 

out.flat = 0 

out.__setmask__(True) 

elif out.dtype.kind in 'biu': 

errmsg = "Masked data information would be lost in one or "\ 

"more location." 

raise MaskError(errmsg) 

else: 

out.flat = np.nan 

return out 

# In case with have an explicit output 

if out is not None: 

# Set the data 

out.flat = dvar 

# Set the mask if needed 

if isinstance(out, MaskedArray): 

out.__setmask__(dvar.mask) 

return out 

return dvar 

var.__doc__ = np.var.__doc__ 

 

def std(self, axis=None, dtype=None, out=None, ddof=0, 

keepdims=np._NoValue): 

""" 

Returns the standard deviation of the array elements along given axis. 

 

Masked entries are ignored. 

 

Refer to `numpy.std` for full documentation. 

 

See Also 

-------- 

ndarray.std : corresponding function for ndarrays 

numpy.std : Equivalent function 

""" 

kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

 

dvar = self.var(axis, dtype, out, ddof, **kwargs) 

if dvar is not masked: 

if out is not None: 

np.power(out, 0.5, out=out, casting='unsafe') 

return out 

dvar = sqrt(dvar) 

return dvar 

 

def round(self, decimals=0, out=None): 

""" 

Return each element rounded to the given number of decimals. 

 

Refer to `numpy.around` for full documentation. 

 

See Also 

-------- 

ndarray.around : corresponding function for ndarrays 

numpy.around : equivalent function 

""" 

result = self._data.round(decimals=decimals, out=out).view(type(self)) 

if result.ndim > 0: 

result._mask = self._mask 

result._update_from(self) 

elif self._mask: 

# Return masked when the scalar is masked 

result = masked 

# No explicit output: we're done 

if out is None: 

return result 

if isinstance(out, MaskedArray): 

out.__setmask__(self._mask) 

return out 

 

def argsort(self, axis=np._NoValue, kind='quicksort', order=None, 

endwith=True, fill_value=None): 

""" 

Return an ndarray of indices that sort the array along the 

specified axis. Masked values are filled beforehand to 

`fill_value`. 

 

Parameters 

---------- 

axis : int, optional 

Axis along which to sort. If None, the default, the flattened array 

is used. 

 

.. versionchanged:: 1.13.0 

Previously, the default was documented to be -1, but that was 

in error. At some future date, the default will change to -1, as 

originally intended. 

Until then, the axis should be given explicitly when 

``arr.ndim > 1``, to avoid a FutureWarning. 

kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional 

Sorting algorithm. 

order : list, optional 

When `a` is an array with fields defined, this argument specifies 

which fields to compare first, second, etc. Not all fields need be 

specified. 

endwith : {True, False}, optional 

Whether missing values (if any) should be treated as the largest values 

(True) or the smallest values (False) 

When the array contains unmasked values at the same extremes of the 

datatype, the ordering of these values and the masked values is 

undefined. 

fill_value : {var}, optional 

Value used internally for the masked values. 

If ``fill_value`` is not None, it supersedes ``endwith``. 

 

Returns 

------- 

index_array : ndarray, int 

Array of indices that sort `a` along the specified axis. 

In other words, ``a[index_array]`` yields a sorted `a`. 

 

See Also 

-------- 

MaskedArray.sort : Describes sorting algorithms used. 

lexsort : Indirect stable sort with multiple keys. 

ndarray.sort : Inplace sort. 

 

Notes 

----- 

See `sort` for notes on the different sorting algorithms. 

 

Examples 

-------- 

>>> a = np.ma.array([3,2,1], mask=[False, False, True]) 

>>> a 

masked_array(data = [3 2 --], 

mask = [False False True], 

fill_value = 999999) 

>>> a.argsort() 

array([1, 0, 2]) 

 

""" 

 

# 2017-04-11, Numpy 1.13.0, gh-8701: warn on axis default 

if axis is np._NoValue: 

axis = _deprecate_argsort_axis(self) 

 

if fill_value is None: 

if endwith: 

# nan > inf 

if np.issubdtype(self.dtype, np.floating): 

fill_value = np.nan 

else: 

fill_value = minimum_fill_value(self) 

else: 

fill_value = maximum_fill_value(self) 

 

filled = self.filled(fill_value) 

return filled.argsort(axis=axis, kind=kind, order=order) 

 

def argmin(self, axis=None, fill_value=None, out=None): 

""" 

Return array of indices to the minimum values along the given axis. 

 

Parameters 

---------- 

axis : {None, integer} 

If None, the index is into the flattened array, otherwise along 

the specified axis 

fill_value : {var}, optional 

Value used to fill in the masked values. If None, the output of 

minimum_fill_value(self._data) is used instead. 

out : {None, array}, optional 

Array into which the result can be placed. Its type is preserved 

and it must be of the right shape to hold the output. 

 

Returns 

------- 

ndarray or scalar 

If multi-dimension input, returns a new ndarray of indices to the 

minimum values along the given axis. Otherwise, returns a scalar 

of index to the minimum values along the given axis. 

 

Examples 

-------- 

>>> x = np.ma.array(arange(4), mask=[1,1,0,0]) 

>>> x.shape = (2,2) 

>>> print(x) 

[[-- --] 

[2 3]] 

>>> print(x.argmin(axis=0, fill_value=-1)) 

[0 0] 

>>> print(x.argmin(axis=0, fill_value=9)) 

[1 1] 

 

""" 

if fill_value is None: 

fill_value = minimum_fill_value(self) 

d = self.filled(fill_value).view(ndarray) 

return d.argmin(axis, out=out) 

 

def argmax(self, axis=None, fill_value=None, out=None): 

""" 

Returns array of indices of the maximum values along the given axis. 

Masked values are treated as if they had the value fill_value. 

 

Parameters 

---------- 

axis : {None, integer} 

If None, the index is into the flattened array, otherwise along 

the specified axis 

fill_value : {var}, optional 

Value used to fill in the masked values. If None, the output of 

maximum_fill_value(self._data) is used instead. 

out : {None, array}, optional 

Array into which the result can be placed. Its type is preserved 

and it must be of the right shape to hold the output. 

 

Returns 

------- 

index_array : {integer_array} 

 

Examples 

-------- 

>>> a = np.arange(6).reshape(2,3) 

>>> a.argmax() 

5 

>>> a.argmax(0) 

array([1, 1, 1]) 

>>> a.argmax(1) 

array([2, 2]) 

 

""" 

if fill_value is None: 

fill_value = maximum_fill_value(self._data) 

d = self.filled(fill_value).view(ndarray) 

return d.argmax(axis, out=out) 

 

def sort(self, axis=-1, kind='quicksort', order=None, 

endwith=True, fill_value=None): 

""" 

Sort the array, in-place 

 

Parameters 

---------- 

a : array_like 

Array to be sorted. 

axis : int, optional 

Axis along which to sort. If None, the array is flattened before 

sorting. The default is -1, which sorts along the last axis. 

kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, optional 

Sorting algorithm. Default is 'quicksort'. 

order : list, optional 

When `a` is a structured array, this argument specifies which fields 

to compare first, second, and so on. This list does not need to 

include all of the fields. 

endwith : {True, False}, optional 

Whether missing values (if any) should be treated as the largest values 

(True) or the smallest values (False) 

When the array contains unmasked values at the same extremes of the 

datatype, the ordering of these values and the masked values is 

undefined. 

fill_value : {var}, optional 

Value used internally for the masked values. 

If ``fill_value`` is not None, it supersedes ``endwith``. 

 

Returns 

------- 

sorted_array : ndarray 

Array of the same type and shape as `a`. 

 

See Also 

-------- 

ndarray.sort : Method to sort an array in-place. 

argsort : Indirect sort. 

lexsort : Indirect stable sort on multiple keys. 

searchsorted : Find elements in a sorted array. 

 

Notes 

----- 

See ``sort`` for notes on the different sorting algorithms. 

 

Examples 

-------- 

>>> a = ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0]) 

>>> # Default 

>>> a.sort() 

>>> print(a) 

[1 3 5 -- --] 

 

>>> a = ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0]) 

>>> # Put missing values in the front 

>>> a.sort(endwith=False) 

>>> print(a) 

[-- -- 1 3 5] 

 

>>> a = ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0]) 

>>> # fill_value takes over endwith 

>>> a.sort(endwith=False, fill_value=3) 

>>> print(a) 

[1 -- -- 3 5] 

 

""" 

if self._mask is nomask: 

ndarray.sort(self, axis=axis, kind=kind, order=order) 

return 

 

if self is masked: 

return 

 

sidx = self.argsort(axis=axis, kind=kind, order=order, 

fill_value=fill_value, endwith=endwith) 

 

self[...] = np.take_along_axis(self, sidx, axis=axis) 

 

def min(self, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

""" 

Return the minimum along a given axis. 

 

Parameters 

---------- 

axis : {None, int}, optional 

Axis along which to operate. By default, ``axis`` is None and the 

flattened input is used. 

out : array_like, optional 

Alternative output array in which to place the result. Must be of 

the same shape and buffer length as the expected output. 

fill_value : {var}, optional 

Value used to fill in the masked values. 

If None, use the output of `minimum_fill_value`. 

 

Returns 

------- 

amin : array_like 

New array holding the result. 

If ``out`` was specified, ``out`` is returned. 

 

See Also 

-------- 

minimum_fill_value 

Returns the minimum filling value for a given datatype. 

 

""" 

kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

 

_mask = self._mask 

newmask = _check_mask_axis(_mask, axis, **kwargs) 

if fill_value is None: 

fill_value = minimum_fill_value(self) 

# No explicit output 

if out is None: 

result = self.filled(fill_value).min( 

axis=axis, out=out, **kwargs).view(type(self)) 

if result.ndim: 

# Set the mask 

result.__setmask__(newmask) 

# Get rid of Infs 

if newmask.ndim: 

np.copyto(result, result.fill_value, where=newmask) 

elif newmask: 

result = masked 

return result 

# Explicit output 

result = self.filled(fill_value).min(axis=axis, out=out, **kwargs) 

if isinstance(out, MaskedArray): 

outmask = getmask(out) 

if (outmask is nomask): 

outmask = out._mask = make_mask_none(out.shape) 

outmask.flat = newmask 

else: 

if out.dtype.kind in 'biu': 

errmsg = "Masked data information would be lost in one or more"\ 

" location." 

raise MaskError(errmsg) 

np.copyto(out, np.nan, where=newmask) 

return out 

 

# unique to masked arrays 

def mini(self, axis=None): 

""" 

Return the array minimum along the specified axis. 

 

.. deprecated:: 1.13.0 

This function is identical to both: 

 

* ``self.min(keepdims=True, axis=axis).squeeze(axis=axis)`` 

* ``np.ma.minimum.reduce(self, axis=axis)`` 

 

Typically though, ``self.min(axis=axis)`` is sufficient. 

 

Parameters 

---------- 

axis : int, optional 

The axis along which to find the minima. Default is None, in which case 

the minimum value in the whole array is returned. 

 

Returns 

------- 

min : scalar or MaskedArray 

If `axis` is None, the result is a scalar. Otherwise, if `axis` is 

given and the array is at least 2-D, the result is a masked array with 

dimension one smaller than the array on which `mini` is called. 

 

Examples 

-------- 

>>> x = np.ma.array(np.arange(6), mask=[0 ,1, 0, 0, 0 ,1]).reshape(3, 2) 

>>> print(x) 

[[0 --] 

[2 3] 

[4 --]] 

>>> x.mini() 

0 

>>> x.mini(axis=0) 

masked_array(data = [0 3], 

mask = [False False], 

fill_value = 999999) 

>>> print(x.mini(axis=1)) 

[0 2 4] 

 

There is a small difference between `mini` and `min`: 

 

>>> x[:,1].mini(axis=0) 

masked_array(data = --, 

mask = True, 

fill_value = 999999) 

>>> x[:,1].min(axis=0) 

masked 

""" 

 

# 2016-04-13, 1.13.0, gh-8764 

warnings.warn( 

"`mini` is deprecated; use the `min` method or " 

"`np.ma.minimum.reduce instead.", 

DeprecationWarning, stacklevel=2) 

return minimum.reduce(self, axis) 

 

def max(self, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

""" 

Return the maximum along a given axis. 

 

Parameters 

---------- 

axis : {None, int}, optional 

Axis along which to operate. By default, ``axis`` is None and the 

flattened input is used. 

out : array_like, optional 

Alternative output array in which to place the result. Must 

be of the same shape and buffer length as the expected output. 

fill_value : {var}, optional 

Value used to fill in the masked values. 

If None, use the output of maximum_fill_value(). 

 

Returns 

------- 

amax : array_like 

New array holding the result. 

If ``out`` was specified, ``out`` is returned. 

 

See Also 

-------- 

maximum_fill_value 

Returns the maximum filling value for a given datatype. 

 

""" 

kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

 

_mask = self._mask 

newmask = _check_mask_axis(_mask, axis, **kwargs) 

if fill_value is None: 

fill_value = maximum_fill_value(self) 

# No explicit output 

if out is None: 

result = self.filled(fill_value).max( 

axis=axis, out=out, **kwargs).view(type(self)) 

if result.ndim: 

# Set the mask 

result.__setmask__(newmask) 

# Get rid of Infs 

if newmask.ndim: 

np.copyto(result, result.fill_value, where=newmask) 

elif newmask: 

result = masked 

return result 

# Explicit output 

result = self.filled(fill_value).max(axis=axis, out=out, **kwargs) 

if isinstance(out, MaskedArray): 

outmask = getmask(out) 

if (outmask is nomask): 

outmask = out._mask = make_mask_none(out.shape) 

outmask.flat = newmask 

else: 

 

if out.dtype.kind in 'biu': 

errmsg = "Masked data information would be lost in one or more"\ 

" location." 

raise MaskError(errmsg) 

np.copyto(out, np.nan, where=newmask) 

return out 

 

def ptp(self, axis=None, out=None, fill_value=None, keepdims=False): 

""" 

Return (maximum - minimum) along the given dimension 

(i.e. peak-to-peak value). 

 

Parameters 

---------- 

axis : {None, int}, optional 

Axis along which to find the peaks. If None (default) the 

flattened array is used. 

out : {None, array_like}, optional 

Alternative output array in which to place the result. It must 

have the same shape and buffer length as the expected output 

but the type will be cast if necessary. 

fill_value : {var}, optional 

Value used to fill in the masked values. 

 

Returns 

------- 

ptp : ndarray. 

A new array holding the result, unless ``out`` was 

specified, in which case a reference to ``out`` is returned. 

 

""" 

if out is None: 

result = self.max(axis=axis, fill_value=fill_value, 

keepdims=keepdims) 

result -= self.min(axis=axis, fill_value=fill_value, 

keepdims=keepdims) 

return result 

out.flat = self.max(axis=axis, out=out, fill_value=fill_value, 

keepdims=keepdims) 

min_value = self.min(axis=axis, fill_value=fill_value, 

keepdims=keepdims) 

np.subtract(out, min_value, out=out, casting='unsafe') 

return out 

 

def partition(self, *args, **kwargs): 

warnings.warn("Warning: 'partition' will ignore the 'mask' " 

"of the {}.".format(self.__class__.__name__), 

stacklevel=2) 

return super(MaskedArray, self).partition(*args, **kwargs) 

 

def argpartition(self, *args, **kwargs): 

warnings.warn("Warning: 'argpartition' will ignore the 'mask' " 

"of the {}.".format(self.__class__.__name__), 

stacklevel=2) 

return super(MaskedArray, self).argpartition(*args, **kwargs) 

 

def take(self, indices, axis=None, out=None, mode='raise'): 

""" 

""" 

(_data, _mask) = (self._data, self._mask) 

cls = type(self) 

# Make sure the indices are not masked 

maskindices = getmask(indices) 

if maskindices is not nomask: 

indices = indices.filled(0) 

# Get the data, promoting scalars to 0d arrays with [...] so that 

# .view works correctly 

if out is None: 

out = _data.take(indices, axis=axis, mode=mode)[...].view(cls) 

else: 

np.take(_data, indices, axis=axis, mode=mode, out=out) 

# Get the mask 

if isinstance(out, MaskedArray): 

if _mask is nomask: 

outmask = maskindices 

else: 

outmask = _mask.take(indices, axis=axis, mode=mode) 

outmask |= maskindices 

out.__setmask__(outmask) 

# demote 0d arrays back to scalars, for consistency with ndarray.take 

return out[()] 

 

# Array methods 

clip = _arraymethod('clip', onmask=False) 

copy = _arraymethod('copy') 

diagonal = _arraymethod('diagonal') 

flatten = _arraymethod('flatten') 

repeat = _arraymethod('repeat') 

squeeze = _arraymethod('squeeze') 

swapaxes = _arraymethod('swapaxes') 

T = property(fget=lambda self: self.transpose()) 

transpose = _arraymethod('transpose') 

 

def tolist(self, fill_value=None): 

""" 

Return the data portion of the masked array as a hierarchical Python list. 

 

Data items are converted to the nearest compatible Python type. 

Masked values are converted to `fill_value`. If `fill_value` is None, 

the corresponding entries in the output list will be ``None``. 

 

Parameters 

---------- 

fill_value : scalar, optional 

The value to use for invalid entries. Default is None. 

 

Returns 

------- 

result : list 

The Python list representation of the masked array. 

 

Examples 

-------- 

>>> x = np.ma.array([[1,2,3], [4,5,6], [7,8,9]], mask=[0] + [1,0]*4) 

>>> x.tolist() 

[[1, None, 3], [None, 5, None], [7, None, 9]] 

>>> x.tolist(-999) 

[[1, -999, 3], [-999, 5, -999], [7, -999, 9]] 

 

""" 

_mask = self._mask 

# No mask ? Just return .data.tolist ? 

if _mask is nomask: 

return self._data.tolist() 

# Explicit fill_value: fill the array and get the list 

if fill_value is not None: 

return self.filled(fill_value).tolist() 

# Structured array. 

names = self.dtype.names 

if names: 

result = self._data.astype([(_, object) for _ in names]) 

for n in names: 

result[n][_mask[n]] = None 

return result.tolist() 

# Standard arrays. 

if _mask is nomask: 

return [None] 

# Set temps to save time when dealing w/ marrays. 

inishape = self.shape 

result = np.array(self._data.ravel(), dtype=object) 

result[_mask.ravel()] = None 

result.shape = inishape 

return result.tolist() 

 

def tostring(self, fill_value=None, order='C'): 

""" 

This function is a compatibility alias for tobytes. Despite its name it 

returns bytes not strings. 

""" 

 

return self.tobytes(fill_value, order='C') 

 

def tobytes(self, fill_value=None, order='C'): 

""" 

Return the array data as a string containing the raw bytes in the array. 

 

The array is filled with a fill value before the string conversion. 

 

.. versionadded:: 1.9.0 

 

Parameters 

---------- 

fill_value : scalar, optional 

Value used to fill in the masked values. Default is None, in which 

case `MaskedArray.fill_value` is used. 

order : {'C','F','A'}, optional 

Order of the data item in the copy. Default is 'C'. 

 

- 'C' -- C order (row major). 

- 'F' -- Fortran order (column major). 

- 'A' -- Any, current order of array. 

- None -- Same as 'A'. 

 

See Also 

-------- 

ndarray.tobytes 

tolist, tofile 

 

Notes 

----- 

As for `ndarray.tobytes`, information about the shape, dtype, etc., 

but also about `fill_value`, will be lost. 

 

Examples 

-------- 

>>> x = np.ma.array(np.array([[1, 2], [3, 4]]), mask=[[0, 1], [1, 0]]) 

>>> x.tobytes() 

'\\x01\\x00\\x00\\x00?B\\x0f\\x00?B\\x0f\\x00\\x04\\x00\\x00\\x00' 

 

""" 

return self.filled(fill_value).tobytes(order=order) 

 

def tofile(self, fid, sep="", format="%s"): 

""" 

Save a masked array to a file in binary format. 

 

.. warning:: 

This function is not implemented yet. 

 

Raises 

------ 

NotImplementedError 

When `tofile` is called. 

 

""" 

raise NotImplementedError("MaskedArray.tofile() not implemented yet.") 

 

def toflex(self): 

""" 

Transforms a masked array into a flexible-type array. 

 

The flexible type array that is returned will have two fields: 

 

* the ``_data`` field stores the ``_data`` part of the array. 

* the ``_mask`` field stores the ``_mask`` part of the array. 

 

Parameters 

---------- 

None 

 

Returns 

------- 

record : ndarray 

A new flexible-type `ndarray` with two fields: the first element 

containing a value, the second element containing the corresponding 

mask boolean. The returned record shape matches self.shape. 

 

Notes 

----- 

A side-effect of transforming a masked array into a flexible `ndarray` is 

that meta information (``fill_value``, ...) will be lost. 

 

Examples 

-------- 

>>> x = np.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) 

>>> print(x) 

[[1 -- 3] 

[-- 5 --] 

[7 -- 9]] 

>>> print(x.toflex()) 

[[(1, False) (2, True) (3, False)] 

[(4, True) (5, False) (6, True)] 

[(7, False) (8, True) (9, False)]] 

 

""" 

# Get the basic dtype. 

ddtype = self.dtype 

# Make sure we have a mask 

_mask = self._mask 

if _mask is None: 

_mask = make_mask_none(self.shape, ddtype) 

# And get its dtype 

mdtype = self._mask.dtype 

 

record = np.ndarray(shape=self.shape, 

dtype=[('_data', ddtype), ('_mask', mdtype)]) 

record['_data'] = self._data 

record['_mask'] = self._mask 

return record 

torecords = toflex 

 

# Pickling 

def __getstate__(self): 

"""Return the internal state of the masked array, for pickling 

purposes. 

 

""" 

cf = 'CF'[self.flags.fnc] 

data_state = super(MaskedArray, self).__reduce__()[2] 

return data_state + (getmaskarray(self).tobytes(cf), self._fill_value) 

 

def __setstate__(self, state): 

"""Restore the internal state of the masked array, for 

pickling purposes. ``state`` is typically the output of the 

``__getstate__`` output, and is a 5-tuple: 

 

- class name 

- a tuple giving the shape of the data 

- a typecode for the data 

- a binary string for the data 

- a binary string for the mask. 

 

""" 

(_, shp, typ, isf, raw, msk, flv) = state 

super(MaskedArray, self).__setstate__((shp, typ, isf, raw)) 

self._mask.__setstate__((shp, make_mask_descr(typ), isf, msk)) 

self.fill_value = flv 

 

def __reduce__(self): 

"""Return a 3-tuple for pickling a MaskedArray. 

 

""" 

return (_mareconstruct, 

(self.__class__, self._baseclass, (0,), 'b',), 

self.__getstate__()) 

 

def __deepcopy__(self, memo=None): 

from copy import deepcopy 

copied = MaskedArray.__new__(type(self), self, copy=True) 

if memo is None: 

memo = {} 

memo[id(self)] = copied 

for (k, v) in self.__dict__.items(): 

copied.__dict__[k] = deepcopy(v, memo) 

return copied 

 

 

def _mareconstruct(subtype, baseclass, baseshape, basetype,): 

"""Internal function that builds a new MaskedArray from the 

information stored in a pickle. 

 

""" 

_data = ndarray.__new__(baseclass, baseshape, basetype) 

_mask = ndarray.__new__(ndarray, baseshape, make_mask_descr(basetype)) 

return subtype.__new__(subtype, _data, mask=_mask, dtype=basetype,) 

 

 

class mvoid(MaskedArray): 

""" 

Fake a 'void' object to use for masked array with structured dtypes. 

""" 

 

def __new__(self, data, mask=nomask, dtype=None, fill_value=None, 

hardmask=False, copy=False, subok=True): 

_data = np.array(data, copy=copy, subok=subok, dtype=dtype) 

_data = _data.view(self) 

_data._hardmask = hardmask 

if mask is not nomask: 

if isinstance(mask, np.void): 

_data._mask = mask 

else: 

try: 

# Mask is already a 0D array 

_data._mask = np.void(mask) 

except TypeError: 

# Transform the mask to a void 

mdtype = make_mask_descr(dtype) 

_data._mask = np.array(mask, dtype=mdtype)[()] 

if fill_value is not None: 

_data.fill_value = fill_value 

return _data 

 

def _get_data(self): 

# Make sure that the _data part is a np.void 

return super(mvoid, self)._data[()] 

 

_data = property(fget=_get_data) 

 

def __getitem__(self, indx): 

""" 

Get the index. 

 

""" 

m = self._mask 

if isinstance(m[indx], ndarray): 

# Can happen when indx is a multi-dimensional field: 

# A = ma.masked_array(data=[([0,1],)], mask=[([True, 

# False],)], dtype=[("A", ">i2", (2,))]) 

# x = A[0]; y = x["A"]; then y.mask["A"].size==2 

# and we can not say masked/unmasked. 

# The result is no longer mvoid! 

# See also issue #6724. 

return masked_array( 

data=self._data[indx], mask=m[indx], 

fill_value=self._fill_value[indx], 

hard_mask=self._hardmask) 

if m is not nomask and m[indx]: 

return masked 

return self._data[indx] 

 

def __setitem__(self, indx, value): 

self._data[indx] = value 

if self._hardmask: 

self._mask[indx] |= getattr(value, "_mask", False) 

else: 

self._mask[indx] = getattr(value, "_mask", False) 

 

def __str__(self): 

m = self._mask 

if m is nomask: 

return str(self._data) 

 

rdtype = _replace_dtype_fields(self._data.dtype, "O") 

data_arr = super(mvoid, self)._data 

res = data_arr.astype(rdtype) 

_recursive_printoption(res, self._mask, masked_print_option) 

return str(res) 

 

__repr__ = __str__ 

 

def __iter__(self): 

"Defines an iterator for mvoid" 

(_data, _mask) = (self._data, self._mask) 

if _mask is nomask: 

for d in _data: 

yield d 

else: 

for (d, m) in zip(_data, _mask): 

if m: 

yield masked 

else: 

yield d 

 

def __len__(self): 

return self._data.__len__() 

 

def filled(self, fill_value=None): 

""" 

Return a copy with masked fields filled with a given value. 

 

Parameters 

---------- 

fill_value : scalar, optional 

The value to use for invalid entries (None by default). 

If None, the `fill_value` attribute is used instead. 

 

Returns 

------- 

filled_void 

A `np.void` object 

 

See Also 

-------- 

MaskedArray.filled 

 

""" 

return asarray(self).filled(fill_value)[()] 

 

def tolist(self): 

""" 

Transforms the mvoid object into a tuple. 

 

Masked fields are replaced by None. 

 

Returns 

------- 

returned_tuple 

Tuple of fields 

""" 

_mask = self._mask 

if _mask is nomask: 

return self._data.tolist() 

result = [] 

for (d, m) in zip(self._data, self._mask): 

if m: 

result.append(None) 

else: 

# .item() makes sure we return a standard Python object 

result.append(d.item()) 

return tuple(result) 

 

 

############################################################################## 

# Shortcuts # 

############################################################################## 

 

 

def isMaskedArray(x): 

""" 

Test whether input is an instance of MaskedArray. 

 

This function returns True if `x` is an instance of MaskedArray 

and returns False otherwise. Any object is accepted as input. 

 

Parameters 

---------- 

x : object 

Object to test. 

 

Returns 

------- 

result : bool 

True if `x` is a MaskedArray. 

 

See Also 

-------- 

isMA : Alias to isMaskedArray. 

isarray : Alias to isMaskedArray. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> a = np.eye(3, 3) 

>>> a 

array([[ 1., 0., 0.], 

[ 0., 1., 0.], 

[ 0., 0., 1.]]) 

>>> m = ma.masked_values(a, 0) 

>>> m 

masked_array(data = 

[[1.0 -- --] 

[-- 1.0 --] 

[-- -- 1.0]], 

mask = 

[[False True True] 

[ True False True] 

[ True True False]], 

fill_value=0.0) 

>>> ma.isMaskedArray(a) 

False 

>>> ma.isMaskedArray(m) 

True 

>>> ma.isMaskedArray([0, 1, 2]) 

False 

 

""" 

return isinstance(x, MaskedArray) 

 

 

isarray = isMaskedArray 

isMA = isMaskedArray # backward compatibility 

 

 

class MaskedConstant(MaskedArray): 

# the lone np.ma.masked instance 

__singleton = None 

 

@classmethod 

def __has_singleton(cls): 

# second case ensures `cls.__singleton` is not just a view on the 

# superclass singleton 

return cls.__singleton is not None and type(cls.__singleton) is cls 

 

def __new__(cls): 

if not cls.__has_singleton(): 

# We define the masked singleton as a float for higher precedence. 

# Note that it can be tricky sometimes w/ type comparison 

data = np.array(0.) 

mask = np.array(True) 

 

# prevent any modifications 

data.flags.writeable = False 

mask.flags.writeable = False 

 

# don't fall back on MaskedArray.__new__(MaskedConstant), since 

# that might confuse it - this way, the construction is entirely 

# within our control 

cls.__singleton = MaskedArray(data, mask=mask).view(cls) 

 

return cls.__singleton 

 

def __array_finalize__(self, obj): 

if not self.__has_singleton(): 

# this handles the `.view` in __new__, which we want to copy across 

# properties normally 

return super(MaskedConstant, self).__array_finalize__(obj) 

elif self is self.__singleton: 

# not clear how this can happen, play it safe 

pass 

else: 

# everywhere else, we want to downcast to MaskedArray, to prevent a 

# duplicate maskedconstant. 

self.__class__ = MaskedArray 

MaskedArray.__array_finalize__(self, obj) 

 

def __array_prepare__(self, obj, context=None): 

return self.view(MaskedArray).__array_prepare__(obj, context) 

 

def __array_wrap__(self, obj, context=None): 

return self.view(MaskedArray).__array_wrap__(obj, context) 

 

def __str__(self): 

return str(masked_print_option._display) 

 

if sys.version_info.major < 3: 

def __unicode__(self): 

return unicode(masked_print_option._display) 

 

def __repr__(self): 

if self is MaskedConstant.__singleton: 

return 'masked' 

else: 

# it's a subclass, or something is wrong, make it obvious 

return object.__repr__(self) 

 

def __reduce__(self): 

"""Override of MaskedArray's __reduce__. 

""" 

return (self.__class__, ()) 

 

# inplace operations have no effect. We have to override them to avoid 

# trying to modify the readonly data and mask arrays 

def __iop__(self, other): 

return self 

__iadd__ = \ 

__isub__ = \ 

__imul__ = \ 

__ifloordiv__ = \ 

__itruediv__ = \ 

__ipow__ = \ 

__iop__ 

del __iop__ # don't leave this around 

 

def copy(self, *args, **kwargs): 

""" Copy is a no-op on the maskedconstant, as it is a scalar """ 

# maskedconstant is a scalar, so copy doesn't need to copy. There's 

# precedent for this with `np.bool_` scalars. 

return self 

 

def __copy__(self): 

return self 

 

def __deepcopy__(self, memo): 

return self 

 

def __setattr__(self, attr, value): 

if not self.__has_singleton(): 

# allow the singleton to be initialized 

return super(MaskedConstant, self).__setattr__(attr, value) 

elif self is self.__singleton: 

raise AttributeError( 

"attributes of {!r} are not writeable".format(self)) 

else: 

# duplicate instance - we can end up here from __array_finalize__, 

# where we set the __class__ attribute 

return super(MaskedConstant, self).__setattr__(attr, value) 

 

 

masked = masked_singleton = MaskedConstant() 

masked_array = MaskedArray 

 

 

def array(data, dtype=None, copy=False, order=None, 

mask=nomask, fill_value=None, keep_mask=True, 

hard_mask=False, shrink=True, subok=True, ndmin=0): 

""" 

Shortcut to MaskedArray. 

 

The options are in a different order for convenience and backwards 

compatibility. 

 

""" 

return MaskedArray(data, mask=mask, dtype=dtype, copy=copy, 

subok=subok, keep_mask=keep_mask, 

hard_mask=hard_mask, fill_value=fill_value, 

ndmin=ndmin, shrink=shrink, order=order) 

array.__doc__ = masked_array.__doc__ 

 

 

def is_masked(x): 

""" 

Determine whether input has masked values. 

 

Accepts any object as input, but always returns False unless the 

input is a MaskedArray containing masked values. 

 

Parameters 

---------- 

x : array_like 

Array to check for masked values. 

 

Returns 

------- 

result : bool 

True if `x` is a MaskedArray with masked values, False otherwise. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> x = ma.masked_equal([0, 1, 0, 2, 3], 0) 

>>> x 

masked_array(data = [-- 1 -- 2 3], 

mask = [ True False True False False], 

fill_value=999999) 

>>> ma.is_masked(x) 

True 

>>> x = ma.masked_equal([0, 1, 0, 2, 3], 42) 

>>> x 

masked_array(data = [0 1 0 2 3], 

mask = False, 

fill_value=999999) 

>>> ma.is_masked(x) 

False 

 

Always returns False if `x` isn't a MaskedArray. 

 

>>> x = [False, True, False] 

>>> ma.is_masked(x) 

False 

>>> x = 'a string' 

>>> ma.is_masked(x) 

False 

 

""" 

m = getmask(x) 

if m is nomask: 

return False 

elif m.any(): 

return True 

return False 

 

 

############################################################################## 

# Extrema functions # 

############################################################################## 

 

 

class _extrema_operation(_MaskedUFunc): 

""" 

Generic class for maximum/minimum functions. 

 

.. note:: 

This is the base class for `_maximum_operation` and 

`_minimum_operation`. 

 

""" 

def __init__(self, ufunc, compare, fill_value): 

super(_extrema_operation, self).__init__(ufunc) 

self.compare = compare 

self.fill_value_func = fill_value 

 

def __call__(self, a, b=None): 

"Executes the call behavior." 

if b is None: 

# 2016-04-13, 1.13.0 

warnings.warn( 

"Single-argument form of np.ma.{0} is deprecated. Use " 

"np.ma.{0}.reduce instead.".format(self.__name__), 

DeprecationWarning, stacklevel=2) 

return self.reduce(a) 

return where(self.compare(a, b), a, b) 

 

def reduce(self, target, axis=np._NoValue): 

"Reduce target along the given axis." 

target = narray(target, copy=False, subok=True) 

m = getmask(target) 

 

if axis is np._NoValue and target.ndim > 1: 

# 2017-05-06, Numpy 1.13.0: warn on axis default 

warnings.warn( 

"In the future the default for ma.{0}.reduce will be axis=0, " 

"not the current None, to match np.{0}.reduce. " 

"Explicitly pass 0 or None to silence this warning.".format( 

self.__name__ 

), 

MaskedArrayFutureWarning, stacklevel=2) 

axis = None 

 

if axis is not np._NoValue: 

kwargs = dict(axis=axis) 

else: 

kwargs = dict() 

 

if m is nomask: 

t = self.f.reduce(target, **kwargs) 

else: 

target = target.filled( 

self.fill_value_func(target)).view(type(target)) 

t = self.f.reduce(target, **kwargs) 

m = umath.logical_and.reduce(m, **kwargs) 

if hasattr(t, '_mask'): 

t._mask = m 

elif m: 

t = masked 

return t 

 

def outer(self, a, b): 

"Return the function applied to the outer product of a and b." 

ma = getmask(a) 

mb = getmask(b) 

if ma is nomask and mb is nomask: 

m = nomask 

else: 

ma = getmaskarray(a) 

mb = getmaskarray(b) 

m = logical_or.outer(ma, mb) 

result = self.f.outer(filled(a), filled(b)) 

if not isinstance(result, MaskedArray): 

result = result.view(MaskedArray) 

result._mask = m 

return result 

 

def min(obj, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

 

try: 

return obj.min(axis=axis, fill_value=fill_value, out=out, **kwargs) 

except (AttributeError, TypeError): 

# If obj doesn't have a min method, or if the method doesn't accept a 

# fill_value argument 

return asanyarray(obj).min(axis=axis, fill_value=fill_value, 

out=out, **kwargs) 

min.__doc__ = MaskedArray.min.__doc__ 

 

def max(obj, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

 

try: 

return obj.max(axis=axis, fill_value=fill_value, out=out, **kwargs) 

except (AttributeError, TypeError): 

# If obj doesn't have a max method, or if the method doesn't accept a 

# fill_value argument 

return asanyarray(obj).max(axis=axis, fill_value=fill_value, 

out=out, **kwargs) 

max.__doc__ = MaskedArray.max.__doc__ 

 

 

def ptp(obj, axis=None, out=None, fill_value=None, keepdims=np._NoValue): 

kwargs = {} if keepdims is np._NoValue else {'keepdims': keepdims} 

try: 

return obj.ptp(axis, out=out, fill_value=fill_value, **kwargs) 

except (AttributeError, TypeError): 

# If obj doesn't have a ptp method or if the method doesn't accept 

# a fill_value argument 

return asanyarray(obj).ptp(axis=axis, fill_value=fill_value, 

out=out, **kwargs) 

ptp.__doc__ = MaskedArray.ptp.__doc__ 

 

 

############################################################################## 

# Definition of functions from the corresponding methods # 

############################################################################## 

 

 

class _frommethod(object): 

""" 

Define functions from existing MaskedArray methods. 

 

Parameters 

---------- 

methodname : str 

Name of the method to transform. 

 

""" 

 

def __init__(self, methodname, reversed=False): 

self.__name__ = methodname 

self.__doc__ = self.getdoc() 

self.reversed = reversed 

 

def getdoc(self): 

"Return the doc of the function (from the doc of the method)." 

meth = getattr(MaskedArray, self.__name__, None) or\ 

getattr(np, self.__name__, None) 

signature = self.__name__ + get_object_signature(meth) 

if meth is not None: 

doc = """ %s\n%s""" % ( 

signature, getattr(meth, '__doc__', None)) 

return doc 

 

def __call__(self, a, *args, **params): 

if self.reversed: 

args = list(args) 

a, args[0] = args[0], a 

 

marr = asanyarray(a) 

method_name = self.__name__ 

method = getattr(type(marr), method_name, None) 

if method is None: 

# use the corresponding np function 

method = getattr(np, method_name) 

 

return method(marr, *args, **params) 

 

 

all = _frommethod('all') 

anomalies = anom = _frommethod('anom') 

any = _frommethod('any') 

compress = _frommethod('compress', reversed=True) 

cumprod = _frommethod('cumprod') 

cumsum = _frommethod('cumsum') 

copy = _frommethod('copy') 

diagonal = _frommethod('diagonal') 

harden_mask = _frommethod('harden_mask') 

ids = _frommethod('ids') 

maximum = _extrema_operation(umath.maximum, greater, maximum_fill_value) 

mean = _frommethod('mean') 

minimum = _extrema_operation(umath.minimum, less, minimum_fill_value) 

nonzero = _frommethod('nonzero') 

prod = _frommethod('prod') 

product = _frommethod('prod') 

ravel = _frommethod('ravel') 

repeat = _frommethod('repeat') 

shrink_mask = _frommethod('shrink_mask') 

soften_mask = _frommethod('soften_mask') 

std = _frommethod('std') 

sum = _frommethod('sum') 

swapaxes = _frommethod('swapaxes') 

#take = _frommethod('take') 

trace = _frommethod('trace') 

var = _frommethod('var') 

 

count = _frommethod('count') 

 

def take(a, indices, axis=None, out=None, mode='raise'): 

""" 

""" 

a = masked_array(a) 

return a.take(indices, axis=axis, out=out, mode=mode) 

 

 

def power(a, b, third=None): 

""" 

Returns element-wise base array raised to power from second array. 

 

This is the masked array version of `numpy.power`. For details see 

`numpy.power`. 

 

See Also 

-------- 

numpy.power 

 

Notes 

----- 

The *out* argument to `numpy.power` is not supported, `third` has to be 

None. 

 

""" 

if third is not None: 

raise MaskError("3-argument power not supported.") 

# Get the masks 

ma = getmask(a) 

mb = getmask(b) 

m = mask_or(ma, mb) 

# Get the rawdata 

fa = getdata(a) 

fb = getdata(b) 

# Get the type of the result (so that we preserve subclasses) 

if isinstance(a, MaskedArray): 

basetype = type(a) 

else: 

basetype = MaskedArray 

# Get the result and view it as a (subclass of) MaskedArray 

with np.errstate(divide='ignore', invalid='ignore'): 

result = np.where(m, fa, umath.power(fa, fb)).view(basetype) 

result._update_from(a) 

# Find where we're in trouble w/ NaNs and Infs 

invalid = np.logical_not(np.isfinite(result.view(ndarray))) 

# Add the initial mask 

if m is not nomask: 

if not (result.ndim): 

return masked 

result._mask = np.logical_or(m, invalid) 

# Fix the invalid parts 

if invalid.any(): 

if not result.ndim: 

return masked 

elif result._mask is nomask: 

result._mask = invalid 

result._data[invalid] = result.fill_value 

return result 

 

argmin = _frommethod('argmin') 

argmax = _frommethod('argmax') 

 

def argsort(a, axis=np._NoValue, kind='quicksort', order=None, endwith=True, fill_value=None): 

"Function version of the eponymous method." 

a = np.asanyarray(a) 

 

# 2017-04-11, Numpy 1.13.0, gh-8701: warn on axis default 

if axis is np._NoValue: 

axis = _deprecate_argsort_axis(a) 

 

if isinstance(a, MaskedArray): 

return a.argsort(axis=axis, kind=kind, order=order, 

endwith=endwith, fill_value=fill_value) 

else: 

return a.argsort(axis=axis, kind=kind, order=order) 

argsort.__doc__ = MaskedArray.argsort.__doc__ 

 

def sort(a, axis=-1, kind='quicksort', order=None, endwith=True, fill_value=None): 

"Function version of the eponymous method." 

a = np.array(a, copy=True, subok=True) 

if axis is None: 

a = a.flatten() 

axis = 0 

 

if isinstance(a, MaskedArray): 

a.sort(axis=axis, kind=kind, order=order, 

endwith=endwith, fill_value=fill_value) 

else: 

a.sort(axis=axis, kind=kind, order=order) 

return a 

sort.__doc__ = MaskedArray.sort.__doc__ 

 

 

def compressed(x): 

""" 

Return all the non-masked data as a 1-D array. 

 

This function is equivalent to calling the "compressed" method of a 

`MaskedArray`, see `MaskedArray.compressed` for details. 

 

See Also 

-------- 

MaskedArray.compressed 

Equivalent method. 

 

""" 

return asanyarray(x).compressed() 

 

 

def concatenate(arrays, axis=0): 

""" 

Concatenate a sequence of arrays along the given axis. 

 

Parameters 

---------- 

arrays : sequence of array_like 

The arrays must have the same shape, except in the dimension 

corresponding to `axis` (the first, by default). 

axis : int, optional 

The axis along which the arrays will be joined. Default is 0. 

 

Returns 

------- 

result : MaskedArray 

The concatenated array with any masked entries preserved. 

 

See Also 

-------- 

numpy.concatenate : Equivalent function in the top-level NumPy module. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> a = ma.arange(3) 

>>> a[1] = ma.masked 

>>> b = ma.arange(2, 5) 

>>> a 

masked_array(data = [0 -- 2], 

mask = [False True False], 

fill_value = 999999) 

>>> b 

masked_array(data = [2 3 4], 

mask = False, 

fill_value = 999999) 

>>> ma.concatenate([a, b]) 

masked_array(data = [0 -- 2 2 3 4], 

mask = [False True False False False False], 

fill_value = 999999) 

 

""" 

d = np.concatenate([getdata(a) for a in arrays], axis) 

rcls = get_masked_subclass(*arrays) 

data = d.view(rcls) 

# Check whether one of the arrays has a non-empty mask. 

for x in arrays: 

if getmask(x) is not nomask: 

break 

else: 

return data 

# OK, so we have to concatenate the masks 

dm = np.concatenate([getmaskarray(a) for a in arrays], axis) 

dm = dm.reshape(d.shape) 

 

# If we decide to keep a '_shrinkmask' option, we want to check that 

# all of them are True, and then check for dm.any() 

data._mask = _shrink_mask(dm) 

return data 

 

 

def diag(v, k=0): 

""" 

Extract a diagonal or construct a diagonal array. 

 

This function is the equivalent of `numpy.diag` that takes masked 

values into account, see `numpy.diag` for details. 

 

See Also 

-------- 

numpy.diag : Equivalent function for ndarrays. 

 

""" 

output = np.diag(v, k).view(MaskedArray) 

if getmask(v) is not nomask: 

output._mask = np.diag(v._mask, k) 

return output 

 

 

def left_shift(a, n): 

""" 

Shift the bits of an integer to the left. 

 

This is the masked array version of `numpy.left_shift`, for details 

see that function. 

 

See Also 

-------- 

numpy.left_shift 

 

""" 

m = getmask(a) 

if m is nomask: 

d = umath.left_shift(filled(a), n) 

return masked_array(d) 

else: 

d = umath.left_shift(filled(a, 0), n) 

return masked_array(d, mask=m) 

 

 

def right_shift(a, n): 

""" 

Shift the bits of an integer to the right. 

 

This is the masked array version of `numpy.right_shift`, for details 

see that function. 

 

See Also 

-------- 

numpy.right_shift 

 

""" 

m = getmask(a) 

if m is nomask: 

d = umath.right_shift(filled(a), n) 

return masked_array(d) 

else: 

d = umath.right_shift(filled(a, 0), n) 

return masked_array(d, mask=m) 

 

 

def put(a, indices, values, mode='raise'): 

""" 

Set storage-indexed locations to corresponding values. 

 

This function is equivalent to `MaskedArray.put`, see that method 

for details. 

 

See Also 

-------- 

MaskedArray.put 

 

""" 

# We can't use 'frommethod', the order of arguments is different 

try: 

return a.put(indices, values, mode=mode) 

except AttributeError: 

return narray(a, copy=False).put(indices, values, mode=mode) 

 

 

def putmask(a, mask, values): # , mode='raise'): 

""" 

Changes elements of an array based on conditional and input values. 

 

This is the masked array version of `numpy.putmask`, for details see 

`numpy.putmask`. 

 

See Also 

-------- 

numpy.putmask 

 

Notes 

----- 

Using a masked array as `values` will **not** transform a `ndarray` into 

a `MaskedArray`. 

 

""" 

# We can't use 'frommethod', the order of arguments is different 

if not isinstance(a, MaskedArray): 

a = a.view(MaskedArray) 

(valdata, valmask) = (getdata(values), getmask(values)) 

if getmask(a) is nomask: 

if valmask is not nomask: 

a._sharedmask = True 

a._mask = make_mask_none(a.shape, a.dtype) 

np.copyto(a._mask, valmask, where=mask) 

elif a._hardmask: 

if valmask is not nomask: 

m = a._mask.copy() 

np.copyto(m, valmask, where=mask) 

a.mask |= m 

else: 

if valmask is nomask: 

valmask = getmaskarray(values) 

np.copyto(a._mask, valmask, where=mask) 

np.copyto(a._data, valdata, where=mask) 

return 

 

 

def transpose(a, axes=None): 

""" 

Permute the dimensions of an array. 

 

This function is exactly equivalent to `numpy.transpose`. 

 

See Also 

-------- 

numpy.transpose : Equivalent function in top-level NumPy module. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> x = ma.arange(4).reshape((2,2)) 

>>> x[1, 1] = ma.masked 

>>>> x 

masked_array(data = 

[[0 1] 

[2 --]], 

mask = 

[[False False] 

[False True]], 

fill_value = 999999) 

 

>>> ma.transpose(x) 

masked_array(data = 

[[0 2] 

[1 --]], 

mask = 

[[False False] 

[False True]], 

fill_value = 999999) 

 

""" 

# We can't use 'frommethod', as 'transpose' doesn't take keywords 

try: 

return a.transpose(axes) 

except AttributeError: 

return narray(a, copy=False).transpose(axes).view(MaskedArray) 

 

 

def reshape(a, new_shape, order='C'): 

""" 

Returns an array containing the same data with a new shape. 

 

Refer to `MaskedArray.reshape` for full documentation. 

 

See Also 

-------- 

MaskedArray.reshape : equivalent function 

 

""" 

# We can't use 'frommethod', it whine about some parameters. Dmmit. 

try: 

return a.reshape(new_shape, order=order) 

except AttributeError: 

_tmp = narray(a, copy=False).reshape(new_shape, order=order) 

return _tmp.view(MaskedArray) 

 

 

def resize(x, new_shape): 

""" 

Return a new masked array with the specified size and shape. 

 

This is the masked equivalent of the `numpy.resize` function. The new 

array is filled with repeated copies of `x` (in the order that the 

data are stored in memory). If `x` is masked, the new array will be 

masked, and the new mask will be a repetition of the old one. 

 

See Also 

-------- 

numpy.resize : Equivalent function in the top level NumPy module. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> a = ma.array([[1, 2] ,[3, 4]]) 

>>> a[0, 1] = ma.masked 

>>> a 

masked_array(data = 

[[1 --] 

[3 4]], 

mask = 

[[False True] 

[False False]], 

fill_value = 999999) 

>>> np.resize(a, (3, 3)) 

array([[1, 2, 3], 

[4, 1, 2], 

[3, 4, 1]]) 

>>> ma.resize(a, (3, 3)) 

masked_array(data = 

[[1 -- 3] 

[4 1 --] 

[3 4 1]], 

mask = 

[[False True False] 

[False False True] 

[False False False]], 

fill_value = 999999) 

 

A MaskedArray is always returned, regardless of the input type. 

 

>>> a = np.array([[1, 2] ,[3, 4]]) 

>>> ma.resize(a, (3, 3)) 

masked_array(data = 

[[1 2 3] 

[4 1 2] 

[3 4 1]], 

mask = 

False, 

fill_value = 999999) 

 

""" 

# We can't use _frommethods here, as N.resize is notoriously whiny. 

m = getmask(x) 

if m is not nomask: 

m = np.resize(m, new_shape) 

result = np.resize(x, new_shape).view(get_masked_subclass(x)) 

if result.ndim: 

result._mask = m 

return result 

 

 

def rank(obj): 

""" 

maskedarray version of the numpy function. 

 

.. note:: 

Deprecated since 1.10.0 

 

""" 

# 2015-04-12, 1.10.0 

warnings.warn( 

"`rank` is deprecated; use the `ndim` function instead. ", 

np.VisibleDeprecationWarning, stacklevel=2) 

return np.ndim(getdata(obj)) 

 

rank.__doc__ = np.rank.__doc__ 

 

 

def ndim(obj): 

""" 

maskedarray version of the numpy function. 

 

""" 

return np.ndim(getdata(obj)) 

 

ndim.__doc__ = np.ndim.__doc__ 

 

 

def shape(obj): 

"maskedarray version of the numpy function." 

return np.shape(getdata(obj)) 

shape.__doc__ = np.shape.__doc__ 

 

 

def size(obj, axis=None): 

"maskedarray version of the numpy function." 

return np.size(getdata(obj), axis) 

size.__doc__ = np.size.__doc__ 

 

 

############################################################################## 

# Extra functions # 

############################################################################## 

 

 

def where(condition, x=_NoValue, y=_NoValue): 

""" 

Return a masked array with elements from `x` or `y`, depending on condition. 

 

.. note:: 

When only `condition` is provided, this function is identical to 

`nonzero`. The rest of this documentation covers only the case where 

all three arguments are provided. 

 

Parameters 

---------- 

condition : array_like, bool 

Where True, yield `x`, otherwise yield `y`. 

x, y : array_like, optional 

Values from which to choose. `x`, `y` and `condition` need to be 

broadcastable to some shape. 

 

Returns 

------- 

out : MaskedArray 

An masked array with `masked` elements where the condition is masked, 

elements from `x` where `condition` is True, and elements from `y` 

elsewhere. 

 

See Also 

-------- 

numpy.where : Equivalent function in the top-level NumPy module. 

nonzero : The function that is called when x and y are omitted 

 

Examples 

-------- 

>>> x = np.ma.array(np.arange(9.).reshape(3, 3), mask=[[0, 1, 0], 

... [1, 0, 1], 

... [0, 1, 0]]) 

>>> print(x) 

[[0.0 -- 2.0] 

[-- 4.0 --] 

[6.0 -- 8.0]] 

>>> print(np.ma.where(x > 5, x, -3.1416)) 

[[-3.1416 -- -3.1416] 

[-- -3.1416 --] 

[6.0 -- 8.0]] 

 

""" 

 

# handle the single-argument case 

missing = (x is _NoValue, y is _NoValue).count(True) 

if missing == 1: 

raise ValueError("Must provide both 'x' and 'y' or neither.") 

if missing == 2: 

return nonzero(condition) 

 

# we only care if the condition is true - false or masked pick y 

cf = filled(condition, False) 

xd = getdata(x) 

yd = getdata(y) 

 

# we need the full arrays here for correct final dimensions 

cm = getmaskarray(condition) 

xm = getmaskarray(x) 

ym = getmaskarray(y) 

 

# deal with the fact that masked.dtype == float64, but we don't actually 

# want to treat it as that. 

if x is masked and y is not masked: 

xd = np.zeros((), dtype=yd.dtype) 

xm = np.ones((), dtype=ym.dtype) 

elif y is masked and x is not masked: 

yd = np.zeros((), dtype=xd.dtype) 

ym = np.ones((), dtype=xm.dtype) 

 

data = np.where(cf, xd, yd) 

mask = np.where(cf, xm, ym) 

mask = np.where(cm, np.ones((), dtype=mask.dtype), mask) 

 

# collapse the mask, for backwards compatibility 

mask = _shrink_mask(mask) 

 

return masked_array(data, mask=mask) 

 

 

def choose(indices, choices, out=None, mode='raise'): 

""" 

Use an index array to construct a new array from a set of choices. 

 

Given an array of integers and a set of n choice arrays, this method 

will create a new array that merges each of the choice arrays. Where a 

value in `a` is i, the new array will have the value that choices[i] 

contains in the same place. 

 

Parameters 

---------- 

a : ndarray of ints 

This array must contain integers in ``[0, n-1]``, where n is the 

number of choices. 

choices : sequence of arrays 

Choice arrays. The index array and all of the choices should be 

broadcastable to the same shape. 

out : array, optional 

If provided, the result will be inserted into this array. It should 

be of the appropriate shape and `dtype`. 

mode : {'raise', 'wrap', 'clip'}, optional 

Specifies how out-of-bounds indices will behave. 

 

* 'raise' : raise an error 

* 'wrap' : wrap around 

* 'clip' : clip to the range 

 

Returns 

------- 

merged_array : array 

 

See Also 

-------- 

choose : equivalent function 

 

Examples 

-------- 

>>> choice = np.array([[1,1,1], [2,2,2], [3,3,3]]) 

>>> a = np.array([2, 1, 0]) 

>>> np.ma.choose(a, choice) 

masked_array(data = [3 2 1], 

mask = False, 

fill_value=999999) 

 

""" 

def fmask(x): 

"Returns the filled array, or True if masked." 

if x is masked: 

return True 

return filled(x) 

 

def nmask(x): 

"Returns the mask, True if ``masked``, False if ``nomask``." 

if x is masked: 

return True 

return getmask(x) 

# Get the indices. 

c = filled(indices, 0) 

# Get the masks. 

masks = [nmask(x) for x in choices] 

data = [fmask(x) for x in choices] 

# Construct the mask 

outputmask = np.choose(c, masks, mode=mode) 

outputmask = make_mask(mask_or(outputmask, getmask(indices)), 

copy=0, shrink=True) 

# Get the choices. 

d = np.choose(c, data, mode=mode, out=out).view(MaskedArray) 

if out is not None: 

if isinstance(out, MaskedArray): 

out.__setmask__(outputmask) 

return out 

d.__setmask__(outputmask) 

return d 

 

 

def round_(a, decimals=0, out=None): 

""" 

Return a copy of a, rounded to 'decimals' places. 

 

When 'decimals' is negative, it specifies the number of positions 

to the left of the decimal point. The real and imaginary parts of 

complex numbers are rounded separately. Nothing is done if the 

array is not of float type and 'decimals' is greater than or equal 

to 0. 

 

Parameters 

---------- 

decimals : int 

Number of decimals to round to. May be negative. 

out : array_like 

Existing array to use for output. 

If not given, returns a default copy of a. 

 

Notes 

----- 

If out is given and does not have a mask attribute, the mask of a 

is lost! 

 

""" 

if out is None: 

return np.round_(a, decimals, out) 

else: 

np.round_(getdata(a), decimals, out) 

if hasattr(out, '_mask'): 

out._mask = getmask(a) 

return out 

round = round_ 

 

 

# Needed by dot, so move here from extras.py. It will still be exported 

# from extras.py for compatibility. 

def mask_rowcols(a, axis=None): 

""" 

Mask rows and/or columns of a 2D array that contain masked values. 

 

Mask whole rows and/or columns of a 2D array that contain 

masked values. The masking behavior is selected using the 

`axis` parameter. 

 

- If `axis` is None, rows *and* columns are masked. 

- If `axis` is 0, only rows are masked. 

- If `axis` is 1 or -1, only columns are masked. 

 

Parameters 

---------- 

a : array_like, MaskedArray 

The array to mask. If not a MaskedArray instance (or if no array 

elements are masked). The result is a MaskedArray with `mask` set 

to `nomask` (False). Must be a 2D array. 

axis : int, optional 

Axis along which to perform the operation. If None, applies to a 

flattened version of the array. 

 

Returns 

------- 

a : MaskedArray 

A modified version of the input array, masked depending on the value 

of the `axis` parameter. 

 

Raises 

------ 

NotImplementedError 

If input array `a` is not 2D. 

 

See Also 

-------- 

mask_rows : Mask rows of a 2D array that contain masked values. 

mask_cols : Mask cols of a 2D array that contain masked values. 

masked_where : Mask where a condition is met. 

 

Notes 

----- 

The input array's mask is modified by this function. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> a = np.zeros((3, 3), dtype=int) 

>>> a[1, 1] = 1 

>>> a 

array([[0, 0, 0], 

[0, 1, 0], 

[0, 0, 0]]) 

>>> a = ma.masked_equal(a, 1) 

>>> a 

masked_array(data = 

[[0 0 0] 

[0 -- 0] 

[0 0 0]], 

mask = 

[[False False False] 

[False True False] 

[False False False]], 

fill_value=999999) 

>>> ma.mask_rowcols(a) 

masked_array(data = 

[[0 -- 0] 

[-- -- --] 

[0 -- 0]], 

mask = 

[[False True False] 

[ True True True] 

[False True False]], 

fill_value=999999) 

 

""" 

a = array(a, subok=False) 

if a.ndim != 2: 

raise NotImplementedError("mask_rowcols works for 2D arrays only.") 

m = getmask(a) 

# Nothing is masked: return a 

if m is nomask or not m.any(): 

return a 

maskedval = m.nonzero() 

a._mask = a._mask.copy() 

if not axis: 

a[np.unique(maskedval[0])] = masked 

if axis in [None, 1, -1]: 

a[:, np.unique(maskedval[1])] = masked 

return a 

 

 

# Include masked dot here to avoid import problems in getting it from 

# extras.py. Note that it is not included in __all__, but rather exported 

# from extras in order to avoid backward compatibility problems. 

def dot(a, b, strict=False, out=None): 

""" 

Return the dot product of two arrays. 

 

This function is the equivalent of `numpy.dot` that takes masked values 

into account. Note that `strict` and `out` are in different position 

than in the method version. In order to maintain compatibility with the 

corresponding method, it is recommended that the optional arguments be 

treated as keyword only. At some point that may be mandatory. 

 

.. note:: 

Works only with 2-D arrays at the moment. 

 

 

Parameters 

---------- 

a, b : masked_array_like 

Inputs arrays. 

strict : bool, optional 

Whether masked data are propagated (True) or set to 0 (False) for 

the computation. Default is False. Propagating the mask means that 

if a masked value appears in a row or column, the whole row or 

column is considered masked. 

out : masked_array, optional 

Output argument. This must have the exact kind that would be returned 

if it was not used. In particular, it must have the right type, must be 

C-contiguous, and its dtype must be the dtype that would be returned 

for `dot(a,b)`. This is a performance feature. Therefore, if these 

conditions are not met, an exception is raised, instead of attempting 

to be flexible. 

 

.. versionadded:: 1.10.2 

 

See Also 

-------- 

numpy.dot : Equivalent function for ndarrays. 

 

Examples 

-------- 

>>> a = ma.array([[1, 2, 3], [4, 5, 6]], mask=[[1, 0, 0], [0, 0, 0]]) 

>>> b = ma.array([[1, 2], [3, 4], [5, 6]], mask=[[1, 0], [0, 0], [0, 0]]) 

>>> np.ma.dot(a, b) 

masked_array(data = 

[[21 26] 

[45 64]], 

mask = 

[[False False] 

[False False]], 

fill_value = 999999) 

>>> np.ma.dot(a, b, strict=True) 

masked_array(data = 

[[-- --] 

[-- 64]], 

mask = 

[[ True True] 

[ True False]], 

fill_value = 999999) 

 

""" 

# !!!: Works only with 2D arrays. There should be a way to get it to run 

# with higher dimension 

if strict and (a.ndim == 2) and (b.ndim == 2): 

a = mask_rowcols(a, 0) 

b = mask_rowcols(b, 1) 

am = ~getmaskarray(a) 

bm = ~getmaskarray(b) 

 

if out is None: 

d = np.dot(filled(a, 0), filled(b, 0)) 

m = ~np.dot(am, bm) 

if d.ndim == 0: 

d = np.asarray(d) 

r = d.view(get_masked_subclass(a, b)) 

r.__setmask__(m) 

return r 

else: 

d = np.dot(filled(a, 0), filled(b, 0), out._data) 

if out.mask.shape != d.shape: 

out._mask = np.empty(d.shape, MaskType) 

np.dot(am, bm, out._mask) 

np.logical_not(out._mask, out._mask) 

return out 

 

 

def inner(a, b): 

""" 

Returns the inner product of a and b for arrays of floating point types. 

 

Like the generic NumPy equivalent the product sum is over the last dimension 

of a and b. The first argument is not conjugated. 

 

""" 

fa = filled(a, 0) 

fb = filled(b, 0) 

if fa.ndim == 0: 

fa.shape = (1,) 

if fb.ndim == 0: 

fb.shape = (1,) 

return np.inner(fa, fb).view(MaskedArray) 

inner.__doc__ = doc_note(np.inner.__doc__, 

"Masked values are replaced by 0.") 

innerproduct = inner 

 

 

def outer(a, b): 

"maskedarray version of the numpy function." 

fa = filled(a, 0).ravel() 

fb = filled(b, 0).ravel() 

d = np.outer(fa, fb) 

ma = getmask(a) 

mb = getmask(b) 

if ma is nomask and mb is nomask: 

return masked_array(d) 

ma = getmaskarray(a) 

mb = getmaskarray(b) 

m = make_mask(1 - np.outer(1 - ma, 1 - mb), copy=0) 

return masked_array(d, mask=m) 

outer.__doc__ = doc_note(np.outer.__doc__, 

"Masked values are replaced by 0.") 

outerproduct = outer 

 

 

def _convolve_or_correlate(f, a, v, mode, propagate_mask): 

""" 

Helper function for ma.correlate and ma.convolve 

""" 

if propagate_mask: 

# results which are contributed to by either item in any pair being invalid 

mask = ( 

f(getmaskarray(a), np.ones(np.shape(v), dtype=bool), mode=mode) 

| f(np.ones(np.shape(a), dtype=bool), getmaskarray(v), mode=mode) 

) 

data = f(getdata(a), getdata(v), mode=mode) 

else: 

# results which are not contributed to by any pair of valid elements 

mask = ~f(~getmaskarray(a), ~getmaskarray(v)) 

data = f(filled(a, 0), filled(v, 0), mode=mode) 

 

return masked_array(data, mask=mask) 

 

 

def correlate(a, v, mode='valid', propagate_mask=True): 

""" 

Cross-correlation of two 1-dimensional sequences. 

 

Parameters 

---------- 

a, v : array_like 

Input sequences. 

mode : {'valid', 'same', 'full'}, optional 

Refer to the `np.convolve` docstring. Note that the default 

is 'valid', unlike `convolve`, which uses 'full'. 

propagate_mask : bool 

If True, then a result element is masked if any masked element contributes towards it. 

If False, then a result element is only masked if no non-masked element 

contribute towards it 

 

Returns 

------- 

out : MaskedArray 

Discrete cross-correlation of `a` and `v`. 

 

See Also 

-------- 

numpy.correlate : Equivalent function in the top-level NumPy module. 

""" 

return _convolve_or_correlate(np.correlate, a, v, mode, propagate_mask) 

 

 

def convolve(a, v, mode='full', propagate_mask=True): 

""" 

Returns the discrete, linear convolution of two one-dimensional sequences. 

 

Parameters 

---------- 

a, v : array_like 

Input sequences. 

mode : {'valid', 'same', 'full'}, optional 

Refer to the `np.convolve` docstring. 

propagate_mask : bool 

If True, then if any masked element is included in the sum for a result 

element, then the result is masked. 

If False, then the result element is only masked if no non-masked cells 

contribute towards it 

 

Returns 

------- 

out : MaskedArray 

Discrete, linear convolution of `a` and `v`. 

 

See Also 

-------- 

numpy.convolve : Equivalent function in the top-level NumPy module. 

""" 

return _convolve_or_correlate(np.convolve, a, v, mode, propagate_mask) 

 

 

def allequal(a, b, fill_value=True): 

""" 

Return True if all entries of a and b are equal, using 

fill_value as a truth value where either or both are masked. 

 

Parameters 

---------- 

a, b : array_like 

Input arrays to compare. 

fill_value : bool, optional 

Whether masked values in a or b are considered equal (True) or not 

(False). 

 

Returns 

------- 

y : bool 

Returns True if the two arrays are equal within the given 

tolerance, False otherwise. If either array contains NaN, 

then False is returned. 

 

See Also 

-------- 

all, any 

numpy.ma.allclose 

 

Examples 

-------- 

>>> a = ma.array([1e10, 1e-7, 42.0], mask=[0, 0, 1]) 

>>> a 

masked_array(data = [10000000000.0 1e-07 --], 

mask = [False False True], 

fill_value=1e+20) 

 

>>> b = array([1e10, 1e-7, -42.0]) 

>>> b 

array([ 1.00000000e+10, 1.00000000e-07, -4.20000000e+01]) 

>>> ma.allequal(a, b, fill_value=False) 

False 

>>> ma.allequal(a, b) 

True 

 

""" 

m = mask_or(getmask(a), getmask(b)) 

if m is nomask: 

x = getdata(a) 

y = getdata(b) 

d = umath.equal(x, y) 

return d.all() 

elif fill_value: 

x = getdata(a) 

y = getdata(b) 

d = umath.equal(x, y) 

dm = array(d, mask=m, copy=False) 

return dm.filled(True).all(None) 

else: 

return False 

 

 

def allclose(a, b, masked_equal=True, rtol=1e-5, atol=1e-8): 

""" 

Returns True if two arrays are element-wise equal within a tolerance. 

 

This function is equivalent to `allclose` except that masked values 

are treated as equal (default) or unequal, depending on the `masked_equal` 

argument. 

 

Parameters 

---------- 

a, b : array_like 

Input arrays to compare. 

masked_equal : bool, optional 

Whether masked values in `a` and `b` are considered equal (True) or not 

(False). They are considered equal by default. 

rtol : float, optional 

Relative tolerance. The relative difference is equal to ``rtol * b``. 

Default is 1e-5. 

atol : float, optional 

Absolute tolerance. The absolute difference is equal to `atol`. 

Default is 1e-8. 

 

Returns 

------- 

y : bool 

Returns True if the two arrays are equal within the given 

tolerance, False otherwise. If either array contains NaN, then 

False is returned. 

 

See Also 

-------- 

all, any 

numpy.allclose : the non-masked `allclose`. 

 

Notes 

----- 

If the following equation is element-wise True, then `allclose` returns 

True:: 

 

absolute(`a` - `b`) <= (`atol` + `rtol` * absolute(`b`)) 

 

Return True if all elements of `a` and `b` are equal subject to 

given tolerances. 

 

Examples 

-------- 

>>> a = ma.array([1e10, 1e-7, 42.0], mask=[0, 0, 1]) 

>>> a 

masked_array(data = [10000000000.0 1e-07 --], 

mask = [False False True], 

fill_value = 1e+20) 

>>> b = ma.array([1e10, 1e-8, -42.0], mask=[0, 0, 1]) 

>>> ma.allclose(a, b) 

False 

 

>>> a = ma.array([1e10, 1e-8, 42.0], mask=[0, 0, 1]) 

>>> b = ma.array([1.00001e10, 1e-9, -42.0], mask=[0, 0, 1]) 

>>> ma.allclose(a, b) 

True 

>>> ma.allclose(a, b, masked_equal=False) 

False 

 

Masked values are not compared directly. 

 

>>> a = ma.array([1e10, 1e-8, 42.0], mask=[0, 0, 1]) 

>>> b = ma.array([1.00001e10, 1e-9, 42.0], mask=[0, 0, 1]) 

>>> ma.allclose(a, b) 

True 

>>> ma.allclose(a, b, masked_equal=False) 

False 

 

""" 

x = masked_array(a, copy=False) 

y = masked_array(b, copy=False) 

 

# make sure y is an inexact type to avoid abs(MIN_INT); will cause 

# casting of x later. 

dtype = np.result_type(y, 1.) 

if y.dtype != dtype: 

y = masked_array(y, dtype=dtype, copy=False) 

 

m = mask_or(getmask(x), getmask(y)) 

xinf = np.isinf(masked_array(x, copy=False, mask=m)).filled(False) 

# If we have some infs, they should fall at the same place. 

if not np.all(xinf == filled(np.isinf(y), False)): 

return False 

# No infs at all 

if not np.any(xinf): 

d = filled(less_equal(absolute(x - y), atol + rtol * absolute(y)), 

masked_equal) 

return np.all(d) 

 

if not np.all(filled(x[xinf] == y[xinf], masked_equal)): 

return False 

x = x[~xinf] 

y = y[~xinf] 

 

d = filled(less_equal(absolute(x - y), atol + rtol * absolute(y)), 

masked_equal) 

 

return np.all(d) 

 

 

def asarray(a, dtype=None, order=None): 

""" 

Convert the input to a masked array of the given data-type. 

 

No copy is performed if the input is already an `ndarray`. If `a` is 

a subclass of `MaskedArray`, a base class `MaskedArray` is returned. 

 

Parameters 

---------- 

a : array_like 

Input data, in any form that can be converted to a masked array. This 

includes lists, lists of tuples, tuples, tuples of tuples, tuples 

of lists, ndarrays and masked arrays. 

dtype : dtype, optional 

By default, the data-type is inferred from the input data. 

order : {'C', 'F'}, optional 

Whether to use row-major ('C') or column-major ('FORTRAN') memory 

representation. Default is 'C'. 

 

Returns 

------- 

out : MaskedArray 

Masked array interpretation of `a`. 

 

See Also 

-------- 

asanyarray : Similar to `asarray`, but conserves subclasses. 

 

Examples 

-------- 

>>> x = np.arange(10.).reshape(2, 5) 

>>> x 

array([[ 0., 1., 2., 3., 4.], 

[ 5., 6., 7., 8., 9.]]) 

>>> np.ma.asarray(x) 

masked_array(data = 

[[ 0. 1. 2. 3. 4.] 

[ 5. 6. 7. 8. 9.]], 

mask = 

False, 

fill_value = 1e+20) 

>>> type(np.ma.asarray(x)) 

<class 'numpy.ma.core.MaskedArray'> 

 

""" 

order = order or 'C' 

return masked_array(a, dtype=dtype, copy=False, keep_mask=True, 

subok=False, order=order) 

 

 

def asanyarray(a, dtype=None): 

""" 

Convert the input to a masked array, conserving subclasses. 

 

If `a` is a subclass of `MaskedArray`, its class is conserved. 

No copy is performed if the input is already an `ndarray`. 

 

Parameters 

---------- 

a : array_like 

Input data, in any form that can be converted to an array. 

dtype : dtype, optional 

By default, the data-type is inferred from the input data. 

order : {'C', 'F'}, optional 

Whether to use row-major ('C') or column-major ('FORTRAN') memory 

representation. Default is 'C'. 

 

Returns 

------- 

out : MaskedArray 

MaskedArray interpretation of `a`. 

 

See Also 

-------- 

asarray : Similar to `asanyarray`, but does not conserve subclass. 

 

Examples 

-------- 

>>> x = np.arange(10.).reshape(2, 5) 

>>> x 

array([[ 0., 1., 2., 3., 4.], 

[ 5., 6., 7., 8., 9.]]) 

>>> np.ma.asanyarray(x) 

masked_array(data = 

[[ 0. 1. 2. 3. 4.] 

[ 5. 6. 7. 8. 9.]], 

mask = 

False, 

fill_value = 1e+20) 

>>> type(np.ma.asanyarray(x)) 

<class 'numpy.ma.core.MaskedArray'> 

 

""" 

# workaround for #8666, to preserve identity. Ideally the bottom line 

# would handle this for us. 

if isinstance(a, MaskedArray) and (dtype is None or dtype == a.dtype): 

return a 

return masked_array(a, dtype=dtype, copy=False, keep_mask=True, subok=True) 

 

 

############################################################################## 

# Pickling # 

############################################################################## 

 

def _pickle_warn(method): 

# NumPy 1.15.0, 2017-12-10 

warnings.warn( 

"np.ma.{method} is deprecated, use pickle.{method} instead" 

.format(method=method), 

DeprecationWarning, 

stacklevel=3) 

 

 

def dump(a, F): 

""" 

Pickle a masked array to a file. 

 

This is a wrapper around ``cPickle.dump``. 

 

Parameters 

---------- 

a : MaskedArray 

The array to be pickled. 

F : str or file-like object 

The file to pickle `a` to. If a string, the full path to the file. 

 

""" 

_pickle_warn('dump') 

if not hasattr(F, 'readline'): 

with open(F, 'w') as F: 

pickle.dump(a, F) 

else: 

pickle.dump(a, F) 

 

 

def dumps(a): 

""" 

Return a string corresponding to the pickling of a masked array. 

 

This is a wrapper around ``cPickle.dumps``. 

 

Parameters 

---------- 

a : MaskedArray 

The array for which the string representation of the pickle is 

returned. 

 

""" 

_pickle_warn('dumps') 

return pickle.dumps(a) 

 

 

def load(F): 

""" 

Wrapper around ``cPickle.load`` which accepts either a file-like object 

or a filename. 

 

Parameters 

---------- 

F : str or file 

The file or file name to load. 

 

See Also 

-------- 

dump : Pickle an array 

 

Notes 

----- 

This is different from `numpy.load`, which does not use cPickle but loads 

the NumPy binary .npy format. 

 

""" 

_pickle_warn('load') 

if not hasattr(F, 'readline'): 

with open(F, 'r') as F: 

return pickle.load(F) 

else: 

return pickle.load(F) 

 

 

def loads(strg): 

""" 

Load a pickle from the current string. 

 

The result of ``cPickle.loads(strg)`` is returned. 

 

Parameters 

---------- 

strg : str 

The string to load. 

 

See Also 

-------- 

dumps : Return a string corresponding to the pickling of a masked array. 

 

""" 

_pickle_warn('loads') 

return pickle.loads(strg) 

 

 

def fromfile(file, dtype=float, count=-1, sep=''): 

raise NotImplementedError( 

"fromfile() not yet implemented for a MaskedArray.") 

 

 

def fromflex(fxarray): 

""" 

Build a masked array from a suitable flexible-type array. 

 

The input array has to have a data-type with ``_data`` and ``_mask`` 

fields. This type of array is output by `MaskedArray.toflex`. 

 

Parameters 

---------- 

fxarray : ndarray 

The structured input array, containing ``_data`` and ``_mask`` 

fields. If present, other fields are discarded. 

 

Returns 

------- 

result : MaskedArray 

The constructed masked array. 

 

See Also 

-------- 

MaskedArray.toflex : Build a flexible-type array from a masked array. 

 

Examples 

-------- 

>>> x = np.ma.array(np.arange(9).reshape(3, 3), mask=[0] + [1, 0] * 4) 

>>> rec = x.toflex() 

>>> rec 

array([[(0, False), (1, True), (2, False)], 

[(3, True), (4, False), (5, True)], 

[(6, False), (7, True), (8, False)]], 

dtype=[('_data', '<i4'), ('_mask', '|b1')]) 

>>> x2 = np.ma.fromflex(rec) 

>>> x2 

masked_array(data = 

[[0 -- 2] 

[-- 4 --] 

[6 -- 8]], 

mask = 

[[False True False] 

[ True False True] 

[False True False]], 

fill_value = 999999) 

 

Extra fields can be present in the structured array but are discarded: 

 

>>> dt = [('_data', '<i4'), ('_mask', '|b1'), ('field3', '<f4')] 

>>> rec2 = np.zeros((2, 2), dtype=dt) 

>>> rec2 

array([[(0, False, 0.0), (0, False, 0.0)], 

[(0, False, 0.0), (0, False, 0.0)]], 

dtype=[('_data', '<i4'), ('_mask', '|b1'), ('field3', '<f4')]) 

>>> y = np.ma.fromflex(rec2) 

>>> y 

masked_array(data = 

[[0 0] 

[0 0]], 

mask = 

[[False False] 

[False False]], 

fill_value = 999999) 

 

""" 

return masked_array(fxarray['_data'], mask=fxarray['_mask']) 

 

 

class _convert2ma(object): 

 

""" 

Convert functions from numpy to numpy.ma. 

 

Parameters 

---------- 

_methodname : string 

Name of the method to transform. 

 

""" 

__doc__ = None 

 

def __init__(self, funcname, params=None): 

self._func = getattr(np, funcname) 

self.__doc__ = self.getdoc() 

self._extras = params or {} 

 

def getdoc(self): 

"Return the doc of the function (from the doc of the method)." 

doc = getattr(self._func, '__doc__', None) 

sig = get_object_signature(self._func) 

if doc: 

# Add the signature of the function at the beginning of the doc 

if sig: 

sig = "%s%s\n" % (self._func.__name__, sig) 

doc = sig + doc 

return doc 

 

def __call__(self, *args, **params): 

# Find the common parameters to the call and the definition 

_extras = self._extras 

common_params = set(params).intersection(_extras) 

# Drop the common parameters from the call 

for p in common_params: 

_extras[p] = params.pop(p) 

# Get the result 

result = self._func.__call__(*args, **params).view(MaskedArray) 

if "fill_value" in common_params: 

result.fill_value = _extras.get("fill_value", None) 

if "hardmask" in common_params: 

result._hardmask = bool(_extras.get("hard_mask", False)) 

return result 

 

arange = _convert2ma('arange', params=dict(fill_value=None, hardmask=False)) 

clip = np.clip 

diff = np.diff 

empty = _convert2ma('empty', params=dict(fill_value=None, hardmask=False)) 

empty_like = _convert2ma('empty_like') 

frombuffer = _convert2ma('frombuffer') 

fromfunction = _convert2ma('fromfunction') 

identity = _convert2ma( 

'identity', params=dict(fill_value=None, hardmask=False)) 

indices = np.indices 

ones = _convert2ma('ones', params=dict(fill_value=None, hardmask=False)) 

ones_like = np.ones_like 

squeeze = np.squeeze 

zeros = _convert2ma('zeros', params=dict(fill_value=None, hardmask=False)) 

zeros_like = np.zeros_like 

 

 

def append(a, b, axis=None): 

"""Append values to the end of an array. 

 

.. versionadded:: 1.9.0 

 

Parameters 

---------- 

a : array_like 

Values are appended to a copy of this array. 

b : array_like 

These values are appended to a copy of `a`. It must be of the 

correct shape (the same shape as `a`, excluding `axis`). If `axis` 

is not specified, `b` can be any shape and will be flattened 

before use. 

axis : int, optional 

The axis along which `v` are appended. If `axis` is not given, 

both `a` and `b` are flattened before use. 

 

Returns 

------- 

append : MaskedArray 

A copy of `a` with `b` appended to `axis`. Note that `append` 

does not occur in-place: a new array is allocated and filled. If 

`axis` is None, the result is a flattened array. 

 

See Also 

-------- 

numpy.append : Equivalent function in the top-level NumPy module. 

 

Examples 

-------- 

>>> import numpy.ma as ma 

>>> a = ma.masked_values([1, 2, 3], 2) 

>>> b = ma.masked_values([[4, 5, 6], [7, 8, 9]], 7) 

>>> print(ma.append(a, b)) 

[1 -- 3 4 5 6 -- 8 9] 

""" 

return concatenate([a, b], axis)