From b4105c84bd7377b38cf3c4ab6f1633437d47276c Mon Sep 17 00:00:00 2001 From: Ibrahim Salihu Yusuf Date: Sat, 21 Sep 2024 06:33:19 +0200 Subject: [PATCH] feat: improve demo notebook with comments (#4) * feat: improve demo notebook with comments * fix: fix typo in notebook --- .../utils/country_code_to_mgrs_tiles.json | 2 +- instageo/apps/viz.py | 3 +- notebooks/InstaGeo_Demo.ipynb | 1398 +++++++++++------ 3 files changed, 885 insertions(+), 518 deletions(-) diff --git a/instageo/apps/utils/country_code_to_mgrs_tiles.json b/instageo/apps/utils/country_code_to_mgrs_tiles.json index 0761832..92dc183 100644 --- a/instageo/apps/utils/country_code_to_mgrs_tiles.json +++ b/instageo/apps/utils/country_code_to_mgrs_tiles.json @@ -1 +1 @@ -{"AE": ["39QYF", "39QWD", "40RBM", "40RBN", "40QBJ", "39QXG", "40QBK", "39QVE", "39QXD", "40QCM", "40QCL", "39QWF", "39QXE", "39QZG", "40QBM"], "AF": ["42STF", "41SPV", "41RPQ", "41RQP", "41SQS", "41SPT", "41RLP", "41SNV", "41SMU", "42STB", "41RNP", "41SPR", "41SQB", "42SVB", "42RTA", "42SUB", "41SPS", "42SWD", "41SQT", "41SNU", "41SNT", "42SXF", "42SUF", "42SXE", "41SQA", "42STA", "41SLR", "42SWF", "42SUD", "41SMS", "41SQU", "41SLV", "41RMN", "42SUA", "41SLT", "41SNR", "41SPA", "42SVD", "41RLQ", "41SQV", "42RTV", "42RTU", "41RPR", "41SQR", "43SBA", "42RUA", "42SWE", "42SVC", "42SVE", "41SLS", "41RQQ", "42SXC"], "AO": ["33LXJ", "33LVL", "34LBK", "34LDK", "33LWF", "33LVH", "33LUD", "34LCS", "33LWJ", "34LEL", "33LWE", "34LFP", "34LFM", "33MVN", "33KXC", "34LBQ", "33LVK", "33LYL", "33MXM", "33MTN", "34LCJ", "33LYK", "34LCP", "33KXB", "33LYH", "33LYJ", "33MUM", "34LEM", "34LFQ", "34LCR", "33LWC", "33LWK", "34LCK", "34LDN", "34LAJ", "33LTC", "33LXK", "34LEP", "33LYC", "34LBR", "34LDS", "34LDR", "33LXG", "33LTD", "34MES", "34LDM", "33LYG", "33MWM", "33MTP", "34LCN", "34LCQ", "33LXH", "32KQG", "33LXD", "34LGP", "33LTE", "33LSD", "33MUN", "33LUC", "33LVE", "33MVP"], "BF": ["30PYU", "30PVV", "30PXV", "30PYV", "31PBQ", "30PWV", "31PCP", "31PBP", "30PVS", "31PBR", "30PWA", "30PXT", "30PYB", "30PUU", "30PXA", "31PCQ", "30PUT", "31PBN", "30PZU", "30PVU", "31PDP"], "BI": ["36MSC", "35MRS", "35MQS"], "BJ": ["31PCM", "31PCJ", "31PDL", "31NCH", "31PCL", "31PDN", "31PCK", "31PBM", "31PEM", "31PDP", "31PDK"], "BW": ["34JFT", "34JFS", "34JGT", "34KFD", "34KEE", "34KDU", "35KPQ", "35KNS", "35KPR", "34JGS", "35KLT", "35KJR", "35KMT", "34JDS", "34KEA", "34KFE", "35JKM", "35JLM", "34KFC", "35KMP", "35KMS", "34KDV", "35KLP", "34KGV", "35KLS", "35KLB", "34KDB", "34JFR", "35KMR", "35KLV", "34JDU", "35KKA", "34KGU", "34KDD", "34JER", "35KKS", "35KKQ", "34KGE", "35KQS", "35KMQ", "35KLU", "34KEV", "35KNQ", "34KFA", "35JLP", "34JGU", "34KDC"], "CD": ["34NGH", "34MGV", "35MPS", "35MLP", "35MPV", "35MKV", "35MMV", "35LML", "34MGA", "34NEF", "34MEU", "34NHG", "35MJT", "35NKC", "35MPT", "35MJM", "34NBF", "35NPB", "33MYM", "34MHT", "34MFD", "34NCH", "35MNS", "35MLS", "34LGQ", "34NEJ", "35NQD", "35NMC", "35LMJ", "34NBK", "34NDF", "35MLQ", "34MDD", "35MNT", "35MMU", "33MZQ", "35NMD", "35MJR", "34MCB", "34MED", "33MXS", "33NYA", "35NKE", "34NDH", "34MAU", "35NLE", "35NQE", "33MXR", "35MKT", "36NTH", "35MMM", "35NLD", "34NCJ", "33NZA", "34MCV", "35NLA", "33MYT", "35MMP", "34MBE", "33MXP", "33LZL", "34MHU", "33MWP", "35NLB", "34NGJ", "33MWQ", "35MNQ", "34MDC", "33MVP", "35MLT", "34MAA", "34MGC", "34NGK", "33MZV", "35MKP", "33MYR", "35MMQ", "34MEC", "35MKS", "34MEV", "35MLV", "34NCF", "34NHJ", "34LGS", "34MDA", "34MBA", "34NCG", "35NPD", "35LNH", "34MDV", "34MFV", "35MQN", "35NLC", "33MYQ", "34NEH", "34MCA", "34MHE", "34LFR", "34MEB", "34MHC", "34MCD", "35MMT", "35MMS", "33MXT", "34MFE", "35LNJ", "34MBT", "33MYP", "35MNU", "34NGF", "35MLU", "34MEA", "34MHV", "35NQB", "35NPC", "34MBV", "34MGU", "35NNA", "34MEE", "35MMN", "35MKN", "34MCU", "35NKA", "35MQP", "33MXU", "34MAE", "35NND", "34MFB", "34MBB"], "CF": ["34PES", "33NZJ", "34PER", "35NME", "33NWH", "34NGP", "35NLG", "33NXD", "35NMH", "34PDR", "33NXJ", "34NEM", "34PEQ", "34PFT", "34PGR", "34PGQ", "34NFM", "34NBJ", "34NDP", "35NKG", "34PGT", "34NDN", "34PHQ", "33NYG", "33NZH", "35NJF", "35NMG", "35NJJ", "33NXE", "34PFP", "34NDM", "33NYH", "34NCL", "34PCQ", "34PDQ", "34NFL", "33NWE", "34NCP", "34NCN", "34NGL", "34NEN", "34PFR", "35NKF", "34NEP", "34NBM", "33NWF"], "CG": ["33NVC", "33MWU", "33NUB", "33MVS", "33MWV", "33MUS", "33MVR", "33NXB", "33NUC", "33MTS", "33NYC", "34NAH", "33NXA", "33NYB", "33MVV", "33NZC", "32MRA", "34NBG", "33NWA", "33MSQ", "34NBH", "33MWT", "33MUR"], "CI": ["30NUM", "29NRG", "30PTR", "30PWR", "29NPJ", "29NPH", "29PQK", "29PQM", "30NWP", "30NVN", "30NUN", "29NQG", "30PUR", "30PVQ", "30PWP", "30PUQ", "30NVM", "29NQH", "30PTQ", "30NUP"], "CM": ["33PVK", "33PVM", "32NPJ", "33NVG", "32NQJ", "33PUL", "33NVH", "33NUJ", "33NSF", "33NVJ", "33PTK", "32NQM", "33NVE", "33NUD", "33NTH", "33PVN", "33NVF", "33NTF", "33PUK", "32NPM", "33PSJ", "33NUF", "32NNK", "32NRJ", "32NPK", "32NNL", "33NUH"], "CN": ["43SEB", "43SFA"], "CY": ["36SVD", "36SWD"], "DJ": ["38PKS", "38PKT", "38PJS", "37PHM"], "DZ": ["31RCK", "32SLB", "30RYN", "32RKP", "31RGP", "29RQK", "31RFP", "31RFL", "31SES", "31RGM", "31REK", "31SFT", "31SEA", "31REJ", "31SDU", "31RDK", "31RFG", "31SBV", "32RLU", "29RNK", "31SDT", "31SDR", "31QGC", "30RYU", "31RDH", "31RGL", "31SEV", "30RWT", "32RLM", "31SGS", "31SDV", "31RDL", "31REH", "30RYV", "31RCN", "31SCU", "31RFN", "31REQ", "32SKC", "31QEG", "32SLD", "30RVU", "32RKU", "30RWR", "32RMR", "29RPL", "31SCV", "31SBU", "32QKM", "30SYA", "30RXT", "29RQJ", "29RPH", "31RFM", "32RLS", "30RXS", "31QBG", "31SEU", "32RKT", "31RCM", "31SFS", "30SYC", "30RTQ", "30SXD", "32RLR", "31SGV", "31RDQ", "31RGH", "30QYM", "31SGT", "31RBP", "30SXC", "31RBM", "30RXU", "31RBH", "31SCA", "31RDM", "31REP", "31RBL", "32RLN", "31REG", "30RXR", "31QGD", "29RMK", "31SCS", "31REM", "31RCR", "31SFR", "31RDN", "32QKL", "31SFV", "31QGE", "32RMP", "30RYP", "31RCH", "30RYS", "32SLA", "29RPK", "31RGJ", "32QLM", "31SFU", "30RYT", "30RXV", "32RNR", "31QEE", "31RDR", "30RTP", "32RNQ", "29RMJ", "31SGR", "31RFJ", "31QFD", "32RPR", "31SCT", "29RQL", "31SBS", "29RNL", "29RQH", "31RCQ", "31QDG", "32SKE", "32SKD", "30RZN", "31RCP", "32QLJ", "31RGK", "32SLC", "32RLQ", "31QDF", "30SXB"], "EG": ["35RMN", "36RUT", "36RVR", "35RLL", "35RMQ", "35RPK", "36RVM", "36RVV", "36RVS", "36QUJ", "35QPG", "35RQK", "36RXS", "36QTL", "36QVL", "35RMP", "36RXP", "35RNM", "35RKL", "35RLP", "36RUU", "36RWQ", "35RMJ", "36RWT", "36RWV", "35RPP", "36RTT", "35RQL", "36RVT", "35RNG", "35RLK", "35RNH", "36RUR", "35QQF", "36RUV", "35RNN", "36RVN", "35RNL", "35RPJ", "36QVH", "36QVK", "36RYS", "36RWR", "35RPH", "35RQG", "36QVJ", "36RTM", "35RKM", "35QNG", "36QTK", "36RXM", "36RXR", "36QUM", "35RMM", "36RTP", "36QXM", "36QXK", "36RTU", "36RWP", "35RLM", "36RWS", "35RKK", "36RTQ", "35RQP"], "EH": ["28REN", "29RMK", "29RLJ", "28RGQ", "29RLK", "28QEL", "28QDK", "28QCL", "28QDL", "28QDM", "28QCK", "28QEK", "28RFP"], "ER": ["38PKV", "37PHQ", "37QDT", "37PCR", "37QDU", "37QET", "37PET", "37PES", "37QDV", "37PGS", "37PFS", "37QEU", "37PDT", "37QCU", "37PCS"], "ES": ["30SWG", "29SQB", "30SVG", "28RDR", "28RFS"], "ET": ["36PZR", "37PEM", "37PGM", "36PXS", "37PCM", "36PYS", "37NDJ", "36NYL", "37PCL", "36PZP", "37PCQ", "37PGK", "36PZQ", "37PCR", "37PDK", "37NBJ", "36NYP", "37NEJ", "37PAL", "37NGF", "36PYP", "37PAK", "37NAG", "37PBK", "37PFP", "37PBL", "37NBH", "37NGJ", "37NCG", "37NFF", "37NCD", "37PFR", "37PEQ", "37NBG", "37NDF", "37NBF", "37PFN", "37NEF", "38NKN", "37PGL", "37NDE", "37PEP", "37PER", "37NHH", "37PFQ", "38PLQ", "38PKQ", "36PYR", "37PCK", "37PCP", "37PDQ", "37NBE", "36NWP", "37PDM", "36NWN", "36PXR", "37PCN"], "GA": ["33MTV", "32MPD", "33MVU", "33MVV", "32MNE", "32NQG", "32MND", "33MTU", "32NPF", "33MTT", "32MQE", "32MRE", "32MNC", "33NTB", "32MRD", "32MQB", "32MQD", "32NNF"], "GH": ["31NAG", "30NXP", "30NZN", "31NBG", "30NWN", "31NBH", "30PZQ", "30NYN", "30NWL", "31NAJ", "30PXQ", "30NXL", "30PYR"], "GM": ["28PFV", "28PEA", "28PCV", "28PEV", "28PCA"], "GN": ["29PKM", "28PFS", "28PET", "28PGT", "29PLL", "28PFU", "29PJP", "28PGS", "29PNM", "29PLM", "28PHU", "29PPK", "28PGV"], "GQ": ["32NQH", "32NNH"], "GR": ["35SMA", "35SNV", "34SGG", "35SKV", "35SLV"], "GW": ["28PEU", "28PDU"], "IL": ["36RXU", "36SYB", "36RXV", "36RXT", "36RXA"], "IN": ["43REN", "43SFV", "43QFU", "43QEU", "43QBE", "43RFN", "43QEV", "43PGS", "43SFU", "43SDT", "43RDG", "43PFS", "43RFK", "43PDQ", "43QGG", "43QDU", "43SES", "43SEU", "43SFR", "43RFG", "43PFP", "43RFM", "43QBF", "43RGL", "43QGD", "43RFP", "43QBC", "43QFC", "43QEF", "43QCV", "43QAD", "43QDA", "43RDH", "43SFT", "42QXJ", "43RFL", "43PDT", "43QFV", "43QCD", "43PGK", "43PCT", "43QFB", "43QDF", "43QCE", "43PES", "43QCU", "43RGN", "43QGF", "43SFS", "43QCB", "43PDR", "43QCA", "43RGK", "43SER", "43PDS", "43RFJ", "43QFA", "43QDV", "43PGQ", "43RBK", "43RCL", "42QWM", "43RDL", "42RYN", "43RDK", "43RDM", "43REM", "42RXR", "43RDN", "43RCK", "42QXL", "43RCN", "42RXN", "43RBJ", "43RCM", "42QWL", "43RDP", "42QVM", "43REL", "42RXP", "42RYP", "43RBL", "42RYQ", "43RCP", "43RCJ", "42QXM", "43RBM", "42RXQ", "43QGE", "43QCF", "43RGM", "43RDJ", "43QEE", "43SGU", "43QDB", "43QDE", "43RFQ", "43PGP", "43QGC", "43PFQ", "43QCC"], "IQ": ["38SQA", "38SKC", "37SGS", "37SFS", "38SMD", "38SMB", "38RQU", "38RKV", "37SES", "38SLC", "38SNC", "38SNB", "38SLE", "38RPU", "38SKE", "38RLT", "38SKB", "37SGT", "38SLD", "38SKD", "38SLA", "38RMU", "37SGU", "38RNV", "38RMV", "39RTP", "38RMA", "38RNU", "38RLV", "38SME", "37SFR", "38SNA", "38SLB"], "IR": ["39SVT", "40SFE", "41RMQ", "38SNC", "40RBT", "39RUP", "40SDG", "39RXR", "40SBF", "40SDC", "39SWT", "39SUT", "40RGV", "38SQC", "39SYU", "40SEA", "41RLN", "40SCC", "38SQG", "40REU", "40RFU", "39RVQ", "38SPF", "39SVA", "38SQD", "40SED", "40SEG", "40SDD", "39SWV", "39STV", "40SCB", "39RWP", "38SPD", "39SXS", "41SLV", "38SQB", "41RKM", "40SDE", "39SXT", "39SXA", "40RDS", "40RDV", "40SCF", "38SQE", "41SKU", "38SPB", "40RCV", "38SPC", "39SUA", "40SCE", "39RVP", "41RLJ", "40REP", "39RXL", "39RWM", "41RKK", "41RKJ", "40RFP", "39RYK", "39RTP", "40RBQ", "40RCR", "40RBR", "40RFR", "39RYL", "40REQ", "41RKL", "40RFQ", "41SKS", "41RLK", "41RKR", "41RKQ", "40RGA", "40RDU", "41RLM", "39RXM", "41RKP", "40RCQ", "41SKT", "40RGQ", "41RLL", "39RYM", "39RVN", "39RWQ", "38SPE", "40REV", "40RBV", "40SDB", "38SNE", "40RGS", "39SVS", "39RYQ", "40SDF", "39SVU", "38SNG", "40REA", "41RLQ", "40SBC", "40SBA"], "IT": ["33SVB"], "JO": ["37SBR", "37RBN", "37RBQ", "36RYU", "37RBP"], "KE": ["37NDC", "36MZC", "37NGF", "37MDT", "37MET", "37NFA", "37MBV", "37MFV", "37MCT", "37NDB", "37NBB", "37MEV", "36MYD", "37MER", "37NFF", "37NBD", "37NCB", "37NFB", "36MYE", "37NAB", "37MGU", "37MCV", "37NBC", "37NCD", "37MFT", "37NCC", "37MDV", "37MGT", "37MDS", "37MDU", "36NYH", "36NXF", "37MBT", "37MEU", "37NGB", "36NYJ", "37MCU", "38NJK", "37NHE", "37NDD", "37NDA"], "KW": ["38RQS"], "LB": ["37SBU", "36SYC"], "LR": ["29NNG", "29NLJ", "29PMK", "29NMH", "29NPF", "29NNF", "29NMF"], "LS": ["35JPG", "35JNG", "35JPH"], "LY": ["34RGP", "34SEB", "34RCP", "33RWJ", "35RKN", "34RFN", "33RXQ", "33RUQ", "34RFT", "34RFP", "33RYM", "33RWK", "35RKH", "34QFL", "35RLH", "32RQP", "32QNK", "32QML", "32RPQ", "35QLC", "33RVP", "33RXJ", "33RTK", "33RVH", "33QUE", "33RVM", "34QFK", "33QTF", "33RYL", "33RWH", "32QQL", "34RBU", "32RPT", "33RYJ", "33RUG", "33STR", "32RMS", "34RES", "32RNM", "34SEA", "34RFA", "33RTH", "34RGT", "33QXG", "34RGQ", "33RXN", "34RCT", "34RCQ", "35RKR", "34SDA", "35RLP", "34QEJ", "34RBP", "34REU", "33RUR", "34RBR", "33RXK", "33RUK", "33RVJ", "33RUN", "33RTM", "33RYP", "34RER", "32QNM", "33QVF", "34RCR", "33QTG", "34RDT", "35QMF", "34QGK", "34REV", "35QKC", "34QEM", "34RET", "34RDV", "33RTR", "33RYK", "34RFV", "34REA", "34RGU", "32RQR", "33SVR", "32RNT", "32RMT", "33RTQ", "34RDS", "34RDU", "33RWM", "35QLF", "34RDP", "32RQM", "34RDM", "34RFQ", "34QGL", "35QKE", "33RVN", "32RPR", "33RWN", "33RVK", "34RBQ", "34RGS", "32RMV", "33RYN", "34REN", "32RNS", "32RNU", "35QKF", "33RTJ", "34RCS", "34RGR", "34RFU", "32RQS", "33RTL", "32RQV", "32RPV", "33RVQ", "33RWQ", "34SFA", "33RUJ", "32QNL", "34SCA", "35QLE", "32RPN", "35RKM", "32RQT", "32RQQ", "32RLV"], "MA": ["29RPP", "29SPS", "30SVC", "30STC", "29RMQ", "30RTR", "30SUC", "29RQQ", "29RLH", "30STD", "29RNN", "29SQU", "30RVR", "30RUQ", "29RKG", "30RVS", "30SUB", "30RYV", "30RUS", "30SUD", "29RNR", "30RTT", "29RPM", "29RPN", "29RMN", "29RMG", "29SNS", "30SXC", "30STE", "29SMR", "29SPR", "28REN", "30SWC", "30RVT", "30SUA", "29RPQ", "29RNP", "30SXA", "29RLM", "29RNQ", "30SVD", "29RNM", "28RFM", "28QFM", "29RMM", "28RFN", "30STB", "30SVA", "29RPR", "30RXV", "30SVB", "30RUU"], "MG": ["38KQF", "39LTE", "38JMU", "38KNV", "38KPE", "38KLA", "38KMD", "38KME", "38KNA", "38KNF", "39KTC", "39LTG", "38KMB", "38KNG", "39LUF", "38KQA", "38KRE", "38KQC", "39LTD", "38KMA", "39LVC", "38LQH", "39KTV", "38KQV", "38KPF", "38JNT", "38KQG", "38KQB", "39LTC", "39KTT", "39LUE", "38KNB", "38KPC", "38KMG", "38KRG", "38KNC", "38KMF", "39KTU", "38KLB", "39LUD", "38KPA"], "ML": ["29PPN", "31QAA", "31QCT", "31PBT", "30QWL", "29QQD", "30PUV", "29QPE", "30QYL", "30QUK", "31QAC", "30PVA", "31QDD", "30QWF", "29PLQ", "31QDE", "30QXD", "30QTL", "29PQM", "29PQS", "30QXC", "30QTK", "29PPP", "30QUG", "30RWN", "30QXK", "30PUB", "31QEB", "30QXL", "30QVD", "30QYE", "29PNP", "31QDU", "31QCV", "29PLP", "30QWJ", "30QXJ", "30QVE", "31QDB", "31QFA", "30QTH", "29QQC", "30QUF", "31QCE", "31QCU", "30PTB", "29PMP", "29PQN", "30QUD", "29PPR", "31QEV", "31QFB", "29PKR", "30QYD", "29PNN", "30QYK", "30RUP", "31PDT", "30PST", "31QBU", "30QTM", "30QZJ", "30QVL", "31QBC", "30QWG", "29PMR", "30QUL", "30QVF", "30PVV", "31QCF", "31QEA", "29QPD", "29PQR", "30QUE", "29PKQ", "30QWC", "31QEC", "30QXG", "30QVH", "30RTN", "30PTV", "30QTD", "30PSU", "30QWH", "29PRQ", "30RWM", "31PET", "31PDS", "30QSH"], "MR": ["29QLA", "29QMC", "29QNB", "29QLG", "29QPC", "29QKB", "29QME", "29QNC", "29QLF", "28QGK", "29QPB", "29QLE", "29QNE", "29QND", "29QKG", "29QNG", "28QGJ", "29QPA", "28QGD", "29QQB", "29QLC", "29QNV", "28QEF", "28QEG", "30QTE", "28QEJ", "28QFM", "28QDJ", "28QFH", "29QLV", "28QEL", "28QEH", "28QFG", "28QCK", "28QEK", "28QFF", "28QGH", "28QFL", "29QMB", "29QQV", "29QKE", "28QGG"], "MU": ["40KEC"], "MW": ["37LBC", "36KYG", "36LWJ", "36LXN", "36LXL", "36KYH", "36KXF", "36LYH", "36LXK", "36KYF", "37KAC", "36LWQ"], "MZ": ["37LAD", "37LDD", "36KXB", "36KXV", "37KEB", "36KWD", "36KXA", "37LBD", "37LCC", "37KCB", "36KYU", "36KYA", "36KWA", "36KZE", "37LED", "36JVS", "37LDF", "37LDE", "36KYE", "36KWV", "36KVU", "37LEF", "36KXC", "36KWF", "37LCF", "37KCA", "36KXE", "37KDB", "37LBF", "36JWT", "37LFF", "37LDG", "37KCC", "36LWH", "36JVT", "37LCD", "36KWG", "36JXT", "36JVR", "37LFH", "37LBE", "37LFE", "37KBA", "36KXD"], "NA": ["34JCT", "34KDV", "34KCE", "33JYP", "34KDA", "33JXN", "33KYU", "33KWA", "33KTV", "33JYK", "33JWN", "34KDU", "33KYP", "33KYA", "33KXB", "33KZV", "34JCR", "33KZS", "33JXL", "34JCQ", "33KTB", "34KFG", "33KZB", "33KYR", "34JDS", "34KDF", "34KBC", "34KEF", "33KWT", "34JBQ", "33JVM", "34KAD", "33JXJ", "34JBT", "34KCU", "34KBG", "33KWS", "33KWV", "33KXT", "33KVS", "33JYL", "33KYQ", "33KWU", "33KVU", "33KVV", "34KBV", "33KYV", "33KTA", "34KDD", "33KUU", "33KXQ", "33JWK", "34KCD", "34KCC", "33KXA", "33KXS", "34KCG", "33KXV", "33JYN", "33KUV", "33KYS", "33JXM", "34JDT", "33KWQ", "33KXP", "33JWL", "34KDC", "34KCF", "34KBA", "33KUA"], "NE": ["32PKA", "31PES", "32QNG", "31PDR", "32QKH", "33QVB", "32QPF", "32QPH", "33QUA", "33QWU", "32QLJ", "31PER", "33QWB", "32QPC", "33PTQ", "32PLA", "32QMH", "32QMK", "31PGR", "33QTA", "33QVV", "32PMA", "32QJC", "32PKC", "31PEQ", "32QQE", "31PBS", "33PST", "32PKB", "32QRD", "32QNH", "31PBR", "33QSC", "32PNA", "32QMJ", "33PTR", "32QLF", "31QHV", "31QHA", "31PHR", "31PDS", "32PJA", "32PRA", "33PVS", "32QNJ", "31PCR", "32PMV", "33PUT", "32PMB", "33QSA", "32QQH", "31QFU", "32QPE", "33QUU"], "NG": ["33PUR", "31PHN", "32NKP", "32PLQ", "32PLP", "32PNS", "32NML", "33PTN", "31PFK", "32PNP", "32PLV", "31PEK", "32NQN", "32PKS", "32PNU", "33PUQ", "31PGQ", "32PKT", "32PPT", "31NEJ", "31PFL", "31NFJ", "31PEQ", "31NFH", "33PUP", "32PKQ", "32PQS", "32PPR", "33PTM", "31PGP", "32NLN", "32PPV", "33PTL", "31PHM", "31PFN", "32NLP", "32PPP", "32NNP", "32NMM", "32PNT", "32PLT", "32PQU", "31PHL", "32PPQ", "32PMT", "31NDH", "33PSQ", "32PMV", "33PTP", "32NKM", "31NGH", "32PLS", "33PUM", "31PGR", "32NQP", "32PQR", "32NJM", "32NJN", "31PFM", "31NGG", "32NLL", "31PFQ", "31PGL"], "OM": ["40QDH", "40QCK", "40QCL", "40QBF", "40QGL", "40QCH", "40QFJ", "40QBG", "40QBD", "40QGK", "40QEM", "40QFL", "40QEK", "40RCM", "40QBE", "40QDF", "39QZU", "40QFM", "39QYU", "40QEL", "40RDM", "40QDL", "40QAD", "40RCN", "40QEG", "40QCM", "40QAE", "40QFK", "40QDM", "40QCG", "40QDK", "40QBJ", "40QCJ", "40QBH"], "PK": ["42RVV", "43SEV", "43SEA", "42RUV", "43RBP", "42SYE", "42SXA", "42SYD", "42RUR", "42RXV", "43SCU", "43SDA", "43SDV", "42SYC", "43RDQ", "41RNK", "42RTN", "42RTS", "42RXN", "41RQM", "42RTP", "42RXR", "41RPN", "43RBR", "42RWS", "42SXB", "42RTT", "41RNM", "41RNJ", "41RPK", "42SYB", "41RMJ", "42RWT", "41RQN", "42RWN", "42RUP", "42RUU", "42RYA", "41RNH", "42RXM", "41RPL", "41RQL", "42RVR", "42RXA", "43RCP", "42RYS", "41RPM", "42RUS", "41RNN", "42RVT", "42SYA", "42RWM", "42RXS", "42RVM", "42RUQ", "41RQJ", "43SBV", "43RBQ", "43SEU"], "PS": ["36SYA"], "PT": ["28SCB"], "QA": ["39QVG", "39RWH"], "SA": ["39RTG", "38RQP", "38RNR", "38QNG", "38QNK", "37RCM", "38RPP", "38QKK", "38RPN", "38QLL", "39RUG", "38RQQ", "38QQJ", "37REH", "38QMK", "38RKV", "39RTH", "37RDQ", "37REM", "37REN", "38QMF", "39RTJ", "37RFP", "38RKU", "39QTD", "37RCR", "38QQK", "38QPG", "38QPF", "37REP", "37RCP", "37RCL", "38RNS", "37REQ", "37QGD", "37RCN", "38QLF", "37QGF", "38QNF", "37RBQ", "37QGE", "39QUD", "37QGB", "38QJE", "38QKE", "37QGC", "37QGA", "38QME", "38RMP", "37RCJ", "38RLQ", "37QEF", "38RMN", "37RDG", "37QFC", "37QED", "37QDG", "37RCK", "38RKR", "37RCH", "37QFD", "37RDK", "38RMQ", "37RGM", "38RQR", "38RLP", "39RUJ", "37QFB", "38QNH", "37RBK", "37RDH", "37QDF", "39RTL", "39RUK", "37QEC", "39RTK", "37REG", "38RKS", "37QEE", "38RPR", "37RDJ", "37RDP", "37RCG", "38RLR", "37RFL", "38QPL", "38QMG", "37RFH", "38RKN", "37RGJ", "38RKP", "38RLN", "38RJP", "37QEG", "38RKM", "37RFG", "38QKH", "37RFJ", "38RLM", "38QKG", "37RGH", "38QKL", "39QTE", "39QUG", "37SGR", "37RER", "38RPQ", "39QUE", "39QUF", "38RQN", "38QMJ"], "SD": ["36PSS", "35QQA", "36PVS", "35PJQ", "36PVT", "35QPU", "35PKQ", "34PHB", "36PYC", "34PFU", "35QNV", "36QTF", "35QQC", "37QBU", "37QCU", "36PUB", "35PKT", "35QQV", "36PWT", "35PMM", "34PGA", "36PZU", "35QMC", "35PLS", "36QUH", "36PYT", "35PQM", "35PLT", "36QXK", "36PYV", "35PPN", "35PNT", "36QXH", "35PKS", "36QYH", "35PKR", "35PNR", "34PHT", "35QMT", "35QND", "35QPA", "35QLC", "36PYB", "36QXG", "35QQD", "36QXD", "35QNE", "35QRV", "36QXF", "37QDV", "37QBD", "37QDA", "36QXE", "37QCA", "36QZK", "37QBA", "37QAD", "37QBE", "37QAE", "36QVF", "36QYL", "37QCB", "36QYF", "37QAA", "36QZJ", "36QYD", "36QZF", "36QUD", "36QVD", "36QWD", "36QUG", "36PWS", "35QPB", "35PKN", "36QVE", "36QYK", "36QUE", "36QVG", "37QAC", "36QWF", "36QYE", "36QWE", "35PPS", "36PXA", "35QQU", "35QQB", "35QLU", "36QYJ", "35QPV", "35PQQ", "35PRN", "35PLQ"], "SH": ["28HGD"], "SL": ["29PJL", "28PGR", "29PJK", "29NLJ", "29PLK", "29PKM", "28PGQ", "29PLL"], "SN": ["28PCB", "28PEV", "28PFA", "28QCD", "28PDV", "28PEA", "28PEB", "28QFD", "28PCU", "29PKP", "28PGA", "28PDB", "28QGC", "28QED", "28PGV"], "SO": ["37MGU", "39NSF", "38NLK", "39PVN", "38NQM", "38NLJ", "38NNJ", "38PMP", "38NKG", "38NMM", "38PQP", "38NMP", "37NGA", "38NLG", "38NLL", "39PWM", "38PNQ", "38PMQ", "38NLF", "37MGV", "38NKH", "39NTG", "38NNM", "38NKJ", "38NJG", "39PSK", "38PLR", "38NPP", "39NUJ", "38NKL", "38NNN", "38NPM", "39PUM", "39PWN", "38PLS", "39PTM", "39PTK", "38PKS", "39PVM", "38PPS", "38PMR", "39NTJ", "38PNS", "38NPN", "38PMS", "38NLM", "38NMN", "39PUK", "38NNP", "38NQN", "39PSM", "38PNR", "38PLP", "38NPJ", "38NLP", "39PTL", "38PLQ", "39PSL", "38NKN", "38NLH", "38NNK", "39NTH", "38NKM"], "SS": ["35NKJ", "36PVS", "35PLK", "36NTN", "35PNL", "36NXM", "35NNF", "35NQJ", "35PKL", "36NUN", "36NTK", "36NVL", "36NUP", "35NRG", "35NNJ", "35NRF", "35NQE", "36NTL", "36NWM", "36NTP", "35NQG", "35PNK", "35PML", "36NVM", "36PSP", "36PUQ", "36PVQ", "36NXL", "36PTQ", "35NMJ", "35PQM", "35NQF", "35PLL", "35NNH", "36NVP", "35NLJ", "35NLH", "35PQK", "36PVR", "36NUM"], "SY": ["37SBS", "36SYE", "37SGA", "37SDV", "37SDA", "37SBV", "37SDU", "37SDS", "37SCU", "37SEU", "37SDT", "37SCT", "37SCA", "37SBT", "38SKF", "37SCS", "36SYB", "37SFA"], "SZ": ["36JVR", "36JUR"], "TD": ["33QYU", "34QCJ", "33PXT", "34QCG", "33QYC", "34QDG", "34PDV", "34QBE", "34PCA", "34QBK", "34QBD", "34PBB", "33PVL", "33PWL", "33QYD", "34QBJ", "34QGE", "34QEG", "34QHD", "33QYV", "33PWT", "33QXV", "35QKA", "34QCD", "34QCM", "34QBL", "33QVT", "33QYG", "34QBC", "34PBQ", "34PES", "35QMV", "34PCR", "34QCK", "33PWN", "34PBR", "33PZN", "33PYM", "34QBH", "33PYN", "34PBS", "34QGH", "34QBG", "34QCE", "34PGB", "34QBF", "35QKB", "34QDF", "33QYF", "33QXF", "35QKU", "34QGG", "33QWC", "33NYJ", "34QGF", "34QDL", "34QDH", "33QXE", "35QLB", "33PWK", "34QDK", "34QHF", "34QFF", "33QXU", "34QDJ", "34QEE", "34QFE", "34RBP", "33PYJ", "34RCN", "34QFH", "33PXQ", "34PDC", "33QYB", "34PET", "33PYK", "34QEH", "33QXC", "35QMA", "33QXD", "33QWU", "33QWB", "34PDT", "33NWJ", "33QYA", "33QWD", "33QYE"], "TG": ["31NCJ", "31NBJ", "31PCJ"], "TJ": ["42SVG", "43SCB"], "TM": ["41SKB", "40SFG", "41SLB"], "TN": ["32SME", "32SMC", "32SNB", "32SPF", "32SNC", "32SNE", "32SND", "32SNF", "32SMD", "32SPB", "32SPE"], "TR": ["38SKG", "36SUF", "37SBA", "36SWF", "36SXF", "38SLG", "36STG", "36SXG", "37SEA", "37SGB", "35SNB", "35SQA", "35SQB", "37SFB"], "TZ": ["36LUS", "35MRM", "37LCL", "36MWT", "37MAQ", "36MTT", "37MBR", "36LYN", "36MXV", "36MZU", "36MVU", "36MTA", "36LWR", "37LDJ", "36MWS", "36MYV", "36MTC", "36MWV", "36MYS", "36MTV", "36MTU", "37LDK", "36MYB", "36MXA", "37LCK", "36MUC", "37MAR", "37MDM", "36MVA", "36LXR", "35MPQ", "36LXQ", "36MWU", "36MSA", "36MWA", "36MXB", "36LWQ", "36MXT", "36MSV", "37LEL", "37MCQ", "36MVB", "36LYQ", "37LBL", "37MDN", "37MCS", "36LYM", "36MYA", "37MCM", "37LAK", "37MBS", "36LUR", "36MWB", "36MUU", "36LZP", "36MVC", "36MYT", "37MCR", "37LEM", "37MEM", "37LAH", "37MCP", "36MTS", "37MEN", "36MVV", "36LZQ", "36LYP", "36MXS", "37LDM", "36MUS", "37MBP", "36MYU", "36MVT", "36MUA", "37LEH", "37LCH", "36MUV"], "UG": ["36NUH", "36NWK", "36NUF", "36NYH", "36NWG", "35NRA", "36NXK", "36MTE", "36NTH", "36NVG", "36NWH", "35MQV", "36NSF", "36NTJ", "36NUJ", "36NVJ", "36NTF", "36NVH", "36MSE", "36NZH", "36NXG", "36NXH", "36NXJ", "36NYK", "36MVE"], "YE": ["39QTA", "38QQE", "38QQG", "39QXA", "39PVS", "39PWS", "39QZB", "39QUC", "38PLA", "38QND", "39QXC", "38PMA", "39QUD", "39QVA", "39QVD", "39PWT", "39QYB", "39QVC", "39QWA", "38QQD", "38PNA", "39QWC", "39QYV", "39QUB", "39PVT", "38PMB", "38PNC", "38PLB", "38PKC", "38QMC", "38PMV", "38PMC", "38PKB", "39QYU", "38PNB", "38PRC", "38QKC", "38PNV", "39QTC", "39QXV", "38PPB", "38PPA", "38PPV", "39QYA"], "ZA": ["35JMG", "34HDH", "35JPE", "35JKE", "36JTP", "35JNL", "36JUQ", "35JLG", "36KVV", "35JNP", "35HKD", "34HCK", "36JVQ", "34HDJ", "34JGM", "36JUU", "36JTT", "34JFP", "36KTV", "35JPF", "33JYF", "35JNK", "36JUT", "35JQK", "34JCM", "34JGR", "35JQL", "35JML", "35JQH", "35JQJ", "34JBL", "35HNE", "35JPK", "36JTR", "35JME", "35JPM", "34HBH", "36KUV", "34JFM", "35JQG", "35JKH", "35JLK", "34JDL", "35JQN", "35JNF", "34JBM", "35JMH", "35KQQ", "34HBJ", "35JKL", "34HGJ", "35JLL", "35JKK", "35HMD", "35JLJ", "36JTS", "35JPL", "36KTU", "34JEL", "35HLD", "36JUP", "35JNJ", "34JEQ", "34JGN", "34JGK", "34JFK", "36JTM", "34JFQ", "36JUN", "35JNE", "35JKG", "34JBN", "36JTQ", "34JCK", "34JGP", "34HEJ", "35JMK", "34JEK"], "ZM": ["35LMF", "35LQJ", "35LKF", "35LND", "36LTQ", "36LTP", "36LVM", "36LUM", "35LMG", "35LKC", "36LUP", "35LNC", "34LEK", "35LQH", "36LVJ", "35LME", "34LGM", "36LTR", "35KKC", "35KPB", "34LGL", "36LTJ", "35KNA", "35LKE", "35LLD", "35LNK", "35LJE", "34LGH", "34LFH", "36LTN", "34LDJ", "35LJH", "35LLG", "36LVP", "35KMB", "35LPF", "35LMD", "35LQF", "35LPD", "35KNB", "34LDH", "35LNF", "35MQM", "34LDK", "35LJF", "36LVK", "35KKB", "36KSH", "36LUN", "35LPK", "34LEJ", "36LWN", "36LUJ", "35LLC", "35LMC", "35LQD", "35MPM", "35KMA", "35LJJ", "35LKG", "35LNG", "35LPE", "34LGJ", "36LSP", "35LQE"], "ZW": ["36KVA", "36KSC", "35KQS", "36KUE", "36KUA", "35KQB", "36KVE", "35KNV", "35KQA", "35KPT", "35KQT", "36KVC", "36KTF", "36KUD", "35KQC", "35LQC", "36KTG", "36KTB", "35KRU", "36KWC", "35KMV", "36LVH", "35KRA", "35KNT"]} +{"AE": ["39QYF", "39QWD", "40RBM", "40RBN", "40QBJ", "39QXG", "40QBK", "39QVE", "39QXD", "40QCM", "40QCL", "39QWF", "39QXE", "39QZG", "40QBM"], "AF": ["42STF", "41SPV", "41RPQ", "41RQP", "41SQS", "41SPT", "41RLP", "41SNV", "41SMU", "42STB", "41RNP", "41SPR", "41SQB", "42SVB", "42RTA", "42SUB", "41SPS", "42SWD", "41SQT", "41SNU", "41SNT", "42SXF", "42SUF", "42SXE", "41SQA", "42STA", "41SLR", "42SWF", "42SUD", "41SMS", "41SQU", "41SLV", "41RMN", "42SUA", "41SLT", "41SNR", "41SPA", "42SVD", "41RLQ", "41SQV", "42RTV", "42RTU", "41RPR", "41SQR", "43SBA", "42RUA", "42SWE", "42SVC", "42SVE", "41SLS", "41RQQ", "42SXC"], "AO": ["33LXJ", "33LVL", "34LBK", "34LDK", "33LWF", "33LVH", "33LUD", "34LCS", "33LWJ", "34LEL", "33LWE", "34LFP", "34LFM", "33MVN", "33KXC", "34LBQ", "33LVK", "33LYL", "33MXM", "33MTN", "34LCJ", "33LYK", "34LCP", "33KXB", "33LYH", "33LYJ", "33MUM", "34LEM", "34LFQ", "34LCR", "33LWC", "33LWK", "34LCK", "34LDN", "34LAJ", "33LTC", "33LXK", "34LEP", "33LYC", "34LBR", "34LDS", "34LDR", "33LXG", "33LTD", "34MES", "34LDM", "33LYG", "33MWM", "33MTP", "34LCN", "34LCQ", "33LXH", "32KQG", "33LXD", "34LGP", "33LTE", "33LSD", "33MUN", "33LUC", "33LVE", "33MVP"], "BF": ["30PYU", "30PVV", "30PXV", "30PYV", "31PBQ", "30PWV", "31PCP", "31PBP", "30PVS", "31PBR", "30PWA", "30PXT", "30PYB", "30PUU", "30PXA", "31PCQ", "30PUT", "31PBN", "30PZU", "30PVU", "31PDP"], "BI": ["36MSC", "35MRS", "35MQS", "36MSB", "36MSA", "35MRT"], "BJ": ["31PCM", "31PCJ", "31PDL", "31NCH", "31PCL", "31PDN", "31PCK", "31PBM", "31PEM", "31PDP", "31PDK"], "BW": ["34JFT", "34JFS", "34JGT", "34KFD", "34KEE", "34KDU", "35KPQ", "35KNS", "35KPR", "34JGS", "35KLT", "35KJR", "35KMT", "34JDS", "34KEA", "34KFE", "35JKM", "35JLM", "34KFC", "35KMP", "35KMS", "34KDV", "35KLP", "34KGV", "35KLS", "35KLB", "34KDB", "34JFR", "35KMR", "35KLV", "34JDU", "35KKA", "34KGU", "34KDD", "34JER", "35KKS", "35KKQ", "34KGE", "35KQS", "35KMQ", "35KLU", "34KEV", "35KNQ", "34KFA", "35JLP", "34JGU", "34KDC"], "CD": ["34NGH", "34MGV", "35MPS", "35MLP", "35MPV", "35MKV", "35MMV", "35LML", "34MGA", "34NEF", "34MEU", "34NHG", "35MJT", "35NKC", "35MPT", "35MJM", "34NBF", "35NPB", "33MYM", "34MHT", "34MFD", "34NCH", "35MNS", "35MLS", "34LGQ", "34NEJ", "35NQD", "35NMC", "35LMJ", "34NBK", "34NDF", "35MLQ", "34MDD", "35MNT", "35MMU", "33MZQ", "35NMD", "35MJR", "34MCB", "34MED", "33MXS", "33NYA", "35NKE", "34NDH", "34MAU", "35NLE", "35NQE", "33MXR", "35MKT", "36NTH", "35MMM", "35NLD", "34NCJ", "33NZA", "34MCV", "35NLA", "33MYT", "35MMP", "34MBE", "33MXP", "33LZL", "34MHU", "33MWP", "35NLB", "34NGJ", "33MWQ", "35MNQ", "34MDC", "33MVP", "35MLT", "34MAA", "34MGC", "34NGK", "33MZV", "35MKP", "33MYR", "35MMQ", "34MEC", "35MKS", "34MEV", "35MLV", "34NCF", "34NHJ", "34LGS", "34MDA", "34MBA", "34NCG", "35NPD", "35LNH", "34MDV", "34MFV", "35MQN", "35NLC", "33MYQ", "34NEH", "34MCA", "34MHE", "34LFR", "34MEB", "34MHC", "34MCD", "35MMT", "35MMS", "33MXT", "34MFE", "35LNJ", "34MBT", "33MYP", "35MNU", "34NGF", "35MLU", "34MEA", "34MHV", "35NQB", "35NPC", "34MBV", "34MGU", "35NNA", "34MEE", "35MMN", "35MKN", "34MCU", "35NKA", "35MQP", "33MXU", "34MAE", "35NND", "34MFB", "34MBB", "35MQT", "35MQU"], "CF": ["34PES", "33NZJ", "34PER", "35NME", "33NWH", "34NGP", "35NLG", "33NXD", "35NMH", "34PDR", "33NXJ", "34NEM", "34PEQ", "34PFT", "34PGR", "34PGQ", "34NFM", "34NBJ", "34NDP", "35NKG", "34PGT", "34NDN", "34PHQ", "33NYG", "33NZH", "35NJF", "35NMG", "35NJJ", "33NXE", "34PFP", "34NDM", "33NYH", "34NCL", "34PCQ", "34PDQ", "34NFL", "33NWE", "34NCP", "34NCN", "34NGL", "34NEN", "34PFR", "35NKF", "34NEP", "34NBM", "33NWF"], "CG": ["33NVC", "33MWU", "33NUB", "33MVS", "33MWV", "33MUS", "33MVR", "33NXB", "33NUC", "33MTS", "33NYC", "34NAH", "33NXA", "33NYB", "33MVV", "33NZC", "32MRA", "34NBG", "33NWA", "33MSQ", "34NBH", "33MWT", "33MUR"], "CI": ["30NUM", "29NRG", "30PTR", "30PWR", "29NPJ", "29NPH", "29PQK", "29PQM", "30NWP", "30NVN", "30NUN", "29NQG", "30PUR", "30PVQ", "30PWP", "30PUQ", "30NVM", "29NQH", "30PTQ", "30NUP"], "CM": ["33PVK", "33PVM", "32NPJ", "33NVG", "32NQJ", "33PUL", "33NVH", "33NUJ", "33NSF", "33NVJ", "33PTK", "32NQM", "33NVE", "33NUD", "33NTH", "33PVN", "33NVF", "33NTF", "33PUK", "32NPM", "33PSJ", "33NUF", "32NNK", "32NRJ", "32NPK", "32NNL", "33NUH"], "CN": ["43SEB", "43SFA"], "CY": ["36SVD", "36SWD"], "DJ": ["38PKS", "38PKT", "38PJS", "37PHM"], "DZ": ["31RCK", "32SLB", "30RYN", "32RKP", "31RGP", "29RQK", "31RFP", "31RFL", "31SES", "31RGM", "31REK", "31SFT", "31SEA", "31REJ", "31SDU", "31RDK", "31RFG", "31SBV", "32RLU", "29RNK", "31SDT", "31SDR", "31QGC", "30RYU", "31RDH", "31RGL", "31SEV", "30RWT", "32RLM", "31SGS", "31SDV", "31RDL", "31REH", "30RYV", "31RCN", "31SCU", "31RFN", "31REQ", "32SKC", "31QEG", "32SLD", "30RVU", "32RKU", "30RWR", "32RMR", "29RPL", "31SCV", "31SBU", "32QKM", "30SYA", "30RXT", "29RQJ", "29RPH", "31RFM", "32RLS", "30RXS", "31QBG", "31SEU", "32RKT", "31RCM", "31SFS", "30SYC", "30RTQ", "30SXD", "32RLR", "31SGV", "31RDQ", "31RGH", "30QYM", "31SGT", "31RBP", "30SXC", "31RBM", "30RXU", "31RBH", "31SCA", "31RDM", "31REP", "31RBL", "32RLN", "31REG", "30RXR", "31QGD", "29RMK", "31SCS", "31REM", "31RCR", "31SFR", "31RDN", "32QKL", "31SFV", "31QGE", "32RMP", "30RYP", "31RCH", "30RYS", "32SLA", "29RPK", "31RGJ", "32QLM", "31SFU", "30RYT", "30RXV", "32RNR", "31QEE", "31RDR", "30RTP", "32RNQ", "29RMJ", "31SGR", "31RFJ", "31QFD", "32RPR", "31SCT", "29RQL", "31SBS", "29RNL", "29RQH", "31RCQ", "31QDG", "32SKE", "32SKD", "30RZN", "31RCP", "32QLJ", "31RGK", "32SLC", "32RLQ", "31QDF", "30SXB"], "EG": ["35RMN", "36RUT", "36RVR", "35RLL", "35RMQ", "35RPK", "36RVM", "36RVV", "36RVS", "36QUJ", "35QPG", "35RQK", "36RXS", "36QTL", "36QVL", "35RMP", "36RXP", "35RNM", "35RKL", "35RLP", "36RUU", "36RWQ", "35RMJ", "36RWT", "36RWV", "35RPP", "36RTT", "35RQL", "36RVT", "35RNG", "35RLK", "35RNH", "36RUR", "35QQF", "36RUV", "35RNN", "36RVN", "35RNL", "35RPJ", "36QVH", "36QVK", "36RYS", "36RWR", "35RPH", "35RQG", "36QVJ", "36RTM", "35RKM", "35QNG", "36QTK", "36RXM", "36RXR", "36QUM", "35RMM", "36RTP", "36QXM", "36QXK", "36RTU", "36RWP", "35RLM", "36RWS", "35RKK", "36RTQ", "35RQP"], "EH": ["28REN", "29RMK", "29RLJ", "28RGQ", "29RLK", "28QEL", "28QDK", "28QCL", "28QDL", "28QDM", "28QCK", "28QEK", "28RFP"], "ER": ["38PKV", "37PHQ", "37QDT", "37PCR", "37QDU", "37QET", "37PET", "37PES", "37QDV", "37PGS", "37PFS", "37QEU", "37PDT", "37QCU", "37PCS"], "ES": ["30SWG", "29SQB", "30SVG", "28RDR", "28RFS"], "ET": ["36PZR", "37PEM", "37PGM", "36PXS", "37PCM", "36PYS", "37NDJ", "36NYL", "37PCL", "36PZP", "37PCQ", "37PGK", "36PZQ", "37PCR", "37PDK", "37NBJ", "36NYP", "37NEJ", "37PAL", "37NGF", "36PYP", "37PAK", "37NAG", "37PBK", "37PFP", "37PBL", "37NBH", "37NGJ", "37NCG", "37NFF", "37NCD", "37PFR", "37PEQ", "37NBG", "37NDF", "37NBF", "37PFN", "37NEF", "38NKN", "37PGL", "37NDE", "37PEP", "37PER", "37NHH", "37PFQ", "38PLQ", "38PKQ", "36PYR", "37PCK", "37PCP", "37PDQ", "37NBE", "36NWP", "37PDM", "36NWN", "36PXR", "37PCN"], "GA": ["33MTV", "32MPD", "33MVU", "33MVV", "32MNE", "32NQG", "32MND", "33MTU", "32NPF", "33MTT", "32MQE", "32MRE", "32MNC", "33NTB", "32MRD", "32MQB", "32MQD", "32NNF"], "GH": ["31NAG", "30NXP", "30NZN", "31NBG", "30NWN", "31NBH", "30PZQ", "30NYN", "30NWL", "31NAJ", "30PXQ", "30NXL", "30PYR"], "GM": ["28PFV", "28PEA", "28PCV", "28PEV", "28PCA"], "GN": ["29PKM", "28PFS", "28PET", "28PGT", "29PLL", "28PFU", "29PJP", "28PGS", "29PNM", "29PLM", "28PHU", "29PPK", "28PGV"], "GQ": ["32NQH", "32NNH"], "GR": ["35SMA", "35SNV", "34SGG", "35SKV", "35SLV"], "GW": ["28PEU", "28PDU"], "IL": ["36RXU", "36SYB", "36RXV", "36RXT", "36RXA"], "IN": ["43REN", "43SFV", "43QFU", "43QEU", "43QBE", "43RFN", "43QEV", "43PGS", "43SFU", "43SDT", "43RDG", "43PFS", "43RFK", "43PDQ", "43QGG", "43QDU", "43SES", "43SEU", "43SFR", "43RFG", "43PFP", "43RFM", "43QBF", "43RGL", "43QGD", "43RFP", "43QBC", "43QFC", "43QEF", "43QCV", "43QAD", "43QDA", "43RDH", "43SFT", "42QXJ", "43RFL", "43PDT", "43QFV", "43QCD", "43PGK", "43PCT", "43QFB", "43QDF", "43QCE", "43PES", "43QCU", "43RGN", "43QGF", "43SFS", "43QCB", "43PDR", "43QCA", "43RGK", "43SER", "43PDS", "43RFJ", "43QFA", "43QDV", "43PGQ", "43RBK", "43RCL", "42QWM", "43RDL", "42RYN", "43RDK", "43RDM", "43REM", "42RXR", "43RDN", "43RCK", "42QXL", "43RCN", "42RXN", "43RBJ", "43RCM", "42QWL", "43RDP", "42QVM", "43REL", "42RXP", "42RYP", "43RBL", "42RYQ", "43RCP", "43RCJ", "42QXM", "43RBM", "42RXQ", "43QGE", "43QCF", "43RGM", "43RDJ", "43QEE", "43SGU", "43QDB", "43QDE", "43RFQ", "43PGP", "43QGC", "43PFQ", "43QCC"], "IQ": ["38SQA", "38SKC", "37SGS", "37SFS", "38SMD", "38SMB", "38RQU", "38RKV", "37SES", "38SLC", "38SNC", "38SNB", "38SLE", "38RPU", "38SKE", "38RLT", "38SKB", "37SGT", "38SLD", "38SKD", "38SLA", "38RMU", "37SGU", "38RNV", "38RMV", "39RTP", "38RMA", "38RNU", "38RLV", "38SME", "37SFR", "38SNA", "38SLB"], "IR": ["39SVT", "40SFE", "41RMQ", "38SNC", "40RBT", "39RUP", "40SDG", "39RXR", "40SBF", "40SDC", "39SWT", "39SUT", "40RGV", "38SQC", "39SYU", "40SEA", "41RLN", "40SCC", "38SQG", "40REU", "40RFU", "39RVQ", "38SPF", "39SVA", "38SQD", "40SED", "40SEG", "40SDD", "39SWV", "39STV", "40SCB", "39RWP", "38SPD", "39SXS", "41SLV", "38SQB", "41RKM", "40SDE", "39SXT", "39SXA", "40RDS", "40RDV", "40SCF", "38SQE", "41SKU", "38SPB", "40RCV", "38SPC", "39SUA", "40SCE", "39RVP", "41RLJ", "40REP", "39RXL", "39RWM", "41RKK", "41RKJ", "40RFP", "39RYK", "39RTP", "40RBQ", "40RCR", "40RBR", "40RFR", "39RYL", "40REQ", "41RKL", "40RFQ", "41SKS", "41RLK", "41RKR", "41RKQ", "40RGA", "40RDU", "41RLM", "39RXM", "41RKP", "40RCQ", "41SKT", "40RGQ", "41RLL", "39RYM", "39RVN", "39RWQ", "38SPE", "40REV", "40RBV", "40SDB", "38SNE", "40RGS", "39SVS", "39RYQ", "40SDF", "39SVU", "38SNG", "40REA", "41RLQ", "40SBC", "40SBA"], "IT": ["33SVB"], "JO": ["37SBR", "37RBN", "37RBQ", "36RYU", "37RBP"], "KE": ["37NDC", "36MZC", "37NGF", "37MDT", "37MET", "37NFA", "37MBV", "37MFV", "37MCT", "37NDB", "37NBB", "37MEV", "36MYD", "37MER", "37NFF", "37NBD", "37NCB", "37NFB", "36MYE", "37NAB", "37MGU", "37MCV", "37NBC", "37NCD", "37MFT", "37NCC", "37MDV", "37MGT", "37MDS", "37MDU", "36NYH", "36NXF", "37MBT", "37MEU", "37NGB", "36NYJ", "37MCU", "38NJK", "37NHE", "37NDD", "37NDA"], "KW": ["38RQS"], "LB": ["37SBU", "36SYC"], "LR": ["29NNG", "29NLJ", "29PMK", "29NMH", "29NPF", "29NNF", "29NMF"], "LS": ["35JPG", "35JNG", "35JPH"], "LY": ["34RGP", "34SEB", "34RCP", "33RWJ", "35RKN", "34RFN", "33RXQ", "33RUQ", "34RFT", "34RFP", "33RYM", "33RWK", "35RKH", "34QFL", "35RLH", "32RQP", "32QNK", "32QML", "32RPQ", "35QLC", "33RVP", "33RXJ", "33RTK", "33RVH", "33QUE", "33RVM", "34QFK", "33QTF", "33RYL", "33RWH", "32QQL", "34RBU", "32RPT", "33RYJ", "33RUG", "33STR", "32RMS", "34RES", "32RNM", "34SEA", "34RFA", "33RTH", "34RGT", "33QXG", "34RGQ", "33RXN", "34RCT", "34RCQ", "35RKR", "34SDA", "35RLP", "34QEJ", "34RBP", "34REU", "33RUR", "34RBR", "33RXK", "33RUK", "33RVJ", "33RUN", "33RTM", "33RYP", "34RER", "32QNM", "33QVF", "34RCR", "33QTG", "34RDT", "35QMF", "34QGK", "34REV", "35QKC", "34QEM", "34RET", "34RDV", "33RTR", "33RYK", "34RFV", "34REA", "34RGU", "32RQR", "33SVR", "32RNT", "32RMT", "33RTQ", "34RDS", "34RDU", "33RWM", "35QLF", "34RDP", "32RQM", "34RDM", "34RFQ", "34QGL", "35QKE", "33RVN", "32RPR", "33RWN", "33RVK", "34RBQ", "34RGS", "32RMV", "33RYN", "34REN", "32RNS", "32RNU", "35QKF", "33RTJ", "34RCS", "34RGR", "34RFU", "32RQS", "33RTL", "32RQV", "32RPV", "33RVQ", "33RWQ", "34SFA", "33RUJ", "32QNL", "34SCA", "35QLE", "32RPN", "35RKM", "32RQT", "32RQQ", "32RLV"], "MA": ["29RPP", "29SPS", "30SVC", "30STC", "29RMQ", "30RTR", "30SUC", "29RQQ", "29RLH", "30STD", "29RNN", "29SQU", "30RVR", "30RUQ", "29RKG", "30RVS", "30SUB", "30RYV", "30RUS", "30SUD", "29RNR", "30RTT", "29RPM", "29RPN", "29RMN", "29RMG", "29SNS", "30SXC", "30STE", "29SMR", "29SPR", "28REN", "30SWC", "30RVT", "30SUA", "29RPQ", "29RNP", "30SXA", "29RLM", "29RNQ", "30SVD", "29RNM", "28RFM", "28QFM", "29RMM", "28RFN", "30STB", "30SVA", "29RPR", "30RXV", "30SVB", "30RUU"], "MG": ["38KQF", "39LTE", "38JMU", "38KNV", "38KPE", "38KLA", "38KMD", "38KME", "38KNA", "38KNF", "39KTC", "39LTG", "38KMB", "38KNG", "39LUF", "38KQA", "38KRE", "38KQC", "39LTD", "38KMA", "39LVC", "38LQH", "39KTV", "38KQV", "38KPF", "38JNT", "38KQG", "38KQB", "39LTC", "39KTT", "39LUE", "38KNB", "38KPC", "38KMG", "38KRG", "38KNC", "38KMF", "39KTU", "38KLB", "39LUD", "38KPA"], "ML": ["29PPN", "31QAA", "31QCT", "31PBT", "30QWL", "29QQD", "30PUV", "29QPE", "30QYL", "30QUK", "31QAC", "30PVA", "31QDD", "30QWF", "29PLQ", "31QDE", "30QXD", "30QTL", "29PQM", "29PQS", "30QXC", "30QTK", "29PPP", "30QUG", "30RWN", "30QXK", "30PUB", "31QEB", "30QXL", "30QVD", "30QYE", "29PNP", "31QDU", "31QCV", "29PLP", "30QWJ", "30QXJ", "30QVE", "31QDB", "31QFA", "30QTH", "29QQC", "30QUF", "31QCE", "31QCU", "30PTB", "29PMP", "29PQN", "30QUD", "29PPR", "31QEV", "31QFB", "29PKR", "30QYD", "29PNN", "30QYK", "30RUP", "31PDT", "30PST", "31QBU", "30QTM", "30QZJ", "30QVL", "31QBC", "30QWG", "29PMR", "30QUL", "30QVF", "30PVV", "31QCF", "31QEA", "29QPD", "29PQR", "30QUE", "29PKQ", "30QWC", "31QEC", "30QXG", "30QVH", "30RTN", "30PTV", "30QTD", "30PSU", "30QWH", "29PRQ", "30RWM", "31PET", "31PDS", "30QSH"], "MR": ["29QLA", "29QMC", "29QNB", "29QLG", "29QPC", "29QKB", "29QME", "29QNC", "29QLF", "28QGK", "29QPB", "29QLE", "29QNE", "29QND", "29QKG", "29QNG", "28QGJ", "29QPA", "28QGD", "29QQB", "29QLC", "29QNV", "28QEF", "28QEG", "30QTE", "28QEJ", "28QFM", "28QDJ", "28QFH", "29QLV", "28QEL", "28QEH", "28QFG", "28QCK", "28QEK", "28QFF", "28QGH", "28QFL", "29QMB", "29QQV", "29QKE", "28QGG"], "MU": ["40KEC"], "MW": ["37LBC", "36KYG", "36LWJ", "36LXN", "36LXL", "36KYH", "36KXF", "36LYH", "36LXK", "36KYF", "37KAC", "36LWQ"], "MZ": ["37LAD", "37LDD", "36KXB", "36KXV", "37KEB", "36KWD", "36KXA", "37LBD", "37LCC", "37KCB", "36KYU", "36KYA", "36KWA", "36KZE", "37LED", "36JVS", "37LDF", "37LDE", "36KYE", "36KWV", "36KVU", "37LEF", "36KXC", "36KWF", "37LCF", "37KCA", "36KXE", "37KDB", "37LBF", "36JWT", "37LFF", "37LDG", "37KCC", "36LWH", "36JVT", "37LCD", "36KWG", "36JXT", "36JVR", "37LFH", "37LBE", "37LFE", "37KBA", "36KXD"], "NA": ["34JCT", "34KDV", "34KCE", "33JYP", "34KDA", "33JXN", "33KYU", "33KWA", "33KTV", "33JYK", "33JWN", "34KDU", "33KYP", "33KYA", "33KXB", "33KZV", "34JCR", "33KZS", "33JXL", "34JCQ", "33KTB", "34KFG", "33KZB", "33KYR", "34JDS", "34KDF", "34KBC", "34KEF", "33KWT", "34JBQ", "33JVM", "34KAD", "33JXJ", "34JBT", "34KCU", "34KBG", "33KWS", "33KWV", "33KXT", "33KVS", "33JYL", "33KYQ", "33KWU", "33KVU", "33KVV", "34KBV", "33KYV", "33KTA", "34KDD", "33KUU", "33KXQ", "33JWK", "34KCD", "34KCC", "33KXA", "33KXS", "34KCG", "33KXV", "33JYN", "33KUV", "33KYS", "33JXM", "34JDT", "33KWQ", "33KXP", "33JWL", "34KDC", "34KCF", "34KBA", "33KUA"], "NE": ["32PKA", "31PES", "32QNG", "31PDR", "32QKH", "33QVB", "32QPF", "32QPH", "33QUA", "33QWU", "32QLJ", "31PER", "33QWB", "32QPC", "33PTQ", "32PLA", "32QMH", "32QMK", "31PGR", "33QTA", "33QVV", "32PMA", "32QJC", "32PKC", "31PEQ", "32QQE", "31PBS", "33PST", "32PKB", "32QRD", "32QNH", "31PBR", "33QSC", "32PNA", "32QMJ", "33PTR", "32QLF", "31QHV", "31QHA", "31PHR", "31PDS", "32PJA", "32PRA", "33PVS", "32QNJ", "31PCR", "32PMV", "33PUT", "32PMB", "33QSA", "32QQH", "31QFU", "32QPE", "33QUU"], "NG": ["33PUR", "31PHN", "32NKP", "32PLQ", "32PLP", "32PNS", "32NML", "33PTN", "31PFK", "32PNP", "32PLV", "31PEK", "32NQN", "32PKS", "32PNU", "33PUQ", "31PGQ", "32PKT", "32PPT", "31NEJ", "31PFL", "31NFJ", "31PEQ", "31NFH", "33PUP", "32PKQ", "32PQS", "32PPR", "33PTM", "31PGP", "32NLN", "32PPV", "33PTL", "31PHM", "31PFN", "32NLP", "32PPP", "32NNP", "32NMM", "32PNT", "32PLT", "32PQU", "31PHL", "32PPQ", "32PMT", "31NDH", "33PSQ", "32PMV", "33PTP", "32NKM", "31NGH", "32PLS", "33PUM", "31PGR", "32NQP", "32PQR", "32NJM", "32NJN", "31PFM", "31NGG", "32NLL", "31PFQ", "31PGL"], "OM": ["40QDH", "40QCK", "40QCL", "40QBF", "40QGL", "40QCH", "40QFJ", "40QBG", "40QBD", "40QGK", "40QEM", "40QFL", "40QEK", "40RCM", "40QBE", "40QDF", "39QZU", "40QFM", "39QYU", "40QEL", "40RDM", "40QDL", "40QAD", "40RCN", "40QEG", "40QCM", "40QAE", "40QFK", "40QDM", "40QCG", "40QDK", "40QBJ", "40QCJ", "40QBH"], "PK": ["42RVV", "43SEV", "43SEA", "42RUV", "43RBP", "42SYE", "42SXA", "42SYD", "42RUR", "42RXV", "43SCU", "43SDA", "43SDV", "42SYC", "43RDQ", "41RNK", "42RTN", "42RTS", "42RXN", "41RQM", "42RTP", "42RXR", "41RPN", "43RBR", "42RWS", "42SXB", "42RTT", "41RNM", "41RNJ", "41RPK", "42SYB", "41RMJ", "42RWT", "41RQN", "42RWN", "42RUP", "42RUU", "42RYA", "41RNH", "42RXM", "41RPL", "41RQL", "42RVR", "42RXA", "43RCP", "42RYS", "41RPM", "42RUS", "41RNN", "42RVT", "42SYA", "42RWM", "42RXS", "42RVM", "42RUQ", "41RQJ", "43SBV", "43RBQ", "43SEU"], "PS": ["36SYA"], "PT": ["28SCB"], "QA": ["39QVG", "39RWH"], "RW": ["36MSC", "35MQU", "35MQT", "35MRT", "35MRU", "36MSD", "36MTC", "36MTD"], "SA": ["39RTG", "38RQP", "38RNR", "38QNG", "38QNK", "37RCM", "38RPP", "38QKK", "38RPN", "38QLL", "39RUG", "38RQQ", "38QQJ", "37REH", "38QMK", "38RKV", "39RTH", "37RDQ", "37REM", "37REN", "38QMF", "39RTJ", "37RFP", "38RKU", "39QTD", "37RCR", "38QQK", "38QPG", "38QPF", "37REP", "37RCP", "37RCL", "38RNS", "37REQ", "37QGD", "37RCN", "38QLF", "37QGF", "38QNF", "37RBQ", "37QGE", "39QUD", "37QGB", "38QJE", "38QKE", "37QGC", "37QGA", "38QME", "38RMP", "37RCJ", "38RLQ", "37QEF", "38RMN", "37RDG", "37QFC", "37QED", "37QDG", "37RCK", "38RKR", "37RCH", "37QFD", "37RDK", "38RMQ", "37RGM", "38RQR", "38RLP", "39RUJ", "37QFB", "38QNH", "37RBK", "37RDH", "37QDF", "39RTL", "39RUK", "37QEC", "39RTK", "37REG", "38RKS", "37QEE", "38RPR", "37RDJ", "37RDP", "37RCG", "38RLR", "37RFL", "38QPL", "38QMG", "37RFH", "38RKN", "37RGJ", "38RKP", "38RLN", "38RJP", "37QEG", "38RKM", "37RFG", "38QKH", "37RFJ", "38RLM", "38QKG", "37RGH", "38QKL", "39QTE", "39QUG", "37SGR", "37RER", "38RPQ", "39QUE", "39QUF", "38RQN", "38QMJ"], "SD": ["36PSS", "35QQA", "36PVS", "35PJQ", "36PVT", "35QPU", "35PKQ", "34PHB", "36PYC", "34PFU", "35QNV", "36QTF", "35QQC", "37QBU", "37QCU", "36PUB", "35PKT", "35QQV", "36PWT", "35PMM", "34PGA", "36PZU", "35QMC", "35PLS", "36QUH", "36PYT", "35PQM", "35PLT", "36QXK", "36PYV", "35PPN", "35PNT", "36QXH", "35PKS", "36QYH", "35PKR", "35PNR", "34PHT", "35QMT", "35QND", "35QPA", "35QLC", "36PYB", "36QXG", "35QQD", "36QXD", "35QNE", "35QRV", "36QXF", "37QDV", "37QBD", "37QDA", "36QXE", "37QCA", "36QZK", "37QBA", "37QAD", "37QBE", "37QAE", "36QVF", "36QYL", "37QCB", "36QYF", "37QAA", "36QZJ", "36QYD", "36QZF", "36QUD", "36QVD", "36QWD", "36QUG", "36PWS", "35QPB", "35PKN", "36QVE", "36QYK", "36QUE", "36QVG", "37QAC", "36QWF", "36QYE", "36QWE", "35PPS", "36PXA", "35QQU", "35QQB", "35QLU", "36QYJ", "35QPV", "35PQQ", "35PRN", "35PLQ"], "SH": ["28HGD"], "SL": ["29PJL", "28PGR", "29PJK", "29NLJ", "29PLK", "29PKM", "28PGQ", "29PLL"], "SN": ["28PCB", "28PEV", "28PFA", "28QCD", "28PDV", "28PEA", "28PEB", "28QFD", "28PCU", "29PKP", "28PGA", "28PDB", "28QGC", "28QED", "28PGV"], "SO": ["37MGU", "39NSF", "38NLK", "39PVN", "38NQM", "38NLJ", "38NNJ", "38PMP", "38NKG", "38NMM", "38PQP", "38NMP", "37NGA", "38NLG", "38NLL", "39PWM", "38PNQ", "38PMQ", "38NLF", "37MGV", "38NKH", "39NTG", "38NNM", "38NKJ", "38NJG", "39PSK", "38PLR", "38NPP", "39NUJ", "38NKL", "38NNN", "38NPM", "39PUM", "39PWN", "38PLS", "39PTM", "39PTK", "38PKS", "39PVM", "38PPS", "38PMR", "39NTJ", "38PNS", "38NPN", "38PMS", "38NLM", "38NMN", "39PUK", "38NNP", "38NQN", "39PSM", "38PNR", "38PLP", "38NPJ", "38NLP", "39PTL", "38PLQ", "39PSL", "38NKN", "38NLH", "38NNK", "39NTH", "38NKM"], "SS": ["35NKJ", "36PVS", "35PLK", "36NTN", "35PNL", "36NXM", "35NNF", "35NQJ", "35PKL", "36NUN", "36NTK", "36NVL", "36NUP", "35NRG", "35NNJ", "35NRF", "35NQE", "36NTL", "36NWM", "36NTP", "35NQG", "35PNK", "35PML", "36NVM", "36PSP", "36PUQ", "36PVQ", "36NXL", "36PTQ", "35NMJ", "35PQM", "35NQF", "35PLL", "35NNH", "36NVP", "35NLJ", "35NLH", "35PQK", "36PVR", "36NUM"], "SY": ["37SBS", "36SYE", "37SGA", "37SDV", "37SDA", "37SBV", "37SDU", "37SDS", "37SCU", "37SEU", "37SDT", "37SCT", "37SCA", "37SBT", "38SKF", "37SCS", "36SYB", "37SFA"], "SZ": ["36JVR", "36JUR"], "TD": ["33QYU", "34QCJ", "33PXT", "34QCG", "33QYC", "34QDG", "34PDV", "34QBE", "34PCA", "34QBK", "34QBD", "34PBB", "33PVL", "33PWL", "33QYD", "34QBJ", "34QGE", "34QEG", "34QHD", "33QYV", "33PWT", "33QXV", "35QKA", "34QCD", "34QCM", "34QBL", "33QVT", "33QYG", "34QBC", "34PBQ", "34PES", "35QMV", "34PCR", "34QCK", "33PWN", "34PBR", "33PZN", "33PYM", "34QBH", "33PYN", "34PBS", "34QGH", "34QBG", "34QCE", "34PGB", "34QBF", "35QKB", "34QDF", "33QYF", "33QXF", "35QKU", "34QGG", "33QWC", "33NYJ", "34QGF", "34QDL", "34QDH", "33QXE", "35QLB", "33PWK", "34QDK", "34QHF", "34QFF", "33QXU", "34QDJ", "34QEE", "34QFE", "34RBP", "33PYJ", "34RCN", "34QFH", "33PXQ", "34PDC", "33QYB", "34PET", "33PYK", "34QEH", "33QXC", "35QMA", "33QXD", "33QWU", "33QWB", "34PDT", "33NWJ", "33QYA", "33QWD", "33QYE"], "TG": ["31NCJ", "31NBJ", "31PCJ"], "TJ": ["42SVG", "43SCB"], "TM": ["41SKB", "40SFG", "41SLB"], "TN": ["32SME", "32SMC", "32SNB", "32SPF", "32SNC", "32SNE", "32SND", "32SNF", "32SMD", "32SPB", "32SPE"], "TR": ["38SKG", "36SUF", "37SBA", "36SWF", "36SXF", "38SLG", "36STG", "36SXG", "37SEA", "37SGB", "35SNB", "35SQA", "35SQB", "37SFB"], "TZ": ["36LUS", "35MRM", "37LCL", "36MWT", "37MAQ", "36MTT", "37MBR", "36LYN", "36MXV", "36MZU", "36MVU", "36MTA", "36LWR", "37LDJ", "36MWS", "36MYV", "36MTC", "36MWV", "36MYS", "36MTV", "36MTU", "37LDK", "36MYB", "36MXA", "37LCK", "36MUC", "37MAR", "37MDM", "36MVA", "36LXR", "35MPQ", "36LXQ", "36MWU", "36MSA", "36MWA", "36MXB", "36LWQ", "36MXT", "36MSV", "37LEL", "37MCQ", "36MVB", "36LYQ", "37LBL", "37MDN", "37MCS", "36LYM", "36MYA", "37MCM", "37LAK", "37MBS", "36LUR", "36MWB", "36MUU", "36LZP", "36MVC", "36MYT", "37MCR", "37LEM", "37MEM", "37LAH", "37MCP", "36MTS", "37MEN", "36MVV", "36LZQ", "36LYP", "36MXS", "37LDM", "36MUS", "37MBP", "36MYU", "36MVT", "36MUA", "37LEH", "37LCH", "36MUV", "36MTB", "36MTD"], "UG": ["36NUH", "36NWK", "36NUF", "36NYH", "36NWG", "35NRA", "36NXK", "36MTE", "36NTH", "36NVG", "36NWH", "35MQV", "36NSF", "36NTJ", "36NUJ", "36NVJ", "36NTF", "36NVH", "36MSE", "36NZH", "36NXG", "36NXH", "36NXJ", "36NYK", "36MVE", "36MSD", "35MQU", "35MRU", "36MTD"], "YE": ["39QTA", "38QQE", "38QQG", "39QXA", "39PVS", "39PWS", "39QZB", "39QUC", "38PLA", "38QND", "39QXC", "38PMA", "39QUD", "39QVA", "39QVD", "39PWT", "39QYB", "39QVC", "39QWA", "38QQD", "38PNA", "39QWC", "39QYV", "39QUB", "39PVT", "38PMB", "38PNC", "38PLB", "38PKC", "38QMC", "38PMV", "38PMC", "38PKB", "39QYU", "38PNB", "38PRC", "38QKC", "38PNV", "39QTC", "39QXV", "38PPB", "38PPA", "38PPV", "39QYA"], "ZA": ["35JMG", "34HDH", "35JPE", "35JKE", "36JTP", "35JNL", "36JUQ", "35JLG", "36KVV", "35JNP", "35HKD", "34HCK", "36JVQ", "34HDJ", "34JGM", "36JUU", "36JTT", "34JFP", "36KTV", "35JPF", "33JYF", "35JNK", "36JUT", "35JQK", "34JCM", "34JGR", "35JQL", "35JML", "35JQH", "35JQJ", "34JBL", "35HNE", "35JPK", "36JTR", "35JME", "35JPM", "34HBH", "36KUV", "34JFM", "35JQG", "35JKH", "35JLK", "34JDL", "35JQN", "35JNF", "34JBM", "35JMH", "35KQQ", "34HBJ", "35JKL", "34HGJ", "35JLL", "35JKK", "35HMD", "35JLJ", "36JTS", "35JPL", "36KTU", "34JEL", "35HLD", "36JUP", "35JNJ", "34JEQ", "34JGN", "34JGK", "34JFK", "36JTM", "34JFQ", "36JUN", "35JNE", "35JKG", "34JBN", "36JTQ", "34JCK", "34JGP", "34HEJ", "35JMK", "34JEK"], "ZM": ["35LMF", "35LQJ", "35LKF", "35LND", "36LTQ", "36LTP", "36LVM", "36LUM", "35LMG", "35LKC", "36LUP", "35LNC", "34LEK", "35LQH", "36LVJ", "35LME", "34LGM", "36LTR", "35KKC", "35KPB", "34LGL", "36LTJ", "35KNA", "35LKE", "35LLD", "35LNK", "35LJE", "34LGH", "34LFH", "36LTN", "34LDJ", "35LJH", "35LLG", "36LVP", "35KMB", "35LPF", "35LMD", "35LQF", "35LPD", "35KNB", "34LDH", "35LNF", "35MQM", "34LDK", "35LJF", "36LVK", "35KKB", "36KSH", "36LUN", "35LPK", "34LEJ", "36LWN", "36LUJ", "35LLC", "35LMC", "35LQD", "35MPM", "35KMA", "35LJJ", "35LKG", "35LNG", "35LPE", "34LGJ", "36LSP", "35LQE"], "ZW": ["36KVA", "36KSC", "35KQS", "36KUE", "36KUA", "35KQB", "36KVE", "35KNV", "35KQA", "35KPT", "35KQT", "36KVC", "36KTF", "36KUD", "35KQC", "35LQC", "36KTG", "36KTB", "35KRU", "36KWC", "35KMV", "36LVH", "35KRA", "35KNT"]} diff --git a/instageo/apps/viz.py b/instageo/apps/viz.py index 53eda88..bdf9f0e 100644 --- a/instageo/apps/viz.py +++ b/instageo/apps/viz.py @@ -68,7 +68,6 @@ def add_raster_to_plotly_figure( # Reproject to EPSG:3857 CRS xarr_dataset = xarr_dataset.rio.write_crs(from_crs).rio.reproject("EPSG:3857") xarr_dataset = xarr_dataset.where(xarr_dataset <= 1, 0) - xarr_dataset = xarr_dataset.where(xarr_dataset > 0.8, 0) # Get Raster dimension and range numpy_data = xarr_dataset[column_name].squeeze().to_numpy() plot_height, plot_width = numpy_data.shape @@ -153,7 +152,7 @@ def create_map_with_geotiff_tiles(tiles_to_overlay: list[str]) -> go.Figure: if tile.endswith(".tif") or tile.endswith(".tiff"): xarr_dataset, crs = read_geotiff_to_xarray(tile) img, coordinates = add_raster_to_plotly_figure( - xarr_dataset, crs, "band_data", scale=0.1 + xarr_dataset, crs, "band_data", scale=1.0 ) mapbox_layers.append( {"sourcetype": "image", "source": img, "coordinates": coordinates} diff --git a/notebooks/InstaGeo_Demo.ipynb b/notebooks/InstaGeo_Demo.ipynb index 2e96341..394f144 100644 --- a/notebooks/InstaGeo_Demo.ipynb +++ b/notebooks/InstaGeo_Demo.ipynb @@ -1,518 +1,886 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "4574f053-60d4-419b-88cc-c58d08a8177c", - "metadata": {}, - "source": [ - "# InstaGeo Demo" - ] - }, - { - "cell_type": "markdown", - "id": "7eee5ac3", - "metadata": {}, - "source": [ - "\"Open" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4fc7ff9c", - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "4fc7ff9c", - "outputId": "bb888e31-f3c5-4497-da9b-71853ca7dfff", - "tags": [] - }, - "outputs": [], - "source": [ - "from getpass import getpass\n", - "import os" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e550a300", - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "e550a300", - "outputId": "57a02930-a586-4b28-dc98-dab26bbcd87c", - "tags": [] - }, - "outputs": [], - "source": [ - "repository_url = \"https://github.com/instadeepai/InstaGeo-E2E-Geospatial-ML\"\n", - "\n", - "!git clone {repository_url}" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9f7e762b", - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "collapsed": true, - "id": "9f7e762b", - "jupyter": { - "outputs_hidden": true - }, - "outputId": "c9bf104b-9352-4254-8622-5894f8283744", - "tags": [] - }, - "outputs": [], - "source": [ - "%%bash\n", - "cd InstaGeo-E2E-Geospatial-ML\n", - "pip install -e .[all]" - ] - }, - { - "cell_type": "markdown", - "id": "238c78e7-720e-49ed-b5ce-6be6567d2585", - "metadata": {}, - "source": [ - "## EarthData Login" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8b7a5f61", - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "8b7a5f61", - "outputId": "1d9437c6-01f1-4680-caa6-f21302bc02f0" - }, - "outputs": [], - "source": [ - "# Create an EarthData user account on https://urs.earthdata.nasa.gov/\n", - "USERNAME = getpass('Enter your EarthDAata username: ')\n", - "PASSWORD = getpass('Enter your EarthDAata password: ')\n", - "\n", - "content = f\"\"\"machine urs.earthdata.nasa.gov login {USERNAME} password {PASSWORD}\"\"\"\n", - "\n", - "with open(os.path.expanduser('~/.netrc'), 'w') as file:\n", - " file.write(content)" - ] - }, - { - "cell_type": "markdown", - "id": "488a15d3-f22e-4b2c-85c0-435c832e708c", - "metadata": {}, - "source": [ - "## InstaGeo - Data\n", - "\n", - "- Searches and retrieves HLS metadata. \n", - "- Downloads the required bands from HLS granules\n", - "- Creates Chips and Target" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c11bfeb8-df6b-4b8c-8c8a-059a5a28b8ea", - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "c11bfeb8-df6b-4b8c-8c8a-059a5a28b8ea", - "outputId": "2636c9ce-912a-4c36-f9c3-6fb7d15f8beb", - "tags": [] - }, - "outputs": [], - "source": [ - "%%bash\n", - "mkdir demo\n", - "python -m \"instageo.data.chip_creator\" \\\n", - " --dataframe_path=\"InstaGeo-E2E-Geospatial-ML/tests/data/test_breeding_data.csv\" \\\n", - " --output_directory=\"demo\" \\\n", - " --min_count=4 \\\n", - " --chip_size=224 \\\n", - " --no_data_value=-1 \\\n", - " --temporal_tolerance=3 \\\n", - " --temporal_step=30 \\\n", - " --mask_cloud=False \\\n", - " --num_steps=3" - ] - }, - { - "cell_type": "markdown", - "id": "bcb132b0-04dd-4583-8e30-e6332446a0e6", - "metadata": {}, - "source": [ - "## InstaGeo - Model" - ] - }, - { - "cell_type": "markdown", - "id": "fd313044-829c-482d-934e-9ae662f132fc", - "metadata": {}, - "source": [ - "Create a dataframe for created chips and target that will be used with model component" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c64fee29-dca3-4611-a43a-4412a6033751", - "metadata": { - "id": "c64fee29-dca3-4611-a43a-4412a6033751" - }, - "outputs": [], - "source": [ - "import os\n", - "import os\n", - "import pandas as pd\n", - "import numpy as np\n", - "from pathlib import Path" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3b11cb3a-1940-4056-a6a7-33baa375bddb", - "metadata": { - "id": "3b11cb3a-1940-4056-a6a7-33baa375bddb" - }, - "outputs": [], - "source": [ - "root_dir = Path.cwd()\n", - "chips_orig = os.listdir(os.path.join(root_dir, \"demo/chips\"))\n", - "chips = [chip.replace(\"chip\", \"chips/chip\") for chip in chips_orig]\n", - "seg_maps = [chip.replace(\"chip\", \"seg_maps/seg_map\") for chip in chips_orig]\n", - "\n", - "df = pd.DataFrame({\"Input\": chips, \"Label\": seg_maps})\n", - "df.to_csv(os.path.join(root_dir, \"demo/demo_train.csv\"))\n", - "df.to_csv(os.path.join(root_dir, \"demo/demo_val.csv\"))" - ] - }, - { - "cell_type": "markdown", - "id": "6778e394-43ef-42ee-ae24-e00122e86d10", - "metadata": {}, - "source": [ - "Launch training" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "47dc76c1-26b9-47b9-8066-5c1df499b40f", - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "collapsed": true, - "id": "47dc76c1-26b9-47b9-8066-5c1df499b40f", - "jupyter": { - "outputs_hidden": true - }, - "outputId": "72e8f6e4-0263-431a-c313-47df5b0cbded", - "tags": [] - }, - "outputs": [], - "source": [ - "# %%bash\n", - "!python -m instageo.model.run --config-name=locust \\\n", - " root_dir='demo' \\\n", - " train.batch_size=8 \\\n", - " train.num_epochs=3 \\\n", - " train_filepath=\"demo/demo_train.csv\" \\\n", - " valid_filepath=\"demo/demo_val.csv\"" - ] - }, - { - "cell_type": "markdown", - "id": "a8a98a64-0962-40e5-a52e-1e8687198862", - "metadata": { - "tags": [] - }, - "source": [ - "Run Model Evaluation" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f8230588-2842-460c-b2e7-4f2f4175dc3e", - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "collapsed": true, - "id": "f8230588-2842-460c-b2e7-4f2f4175dc3e", - "jupyter": { - "outputs_hidden": true - }, - "outputId": "94515cc4-972a-4e15-d3fe-1dc28200f848", - "tags": [] - }, - "outputs": [], - "source": [ - "# %%bash\n", - "!python -m instageo.model.run --config-name=locust \\\n", - " root_dir='demo' \\\n", - " test_filepath=\"demo/demo_val.csv\" \\\n", - " train.batch_size=8 \\\n", - " checkpoint_path='add-checkpoint-path' \\\n", - " mode=eval" - ] - }, - { - "cell_type": "markdown", - "id": "b9a73d79-f69f-4fb8-aa63-768ee3ee47ea", - "metadata": {}, - "source": [ - "**Run Inference**\n", - "\n", - "- Runs inference on the Africa continent (plus some part of Asia)\n", - "- Downloads and run inference on 2,120 HLS tiles" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "YgxyC5GnvjJU", - "metadata": { - "collapsed": true, - "id": "YgxyC5GnvjJU", - "jupyter": { - "outputs_hidden": true - }, - "tags": [] - }, - "outputs": [], - "source": [ - "!gsutil -m cp -r gs://instageo/checkpoints/locust_breeding_ckpt .\n", - "!gsutil cp gs://instageo/utils/africa_prediction_template.csv .\n", - "!mkdir -p inference/2023-01" - ] - }, - { - "cell_type": "markdown", - "id": "9c30afd0-73ec-4eb1-b9c1-a2d36475eae7", - "metadata": {}, - "source": [ - "**Create Inference Data**\n", - "\n", - "During inference we only download HLS tiles and irectly runinference on them using the sliding window inference feature." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8f76b3ea-8ef7-473b-8f2e-72d493fdba03", - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "collapsed": true, - "id": "8f76b3ea-8ef7-473b-8f2e-72d493fdba03", - "jupyter": { - "outputs_hidden": true - }, - "outputId": "f623f2a0-77b2-46c8-aa5a-586452c84c9f", - "tags": [] - }, - "outputs": [], - "source": [ - "!python -m \"instageo.data.chip_creator\" \\\n", - " --dataframe_path=\"africa_prediction_template.csv\" \\\n", - " --output_directory=\"inference/2023-01\" \\\n", - " --min_count=1 \\\n", - " --no_data_value=-1 \\\n", - " --temporal_tolerance=3 \\\n", - " --temporal_step=30 \\\n", - " --num_steps=3 \\\n", - " --download_only" - ] - }, - { - "cell_type": "markdown", - "id": "65e86341-0717-458f-b061-3e957ce8536d", - "metadata": {}, - "source": [ - "**Run Inference**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "JJXq8oWNAr1w", - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "JJXq8oWNAr1w", - "outputId": "74f43e30-f642-4eb2-ca6f-64f9343a275c", - "tags": [] - }, - "outputs": [], - "source": [ - "!python -m instageo.model.run --config-name=locust \\\n", - " root_dir='inference/2023-01' \\\n", - " test_filepath='hls_dataset.json' \\\n", - " train.batch_size=16 \\\n", - " test.mask_cloud=True \\\n", - " checkpoint_path='add-checkpoint-path' \\\n", - " mode=predict" - ] - }, - { - "cell_type": "markdown", - "id": "8d79e412-8176-411a-8a73-6068e22a0d25", - "metadata": {}, - "source": [ - "## InstaGeo - Apps\n", - "\n", - "Visualize predictions my moving HLS prediction GeoTiff files to an appropriate directory." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8a904882-cde9-40c8-affb-f988892e5183", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "!mkdir -p predictions/2023/1\n", - "!mv inference/2023-01/predictions/* content/predictions/2023/1" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "tQGnk67MY6Cd", - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "tQGnk67MY6Cd", - "outputId": "8b7a5935-7817-40f3-97d6-94a0ea2f69ef", - "tags": [] - }, - "outputs": [], - "source": [ - "!npm install localtunnel" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "BeJsQzkeBNm7", - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "collapsed": true, - "id": "BeJsQzkeBNm7", - "jupyter": { - "outputs_hidden": true - }, - "outputId": "d4488061-d390-4c9e-c10c-bdd4c0222f93", - "tags": [] - }, - "outputs": [], - "source": [ - "!nohup streamlit run InstaGeo/instageo/apps/app.py --server.address=localhost &" - ] - }, - { - "cell_type": "markdown", - "id": "48459844-9277-473b-8cd8-e47691c59c0a", - "metadata": {}, - "source": [ - "Retrieve your IP address which is the password of the localtunnel" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "S5rCS-lVZiWe", - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "S5rCS-lVZiWe", - "outputId": "cbd68bed-b165-4fd3-8c87-14a5dcad4dbc", - "tags": [] - }, - "outputs": [], - "source": [ - "import urllib\n", - "print(\"Password/Enpoint IP for localtunnel is:\",urllib.request.urlopen('https://ipv4.icanhazip.com').read().decode('utf8').strip(\"\\n\"))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "bB61RRBNY-48", - "metadata": { + "cells": [ + { + "cell_type": "markdown", + "id": "4574f053-60d4-419b-88cc-c58d08a8177c", + "metadata": { + "id": "4574f053-60d4-419b-88cc-c58d08a8177c" + }, + "source": [ + "# InstaGeo Demo\n", + "\n", + "\"Open\n", + "\n", + "Welcome to the InstaGeo demo notebook! This tutorial showcases the capabilities of InstaGeo, an end-to-end package designed for geospatial machine learning with multispectral data.\n", + "\n", + "In this demonstration, we use ground truth geospatial point observations for cropland classification in Rwanda. The notebook will guide you through the process of creating segmentation-like data from these observations, fine-tuning the [Prithvi](https://huggingface.co/ibm-nasa-geospatial/Prithvi-100M) model, and finally visualizing the inference results on an interactive map.\n", + "\n", + "By the end of this demo, you will gain hands-on experience with key InstaGeo functionalities and learn how it streamlines geospatial ML workflows from data preparation to model inference." + ] + }, + { + "cell_type": "markdown", + "id": "380ead2a", + "metadata": {}, + "source": [ + "# Install InstaGeo" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e550a300", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "e550a300", + "outputId": "3cbc267b-6c02-4539-fd64-c7b386bc1156", + "tags": [] + }, + "outputs": [], + "source": [ + "repository_url = \"https://github.com/instadeepai/InstaGeo-E2E-Geospatial-ML\"\n", + "\n", + "!git clone {repository_url}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9f7e762b", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "collapsed": true, + "id": "9f7e762b", + "jupyter": { + "outputs_hidden": true + }, + "outputId": "4372ac59-3158-48dc-f321-fa2a24ee9255", + "tags": [] + }, + "outputs": [], + "source": [ + "%%bash\n", + "cd InstaGeo-E2E-Geospatial-ML\n", + "pip install -e .[all]" + ] + }, + { + "cell_type": "markdown", + "id": "238c78e7-720e-49ed-b5ce-6be6567d2585", + "metadata": { + "id": "238c78e7-720e-49ed-b5ce-6be6567d2585" + }, + "source": [ + "## EarthData Login\n", + "\n", + "InstaGeo currently supports multispectral data from NASA [Harmonized Landsat and Sentinel-2 (HLS)](https://hls.gsfc.nasa.gov/). Accessing HLS data requires an EarthData user account which can be created [here](https://urs.earthdata.nasa.gov/)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4fc7ff9c", + "metadata": { + "id": "4fc7ff9c", + "tags": [] + }, + "outputs": [], + "source": [ + "from getpass import getpass\n", + "import os" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8b7a5f61", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "8b7a5f61", + "outputId": "78a1c750-3a23-4c0a-f45e-94388625fb8b" + }, + "outputs": [], + "source": [ + "# Enter you EarthData user account credentials\n", + "USERNAME = getpass('Enter your EarthData username: ')\n", + "PASSWORD = getpass('Enter your EarthData password: ')\n", + "\n", + "content = f\"\"\"machine urs.earthdata.nasa.gov login {USERNAME} password {PASSWORD}\"\"\"\n", + "\n", + "with open(os.path.expanduser('~/.netrc'), 'w') as file:\n", + " file.write(content)" + ] + }, + { + "cell_type": "markdown", + "id": "488a15d3-f22e-4b2c-85c0-435c832e708c", + "metadata": { + "id": "488a15d3-f22e-4b2c-85c0-435c832e708c" + }, + "source": [ + "## InstaGeo - Data\n", + "\n", + "With InstaGeo installed and EarthData authentication configured, we are now ready to download and process HLS (Harmonized Landsat and Sentinel) granules using the `InstaGeo-Data` module. This module offers several powerful functionalities for handling geospatial data, including:\n", + "\n", + "- Searching and retrieving metadata for HLS granules\n", + "- Downloading specific spectral bands from HLS granules\n", + "- Generating data chips and corresponding target labels for machine learning tasks\n", + "\n", + "These capabilities streamline the preprocessing of multispectral data, setting the foundation for efficient geospatial model development.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "38e36f50", + "metadata": { + "id": "38e36f50" + }, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "from pathlib import Path" + ] + }, + { + "cell_type": "markdown", + "id": "c4d83f72", + "metadata": {}, + "source": [ + "The ground-truth geospatial observations for Rwanda cropland classification used in this notebook were sourced from the following datasets:\n", + "\n", + "- [Rwanda Crop Type Dataset (RTI)](https://beta.source.coop/rti/rwanda-crop-type/)\n", + "- [Rwanda 2019 Crop/Non-Crop Labels (HarvestPortal)](https://data.harvestportal.org/dataset/rwanda-2019-crop-non-crop-labels)\n", + "- [Processed Crop/Non-Crop Labels (HarvestPortal)](https://data.harvestportal.org/dataset/processed-crop-non-crop-labels/resource/037bff27-4f9f-44e5-9eb2-72eff840becb)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "adf67434", + "metadata": { + "id": "adf67434" + }, + "outputs": [], + "source": [ + "df1 = pd.read_csv(\"ed0ab379-a688-4419-ab96-181c726e1b22.csv\")\n", + "df2 = pd.read_csv(\"0cfc1320-f909-4759-90f9-cb5c92ca019e.csv\")\n", + "df3 = pd.read_csv(\"ceo-2019-rwanda-cropland-rcmrd-set-2-sample-data-2021-04-20.csv\")\n", + "\n", + "df = pd.concat([df1, df2, df3])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f6541bd6", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 363 + }, + "id": "f6541bd6", + "outputId": "0a55e877-f163-4d7d-c479-542315a0cd37" + }, + "outputs": [], + "source": [ + "df = df[['lat', 'lon', 'collection_time', 'Crop/ or not', 'sample_id']]\n", + "df = df.rename({\"lon\": \"x\", \"lat\":\"y\", \"Crop/ or not\":'label', 'collection_time':\"date\"}, axis=1)\n", + "df.head(10)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ea228e76", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "ea228e76", + "outputId": "4c5745bf-60d6-455f-9cea-d3c7c8069379" + }, + "outputs": [], + "source": [ + "print(f\"The size of the dataset is: {df.size}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e7ac02c8", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 363 + }, + "id": "e7ac02c8", + "outputId": "40da1092-af57-419f-f75f-781ebdfd3f46" + }, + "outputs": [], + "source": [ + "def label_map(x):\n", + " if x == \"Cropland\":\n", + " return 1\n", + " elif x == \"Non-crop\":\n", + " return 0\n", + " else:\n", + " return np.nan\n", + "\n", + "df['date'] = df['date'].map(lambda x: pd.to_datetime(x).strftime(\"%Y-%m-%d\"))\n", + "df['label'] = df['label'].map(label_map)\n", + "df = df.dropna().reset_index()\n", + "df.head(10)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "66e324e2", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "66e324e2", + "outputId": "5a56ba17-d580-4646-b970-f5fd90367aba" + }, + "outputs": [], + "source": [ + "from sklearn.model_selection import train_test_split\n", + "\n", + "train, val_and_test = train_test_split(df, test_size=0.3)\n", + "val, test = train_test_split(val_and_test, test_size=0.5)\n", + "\n", + "print(train.size, val.size, test.size)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "527edae6", + "metadata": { + "id": "527edae6" + }, + "outputs": [], + "source": [ + "train.to_csv(\"rwanda_cropland_data_train.csv\")\n", + "val.to_csv(\"rwanda_cropland_data_val.csv\")\n", + "test.to_csv(\"rwanda_cropland_data_test.csv\")" + ] + }, + { + "cell_type": "markdown", + "id": "fcc545f4", + "metadata": {}, + "source": [ + "After splitting the data into training, validation, and test sets, the next step is to group the data by the HLS granules they belong to and download the corresponding spectral bands for each granule. Once the bands are retrieved, we will generate smaller chips and target labels with dimensions of 224 x 224 pixels.\n", + "\n", + "By the end of this process, the input data will have a shape of 3 x 6 x 224 x 224 (representing three sets of six spectral bands and 224 x 224 pixel chips), and the target labels will have a shape of 224 x 224.\n", + "\n", + "While these tasks might seem complex, the `InstaGeo-Data` module abstracts this process, allowing you to configure it with a simple command as shown in the following cells" + ] + }, + { + "cell_type": "markdown", + "id": "b901a48e", + "metadata": {}, + "source": [ + "### Training Split" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c11bfeb8-df6b-4b8c-8c8a-059a5a28b8ea", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "c11bfeb8-df6b-4b8c-8c8a-059a5a28b8ea", + "outputId": "4ba7dbb9-0572-4bd8-8972-51418efb5ec3", + "tags": [] + }, + "outputs": [], + "source": [ + "%%bash\n", + "mkdir train\n", + "python -m \"instageo.data.chip_creator\" \\\n", + " --dataframe_path=\"rwanda_cropland_data_train.csv\" \\\n", + " --output_directory=\"train\" \\\n", + " --min_count=4 \\\n", + " --chip_size=224 \\\n", + " --no_data_value=-1 \\\n", + " --temporal_tolerance=3 \\\n", + " --temporal_step=30 \\\n", + " --mask_cloud=False \\\n", + " --num_steps=3" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "22FADUFcfYsR", + "metadata": { + "id": "22FADUFcfYsR" + }, + "outputs": [], + "source": [ + "root_dir = Path.cwd()\n", + "chips_orig = os.listdir(os.path.join(root_dir, \"train/chips\"))\n", + "chips = [chip.replace(\"chip\", \"train/chips/chip\") for chip in chips_orig]\n", + "seg_maps = [chip.replace(\"chip\", \"train/seg_maps/seg_map\") for chip in chips_orig]\n", + "\n", + "df = pd.DataFrame({\"Input\": chips, \"Label\": seg_maps})\n", + "df.to_csv(os.path.join(\"train.csv\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "UTu-qJkYflGD", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "UTu-qJkYflGD", + "outputId": "36691e05-0a25-4e5f-f3d9-21255cd6c143" + }, + "outputs": [], + "source": [ + "print(f\"The size of the train split: {df.size}\")" + ] + }, + { + "cell_type": "markdown", + "id": "5f87be84", + "metadata": {}, + "source": [ + "### Validation Split" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "qN2Zm9MxfsGc", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "qN2Zm9MxfsGc", + "outputId": "c0c11731-ebef-4fa9-a9be-4be6290a7bfd" + }, + "outputs": [], + "source": [ + "%%bash\n", + "mkdir val\n", + "python -m \"instageo.data.chip_creator\" \\\n", + " --dataframe_path=\"rwanda_cropland_data_val.csv\" \\\n", + " --output_directory=\"val\" \\\n", + " --min_count=4 \\\n", + " --chip_size=224 \\\n", + " --no_data_value=-1 \\\n", + " --temporal_tolerance=3 \\\n", + " --temporal_step=30 \\\n", + " --mask_cloud=False \\\n", + " --num_steps=3" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "IAhs3vF9fyO4", + "metadata": { + "id": "IAhs3vF9fyO4" + }, + "outputs": [], + "source": [ + "root_dir = Path.cwd()\n", + "chips_orig = os.listdir(os.path.join(root_dir, \"val/chips\"))\n", + "chips = [chip.replace(\"chip\", \"val/chips/chip\") for chip in chips_orig]\n", + "seg_maps = [chip.replace(\"chip\", \"val/seg_maps/seg_map\") for chip in chips_orig]\n", + "\n", + "df = pd.DataFrame({\"Input\": chips, \"Label\": seg_maps})\n", + "df.to_csv(os.path.join(\"val.csv\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c1S26jbTmH4J", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "c1S26jbTmH4J", + "outputId": "1a2f9742-5dea-4b50-c499-0431567cc624" + }, + "outputs": [], + "source": [ + "print(f\"The size of the validation split: {df.size}\")" + ] + }, + { + "cell_type": "markdown", + "id": "3d4e7fa6", + "metadata": {}, + "source": [ + "### Test Split" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "_xaa5V3sf3pJ", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "_xaa5V3sf3pJ", + "outputId": "569456fa-1953-4ebc-cd00-97a361c4cf7f" + }, + "outputs": [], + "source": [ + "%%bash\n", + "mkdir test\n", + "python -m \"instageo.data.chip_creator\" \\\n", + " --dataframe_path=\"rwanda_cropland_data_test.csv\" \\\n", + " --output_directory=\"test\" \\\n", + " --min_count=4 \\\n", + " --chip_size=224 \\\n", + " --no_data_value=-1 \\\n", + " --temporal_tolerance=3 \\\n", + " --temporal_step=30 \\\n", + " --mask_cloud=False \\\n", + " --num_steps=3" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "v7RvCMofgCCa", + "metadata": { + "id": "v7RvCMofgCCa" + }, + "outputs": [], + "source": [ + "root_dir = Path.cwd()\n", + "chips_orig = os.listdir(os.path.join(root_dir, \"test/chips\"))\n", + "chips = [chip.replace(\"chip\", \"test/chips/chip\") for chip in chips_orig]\n", + "seg_maps = [chip.replace(\"chip\", \"test/seg_maps/seg_map\") for chip in chips_orig]\n", + "\n", + "df = pd.DataFrame({\"Input\": chips, \"Label\": seg_maps})\n", + "df.to_csv(os.path.join(\"test.csv\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "XYrUAef1mJ0N", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "XYrUAef1mJ0N", + "outputId": "646a14c8-60ea-4780-ca23-8d71ec8635fb" + }, + "outputs": [], + "source": [ + "print(f\"The size of the test split: {df.size}\")" + ] + }, + { + "cell_type": "markdown", + "id": "bcb132b0-04dd-4583-8e30-e6332446a0e6", + "metadata": { + "id": "bcb132b0-04dd-4583-8e30-e6332446a0e6" + }, + "source": [ + "## InstaGeo - Model" + ] + }, + { + "cell_type": "markdown", + "id": "fd313044-829c-482d-934e-9ae662f132fc", + "metadata": { + "id": "fd313044-829c-482d-934e-9ae662f132fc" + }, + "source": [ + "After creating our dataset using the `InstaGeo-Data` module, we can move on to fine-tuning a model that includes a Prithvi backbone paired with a classification head. For regression tasks, the classification head can easily be replaced with a suitable regression head. Additionally, if a completely different model architecture is needed, it can be designed and implemented within this framework." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c64fee29-dca3-4611-a43a-4412a6033751", + "metadata": { + "id": "c64fee29-dca3-4611-a43a-4412a6033751" + }, + "outputs": [], + "source": [ + "import os\n", + "import os\n", + "import pandas as pd\n", + "import numpy as np\n", + "from pathlib import Path" + ] + }, + { + "cell_type": "markdown", + "id": "115cbc92", + "metadata": {}, + "source": [ + "**Launch Training**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "47dc76c1-26b9-47b9-8066-5c1df499b40f", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "collapsed": true, + "id": "47dc76c1-26b9-47b9-8066-5c1df499b40f", + "jupyter": { + "outputs_hidden": true + }, + "outputId": "3669afc6-e528-4211-fc51-27ec8a96eacb", + "tags": [] + }, + "outputs": [], + "source": [ + "!python -m instageo.model.run --config-name=locust \\\n", + " root_dir='.' \\\n", + " train.batch_size=8 \\\n", + " train.num_epochs=3 \\\n", + " train_filepath=\"train.csv\" \\\n", + " valid_filepath=\"val.csv\"" + ] + }, + { + "cell_type": "markdown", + "id": "10db019e", + "metadata": {}, + "source": [ + "**Run Model Evaluation**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f8230588-2842-460c-b2e7-4f2f4175dc3e", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "collapsed": true, + "id": "f8230588-2842-460c-b2e7-4f2f4175dc3e", + "jupyter": { + "outputs_hidden": true + }, + "outputId": "732da70c-6b84-474f-f047-c27292804085", + "tags": [] + }, + "outputs": [], + "source": [ + "!python -m instageo.model.run --config-name=locust \\\n", + " root_dir='.' \\\n", + " test_filepath=\"test.csv\" \\\n", + " train.batch_size=8 \\\n", + " checkpoint_path='checkpoint-path' \\\n", + " mode=eval" + ] + }, + { + "cell_type": "markdown", + "id": "b9a73d79-f69f-4fb8-aa63-768ee3ee47ea", + "metadata": { + "id": "b9a73d79-f69f-4fb8-aa63-768ee3ee47ea" + }, + "source": [ + "**Run Inference**" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "YgxyC5GnvjJU", + "metadata": { + "collapsed": true, + "id": "YgxyC5GnvjJU", + "jupyter": { + "outputs_hidden": true + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# !gsutil cp gs://instageo/utils/africa_prediction_template.csv .\n", + "!mkdir -p inference/2021-06" + ] + }, + { + "cell_type": "markdown", + "id": "9c30afd0-73ec-4eb1-b9c1-a2d36475eae7", + "metadata": { + "id": "9c30afd0-73ec-4eb1-b9c1-a2d36475eae7" + }, + "source": [ + "**Create Inference Data**\n", + "\n", + "For inference, we only need to download the necessary HLS tiles and run inference directly using the sliding window inference feature.\n", + "\n", + "If you're running inference across the entire African continent, you can use the `africa_prediction_template.csv`, which will automatically download 2,120 HLS granules covering Africa and parts of Asia.\n", + "\n", + "For this demo, we'll limit the scope to the HLS granules included in our test split.\n", + "\n", + "Note: Ensure you have approximately 1TB of storage space available for this process if you are running inference across Africa." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8f76b3ea-8ef7-473b-8f2e-72d493fdba03", + "metadata": { + "collapsed": true, + "id": "8f76b3ea-8ef7-473b-8f2e-72d493fdba03", + "jupyter": { + "outputs_hidden": true + }, + "tags": [] + }, + "outputs": [], + "source": [ + "!python -m \"instageo.data.chip_creator\" \\\n", + " --dataframe_path=\"test.csv\" \\\n", + " --output_directory=\"inference/2021-06\" \\\n", + " --min_count=1 \\\n", + " --no_data_value=-1 \\\n", + " --temporal_tolerance=3 \\\n", + " --temporal_step=30 \\\n", + " --num_steps=3 \\\n", + " --download_only" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ku-49mTIqWvW", + "metadata": { + "id": "ku-49mTIqWvW" + }, + "outputs": [], + "source": [ + "# Instead of downloading new set of HLS tiles, we can use the one for our test split for inference.\n", + "\n", + "!cp -r test/* inference/2021-06" + ] + }, + { + "cell_type": "markdown", + "id": "65e86341-0717-458f-b061-3e957ce8536d", + "metadata": { + "id": "65e86341-0717-458f-b061-3e957ce8536d" + }, + "source": [ + "**Run Inference**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "JJXq8oWNAr1w", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "JJXq8oWNAr1w", + "outputId": "c5611f61-ae55-41a3-d60d-9cf5644c7a4c", + "tags": [] + }, + "outputs": [], + "source": [ + "!python -m instageo.model.run --config-name=locust \\\n", + " root_dir='inference/2021-06' \\\n", + " test_filepath='hls_dataset.json' \\\n", + " train.batch_size=16 \\\n", + " test.mask_cloud=True \\\n", + " checkpoint_path='checkpoint-path' \\\n", + " mode=predict" + ] + }, + { + "cell_type": "markdown", + "id": "8d79e412-8176-411a-8a73-6068e22a0d25", + "metadata": { + "id": "8d79e412-8176-411a-8a73-6068e22a0d25" + }, + "source": [ + "## InstaGeo - Apps\n", + "Once inference has been completed on the HLS tiles and the results have been saved, we can use the `InstaGeo-Apps` module to visualize the predictions on an interactive map.\n", + "\n", + "To visualize the results, simply move the HLS prediction GeoTIFF files to the appropriate directory, and `InstaGeo-Apps` will handle the rest, providing an intuitive and interactive mapping experience." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8a904882-cde9-40c8-affb-f988892e5183", + "metadata": { + "id": "8a904882-cde9-40c8-affb-f988892e5183", + "tags": [] + }, + "outputs": [], + "source": [ + "!mkdir -p predictions/2023/6\n", + "!mv inference/2023-06/predictions/* /content/predictions/2023/6" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "tQGnk67MY6Cd", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "tQGnk67MY6Cd", + "outputId": "a3ac2e6a-3f41-42aa-ad59-67fab121f1ea", + "tags": [] + }, + "outputs": [], + "source": [ + "!npm install localtunnel" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "BeJsQzkeBNm7", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "collapsed": true, + "id": "BeJsQzkeBNm7", + "jupyter": { + "outputs_hidden": true + }, + "outputId": "5dc4d215-e2b2-42dd-bd33-8e7070cc73ce", + "tags": [] + }, + "outputs": [], + "source": [ + "!nohup streamlit run InstaGeo-E2E-Geospatial-ML/instageo/apps/app.py --server.address=localhost &" + ] + }, + { + "cell_type": "markdown", + "id": "48459844-9277-473b-8cd8-e47691c59c0a", + "metadata": { + "id": "48459844-9277-473b-8cd8-e47691c59c0a" + }, + "source": [ + "Retrieve your IP address which is the password of the localtunnel" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "S5rCS-lVZiWe", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "S5rCS-lVZiWe", + "outputId": "c6fbbe9d-047f-48b0-f0b0-695fc70dd2f8", + "tags": [] + }, + "outputs": [], + "source": [ + "import urllib\n", + "print(\"Password/Enpoint IP for localtunnel is:\",urllib.request.urlopen('https://ipv4.icanhazip.com').read().decode('utf8').strip(\"\\n\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bB61RRBNY-48", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "bB61RRBNY-48", + "outputId": "6336b355-b880-4b88-ba9b-0e37ddd6b859", + "tags": [] + }, + "outputs": [], + "source": [ + "!npx localtunnel --port 8501" + ] + }, + { + "cell_type": "markdown", + "id": "9f7d922e", + "metadata": {}, + "source": [ + "## Summary\n", + "\n", + "In this notebook, we demonstrated the end-to-end capabilities of InstaGeo for geospatial machine learning using multispectral data. We began by downloading and processing HLS granules, creating data chips for training, and fine-tuning a model with the Prithvi backbone. Finally, we ran inference on test data and visualized the results using the `InstaGeo-Apps` module.\n", + "\n", + "By leveraging InstaGeo, complex tasks such as data preprocessing, model training, and large-scale inference can be streamlined and efficiently handled with minimal configuration.\n", + "\n", + "If you found this demo helpful, please consider giving our [InstaGeo GitHub repository](https://github.com/instadeepai/InstaGeo-E2E-Geospatial-ML) a star ⭐! Your support helps us continue improving the tool for the community.\n", + "\n", + "Thank you for exploring InstaGeo with us!" + ] + }, + { + "cell_type": "markdown", + "id": "316908ce", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "accelerator": "GPU", "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "bB61RRBNY-48", - "outputId": "28bb4e8b-56c9-454c-89f2-47f576a5723b", - "tags": [] - }, - "outputs": [], - "source": [ - "!npx localtunnel --port 8501" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3c44bc28-bc5d-43d8-aad8-1e69bace9b0f", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "accelerator": "GPU", - "colab": { - "gpuType": "T4", - "provenance": [] - }, - "environment": { - "kernel": "python3", - "name": "tf2-cpu.2-11.m115", - "type": "gcloud", - "uri": "gcr.io/deeplearning-platform-release/tf2-cpu.2-11:m115" - }, - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.13" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "gpuType": "T4", + "provenance": [] + }, + "environment": { + "kernel": "python3", + "name": "tf2-cpu.2-11.m115", + "type": "gcloud", + "uri": "gcr.io/deeplearning-platform-release/tf2-cpu.2-11:m115" + }, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.14" + } + }, + "nbformat": 4, + "nbformat_minor": 5 }