From 5063c9a66165ab689b9cafa0a522ac84772d69fc Mon Sep 17 00:00:00 2001 From: tkekec Date: Sun, 18 Sep 2022 16:54:06 +0300 Subject: [PATCH] init --- employee_file.csv | 4 + examples/kiz-kulesi.jpg | Bin 0 -> 156963 bytes examples/pokemon_data.txt | 801 +++++++++++ extractPythonCodes.py | 69 + python-core.tex | 2661 +++++++++++++++++++++++++++++++++++++ taypack.tex | 29 + 6 files changed, 3564 insertions(+) create mode 100644 employee_file.csv create mode 100755 examples/kiz-kulesi.jpg create mode 100644 examples/pokemon_data.txt create mode 100644 extractPythonCodes.py create mode 100755 python-core.tex create mode 100644 taypack.tex diff --git a/employee_file.csv b/employee_file.csv new file mode 100644 index 0000000..133c07c --- /dev/null +++ b/employee_file.csv @@ -0,0 +1,4 @@ +name,department,birthday month,salary,gender +John Smith,Accounting,November,100,m +Erica Meyers,IT,March,200,f +Monica Barker,,,400,f diff --git a/examples/kiz-kulesi.jpg b/examples/kiz-kulesi.jpg new file mode 100755 index 0000000000000000000000000000000000000000..b2722d7a54bdd2bfa4b9c1f3e8f2d7c88469c56a GIT binary patch literal 156963 zcmb5Wc|4Ts8$W(OvuI3{GaNdTq!~tytwuFvOM@Xx$<|mxld*(KSt_C)LL*DaQg*Ut z$dXD)Q;85NTT-dSgwt`dRJ5GmJ$-(!@9Xvb{r7vk80LBAzOMUP-`92B_1}yC-U70f zxurQk5C9PP1^ycWrhp(NwM+_6Shj4Lv^0T8Qjj4nUrt&j_var9%B!hsl~=D>LsMg_ z(^R$TYu0G!X=v+g-nw-wm0_?$e~S^5wRN*(5ky*AnzWomk&&TnR#~I6`TzIz-vb~^ zz}4bvv4||d$Rb!-AH~j%YtX zNI0hCmaQkHU#X;U(Eg5hHl_|;;Vk2%iJ&4Wpvwb5VLWpG77A!9lta)5NCjZ=n2->V zBEF@>0iZ(y06qkmAOppukbpc}-k5{1fic^d4d4EKAt(?9o7&I|$NdLHg>6iwY74$( z2_6$FYy9V#Epde;DJ+GAQ9Mumy}C%Ma0N%_+4(U>_1^(kH zR$JNSm ztzt-_6=2Dt|51WkP(*d5S$c)%S)9@Xntn+V?nMVkfB|rhsRV^$JHwePA`;YRq5^8w zh6P9!5*@Wd5e0;PWA;u=9Z4QY*2UBUK;TIh{Xc6<{*af5E!kG8KD+)Pk_zJbxQV

ZhLl(NDYeV}+2Q2HsFFa|MkP{L%$AaR8p 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

wf-K>>%)k+IA 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ᝳ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

b6 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 literal 0 HcmV?d00001 diff --git a/examples/pokemon_data.txt b/examples/pokemon_data.txt new file mode 100644 index 0000000..5ece3f2 --- /dev/null +++ b/examples/pokemon_data.txt @@ -0,0 +1,801 @@ +# Name Type 1 Type 2 HP Attack Defense Sp. Atk Sp. Def Speed Generation Legendary +1 Bulbasaur Grass Poison 45 49 49 65 65 45 1 FALSE +2 Ivysaur Grass Poison 60 62 63 80 80 60 1 FALSE +3 Venusaur Grass Poison 80 82 83 100 100 80 1 FALSE +3 VenusaurMega Venusaur Grass Poison 80 100 123 122 120 80 1 FALSE +4 Charmander Fire 39 52 43 60 50 65 1 FALSE +5 Charmeleon Fire 58 64 58 80 65 80 1 FALSE +6 Charizard Fire Flying 78 84 78 109 85 100 1 FALSE +6 CharizardMega Charizard X Fire Dragon 78 130 111 130 85 100 1 FALSE +6 CharizardMega Charizard Y Fire Flying 78 104 78 159 115 100 1 FALSE +7 Squirtle Water 44 48 65 50 64 43 1 FALSE +8 Wartortle Water 59 63 80 65 80 58 1 FALSE +9 Blastoise Water 79 83 100 85 105 78 1 FALSE +9 BlastoiseMega Blastoise Water 79 103 120 135 115 78 1 FALSE +10 Caterpie Bug 45 30 35 20 20 45 1 FALSE +11 Metapod Bug 50 20 55 25 25 30 1 FALSE +12 Butterfree Bug Flying 60 45 50 90 80 70 1 FALSE +13 Weedle Bug Poison 40 35 30 20 20 50 1 FALSE +14 Kakuna Bug Poison 45 25 50 25 25 35 1 FALSE +15 Beedrill Bug Poison 65 90 40 45 80 75 1 FALSE +15 BeedrillMega Beedrill Bug Poison 65 150 40 15 80 145 1 FALSE +16 Pidgey Normal Flying 40 45 40 35 35 56 1 FALSE +17 Pidgeotto Normal Flying 63 60 55 50 50 71 1 FALSE +18 Pidgeot Normal Flying 83 80 75 70 70 101 1 FALSE +18 PidgeotMega Pidgeot Normal Flying 83 80 80 135 80 121 1 FALSE +19 Rattata Normal 30 56 35 25 35 72 1 FALSE +20 Raticate Normal 55 81 60 50 70 97 1 FALSE +21 Spearow Normal Flying 40 60 30 31 31 70 1 FALSE +22 Fearow Normal Flying 65 90 65 61 61 100 1 FALSE +23 Ekans Poison 35 60 44 40 54 55 1 FALSE +24 Arbok Poison 60 85 69 65 79 80 1 FALSE +25 Pikachu Electric 35 55 40 50 50 90 1 FALSE +26 Raichu Electric 60 90 55 90 80 110 1 FALSE +27 Sandshrew Ground 50 75 85 20 30 40 1 FALSE +28 Sandslash Ground 75 100 110 45 55 65 1 FALSE +29 Nidoran (Female) Poison 55 47 52 40 40 41 1 FALSE +30 Nidorina Poison 70 62 67 55 55 56 1 FALSE +31 Nidoqueen Poison Ground 90 92 87 75 85 76 1 FALSE +32 Nidoran (Male) Poison 46 57 40 40 40 50 1 FALSE +33 Nidorino Poison 61 72 57 55 55 65 1 FALSE +34 Nidoking Poison Ground 81 102 77 85 75 85 1 FALSE +35 Clefairy Fairy 70 45 48 60 65 35 1 FALSE +36 Clefable Fairy 95 70 73 95 90 60 1 FALSE +37 Vulpix Fire 38 41 40 50 65 65 1 FALSE +38 Ninetales Fire 73 76 75 81 100 100 1 FALSE +39 Jigglypuff Normal Fairy 115 45 20 45 25 20 1 FALSE +40 Wigglytuff Normal Fairy 140 70 45 85 50 45 1 FALSE +41 Zubat Poison Flying 40 45 35 30 40 55 1 FALSE +42 Golbat Poison Flying 75 80 70 65 75 90 1 FALSE +43 Oddish Grass Poison 45 50 55 75 65 30 1 FALSE +44 Gloom Grass Poison 60 65 70 85 75 40 1 FALSE +45 Vileplume Grass Poison 75 80 85 110 90 50 1 FALSE +46 Paras Bug Grass 35 70 55 45 55 25 1 FALSE +47 Parasect Bug Grass 60 95 80 60 80 30 1 FALSE +48 Venonat Bug Poison 60 55 50 40 55 45 1 FALSE +49 Venomoth Bug Poison 70 65 60 90 75 90 1 FALSE +50 Diglett Ground 10 55 25 35 45 95 1 FALSE +51 Dugtrio Ground 35 80 50 50 70 120 1 FALSE +52 Meowth Normal 40 45 35 40 40 90 1 FALSE +53 Persian Normal 65 70 60 65 65 115 1 FALSE +54 Psyduck Water 50 52 48 65 50 55 1 FALSE +55 Golduck Water 80 82 78 95 80 85 1 FALSE +56 Mankey Fighting 40 80 35 35 45 70 1 FALSE +57 Primeape Fighting 65 105 60 60 70 95 1 FALSE +58 Growlithe Fire 55 70 45 70 50 60 1 FALSE +59 Arcanine Fire 90 110 80 100 80 95 1 FALSE +60 Poliwag Water 40 50 40 40 40 90 1 FALSE +61 Poliwhirl Water 65 65 65 50 50 90 1 FALSE +62 Poliwrath Water Fighting 90 95 95 70 90 70 1 FALSE +63 Abra Psychic 25 20 15 105 55 90 1 FALSE +64 Kadabra Psychic 40 35 30 120 70 105 1 FALSE +65 Alakazam Psychic 55 50 45 135 95 120 1 FALSE +65 AlakazamMega Alakazam Psychic 55 50 65 175 95 150 1 FALSE +66 Machop Fighting 70 80 50 35 35 35 1 FALSE +67 Machoke Fighting 80 100 70 50 60 45 1 FALSE +68 Machamp Fighting 90 130 80 65 85 55 1 FALSE +69 Bellsprout Grass Poison 50 75 35 70 30 40 1 FALSE +70 Weepinbell Grass Poison 65 90 50 85 45 55 1 FALSE +71 Victreebel Grass Poison 80 105 65 100 70 70 1 FALSE +72 Tentacool Water Poison 40 40 35 50 100 70 1 FALSE +73 Tentacruel Water Poison 80 70 65 80 120 100 1 FALSE +74 Geodude Rock Ground 40 80 100 30 30 20 1 FALSE +75 Graveler Rock Ground 55 95 115 45 45 35 1 FALSE +76 Golem Rock Ground 80 120 130 55 65 45 1 FALSE +77 Ponyta Fire 50 85 55 65 65 90 1 FALSE +78 Rapidash Fire 65 100 70 80 80 105 1 FALSE +79 Slowpoke Water Psychic 90 65 65 40 40 15 1 FALSE +80 Slowbro Water Psychic 95 75 110 100 80 30 1 FALSE +80 SlowbroMega Slowbro Water Psychic 95 75 180 130 80 30 1 FALSE +81 Magnemite Electric Steel 25 35 70 95 55 45 1 FALSE +82 Magneton Electric Steel 50 60 95 120 70 70 1 FALSE +83 Farfetch'd Normal Flying 52 65 55 58 62 60 1 FALSE +84 Doduo Normal Flying 35 85 45 35 35 75 1 FALSE +85 Dodrio Normal Flying 60 110 70 60 60 100 1 FALSE +86 Seel Water 65 45 55 45 70 45 1 FALSE +87 Dewgong Water Ice 90 70 80 70 95 70 1 FALSE +88 Grimer Poison 80 80 50 40 50 25 1 FALSE +89 Muk Poison 105 105 75 65 100 50 1 FALSE +90 Shellder Water 30 65 100 45 25 40 1 FALSE +91 Cloyster Water Ice 50 95 180 85 45 70 1 FALSE +92 Gastly Ghost Poison 30 35 30 100 35 80 1 FALSE +93 Haunter Ghost Poison 45 50 45 115 55 95 1 FALSE +94 Gengar Ghost Poison 60 65 60 130 75 110 1 FALSE +94 GengarMega Gengar Ghost Poison 60 65 80 170 95 130 1 FALSE +95 Onix Rock Ground 35 45 160 30 45 70 1 FALSE +96 Drowzee Psychic 60 48 45 43 90 42 1 FALSE +97 Hypno Psychic 85 73 70 73 115 67 1 FALSE +98 Krabby Water 30 105 90 25 25 50 1 FALSE +99 Kingler Water 55 130 115 50 50 75 1 FALSE +100 Voltorb Electric 40 30 50 55 55 100 1 FALSE +101 Electrode Electric 60 50 70 80 80 140 1 FALSE +102 Exeggcute Grass Psychic 60 40 80 60 45 40 1 FALSE +103 Exeggutor Grass Psychic 95 95 85 125 65 55 1 FALSE +104 Cubone Ground 50 50 95 40 50 35 1 FALSE +105 Marowak Ground 60 80 110 50 80 45 1 FALSE +106 Hitmonlee Fighting 50 120 53 35 110 87 1 FALSE +107 Hitmonchan Fighting 50 105 79 35 110 76 1 FALSE +108 Lickitung Normal 90 55 75 60 75 30 1 FALSE +109 Koffing Poison 40 65 95 60 45 35 1 FALSE +110 Weezing Poison 65 90 120 85 70 60 1 FALSE +111 Rhyhorn Ground Rock 80 85 95 30 30 25 1 FALSE +112 Rhydon Ground Rock 105 130 120 45 45 40 1 FALSE +113 Chansey Normal 250 5 5 35 105 50 1 FALSE +114 Tangela Grass 65 55 115 100 40 60 1 FALSE +115 Kangaskhan Normal 105 95 80 40 80 90 1 FALSE +115 KangaskhanMega Kangaskhan Normal 105 125 100 60 100 100 1 FALSE +116 Horsea Water 30 40 70 70 25 60 1 FALSE +117 Seadra Water 55 65 95 95 45 85 1 FALSE +118 Goldeen Water 45 67 60 35 50 63 1 FALSE +119 Seaking Water 80 92 65 65 80 68 1 FALSE +120 Staryu Water 30 45 55 70 55 85 1 FALSE +121 Starmie Water Psychic 60 75 85 100 85 115 1 FALSE +122 Mr. Mime Psychic Fairy 40 45 65 100 120 90 1 FALSE +123 Scyther Bug Flying 70 110 80 55 80 105 1 FALSE +124 Jynx Ice Psychic 65 50 35 115 95 95 1 FALSE +125 Electabuzz Electric 65 83 57 95 85 105 1 FALSE +126 Magmar Fire 65 95 57 100 85 93 1 FALSE +127 Pinsir Bug 65 125 100 55 70 85 1 FALSE +127 PinsirMega Pinsir Bug Flying 65 155 120 65 90 105 1 FALSE +128 Tauros Normal 75 100 95 40 70 110 1 FALSE +129 Magikarp Water 20 10 55 15 20 80 1 FALSE +130 Gyarados Water Flying 95 125 79 60 100 81 1 FALSE +130 GyaradosMega Gyarados Water Dark 95 155 109 70 130 81 1 FALSE +131 Lapras Water Ice 130 85 80 85 95 60 1 FALSE +132 Ditto Normal 48 48 48 48 48 48 1 FALSE +133 Eevee Normal 55 55 50 45 65 55 1 FALSE +134 Vaporeon Water 130 65 60 110 95 65 1 FALSE +135 Jolteon Electric 65 65 60 110 95 130 1 FALSE +136 Flareon Fire 65 130 60 95 110 65 1 FALSE +137 Porygon Normal 65 60 70 85 75 40 1 FALSE +138 Omanyte Rock Water 35 40 100 90 55 35 1 FALSE +139 Omastar Rock Water 70 60 125 115 70 55 1 FALSE +140 Kabuto Rock Water 30 80 90 55 45 55 1 FALSE +141 Kabutops Rock Water 60 115 105 65 70 80 1 FALSE +142 Aerodactyl Rock Flying 80 105 65 60 75 130 1 FALSE +142 AerodactylMega Aerodactyl Rock Flying 80 135 85 70 95 150 1 FALSE +143 Snorlax Normal 160 110 65 65 110 30 1 FALSE +144 Articuno Ice Flying 90 85 100 95 125 85 1 TRUE +145 Zapdos Electric Flying 90 90 85 125 90 100 1 TRUE +146 Moltres Fire Flying 90 100 90 125 85 90 1 TRUE +147 Dratini Dragon 41 64 45 50 50 50 1 FALSE +148 Dragonair Dragon 61 84 65 70 70 70 1 FALSE +149 Dragonite Dragon Flying 91 134 95 100 100 80 1 FALSE +150 Mewtwo Psychic 106 110 90 154 90 130 1 TRUE +150 MewtwoMega Mewtwo X Psychic Fighting 106 190 100 154 100 130 1 TRUE +150 MewtwoMega Mewtwo Y Psychic 106 150 70 194 120 140 1 TRUE +151 Mew Psychic 100 100 100 100 100 100 1 FALSE +152 Chikorita Grass 45 49 65 49 65 45 2 FALSE +153 Bayleef Grass 60 62 80 63 80 60 2 FALSE +154 Meganium Grass 80 82 100 83 100 80 2 FALSE +155 Cyndaquil Fire 39 52 43 60 50 65 2 FALSE +156 Quilava Fire 58 64 58 80 65 80 2 FALSE +157 Typhlosion Fire 78 84 78 109 85 100 2 FALSE +158 Totodile Water 50 65 64 44 48 43 2 FALSE +159 Croconaw Water 65 80 80 59 63 58 2 FALSE +160 Feraligatr Water 85 105 100 79 83 78 2 FALSE +161 Sentret Normal 35 46 34 35 45 20 2 FALSE +162 Furret Normal 85 76 64 45 55 90 2 FALSE +163 Hoothoot Normal Flying 60 30 30 36 56 50 2 FALSE +164 Noctowl Normal Flying 100 50 50 76 96 70 2 FALSE +165 Ledyba Bug Flying 40 20 30 40 80 55 2 FALSE +166 Ledian Bug Flying 55 35 50 55 110 85 2 FALSE +167 Spinarak Bug Poison 40 60 40 40 40 30 2 FALSE +168 Ariados Bug Poison 70 90 70 60 60 40 2 FALSE +169 Crobat Poison Flying 85 90 80 70 80 130 2 FALSE +170 Chinchou Water Electric 75 38 38 56 56 67 2 FALSE +171 Lanturn Water Electric 125 58 58 76 76 67 2 FALSE +172 Pichu Electric 20 40 15 35 35 60 2 FALSE +173 Cleffa Fairy 50 25 28 45 55 15 2 FALSE +174 Igglybuff Normal Fairy 90 30 15 40 20 15 2 FALSE +175 Togepi Fairy 35 20 65 40 65 20 2 FALSE +176 Togetic Fairy Flying 55 40 85 80 105 40 2 FALSE +177 Natu Psychic Flying 40 50 45 70 45 70 2 FALSE +178 Xatu Psychic Flying 65 75 70 95 70 95 2 FALSE +179 Mareep Electric 55 40 40 65 45 35 2 FALSE +180 Flaaffy Electric 70 55 55 80 60 45 2 FALSE +181 Ampharos Electric 90 75 85 115 90 55 2 FALSE +181 AmpharosMega Ampharos Electric Dragon 90 95 105 165 110 45 2 FALSE +182 Bellossom Grass 75 80 95 90 100 50 2 FALSE +183 Marill Water Fairy 70 20 50 20 50 40 2 FALSE +184 Azumarill Water Fairy 100 50 80 60 80 50 2 FALSE +185 Sudowoodo Rock 70 100 115 30 65 30 2 FALSE +186 Politoed Water 90 75 75 90 100 70 2 FALSE +187 Hoppip Grass Flying 35 35 40 35 55 50 2 FALSE +188 Skiploom Grass Flying 55 45 50 45 65 80 2 FALSE +189 Jumpluff Grass Flying 75 55 70 55 95 110 2 FALSE +190 Aipom Normal 55 70 55 40 55 85 2 FALSE +191 Sunkern Grass 30 30 30 30 30 30 2 FALSE +192 Sunflora Grass 75 75 55 105 85 30 2 FALSE +193 Yanma Bug Flying 65 65 45 75 45 95 2 FALSE +194 Wooper Water Ground 55 45 45 25 25 15 2 FALSE +195 Quagsire Water Ground 95 85 85 65 65 35 2 FALSE +196 Espeon Psychic 65 65 60 130 95 110 2 FALSE +197 Umbreon Dark 95 65 110 60 130 65 2 FALSE +198 Murkrow Dark Flying 60 85 42 85 42 91 2 FALSE +199 Slowking Water Psychic 95 75 80 100 110 30 2 FALSE +200 Misdreavus Ghost 60 60 60 85 85 85 2 FALSE +201 Unown Psychic 48 72 48 72 48 48 2 FALSE +202 Wobbuffet Psychic 190 33 58 33 58 33 2 FALSE +203 Girafarig Normal Psychic 70 80 65 90 65 85 2 FALSE +204 Pineco Bug 50 65 90 35 35 15 2 FALSE +205 Forretress Bug Steel 75 90 140 60 60 40 2 FALSE +206 Dunsparce Normal 100 70 70 65 65 45 2 FALSE +207 Gligar Ground Flying 65 75 105 35 65 85 2 FALSE +208 Steelix Steel Ground 75 85 200 55 65 30 2 FALSE +208 SteelixMega Steelix Steel Ground 75 125 230 55 95 30 2 FALSE +209 Snubbull Fairy 60 80 50 40 40 30 2 FALSE +210 Granbull Fairy 90 120 75 60 60 45 2 FALSE +211 Qwilfish Water Poison 65 95 75 55 55 85 2 FALSE +212 Scizor Bug Steel 70 130 100 55 80 65 2 FALSE +212 ScizorMega Scizor Bug Steel 70 150 140 65 100 75 2 FALSE +213 Shuckle Bug Rock 20 10 230 10 230 5 2 FALSE +214 Heracross Bug Fighting 80 125 75 40 95 85 2 FALSE +214 HeracrossMega Heracross Bug Fighting 80 185 115 40 105 75 2 FALSE +215 Sneasel Dark Ice 55 95 55 35 75 115 2 FALSE +216 Teddiursa Normal 60 80 50 50 50 40 2 FALSE +217 Ursaring Normal 90 130 75 75 75 55 2 FALSE +218 Slugma Fire 40 40 40 70 40 20 2 FALSE +219 Magcargo Fire Rock 50 50 120 80 80 30 2 FALSE +220 Swinub Ice Ground 50 50 40 30 30 50 2 FALSE +221 Piloswine Ice Ground 100 100 80 60 60 50 2 FALSE +222 Corsola Water Rock 55 55 85 65 85 35 2 FALSE +223 Remoraid Water 35 65 35 65 35 65 2 FALSE +224 Octillery Water 75 105 75 105 75 45 2 FALSE +225 Delibird Ice Flying 45 55 45 65 45 75 2 FALSE +226 Mantine Water Flying 65 40 70 80 140 70 2 FALSE +227 Skarmory Steel Flying 65 80 140 40 70 70 2 FALSE +228 Houndour Dark Fire 45 60 30 80 50 65 2 FALSE +229 Houndoom Dark Fire 75 90 50 110 80 95 2 FALSE +229 HoundoomMega Houndoom Dark Fire 75 90 90 140 90 115 2 FALSE +230 Kingdra Water Dragon 75 95 95 95 95 85 2 FALSE +231 Phanpy Ground 90 60 60 40 40 40 2 FALSE +232 Donphan Ground 90 120 120 60 60 50 2 FALSE +233 Porygon2 Normal 85 80 90 105 95 60 2 FALSE +234 Stantler Normal 73 95 62 85 65 85 2 FALSE +235 Smeargle Normal 55 20 35 20 45 75 2 FALSE +236 Tyrogue Fighting 35 35 35 35 35 35 2 FALSE +237 Hitmontop Fighting 50 95 95 35 110 70 2 FALSE +238 Smoochum Ice Psychic 45 30 15 85 65 65 2 FALSE +239 Elekid Electric 45 63 37 65 55 95 2 FALSE +240 Magby Fire 45 75 37 70 55 83 2 FALSE +241 Miltank Normal 95 80 105 40 70 100 2 FALSE +242 Blissey Normal 255 10 10 75 135 55 2 FALSE +243 Raikou Electric 90 85 75 115 100 115 2 TRUE +244 Entei Fire 115 115 85 90 75 100 2 TRUE +245 Suicune Water 100 75 115 90 115 85 2 TRUE +246 Larvitar Rock Ground 50 64 50 45 50 41 2 FALSE +247 Pupitar Rock Ground 70 84 70 65 70 51 2 FALSE +248 Tyranitar Rock Dark 100 134 110 95 100 61 2 FALSE +248 TyranitarMega Tyranitar Rock Dark 100 164 150 95 120 71 2 FALSE +249 Lugia Psychic Flying 106 90 130 90 154 110 2 TRUE +250 Ho-oh Fire Flying 106 130 90 110 154 90 2 TRUE +251 Celebi Psychic Grass 100 100 100 100 100 100 2 FALSE +252 Treecko Grass 40 45 35 65 55 70 3 FALSE +253 Grovyle Grass 50 65 45 85 65 95 3 FALSE +254 Sceptile Grass 70 85 65 105 85 120 3 FALSE +254 SceptileMega Sceptile Grass Dragon 70 110 75 145 85 145 3 FALSE +255 Torchic Fire 45 60 40 70 50 45 3 FALSE +256 Combusken Fire Fighting 60 85 60 85 60 55 3 FALSE +257 Blaziken Fire Fighting 80 120 70 110 70 80 3 FALSE +257 BlazikenMega Blaziken Fire Fighting 80 160 80 130 80 100 3 FALSE +258 Mudkip Water 50 70 50 50 50 40 3 FALSE +259 Marshtomp Water Ground 70 85 70 60 70 50 3 FALSE +260 Swampert Water Ground 100 110 90 85 90 60 3 FALSE +260 SwampertMega Swampert Water Ground 100 150 110 95 110 70 3 FALSE +261 Poochyena Dark 35 55 35 30 30 35 3 FALSE +262 Mightyena Dark 70 90 70 60 60 70 3 FALSE +263 Zigzagoon Normal 38 30 41 30 41 60 3 FALSE +264 Linoone Normal 78 70 61 50 61 100 3 FALSE +265 Wurmple Bug 45 45 35 20 30 20 3 FALSE +266 Silcoon Bug 50 35 55 25 25 15 3 FALSE +267 Beautifly Bug Flying 60 70 50 100 50 65 3 FALSE +268 Cascoon Bug 50 35 55 25 25 15 3 FALSE +269 Dustox Bug Poison 60 50 70 50 90 65 3 FALSE +270 Lotad Water Grass 40 30 30 40 50 30 3 FALSE +271 Lombre Water Grass 60 50 50 60 70 50 3 FALSE +272 Ludicolo Water Grass 80 70 70 90 100 70 3 FALSE +273 Seedot Grass 40 40 50 30 30 30 3 FALSE +274 Nuzleaf Grass Dark 70 70 40 60 40 60 3 FALSE +275 Shiftry Grass Dark 90 100 60 90 60 80 3 FALSE +276 Taillow Normal Flying 40 55 30 30 30 85 3 FALSE +277 Swellow Normal Flying 60 85 60 50 50 125 3 FALSE +278 Wingull Water Flying 40 30 30 55 30 85 3 FALSE +279 Pelipper Water Flying 60 50 100 85 70 65 3 FALSE +280 Ralts Psychic Fairy 28 25 25 45 35 40 3 FALSE +281 Kirlia Psychic Fairy 38 35 35 65 55 50 3 FALSE +282 Gardevoir Psychic Fairy 68 65 65 125 115 80 3 FALSE +282 GardevoirMega Gardevoir Psychic Fairy 68 85 65 165 135 100 3 FALSE +283 Surskit Bug Water 40 30 32 50 52 65 3 FALSE +284 Masquerain Bug Flying 70 60 62 80 82 60 3 FALSE +285 Shroomish Grass 60 40 60 40 60 35 3 FALSE +286 Breloom Grass Fighting 60 130 80 60 60 70 3 FALSE +287 Slakoth Normal 60 60 60 35 35 30 3 FALSE +288 Vigoroth Normal 80 80 80 55 55 90 3 FALSE +289 Slaking Normal 150 160 100 95 65 100 3 FALSE +290 Nincada Bug Ground 31 45 90 30 30 40 3 FALSE +291 Ninjask Bug Flying 61 90 45 50 50 160 3 FALSE +292 Shedinja Bug Ghost 1 90 45 30 30 40 3 FALSE +293 Whismur Normal 64 51 23 51 23 28 3 FALSE +294 Loudred Normal 84 71 43 71 43 48 3 FALSE +295 Exploud Normal 104 91 63 91 73 68 3 FALSE +296 Makuhita Fighting 72 60 30 20 30 25 3 FALSE +297 Hariyama Fighting 144 120 60 40 60 50 3 FALSE +298 Azurill Normal Fairy 50 20 40 20 40 20 3 FALSE +299 Nosepass Rock 30 45 135 45 90 30 3 FALSE +300 Skitty Normal 50 45 45 35 35 50 3 FALSE +301 Delcatty Normal 70 65 65 55 55 70 3 FALSE +302 Sableye Dark Ghost 50 75 75 65 65 50 3 FALSE +302 SableyeMega Sableye Dark Ghost 50 85 125 85 115 20 3 FALSE +303 Mawile Steel Fairy 50 85 85 55 55 50 3 FALSE +303 MawileMega Mawile Steel Fairy 50 105 125 55 95 50 3 FALSE +304 Aron Steel Rock 50 70 100 40 40 30 3 FALSE +305 Lairon Steel Rock 60 90 140 50 50 40 3 FALSE +306 Aggron Steel Rock 70 110 180 60 60 50 3 FALSE +306 AggronMega Aggron Steel 70 140 230 60 80 50 3 FALSE +307 Meditite Fighting Psychic 30 40 55 40 55 60 3 FALSE +308 Medicham Fighting Psychic 60 60 75 60 75 80 3 FALSE +308 MedichamMega Medicham Fighting Psychic 60 100 85 80 85 100 3 FALSE +309 Electrike Electric 40 45 40 65 40 65 3 FALSE +310 Manectric Electric 70 75 60 105 60 105 3 FALSE +310 ManectricMega Manectric Electric 70 75 80 135 80 135 3 FALSE +311 Plusle Electric 60 50 40 85 75 95 3 FALSE +312 Minun Electric 60 40 50 75 85 95 3 FALSE +313 Volbeat Bug 65 73 55 47 75 85 3 FALSE +314 Illumise Bug 65 47 55 73 75 85 3 FALSE +315 Roselia Grass Poison 50 60 45 100 80 65 3 FALSE +316 Gulpin Poison 70 43 53 43 53 40 3 FALSE +317 Swalot Poison 100 73 83 73 83 55 3 FALSE +318 Carvanha Water Dark 45 90 20 65 20 65 3 FALSE +319 Sharpedo Water Dark 70 120 40 95 40 95 3 FALSE +319 SharpedoMega Sharpedo Water Dark 70 140 70 110 65 105 3 FALSE +320 Wailmer Water 130 70 35 70 35 60 3 FALSE +321 Wailord Water 170 90 45 90 45 60 3 FALSE +322 Numel Fire Ground 60 60 40 65 45 35 3 FALSE +323 Camerupt Fire Ground 70 100 70 105 75 40 3 FALSE +323 CameruptMega Camerupt Fire Ground 70 120 100 145 105 20 3 FALSE +324 Torkoal Fire 70 85 140 85 70 20 3 FALSE +325 Spoink Psychic 60 25 35 70 80 60 3 FALSE +326 Grumpig Psychic 80 45 65 90 110 80 3 FALSE +327 Spinda Normal 60 60 60 60 60 60 3 FALSE +328 Trapinch Ground 45 100 45 45 45 10 3 FALSE +329 Vibrava Ground Dragon 50 70 50 50 50 70 3 FALSE +330 Flygon Ground Dragon 80 100 80 80 80 100 3 FALSE +331 Cacnea Grass 50 85 40 85 40 35 3 FALSE +332 Cacturne Grass Dark 70 115 60 115 60 55 3 FALSE +333 Swablu Normal Flying 45 40 60 40 75 50 3 FALSE +334 Altaria Dragon Flying 75 70 90 70 105 80 3 FALSE +334 AltariaMega Altaria Dragon Fairy 75 110 110 110 105 80 3 FALSE +335 Zangoose Normal 73 115 60 60 60 90 3 FALSE +336 Seviper Poison 73 100 60 100 60 65 3 FALSE +337 Lunatone Rock Psychic 70 55 65 95 85 70 3 FALSE +338 Solrock Rock Psychic 70 95 85 55 65 70 3 FALSE +339 Barboach Water Ground 50 48 43 46 41 60 3 FALSE +340 Whiscash Water Ground 110 78 73 76 71 60 3 FALSE +341 Corphish Water 43 80 65 50 35 35 3 FALSE +342 Crawdaunt Water Dark 63 120 85 90 55 55 3 FALSE +343 Baltoy Ground Psychic 40 40 55 40 70 55 3 FALSE +344 Claydol Ground Psychic 60 70 105 70 120 75 3 FALSE +345 Lileep Rock Grass 66 41 77 61 87 23 3 FALSE +346 Cradily Rock Grass 86 81 97 81 107 43 3 FALSE +347 Anorith Rock Bug 45 95 50 40 50 75 3 FALSE +348 Armaldo Rock Bug 75 125 100 70 80 45 3 FALSE +349 Feebas Water 20 15 20 10 55 80 3 FALSE +350 Milotic Water 95 60 79 100 125 81 3 FALSE +351 Castform Normal 70 70 70 70 70 70 3 FALSE +352 Kecleon Normal 60 90 70 60 120 40 3 FALSE +353 Shuppet Ghost 44 75 35 63 33 45 3 FALSE +354 Banette Ghost 64 115 65 83 63 65 3 FALSE +354 BanetteMega Banette Ghost 64 165 75 93 83 75 3 FALSE +355 Duskull Ghost 20 40 90 30 90 25 3 FALSE +356 Dusclops Ghost 40 70 130 60 130 25 3 FALSE +357 Tropius Grass Flying 99 68 83 72 87 51 3 FALSE +358 Chimecho Psychic 65 50 70 95 80 65 3 FALSE +359 Absol Dark 65 130 60 75 60 75 3 FALSE +359 AbsolMega Absol Dark 65 150 60 115 60 115 3 FALSE +360 Wynaut Psychic 95 23 48 23 48 23 3 FALSE +361 Snorunt Ice 50 50 50 50 50 50 3 FALSE +362 Glalie Ice 80 80 80 80 80 80 3 FALSE +362 GlalieMega Glalie Ice 80 120 80 120 80 100 3 FALSE +363 Spheal Ice Water 70 40 50 55 50 25 3 FALSE +364 Sealeo Ice Water 90 60 70 75 70 45 3 FALSE +365 Walrein Ice Water 110 80 90 95 90 65 3 FALSE +366 Clamperl Water 35 64 85 74 55 32 3 FALSE +367 Huntail Water 55 104 105 94 75 52 3 FALSE +368 Gorebyss Water 55 84 105 114 75 52 3 FALSE +369 Relicanth Water Rock 100 90 130 45 65 55 3 FALSE +370 Luvdisc Water 43 30 55 40 65 97 3 FALSE +371 Bagon Dragon 45 75 60 40 30 50 3 FALSE +372 Shelgon Dragon 65 95 100 60 50 50 3 FALSE +373 Salamence Dragon Flying 95 135 80 110 80 100 3 FALSE +373 SalamenceMega Salamence Dragon Flying 95 145 130 120 90 120 3 FALSE +374 Beldum Steel Psychic 40 55 80 35 60 30 3 FALSE +375 Metang Steel Psychic 60 75 100 55 80 50 3 FALSE +376 Metagross Steel Psychic 80 135 130 95 90 70 3 FALSE +376 MetagrossMega Metagross Steel Psychic 80 145 150 105 110 110 3 FALSE +377 Regirock Rock 80 100 200 50 100 50 3 TRUE +378 Regice Ice 80 50 100 100 200 50 3 TRUE +379 Registeel Steel 80 75 150 75 150 50 3 TRUE +380 Latias Dragon Psychic 80 80 90 110 130 110 3 TRUE +380 LatiasMega Latias Dragon Psychic 80 100 120 140 150 110 3 TRUE +381 Latios Dragon Psychic 80 90 80 130 110 110 3 TRUE +381 LatiosMega Latios Dragon Psychic 80 130 100 160 120 110 3 TRUE +382 Kyogre Water 100 100 90 150 140 90 3 TRUE +382 KyogrePrimal Kyogre Water 100 150 90 180 160 90 3 TRUE +383 Groudon Ground 100 150 140 100 90 90 3 TRUE +383 GroudonPrimal Groudon Ground Fire 100 180 160 150 90 90 3 TRUE +384 Rayquaza Dragon Flying 105 150 90 150 90 95 3 TRUE +384 RayquazaMega Rayquaza Dragon Flying 105 180 100 180 100 115 3 TRUE +385 Jirachi Steel Psychic 100 100 100 100 100 100 3 TRUE +386 DeoxysNormal Forme Psychic 50 150 50 150 50 150 3 TRUE +386 DeoxysAttack Forme Psychic 50 180 20 180 20 150 3 TRUE +386 DeoxysDefense Forme Psychic 50 70 160 70 160 90 3 TRUE +386 DeoxysSpeed Forme Psychic 50 95 90 95 90 180 3 TRUE +387 Turtwig Grass 55 68 64 45 55 31 4 FALSE +388 Grotle Grass 75 89 85 55 65 36 4 FALSE +389 Torterra Grass Ground 95 109 105 75 85 56 4 FALSE +390 Chimchar Fire 44 58 44 58 44 61 4 FALSE +391 Monferno Fire Fighting 64 78 52 78 52 81 4 FALSE +392 Infernape Fire Fighting 76 104 71 104 71 108 4 FALSE +393 Piplup Water 53 51 53 61 56 40 4 FALSE +394 Prinplup Water 64 66 68 81 76 50 4 FALSE +395 Empoleon Water Steel 84 86 88 111 101 60 4 FALSE +396 Starly Normal Flying 40 55 30 30 30 60 4 FALSE +397 Staravia Normal Flying 55 75 50 40 40 80 4 FALSE +398 Staraptor Normal Flying 85 120 70 50 60 100 4 FALSE +399 Bidoof Normal 59 45 40 35 40 31 4 FALSE +400 Bibarel Normal Water 79 85 60 55 60 71 4 FALSE +401 Kricketot Bug 37 25 41 25 41 25 4 FALSE +402 Kricketune Bug 77 85 51 55 51 65 4 FALSE +403 Shinx Electric 45 65 34 40 34 45 4 FALSE +404 Luxio Electric 60 85 49 60 49 60 4 FALSE +405 Luxray Electric 80 120 79 95 79 70 4 FALSE +406 Budew Grass Poison 40 30 35 50 70 55 4 FALSE +407 Roserade Grass Poison 60 70 65 125 105 90 4 FALSE +408 Cranidos Rock 67 125 40 30 30 58 4 FALSE +409 Rampardos Rock 97 165 60 65 50 58 4 FALSE +410 Shieldon Rock Steel 30 42 118 42 88 30 4 FALSE +411 Bastiodon Rock Steel 60 52 168 47 138 30 4 FALSE +412 Burmy Bug 40 29 45 29 45 36 4 FALSE +413 WormadamPlant Cloak Bug Grass 60 59 85 79 105 36 4 FALSE +413 WormadamSandy Cloak Bug Ground 60 79 105 59 85 36 4 FALSE +413 WormadamTrash Cloak Bug Steel 60 69 95 69 95 36 4 FALSE +414 Mothim Bug Flying 70 94 50 94 50 66 4 FALSE +415 Combee Bug Flying 30 30 42 30 42 70 4 FALSE +416 Vespiquen Bug Flying 70 80 102 80 102 40 4 FALSE +417 Pachirisu Electric 60 45 70 45 90 95 4 FALSE +418 Buizel Water 55 65 35 60 30 85 4 FALSE +419 Floatzel Water 85 105 55 85 50 115 4 FALSE +420 Cherubi Grass 45 35 45 62 53 35 4 FALSE +421 Cherrim Grass 70 60 70 87 78 85 4 FALSE +422 Shellos Water 76 48 48 57 62 34 4 FALSE +423 Gastrodon Water Ground 111 83 68 92 82 39 4 FALSE +424 Ambipom Normal 75 100 66 60 66 115 4 FALSE +425 Drifloon Ghost Flying 90 50 34 60 44 70 4 FALSE +426 Drifblim Ghost Flying 150 80 44 90 54 80 4 FALSE +427 Buneary Normal 55 66 44 44 56 85 4 FALSE +428 Lopunny Normal 65 76 84 54 96 105 4 FALSE +428 LopunnyMega Lopunny Normal Fighting 65 136 94 54 96 135 4 FALSE +429 Mismagius Ghost 60 60 60 105 105 105 4 FALSE +430 Honchkrow Dark Flying 100 125 52 105 52 71 4 FALSE +431 Glameow Normal 49 55 42 42 37 85 4 FALSE +432 Purugly Normal 71 82 64 64 59 112 4 FALSE +433 Chingling Psychic 45 30 50 65 50 45 4 FALSE +434 Stunky Poison Dark 63 63 47 41 41 74 4 FALSE +435 Skuntank Poison Dark 103 93 67 71 61 84 4 FALSE +436 Bronzor Steel Psychic 57 24 86 24 86 23 4 FALSE +437 Bronzong Steel Psychic 67 89 116 79 116 33 4 FALSE +438 Bonsly Rock 50 80 95 10 45 10 4 FALSE +439 Mime Jr. Psychic Fairy 20 25 45 70 90 60 4 FALSE +440 Happiny Normal 100 5 5 15 65 30 4 FALSE +441 Chatot Normal Flying 76 65 45 92 42 91 4 FALSE +442 Spiritomb Ghost Dark 50 92 108 92 108 35 4 FALSE +443 Gible Dragon Ground 58 70 45 40 45 42 4 FALSE +444 Gabite Dragon Ground 68 90 65 50 55 82 4 FALSE +445 Garchomp Dragon Ground 108 130 95 80 85 102 4 FALSE +445 GarchompMega Garchomp Dragon Ground 108 170 115 120 95 92 4 FALSE +446 Munchlax Normal 135 85 40 40 85 5 4 FALSE +447 Riolu Fighting 40 70 40 35 40 60 4 FALSE +448 Lucario Fighting Steel 70 110 70 115 70 90 4 FALSE +448 LucarioMega Lucario Fighting Steel 70 145 88 140 70 112 4 FALSE +449 Hippopotas Ground 68 72 78 38 42 32 4 FALSE +450 Hippowdon Ground 108 112 118 68 72 47 4 FALSE +451 Skorupi Poison Bug 40 50 90 30 55 65 4 FALSE +452 Drapion Poison Dark 70 90 110 60 75 95 4 FALSE +453 Croagunk Poison Fighting 48 61 40 61 40 50 4 FALSE +454 Toxicroak Poison Fighting 83 106 65 86 65 85 4 FALSE +455 Carnivine Grass 74 100 72 90 72 46 4 FALSE +456 Finneon Water 49 49 56 49 61 66 4 FALSE +457 Lumineon Water 69 69 76 69 86 91 4 FALSE +458 Mantyke Water Flying 45 20 50 60 120 50 4 FALSE +459 Snover Grass Ice 60 62 50 62 60 40 4 FALSE +460 Abomasnow Grass Ice 90 92 75 92 85 60 4 FALSE +460 AbomasnowMega Abomasnow Grass Ice 90 132 105 132 105 30 4 FALSE +461 Weavile Dark Ice 70 120 65 45 85 125 4 FALSE +462 Magnezone Electric Steel 70 70 115 130 90 60 4 FALSE +463 Lickilicky Normal 110 85 95 80 95 50 4 FALSE +464 Rhyperior Ground Rock 115 140 130 55 55 40 4 FALSE +465 Tangrowth Grass 100 100 125 110 50 50 4 FALSE +466 Electivire Electric 75 123 67 95 85 95 4 FALSE +467 Magmortar Fire 75 95 67 125 95 83 4 FALSE +468 Togekiss Fairy Flying 85 50 95 120 115 80 4 FALSE +469 Yanmega Bug Flying 86 76 86 116 56 95 4 FALSE +470 Leafeon Grass 65 110 130 60 65 95 4 FALSE +471 Glaceon Ice 65 60 110 130 95 65 4 FALSE +472 Gliscor Ground Flying 75 95 125 45 75 95 4 FALSE +473 Mamoswine Ice Ground 110 130 80 70 60 80 4 FALSE +474 Porygon-Z Normal 85 80 70 135 75 90 4 FALSE +475 Gallade Psychic Fighting 68 125 65 65 115 80 4 FALSE +475 GalladeMega Gallade Psychic Fighting 68 165 95 65 115 110 4 FALSE +476 Probopass Rock Steel 60 55 145 75 150 40 4 FALSE +477 Dusknoir Ghost 45 100 135 65 135 45 4 FALSE +478 Froslass Ice Ghost 70 80 70 80 70 110 4 FALSE +479 Rotom Electric Ghost 50 50 77 95 77 91 4 FALSE +479 RotomHeat Rotom Electric Fire 50 65 107 105 107 86 4 FALSE +479 RotomWash Rotom Electric Water 50 65 107 105 107 86 4 FALSE +479 RotomFrost Rotom Electric Ice 50 65 107 105 107 86 4 FALSE +479 RotomFan Rotom Electric Flying 50 65 107 105 107 86 4 FALSE +479 RotomMow Rotom Electric Grass 50 65 107 105 107 86 4 FALSE +480 Uxie Psychic 75 75 130 75 130 95 4 TRUE +481 Mesprit Psychic 80 105 105 105 105 80 4 TRUE +482 Azelf Psychic 75 125 70 125 70 115 4 TRUE +483 Dialga Steel Dragon 100 120 120 150 100 90 4 TRUE +484 Palkia Water Dragon 90 120 100 150 120 100 4 TRUE +485 Heatran Fire Steel 91 90 106 130 106 77 4 TRUE +486 Regigigas Normal 110 160 110 80 110 100 4 TRUE +487 GiratinaAltered Forme Ghost Dragon 150 100 120 100 120 90 4 TRUE +487 GiratinaOrigin Forme Ghost Dragon 150 120 100 120 100 90 4 TRUE +488 Cresselia Psychic 120 70 120 75 130 85 4 FALSE +489 Phione Water 80 80 80 80 80 80 4 FALSE +490 Manaphy Water 100 100 100 100 100 100 4 FALSE +491 Darkrai Dark 70 90 90 135 90 125 4 TRUE +492 ShayminLand Forme Grass 100 100 100 100 100 100 4 TRUE +492 ShayminSky Forme Grass Flying 100 103 75 120 75 127 4 TRUE +493 Arceus Normal 120 120 120 120 120 120 4 TRUE +494 Victini Psychic Fire 100 100 100 100 100 100 5 TRUE +495 Snivy Grass 45 45 55 45 55 63 5 FALSE +496 Servine Grass 60 60 75 60 75 83 5 FALSE +497 Serperior Grass 75 75 95 75 95 113 5 FALSE +498 Tepig Fire 65 63 45 45 45 45 5 FALSE +499 Pignite Fire Fighting 90 93 55 70 55 55 5 FALSE +500 Emboar Fire Fighting 110 123 65 100 65 65 5 FALSE +501 Oshawott Water 55 55 45 63 45 45 5 FALSE +502 Dewott Water 75 75 60 83 60 60 5 FALSE +503 Samurott Water 95 100 85 108 70 70 5 FALSE +504 Patrat Normal 45 55 39 35 39 42 5 FALSE +505 Watchog Normal 60 85 69 60 69 77 5 FALSE +506 Lillipup Normal 45 60 45 25 45 55 5 FALSE +507 Herdier Normal 65 80 65 35 65 60 5 FALSE +508 Stoutland Normal 85 110 90 45 90 80 5 FALSE +509 Purrloin Dark 41 50 37 50 37 66 5 FALSE +510 Liepard Dark 64 88 50 88 50 106 5 FALSE +511 Pansage Grass 50 53 48 53 48 64 5 FALSE +512 Simisage Grass 75 98 63 98 63 101 5 FALSE +513 Pansear Fire 50 53 48 53 48 64 5 FALSE +514 Simisear Fire 75 98 63 98 63 101 5 FALSE +515 Panpour Water 50 53 48 53 48 64 5 FALSE +516 Simipour Water 75 98 63 98 63 101 5 FALSE +517 Munna Psychic 76 25 45 67 55 24 5 FALSE +518 Musharna Psychic 116 55 85 107 95 29 5 FALSE +519 Pidove Normal Flying 50 55 50 36 30 43 5 FALSE +520 Tranquill Normal Flying 62 77 62 50 42 65 5 FALSE +521 Unfezant Normal Flying 80 115 80 65 55 93 5 FALSE +522 Blitzle Electric 45 60 32 50 32 76 5 FALSE +523 Zebstrika Electric 75 100 63 80 63 116 5 FALSE +524 Roggenrola Rock 55 75 85 25 25 15 5 FALSE +525 Boldore Rock 70 105 105 50 40 20 5 FALSE +526 Gigalith Rock 85 135 130 60 80 25 5 FALSE +527 Woobat Psychic Flying 55 45 43 55 43 72 5 FALSE +528 Swoobat Psychic Flying 67 57 55 77 55 114 5 FALSE +529 Drilbur Ground 60 85 40 30 45 68 5 FALSE +530 Excadrill Ground Steel 110 135 60 50 65 88 5 FALSE +531 Audino Normal 103 60 86 60 86 50 5 FALSE +531 AudinoMega Audino Normal Fairy 103 60 126 80 126 50 5 FALSE +532 Timburr Fighting 75 80 55 25 35 35 5 FALSE +533 Gurdurr Fighting 85 105 85 40 50 40 5 FALSE +534 Conkeldurr Fighting 105 140 95 55 65 45 5 FALSE +535 Tympole Water 50 50 40 50 40 64 5 FALSE +536 Palpitoad Water Ground 75 65 55 65 55 69 5 FALSE +537 Seismitoad Water Ground 105 95 75 85 75 74 5 FALSE +538 Throh Fighting 120 100 85 30 85 45 5 FALSE +539 Sawk Fighting 75 125 75 30 75 85 5 FALSE +540 Sewaddle Bug Grass 45 53 70 40 60 42 5 FALSE +541 Swadloon Bug Grass 55 63 90 50 80 42 5 FALSE +542 Leavanny Bug Grass 75 103 80 70 80 92 5 FALSE +543 Venipede Bug Poison 30 45 59 30 39 57 5 FALSE +544 Whirlipede Bug Poison 40 55 99 40 79 47 5 FALSE +545 Scolipede Bug Poison 60 100 89 55 69 112 5 FALSE +546 Cottonee Grass Fairy 40 27 60 37 50 66 5 FALSE +547 Whimsicott Grass Fairy 60 67 85 77 75 116 5 FALSE +548 Petilil Grass 45 35 50 70 50 30 5 FALSE +549 Lilligant Grass 70 60 75 110 75 90 5 FALSE +550 Basculin Water 70 92 65 80 55 98 5 FALSE +551 Sandile Ground Dark 50 72 35 35 35 65 5 FALSE +552 Krokorok Ground Dark 60 82 45 45 45 74 5 FALSE +553 Krookodile Ground Dark 95 117 80 65 70 92 5 FALSE +554 Darumaka Fire 70 90 45 15 45 50 5 FALSE +555 DarmanitanStandard Mode Fire 105 140 55 30 55 95 5 FALSE +555 DarmanitanZen Mode Fire Psychic 105 30 105 140 105 55 5 FALSE +556 Maractus Grass 75 86 67 106 67 60 5 FALSE +557 Dwebble Bug Rock 50 65 85 35 35 55 5 FALSE +558 Crustle Bug Rock 70 95 125 65 75 45 5 FALSE +559 Scraggy Dark Fighting 50 75 70 35 70 48 5 FALSE +560 Scrafty Dark Fighting 65 90 115 45 115 58 5 FALSE +561 Sigilyph Psychic Flying 72 58 80 103 80 97 5 FALSE +562 Yamask Ghost 38 30 85 55 65 30 5 FALSE +563 Cofagrigus Ghost 58 50 145 95 105 30 5 FALSE +564 Tirtouga Water Rock 54 78 103 53 45 22 5 FALSE +565 Carracosta Water Rock 74 108 133 83 65 32 5 FALSE +566 Archen Rock Flying 55 112 45 74 45 70 5 FALSE +567 Archeops Rock Flying 75 140 65 112 65 110 5 FALSE +568 Trubbish Poison 50 50 62 40 62 65 5 FALSE +569 Garbodor Poison 80 95 82 60 82 75 5 FALSE +570 Zorua Dark 40 65 40 80 40 65 5 FALSE +571 Zoroark Dark 60 105 60 120 60 105 5 FALSE +572 Minccino Normal 55 50 40 40 40 75 5 FALSE +573 Cinccino Normal 75 95 60 65 60 115 5 FALSE +574 Gothita Psychic 45 30 50 55 65 45 5 FALSE +575 Gothorita Psychic 60 45 70 75 85 55 5 FALSE +576 Gothitelle Psychic 70 55 95 95 110 65 5 FALSE +577 Solosis Psychic 45 30 40 105 50 20 5 FALSE +578 Duosion Psychic 65 40 50 125 60 30 5 FALSE +579 Reuniclus Psychic 110 65 75 125 85 30 5 FALSE +580 Ducklett Water Flying 62 44 50 44 50 55 5 FALSE +581 Swanna Water Flying 75 87 63 87 63 98 5 FALSE +582 Vanillite Ice 36 50 50 65 60 44 5 FALSE +583 Vanillish Ice 51 65 65 80 75 59 5 FALSE +584 Vanilluxe Ice 71 95 85 110 95 79 5 FALSE +585 Deerling Normal Grass 60 60 50 40 50 75 5 FALSE +586 Sawsbuck Normal Grass 80 100 70 60 70 95 5 FALSE +587 Emolga Electric Flying 55 75 60 75 60 103 5 FALSE +588 Karrablast Bug 50 75 45 40 45 60 5 FALSE +589 Escavalier Bug Steel 70 135 105 60 105 20 5 FALSE +590 Foongus Grass Poison 69 55 45 55 55 15 5 FALSE +591 Amoonguss Grass Poison 114 85 70 85 80 30 5 FALSE +592 Frillish Water Ghost 55 40 50 65 85 40 5 FALSE +593 Jellicent Water Ghost 100 60 70 85 105 60 5 FALSE +594 Alomomola Water 165 75 80 40 45 65 5 FALSE +595 Joltik Bug Electric 50 47 50 57 50 65 5 FALSE +596 Galvantula Bug Electric 70 77 60 97 60 108 5 FALSE +597 Ferroseed Grass Steel 44 50 91 24 86 10 5 FALSE +598 Ferrothorn Grass Steel 74 94 131 54 116 20 5 FALSE +599 Klink Steel 40 55 70 45 60 30 5 FALSE +600 Klang Steel 60 80 95 70 85 50 5 FALSE +601 Klinklang Steel 60 100 115 70 85 90 5 FALSE +602 Tynamo Electric 35 55 40 45 40 60 5 FALSE +603 Eelektrik Electric 65 85 70 75 70 40 5 FALSE +604 Eelektross Electric 85 115 80 105 80 50 5 FALSE +605 Elgyem Psychic 55 55 55 85 55 30 5 FALSE +606 Beheeyem Psychic 75 75 75 125 95 40 5 FALSE +607 Litwick Ghost Fire 50 30 55 65 55 20 5 FALSE +608 Lampent Ghost Fire 60 40 60 95 60 55 5 FALSE +609 Chandelure Ghost Fire 60 55 90 145 90 80 5 FALSE +610 Axew Dragon 46 87 60 30 40 57 5 FALSE +611 Fraxure Dragon 66 117 70 40 50 67 5 FALSE +612 Haxorus Dragon 76 147 90 60 70 97 5 FALSE +613 Cubchoo Ice 55 70 40 60 40 40 5 FALSE +614 Beartic Ice 95 110 80 70 80 50 5 FALSE +615 Cryogonal Ice 70 50 30 95 135 105 5 FALSE +616 Shelmet Bug 50 40 85 40 65 25 5 FALSE +617 Accelgor Bug 80 70 40 100 60 145 5 FALSE +618 Stunfisk Ground Electric 109 66 84 81 99 32 5 FALSE +619 Mienfoo Fighting 45 85 50 55 50 65 5 FALSE +620 Mienshao Fighting 65 125 60 95 60 105 5 FALSE +621 Druddigon Dragon 77 120 90 60 90 48 5 FALSE +622 Golett Ground Ghost 59 74 50 35 50 35 5 FALSE +623 Golurk Ground Ghost 89 124 80 55 80 55 5 FALSE +624 Pawniard Dark Steel 45 85 70 40 40 60 5 FALSE +625 Bisharp Dark Steel 65 125 100 60 70 70 5 FALSE +626 Bouffalant Normal 95 110 95 40 95 55 5 FALSE +627 Rufflet Normal Flying 70 83 50 37 50 60 5 FALSE +628 Braviary Normal Flying 100 123 75 57 75 80 5 FALSE +629 Vullaby Dark Flying 70 55 75 45 65 60 5 FALSE +630 Mandibuzz Dark Flying 110 65 105 55 95 80 5 FALSE +631 Heatmor Fire 85 97 66 105 66 65 5 FALSE +632 Durant Bug Steel 58 109 112 48 48 109 5 FALSE +633 Deino Dark Dragon 52 65 50 45 50 38 5 FALSE +634 Zweilous Dark Dragon 72 85 70 65 70 58 5 FALSE +635 Hydreigon Dark Dragon 92 105 90 125 90 98 5 FALSE +636 Larvesta Bug Fire 55 85 55 50 55 60 5 FALSE +637 Volcarona Bug Fire 85 60 65 135 105 100 5 FALSE +638 Cobalion Steel Fighting 91 90 129 90 72 108 5 TRUE +639 Terrakion Rock Fighting 91 129 90 72 90 108 5 TRUE +640 Virizion Grass Fighting 91 90 72 90 129 108 5 TRUE +641 TornadusIncarnate Forme Flying 79 115 70 125 80 111 5 TRUE +641 TornadusTherian Forme Flying 79 100 80 110 90 121 5 TRUE +642 ThundurusIncarnate Forme Electric Flying 79 115 70 125 80 111 5 TRUE +642 ThundurusTherian Forme Electric Flying 79 105 70 145 80 101 5 TRUE +643 Reshiram Dragon Fire 100 120 100 150 120 90 5 TRUE +644 Zekrom Dragon Electric 100 150 120 120 100 90 5 TRUE +645 LandorusIncarnate Forme Ground Flying 89 125 90 115 80 101 5 TRUE +645 LandorusTherian Forme Ground Flying 89 145 90 105 80 91 5 TRUE +646 Kyurem Dragon Ice 125 130 90 130 90 95 5 TRUE +646 KyuremBlack Kyurem Dragon Ice 125 170 100 120 90 95 5 TRUE +646 KyuremWhite Kyurem Dragon Ice 125 120 90 170 100 95 5 TRUE +647 KeldeoOrdinary Forme Water Fighting 91 72 90 129 90 108 5 FALSE +647 KeldeoResolute Forme Water Fighting 91 72 90 129 90 108 5 FALSE +648 MeloettaAria Forme Normal Psychic 100 77 77 128 128 90 5 FALSE +648 MeloettaPirouette Forme Normal Fighting 100 128 90 77 77 128 5 FALSE +649 Genesect Bug Steel 71 120 95 120 95 99 5 FALSE +650 Chespin Grass 56 61 65 48 45 38 6 FALSE +651 Quilladin Grass 61 78 95 56 58 57 6 FALSE +652 Chesnaught Grass Fighting 88 107 122 74 75 64 6 FALSE +653 Fennekin Fire 40 45 40 62 60 60 6 FALSE +654 Braixen Fire 59 59 58 90 70 73 6 FALSE +655 Delphox Fire Psychic 75 69 72 114 100 104 6 FALSE +656 Froakie Water 41 56 40 62 44 71 6 FALSE +657 Frogadier Water 54 63 52 83 56 97 6 FALSE +658 Greninja Water Dark 72 95 67 103 71 122 6 FALSE +659 Bunnelby Normal 38 36 38 32 36 57 6 FALSE +660 Diggersby Normal Ground 85 56 77 50 77 78 6 FALSE +661 Fletchling Normal Flying 45 50 43 40 38 62 6 FALSE +662 Fletchinder Fire Flying 62 73 55 56 52 84 6 FALSE +663 Talonflame Fire Flying 78 81 71 74 69 126 6 FALSE +664 Scatterbug Bug 38 35 40 27 25 35 6 FALSE +665 Spewpa Bug 45 22 60 27 30 29 6 FALSE +666 Vivillon Bug Flying 80 52 50 90 50 89 6 FALSE +667 Litleo Fire Normal 62 50 58 73 54 72 6 FALSE +668 Pyroar Fire Normal 86 68 72 109 66 106 6 FALSE +669 Flabébé Fairy 44 38 39 61 79 42 6 FALSE +670 Floette Fairy 54 45 47 75 98 52 6 FALSE +671 Florges Fairy 78 65 68 112 154 75 6 FALSE +672 Skiddo Grass 66 65 48 62 57 52 6 FALSE +673 Gogoat Grass 123 100 62 97 81 68 6 FALSE +674 Pancham Fighting 67 82 62 46 48 43 6 FALSE +675 Pangoro Fighting Dark 95 124 78 69 71 58 6 FALSE +676 Furfrou Normal 75 80 60 65 90 102 6 FALSE +677 Espurr Psychic 62 48 54 63 60 68 6 FALSE +678 MeowsticMale Psychic 74 48 76 83 81 104 6 FALSE +678 MeowsticFemale Psychic 74 48 76 83 81 104 6 FALSE +679 Honedge Steel Ghost 45 80 100 35 37 28 6 FALSE +680 Doublade Steel Ghost 59 110 150 45 49 35 6 FALSE +681 AegislashBlade Forme Steel Ghost 60 150 50 150 50 60 6 FALSE +681 AegislashShield Forme Steel Ghost 60 50 150 50 150 60 6 FALSE +682 Spritzee Fairy 78 52 60 63 65 23 6 FALSE +683 Aromatisse Fairy 101 72 72 99 89 29 6 FALSE +684 Swirlix Fairy 62 48 66 59 57 49 6 FALSE +685 Slurpuff Fairy 82 80 86 85 75 72 6 FALSE +686 Inkay Dark Psychic 53 54 53 37 46 45 6 FALSE +687 Malamar Dark Psychic 86 92 88 68 75 73 6 FALSE +688 Binacle Rock Water 42 52 67 39 56 50 6 FALSE +689 Barbaracle Rock Water 72 105 115 54 86 68 6 FALSE +690 Skrelp Poison Water 50 60 60 60 60 30 6 FALSE +691 Dragalge Poison Dragon 65 75 90 97 123 44 6 FALSE +692 Clauncher Water 50 53 62 58 63 44 6 FALSE +693 Clawitzer Water 71 73 88 120 89 59 6 FALSE +694 Helioptile Electric Normal 44 38 33 61 43 70 6 FALSE +695 Heliolisk Electric Normal 62 55 52 109 94 109 6 FALSE +696 Tyrunt Rock Dragon 58 89 77 45 45 48 6 FALSE +697 Tyrantrum Rock Dragon 82 121 119 69 59 71 6 FALSE +698 Amaura Rock Ice 77 59 50 67 63 46 6 FALSE +699 Aurorus Rock Ice 123 77 72 99 92 58 6 FALSE +700 Sylveon Fairy 95 65 65 110 130 60 6 FALSE +701 Hawlucha Fighting Flying 78 92 75 74 63 118 6 FALSE +702 Dedenne Electric Fairy 67 58 57 81 67 101 6 FALSE +703 Carbink Rock Fairy 50 50 150 50 150 50 6 FALSE +704 Goomy Dragon 45 50 35 55 75 40 6 FALSE +705 Sliggoo Dragon 68 75 53 83 113 60 6 FALSE +706 Goodra Dragon 90 100 70 110 150 80 6 FALSE +707 Klefki Steel Fairy 57 80 91 80 87 75 6 FALSE +708 Phantump Ghost Grass 43 70 48 50 60 38 6 FALSE +709 Trevenant Ghost Grass 85 110 76 65 82 56 6 FALSE +710 PumpkabooAverage Size Ghost Grass 49 66 70 44 55 51 6 FALSE +710 PumpkabooSmall Size Ghost Grass 44 66 70 44 55 56 6 FALSE +710 PumpkabooLarge Size Ghost Grass 54 66 70 44 55 46 6 FALSE +710 PumpkabooSuper Size Ghost Grass 59 66 70 44 55 41 6 FALSE +711 GourgeistAverage Size Ghost Grass 65 90 122 58 75 84 6 FALSE +711 GourgeistSmall Size Ghost Grass 55 85 122 58 75 99 6 FALSE +711 GourgeistLarge Size Ghost Grass 75 95 122 58 75 69 6 FALSE +711 GourgeistSuper Size Ghost Grass 85 100 122 58 75 54 6 FALSE +712 Bergmite Ice 55 69 85 32 35 28 6 FALSE +713 Avalugg Ice 95 117 184 44 46 28 6 FALSE +714 Noibat Flying Dragon 40 30 35 45 40 55 6 FALSE +715 Noivern Flying Dragon 85 70 80 97 80 123 6 FALSE +716 Xerneas Fairy 126 131 95 131 98 99 6 TRUE +717 Yveltal Dark Flying 126 131 95 131 98 99 6 TRUE +718 Zygarde50% Forme Dragon Ground 108 100 121 81 95 95 6 TRUE +719 Diancie Rock Fairy 50 100 150 100 150 50 6 TRUE +719 DiancieMega Diancie Rock Fairy 50 160 110 160 110 110 6 TRUE +720 HoopaHoopa Confined Psychic Ghost 80 110 60 150 130 70 6 TRUE +720 HoopaHoopa Unbound Psychic Dark 80 160 60 170 130 80 6 TRUE +721 Volcanion Fire Water 80 110 120 130 90 70 6 TRUE diff --git a/extractPythonCodes.py b/extractPythonCodes.py new file mode 100644 index 0000000..09419a4 --- /dev/null +++ b/extractPythonCodes.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Sat Jun 18 10:40:57 2022 + +@author: solid +""" +import re +import os + +content = open('python-core.tex', 'r').read() +#split the file by \subsection, \section, \subsubsection tokens +splitted = content.split('\section') +splitted = ['\section\n' + s for s in splitted ] ## add splitter again + +splitted2 = [s for s in splitted if '{python}' in s ] +for i, s in enumerate(splitted2): + ## find and record section name + lines = s.split('\n') + header = lines[1].replace('{','') + header = header[: header.index('}')] + print("HEADER=== " + header) + ## find and record section name + + directoryPath = "examples/" + str(i).zfill(2) + "-" + header + os.makedirs(directoryPath,exist_ok = True) + + for j, k in enumerate( s.split('\subsection') ): + + try: + subHeader = k.split('\n')[0] + subHeader = subHeader.replace('{','') + subHeader = subHeader[ : subHeader.index("}")] + print(subHeader) + except: + subHeader = "intro" + + + z = '\section\n' + k + z = z.replace('\section','###################\n###################\n###################') + z = z.replace('\subsubsection','###################') +# z = k.replace('\subsection','###\n####') +# print(z) + + ##### annotate python block intervals + inPyBlock = [0 for f in range(len(z.split('\n')) ) ] + for l,line in enumerate(z.split('\n')): + if '\\begin{python}' in line: + inPyBlock[l:] = [1 for xxx in inPyBlock[l:]] + if '\\end{python}' in line: + inPyBlock[l+1:] = [0 for xxx in inPyBlock[l+1:]] + + procLines = [] + for l,line in enumerate(z.split('\n')): + if inPyBlock[l]: + lineProc = line + else: + lineProc = '#' + line + + lineProc = lineProc.replace('\\begin{python}','') + lineProc = lineProc.replace('\\end{python}','') + procLines.append(lineProc) + zz = '\n'.join(procLines) + + with open('%s/%s-%s.py' % (directoryPath,str(j).zfill(2),subHeader) , 'w+') as fp: + fp.write(zz) + + + \ No newline at end of file diff --git a/python-core.tex b/python-core.tex new file mode 100755 index 0000000..eb13ec9 --- /dev/null +++ b/python-core.tex @@ -0,0 +1,2661 @@ +\documentclass[11pt,a4paper]{article} +%%\documentclass[8pt,a4paper,twocolumn]{article} +\usepackage[a4paper,left=1cm,right=1cm,top=1.0cm,bottom=2.5cm]{geometry} +\usepackage[turkish]{babel} +\usepackage{times} +\usepackage{graphicx} +\usepackage{natbib} +\usepackage{algorithm} +\usepackage{algorithmic} +\usepackage[utf8]{inputenc} +\usepackage{nomencl} +\usepackage{commath} +\usepackage{url} +\usepackage{subfig} +\usepackage[colorinlistoftodos]{todonotes} +\usepackage{epstopdf} +\usepackage{amsmath} +\usepackage{mathtools} +\usepackage{paralist} +\usepackage{hyperref} +\usepackage{pythonhighlight} +\usepackage{listings} + + +\definecolor{codegreen}{rgb}{0,0.6,0} +\definecolor{codegray}{rgb}{0.5,0.5,0.5} +\definecolor{codepurple}{rgb}{0.58,0,0.82} +\definecolor{backcolour}{rgb}{0.95,0.95,0.92} + +\lstdefinestyle{mystyle}{ + backgroundcolor=\color{backcolour}, + commentstyle=\color{codegreen}, + keywordstyle=\color{magenta}, + numberstyle=\tiny\color{codegray}, + stringstyle=\color{codepurple}, + basicstyle=\footnotesize, + breakatwhitespace=false, + breaklines=true, + captionpos=b, + keepspaces=true, + numbers=left, + numbersep=5pt, + showspaces=false, + showstringspaces=false, + showtabs=false, + tabsize=2 +} + + + + +\def\ExtendVersion{1} +\newcommand{\credit}[1]{Thanks to: #1} + + +\input{taypack.tex} +%turning on/off comments +\usepackage{comment} +\includecomment{comment} %show comments +%\excludecomment{comment} %do not show comments + +\lstset{style=mystyle} +\begin{document} +\lstset{language=Python} + +% first the title is needed +\title{\centering{Python: From Basics to the Extreme}} + +% the name(s) of the author(s) follow(s) next +%\author{Keke\c{c}} +%\author{İbrâhim Taygun Keke\c{c}} +%\author{İbrâhim Taygun Keke\c{c}} +%\author{UL} + +\maketitle + +%\begin{abstract} +%\end{abstract} + +\newcounter{Madde}[section] +\newenvironment{Madde}[1][]{\refstepcounter{Madde}\par\medskip + \textbf{Md ~\theMadde. #1} \rmfamily}{\medskip} + +\newcommand{\citemd}[1]{(\textbf{M. {#1}})} + +\tableofcontents + +\section{Introduction} +This reference book contains very frequently used concepts in Python language. +The reader is assumed to be familiar with the abstract concepts of variables, loops, functions and such. +At each section, a working code example is provided. + +\textbf{Correct usage of the material.} +\begin{itemize} +\item analyze the code example +\item copy/paste and run the example +\item check the output of the code whether it makes sense. +\end{itemize} + +\section{Basics} + +\subsection{Variables and Data Types} +You can declare integer and string variables. +\begin{python} +x = 5 +y = "John" +print(x) +#5 +print(y) +#John +\end{python} + +Declare string, integer or float. +\begin{python} +x = str(3) # x will be '3' +y = int(3) # y will be 3 +z = float(3) # z will be 3.0 +print(type(x)) +# +print(type(y)) +# +\end{python} + +Different variable types exist. But for now, focus on string, integer, float, list, tuple, dictionary, and sets. +\begin{python} +Text Type: str +Numeric Types: int, float, complex +Sequence Types: list, tuple, range +Mapping Type: dict +Set Types: set, frozenset +Boolean Type: bool +Binary Types: bytes, bytearray, memoryview +None Type: NoneType +\end{python} + + +List is a collection which is ordered and changeable. Allows duplicate members. + +Tuple is a collection which is ordered and unchangeable. Allows duplicate members. + +Set is a collection which is unordered, unchangeable, and unindexed. No duplicate members. + +Dictionary is a collection which is ordered and changeable. No duplicate members. + +\subsection{List} +List is a python data type. Lists can store multiple variables in a single variable. +\begin{python} +thislist = ["apple", "banana", "cherry"] +print(thislist) +#['apple', 'banana', 'cherry'] +\end{python} + +\subsubsection{access list items} +\begin{python} +thislist = ["apple", "banana", "cherry"] +print(thislist[1]) +#banana +\end{python} + +\subsubsection{change list item value} +\begin{python} +thislist = ["apple", "banana", "cherry"] +thislist[1] = "blackcurrant" +print(thislist) +#['apple', 'blackcurrant', 'cherry'] +\end{python} + +\subsubsection{change a range of list item values} +\begin{python} +thislist = ["apple", "banana", "cherry", "orange", "kiwi", "mango"] +thislist[1:3] = ["blackcurrant", "watermelon"] +print(thislist) +#['apple', 'blackcurrant', 'watermelon', 'orange', 'kiwi', 'mango'] +\end{python} + +\subsubsection{add list items} +\begin{python} +thislist = ["apple", "banana", "cherry"] +thislist.append("orange") +print(thislist) +#['apple', 'banana', 'cherry', 'orange'] +\end{python} + +\subsubsection{remove list items} +\begin{python} +thislist = ["apple", "banana", "cherry"] +thislist.remove("banana") +print(thislist) +#['apple', 'cherry'] +\end{python} + +\paragraph{remove duplicates from the list} + +If new element is seen, first adds it to the list, and then returns it. + +\begin{python} +a = [1,2,3,2,1,5,6,5,5,5] +seen = set() +uniq = [x for x in a if x not in seen and not seen.add(x)] +print(uniq) +#[1, 2, 3, 5, 6] +\end{python} + +\subsubsection{looping a list} +\begin{python} +thislist = ["apple", "banana", "cherry"] +for x in thislist: + print(x) +#apple +#banana +#cherry +\end{python} + +\subsubsection{list slicing} +you can access multiple elements with slicing operation. +\begin{python} +thislist = ["apple", "banana", "cherry", "watermelon", "grape", "kiwi"] +print(thislist[1:4] ) +#['banana', 'cherry', 'watermelon'] + +## Here, we access each 2nd element from 1st to 6th element of the list. +print(thislist[1:6:2]) +#['banana', 'watermelon', 'kiwi'] + +## Reverse slicing: access elements from end to beginning of the list. +print(thislist[6:1:-1]) +#['kiwi', 'grape', 'watermelon', 'cherry'] + +\end{python} + +\subsubsection{list comprehension} +This powerful concept can single-line the traditional loops. +\begin{python} +fruits = ["apple", "banana", "cherry", "kiwi", "mango"] +newlist = [] + +for x in fruits: + if "a" in x: + newlist.append(x) + +print(newlist) +# ['apple', 'banana', 'mango'] + +fruits = ["apple", "banana", "cherry", "kiwi", "mango"] +newlist = [x for x in fruits if "a" in x] + +print(newlist) +# ['apple', 'banana', 'mango'] +\end{python} + +\subsubsection{list comprehension: condition + operation} +\begin{python} +fruits = ["apple", "banana", "cherry", "kiwi", "mango"] +newlist = [x.upper() for x in fruits] +print(newlist) +#['APPLE', 'BANANA', 'CHERRY', 'KIWI', 'MANGO'] +\end{python} + +\subsubsection{sorting a list} +\begin{python} +thislist = ["orange", "mango", "kiwi", "pineapple", "banana"] +thislist.sort() +print(thislist) +#['banana', 'kiwi', 'mango', 'orange', 'pineapple'] +\end{python} + +\subsubsection{copying a list} +\begin{python} +thislist = ["apple", "banana", "cherry"] +mylist = thislist.copy() +print(mylist) +#['apple', 'banana', 'cherry'] +\end{python} + +\subsubsection{join two lists} +\begin{python} +list1 = ["a", "b", "c"] +list2 = [1, 2, 3] + +list3 = list1 + list2 +print(list3) +#['a', 'b', 'c', 1, 2, 3] +\end{python} + + +\subsubsection{looping through multiple Lists} +\begin{python} +a = ['a1', 'a2', 'a3'] +b = ['b1', 'b2'] + +for x, y in zip(a, b): + print(x, y) +#a1 b1 +#a2 b2 +\end{python} + + +\subsubsection{other list methods} +\begin{python} +Method Description +append() Adds an element at the end of the list +clear() Removes all the elements from the list +copy() Returns a copy of the list +count() Returns the number of elements with the specified value +extend() Add the elements of a list (or any iterable), to the end of the current list +index() Returns the index of the first element with the specified value +insert() Adds an element at the specified position +pop() Removes the element at the specified position +remove() Removes the item with the specified value +reverse() Reverses the order of the list +sort() Sorts the list +\end{python} + +\subsection{Dictionary} +Unlike lists, in dictionary each entry has a key, and a value. These key, value pairs constitute the dictionary content. +\begin{python} +thisdict = { + "brand": "Ford", + "model": "Mustang", + "year": 1964 +} +print(thisdict) +#{'brand': 'Ford', 'model': 'Mustang', 'year': 1964} +\end{python} + +\subsubsection{access dictionary values} +\begin{python} +thisdict = { + "brand": "Ford", + "model": "Mustang", + "year": 1964 +} +print(thisdict["brand"]) +#Ford +\end{python} + +\subsubsection{access dictionary keys or values} +\begin{python} +car = { +"brand": "Ford", +"model": "Mustang", +"year": 1964 +} + +x = car.keys() +print(x) +#dict_keys(['brand', 'model', 'year']) +v = car.values() +print(v) +#dict_values(['Ford', 'Mustang', 1964]) +\end{python} + +\subsubsection{inverse dictionary lookup} +\begin{python} +d = {"a":0, "b":1, "c":2} +dict(zip(d.values(), d.keys())) +#{0: 'a', 1: 'b', 2: 'c'} +\end{python} + +\subsubsection{change dictionary items} +\begin{python} +car = { +"brand": "Ford", +"model": "Mustang", +"year": 1964 +} +x = car.items() + +print(x) #before the change +#dict_items([('brand', 'Ford'), ('model', 'Mustang'), ('year', 1964)]) + +car["year"] = 2020 +print(x) #after the change +#dict_items([('brand', 'Ford'), ('model', 'Mustang'), ('year', 2020)]) +\end{python} + +\subsubsection{add dictionary items} +\begin{python} +thisdict = { + "brand": "Ford", + "model": "Mustang", + "year": 1964 +} +thisdict["color"] = "red" +print(thisdict) +#{'brand': 'Ford', 'model': 'Mustang', 'year': 1964, 'color': 'red'} +\end{python} + +\subsubsection{remove dictionary item} +\begin{python} +thisdict = { + "brand": "Ford", + "model": "Mustang", + "year": 1964 +} +del thisdict["model"] +print(thisdict) +#{'brand': 'Ford', 'year': 1964} +\end{python} + +\subsubsection{looping a dictionary} +\begin{python} +thisdict={'brand': 'Ford', 'year': 1964} +for x, y in thisdict.items(): + print(x, y) +#brand Ford +#year 1964 +\end{python} + +\subsubsection{copy a dictionary} +\begin{python} +thisdict = { + "brand": "Ford", + "model": "Mustang", + "year": 1964 +} +mydict = thisdict.copy() +print(mydict) +#{'brand': 'Ford', 'model': 'Mustang', 'year': 1964} +\end{python} + + +\subsubsection{intersections of two dictionaries} +\begin{python} +some_dict = {'zope':'zzz', 'python':'rocks' } +another_dict = {'python':'rocks', 'perl':'interesting' } + +print "Intersects:", [k for k in some_dict if k in another_dict] +#python +\end{python} + +\subsubsection{other dictionary operations} +\begin{python} +clear() Removes all the elements from the dictionary +copy() Returns a copy of the dictionary +fromkeys() Returns a dictionary with the specified keys and value +get() Returns the value of the specified key +items() Returns a list containing a tuple for each key value pair +keys() Returns a list containing the dictionary's keys +pop() Removes the element with the specified key +popitem() Removes the last inserted key-value pair +setdefault() Returns the value of the specified key. If the key does not exist: insert the key, with the specified value +update() Updates the dictionary with the specified key-value pairs +values() Returns a list of all the values in the dictionary +\end{python} + +\subsection{Sets} +Python sets are like lists. They are used to store multiple items in a single variable.Set elements are unordered. Items are unchangeable, can't be altered after creation. But we can add and remove elements to the set. Unlike lists, they can't have two identical elements. + +\begin{python} +thisset = {"apple", "banana", "cherry"} +print(thisset) +#{'apple', 'cherry', 'banana'} + +##length +print(len(thisset)) +#3 +\end{python} + +Sets can have different objects as elements. +\begin{python} +set1 = {"abc", 34, True, 40, "male"} +\end{python} + +\subsubsection{access elements} +\begin{python} +thisset = {"apple", "banana", "cherry"} +for x in thisset: + print(x) +#apple +#cherry +#banana +\end{python} + +\subsubsection{check element existence} +\begin{python} +thisset = {"apple", "banana", "cherry"} +print("banana" in thisset) +#True +\end{python} + +\subsubsection{add elements} +\begin{python} +thisset = {"apple", "banana", "cherry"} +thisset.add("orange") +print(thisset) +#{'orange', 'apple', 'cherry', 'banana'} +\end{python} + +\subsubsection{remove elements} +We can remove the set elements with remove() function. +\begin{python} +thisset = {"apple", "banana", "cherry"} +thisset.remove("banana") +print(thisset) +#{'apple', 'cherry'} +\end{python} + +Alternatively we can remove the last element using the pop() function. +\begin{python} +thisset = {"apple", "banana", "cherry"} + +x = thisset.pop() +print(x) +#apple +print(thisset) +#{'cherry', 'banana'} +\end{python} + +\subsubsection{looping sets} +\begin{python} +thisset = {"apple", "banana", "cherry"} + +for x in thisset: + print(x) +#apple +#cherry +#banana +\end{python} + +\subsubsection{joining/combining/ (union) of sets} +\begin{python} +set1 = {"a", "b" , "c"} +set2 = {1, 2, 3} +set3 = set1.union(set2) +print(set3) +#{'a', 'b', 1, 2, 3, 'c'} +\end{python} + +\subsubsection{merge (intersection) of sets} +\begin{python} +x = {"apple", "banana", "cherry"} +y = {"google", "microsoft", "apple"} +z = x.intersection(y) +print(z) +#{'apple'} +\end{python} + +\subsection{Tuples} +Tuples are used to store multiple items in a single variable. +Elements of tuples are ordered and unchangeable. +\begin{python} +thistuple = ("apple", "banana", "cherry") +print(thistuple) +#('apple', 'banana', 'cherry') + +print(len(thistuple)) +#3 + +## a tuple with different objects +tuple1 = ("abc", 34, True, 40, "male") +\end{python} + +\subsubsection{accessing elements} +\begin{python} +thistuple = ("apple", "banana", "cherry") +print(thistuple[1]) +#banana + +##negative indexing +print(thistuple[-1]) +#cherry + +##slicing +thistuple = ("apple", "banana", "cherry", "orange", "kiwi", "melon", "mango") +print(thistuple[2:5]) +#('cherry', 'orange', 'kiwi') + +print(thistuple[:4]) +#('apple', 'banana', 'cherry', 'orange') +\end{python} + +\subsubsection{check element existence} +\begin{python} +thistuple = ("apple", "banana", "cherry") +if "apple" in thistuple: + print("Yes, 'apple' is in the fruits tuple") +#Yes, 'apple' is in the fruits tuple +\end{python} + + +\subsubsection{unpack elements} +\begin{python} +fruits = ("apple", "banana", "cherry", "strawberry", "raspberry") + +(green, yellow, *red) = fruits + +print(green) +#apple +print(yellow) +#banana +print(red) +#['cherry', 'strawberry', 'raspberry'] +\end{python} + + +\subsubsection{looping elements} +\begin{python} +thistuple = ("apple", "banana", "cherry") +for x in thistuple: + print(x) +#apple +#banana +#cherry +\end{python} + + +\subsubsection{joining two tuples} +\begin{python} +tuple1 = ("a", "b" , "c") +tuple2 = (1, 2, 3) + +tuple3 = tuple1 + tuple2 +print(tuple3) +#('a', 'b', 'c', 1, 2, 3) +\end{python} + +\subsubsection{multiply tuples} +\begin{python} +fruits = ("apple", "banana", "cherry") +mytuple = fruits * 2 +print(mytuple) +#('apple', 'banana', 'cherry', 'apple', 'banana', 'cherry') +\end{python} + +\subsection{If conditional} +If conditional checks for cases in your program. +\begin{python} +if 5 > 2: + print("Five is greater than two!") +#Five is greater than two! +\end{python} + +\subsubsection{Elif conditional} +\begin{python} +a = 33 +b = 33 +if b > a: + print("b is greater than a") +elif a == b: + print("a and b are equal") +#a and b are equal +\end{python} + +\subsubsection{Else-If conditional} +\begin{python} +a = 200 +b = 33 +if b > a: + print("b is greater than a") +elif a == b: + print("a and b are equal") +else: + print("a is greater than b") +#a is greater than b +\end{python} + +\subsubsection{Short If} +\begin{python} +if a > b: print("a is greater than b") +#a is greater than b +\end{python} + +\subsubsection{Short If-Else} +\begin{python} +a = 2 +b = 330 +print("A") if a > b else print("B") +# B +\end{python} + +\subsubsection{And or conditional} +\begin{python} +a = 200 +b = 33 +c = 500 +if a > b and c > a: + print("Both conditions are True") +# Both conditions are True + +if a > b or a > c: + print("At least one of the conditions is True") +#At least one of the conditions is True +\end{python} + +\subsubsection{Nested if} +With nested if's you can create branches in your program. +\begin{python} +x = 41 +if x > 10: + print("Above ten,") + if x > 20: + print("and also above 20!") + else: + print("but not above 20.") +#Above ten, +#and also above 20! +\end{python} + +\subsubsection{Pass} +if statements cannot be empty, if you need to have empty statment, use pass statement to avoid getting an error. +\begin{python} +a = 33 +b = 200 +if b > a: + pass +\end{python} + +\subsection{While Loop} +\begin{python} +i = 1 +while i < 4: + print(i) + i += 1 +#1 +#2 +#3 +\end{python} + +\subsubsection{Break statement} +You can exit the loops immediately with break statement. +\begin{python} +i = 1 +while i < 6: + print(i) + if i == 3: + break + i += 1 +#1 +#2 +#3 +\end{python} + +\subsubsection{Continue statement} +With continue statement we can stop the current iteration, and continue with the next. +\begin{python} +i = 0 +while i < 6: + i += 1 + if i == 3: + continue + print(i) +#1 +#2 +#4 +#5 +#6 +\end{python} + +\subsubsection{While-Else statement} +\begin{python} +i = 1 +while i < 6: + print(i) + i += 1 +else: + print("i is no longer less than 6") +#1 +#2 +#3 +#4 +#5 +#i is no longer less than 6 +\end{python} + +\subsection{For Loop} +\begin{python} +fruits = ["apple", "banana", "cherry"] +for x in fruits: + print(x) +#apple +#banana +#cherry +\end{python} + + +\subsubsection{Looping integers} +\begin{python} +for x in range(4): + print(x) +#0 +#1 +#2 +#3 +\end{python} + +\subsubsection{Looping a string variable} +\begin{python} +for x in "car": + print(x) +#c +#a +#r +\end{python} + +\subsubsection{breaking the loop} +\begin{python} +fruits = ["apple", "banana", "cherry"] +for x in fruits: + print(x) + if x == "banana": + break +#apple +#banana +\end{python} + +\subsubsection{for loop nested} +\begin{python} +adj = ["red", "big", "tasty"] +fruits = ["apple", "banana", "cherry"] + +for x in adj: + for y in fruits: + print(x, y) +#red apple +#red banana +#red cherry +#big apple +#big banana +#big cherry +#tasty apple +#tasty banana +#tasty cherry +\end{python} + +\subsubsection{for loop pass statement} +\begin{python} +for x in [0, 1, 2]: + pass +\end{python} + +\subsection{Function} +In python, you can declare functions. Functions are code pieces that you can execute multiple times easily. + +\subsubsection{defining a function} +\begin{python} +# define the function +def my_function(): + print("Hello from a function") +\end{python} + +\subsubsection{calling a function} +\begin{python} +def my_function(): + print("Hello from a function") + +my_function() +#Hello from a function +\end{python} + +\subsubsection{giving function an argument} + +\begin{python} +def my_function(fname): + print(fname + " Refsnes") + +my_function("Emil") +#Emil Refsnes +my_function("Tobias") +#Tobias Refsnes +my_function("Linus") +#Linus Refsnes +\end{python} + + +\subsubsection{giving function multiple arguments} +\begin{python} +def my_function(fname, lname): + print(fname + " " + lname) + +my_function("Emil", "Refsnes") +#Emil Refsnes +\end{python} + +\subsubsection{giving function with default parameters} +\begin{python} +def my_function(country = "Norway"): + print("I am from " + country) + +my_function("Sweden") +#I am from Sweden +my_function("India") +#I am from India +my_function() +#I am from Norway +my_function("Brazil") +#I am from Brazil +\end{python} + +\subsubsection{giving function unknown number of parameters} +\begin{python} +def my_function(*kids): + print("The youngest child is " + kids[2]) + +my_function("Emil", "Tobias", "Linus") +#The youngest child is Linus +\end{python} + +\subsubsection{function returning values} +\begin{python} +def my_function(x): + return 5 * x + +print(my_function(3)) +#15 +print(my_function(5)) +#25 +print(my_function(9)) +#45 + +\end{python} + +\subsubsection{function returning multiple values} +\begin{python} +def my_function(x): + return 5 * x, x * x + +print(my_function(3)) +#(15, 9) +print(my_function(10)) +#(50, 100) +print(type(my_function(10))) +# +\end{python} + +\subsubsection{shortcut function: lambda} +Lambda functions are one-liner functions. Sometimes you need to define such functions inside others. This gives very much ease. +\begin{python} +x = lambda a : a + 10 +print(x(5)) +#15 + +x = lambda a, b : a * b +print(x(5, 6)) +#30 + +x = lambda a, b, c : a + b + c +print(x(5, 6, 2)) +#13 +\end{python} + +\subsection{Modules} +Python modules are libraries (set of functions) written by others. Using these code pieces help you to re-use written code. + +\subsubsection{writing a module} +Save the following to a file named mymodule.py . +\begin{python} +def greeting(name): + print("Hello, " + name) + +person1 = { + "name": "John", + "age": 36, + "country": "Norway" +} + +\end{python} + +\subsubsection{use functions of a module} +\begin{python} +import mymodule +mymodule.greeting("Jonathan") +#Hello Jonathan +\end{python} + +\subsubsection{custom naming a module} +\begin{python} +import mymodule as mx +a = mx.person1["age"] +print(a) +#36 +\end{python} + +\subsubsection{partial import of a module} +Sometimes, you just need a function, or an object from a module package. In these cases, you only import that part of the module. No need to import whole module. This is a better practice. +\begin{python} +from mymodule import person1 +print (person1["age"]) +#36 +\end{python} + +\subsubsection{listing functions of the module} +You can list all the function names in a module with dir command. +\begin{python} +import platform +x = dir(platform) +# too long to write the output... check your program. +\end{python} + +\subsection{Classes} +%Python supports object oriented programming (OOP). In default, what we are doing is functional programming. That is, +%the program is a composition of functions. In OOP, similar to the real world, we have objects. These objects are represented by classes in the program. + +%A class has attributes, and methods (in other word class functions). We create instances from that class using class constructor. +\begin{python} +class Person: + def __init__(mysillyobject, name, age): + mysillyobject.name = name + mysillyobject.age = age + + def myfunc(abc): + print("Hello my name is " + abc.name) + +p1 = Person("John", 36) +p1.myfunc() +\end{python} + +\subsection{Uncategorized} + +\subsubsection{add padding to opencv image} +\begin{python} + +#cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color) +padSize = 500 +ib = cv2.copyMakeBorder(img_dilated, padSize, padSize, padSize, padSize, cv2.BORDER_CONSTANT, (0,0,0)) + +\end{python} +\subsubsection{find neighboring pairs in list} +\begin{python} +A = [1, 2, 3, 4] +B = [(i,j) for i,j in zip(A, A[1:])] +#[(1, 2), (2, 3), (3, 4)] +\end{python} + +\subsubsection{find most frequent elements in list} +\begin{python} +from collections import Counter +mylist = [1,1,1,1,3,4,5,5,5,6,6,7,8,9] +counter = Counter(mylist) +most_common = counter.most_common(2) +print(most_common) +#[(1, 4), (5, 3)] # 4 ones, 3 fives seen. +\end{python} + +\subsubsection{cartesian product of two lists} +\begin{python} +import itertools +a = [1,2,3] +b = [4,5,6] +for i in itertools.product( a, b ): + print(i) +\end{python} + +\subsubsection{pad integer to have zeros} +\begin{python} +def NDigited(x,n=3): + return (n-len(x)) * '0' + x +\end{python} + +\paragraph{optimized version} +\credit{jnmbk} +\begin{python} +def NDigited(x,n=3) +return x.zfill(n) +\end{python} + +\subsubsection{matplotlib display strings on y-axis} +\begin{python} +yticks(np.arange(5), ('String1', 'String2', 'String3', '4', '5')) +\end{python} + +\subsubsection{broadcast image or matrix channels} +This operation is usually needed to go from 1d image to 3d image. +\begin{python} +nChannels = 3 +m3d = np.repeat( m.reshape(m.shape[0], m.shape[1], 1), nChannels, axis=2) +\end{python} + +Another identical way to do it. +\begin{python} +nChannels = 3 +m3d = np.tile(m[:, :, None], [1, 1, nChannels]) +\end{python} + +\subsubsection{1d interpolation of x-y values} +Given a set of 2D points, we fit a curve to these points. +\begin{python} +xdata = [0,1,2,3,4,5] +ydata = [0,1,4,9,16,25] +f2 = interp1d(xdata, ydata, kind = 'quadratic') +xnew = np.linspace(-5, 5, 1000) +ynew = f2(xnew) +\end{python} + +\subsection{useful numpy functions} +\begin{python} +## remove empty dimension +x = np.array([[[0], [1], [2]]]) +print(x.shape) +#(1, 3, 1) +dd = np.squeeze(cc) +print(x.shape) +#(3,) + +## vertically stack list of matrices +x = np.dstack( possibleCurves ) + +## randomly choose 5 values from the interval 0-100 +randIdxs = np.random.choice(100 , 5, replace=False) + +## reshape 1D data for one feature problems +X = x.reshape(-1,1) + +\end{python} + +\section{String Manipulation, Searching, Sorting}\label{sect:strings} + +\subsection{substring search} + +\begin{python} +word = 'cart for supermarket' + +##substring search: find first occurrence +result = word.find('supermarket') +print("Substring 'geeks' found at index:", result) +#Substring 'geeks' found at index: 9 + +##substring search with start end specification: searched in 'for su'. +print(word.find('su', 4, 12)) +#9 +\end{python} + +\subsubsection{string between two substrings} +\begin{python} +import re +s = 'asdf=5;iwantthis123jasd' +result = re.search('asdf=5;(.*)123jasd', s) +print(result.group(1)) +#iwantthis +\end{python} + +\subsubsection{Create index for strings} +\begin{python} +a = ['a', 'b', 'c'] +b = dict(map(lambda t: (t[1], t[0]), enumerate(a))) +#{'a':0, 'b':1, 'c':2} +\end{python} + +\subsection{string concatenation} +\begin{python} +s1 = "myStrFirst" +s2 = "secondString" +s3 = s1 + " " + s2 +print(s3) +#myStrFirst secondString +\end{python} + +\subsection{string splitting} +\begin{python} +## simple string splitting +txt = "apple#banana#cherry#orange" +x = txt.split("#") +print(x) +#['apple', 'banana', 'cherry', 'orange'] + +## setting the maxsplit parameter to 1, will return a list with 2 elements! +txt = "apple#banana#cherry#orange" +x = txt.split("#", 1) +#['apple', 'banana#cherry#orange'] +\end{python} + +\subsection{stripping string} +Remove leading and trailing spaces and specific characters at the beginning and at the end of a string. +\begin{python} +txt = " banana sss " +x = txt.strip() +print("of all fruits", x, "is my favorite") +#of all fruits banana is my favorite + +txt = ",,,,,rrttgg.....banana....rrr" +x = txt.strip(",.grt") +print(x) +#banana +\end{python} + + + +\subsection{combining list of strings} +\begin{python} +text = ['Python', 'is', 'a', 'fun', 'programming', 'language'] +print(' '.join(text)) +# Python is a fun programming language +\end{python} + + + +\section{Input Output Operations}\label{sect:io} + +\subsection{create a file} +\begin{python} +f = open("demofile3.txt", "w") +f.write("I have added content!") +f.close() +\end{python} + +\subsection{write to a file: fast shortcut} +In this version, you don't have to remember closing the file. +\begin{python} +with open("demofile3.txt", "w") as fp: + fp.write(f.write("I have added content!") +\end{python} + +\subsection{create directory} +The following program checks for a directory, and creates it if not present. +\begin{python} +import os +directory = "newDirectory" +parent_dir = "/home/User/Documents" +path = os.path.join(parent_dir, directory) +os.makedirs(path,exist_ok = True) +\end{python} + +\subsection{remove file} +\begin{python} +import os +fileName = 'myFile.txt' # File name +location = "/home/User/Documents" +path = os.path.join(location, fileName) + +if os.path.exists(path): + os.remove(path) +else: + print("The file does not exist") +\end{python} + +\subsection{save and load pickle file} +Pickle is the default binary storage format of Python. It can store any type of variable inside. +\begin{python} + +import pickle + +a = {'hello': 'world'} + +with open('filename.pkl', 'wb') as handle: + pickle.dump(a, handle, protocol=pickle.HIGHEST_PROTOCOL) + +with open('filename.pkl', 'rb') as handle: + b = pickle.load(handle) + +print(a == b) +\end{python} + +\begin{python} +def load_obj(name): + with open(name + '.pkl', 'rb') as f: + return pickle.load(f) + +def write_obj(name, data): + with open(name, 'wb') as handle: + pickle.dump(data, handle, protocol=pickle.HIGHEST_PROTOCOL) +\end{python} + +\subsection{joining paths} +\begin{python} +import os +path = "/home" +## Join various path components +print(os.path.join(path, "User/Desktop", "file.txt")) +#/home/User/Desktop/file.txt +\end{python} + +\subsection{check file existence} +\begin{python} +path = 'D:/Pycharm/USER/testFile.txt' + +isFile = os.path.isfile(path) +print(isFile) +#False +\end{python} + +\subsection{list files in a directory} +\begin{python} +import os +path = "/" +dir_list = os.listdir(path) + +print(dir_list) +# too many output, please run the code yourself. +\end{python} + +\subsection{iterate (traverse) files in a folder} +\begin{python} +import os +for (root,dirs,files) in os.walk('Test', topdown=true): + print (root) + print (dirs) + print (files) +# too many output, please run the code yourself. +\end{python} + +\subsection{sort files by date} +\begin{python} +import os +search_dir = "/mydir/" +files = os.listdir(search_dir) +files = [os.path.join(search_dir, f) for f in files] +files.sort(key=lambda x: os.path.getmtime(x)) +\end{python} + +\subsection{write to CSV file} +\begin{python} +import csv + +with open('employee_file.csv', mode='w') as employee_file: + employee_writer = csv.writer(employee_file, delimiter=',', quotechar='"') + employee_writer.writerow(['name', 'department', 'birthday month']) + employee_writer.writerow(['John Smith', 'Accounting', 'November']) + employee_writer.writerow(['Erica Meyers', 'IT', 'March']) + employee_writer.writerow(['Monica Barker', 'HR', 'December']) +## open the employee_file.csv and you will see: +## name,department,birthday month +## John Smith,Accounting,November +## Erica Meyers,IT,March +## Monica Barker,HR,December +\end{python} + +\subsection{read CSV file example} +\begin{python} +import csv + +with open('employee_file.csv', mode='w') as employee_file: + employee_writer = csv.writer(employee_file, delimiter=',', quotechar='"') + employee_writer.writerow(['name', 'department', 'birthday month']) + employee_writer.writerow(['John Smith', 'Accounting', 'November']) + employee_writer.writerow(['Erica Meyers', 'IT', 'March']) + employee_writer.writerow(['Monica Barker', 'HR', 'December']) + +with open('employee_birthday.txt') as csv_file: + csv_reader = csv.reader(csv_file, delimiter=',') + line_count = 0 + for row in csv_reader: + if line_count == 0: + print(f'Column names are {", ".join(row)}') + line_count += 1 + else: + print(f'\t{row[0]} works in the {row[1]} department, and was born in {row[2]}.') + line_count += 1 + print(f'Processed {line_count} lines.') + +\end{python} + +\subsubsection{read CSV into list} +\begin{python} +import csv + +with open('employee_file.csv', mode='w') as employee_file: + employee_writer = csv.writer(employee_file, delimiter=',', quotechar='"') + employee_writer.writerow(['name', 'department', 'birthday month']) + employee_writer.writerow(['John Smith', 'Accounting', 'November']) + employee_writer.writerow(['Erica Meyers', 'IT', 'March']) + employee_writer.writerow(['Monica Barker', 'HR', 'December']) + +## +import csv +def readCSVIntoList(fileName, discardHeader=False): + rows = [] + with open(fileName) as csv_file: + csv_reader = csv.reader(csv_file, delimiter=',') + for row in csv_reader: + rows.append(row) + if discardHeader: + rows.remove(rows[0]) + return rows + +rows = readCSVIntoList('employee_birthday.txt',discardHeader=True) +print(rows) +#[['John Smith', 'Accounting', 'November'], ['Erica Meyers', 'IT', 'March'], ['Monica Barker', 'HR', 'December']] +\end{python} + +\subsection{Adding Command Line Arguments} +The following program expects command line arguments. If not provided, uses default arguments. +\begin{python} +## run with python sourcefile.py --keyword mykeyword --page 1 +## or python sourcefile.py +import argparse + +parser = argparse.ArgumentParser(description="Just an example",formatter_class=argparse.ArgumentDefaultsHelpFormatter) +parser.add_argument("-k", "--keyword", type=str, help="query keywords") +parser.add_argument("-p", "--page", type=str, help="query page") +args = parser.parse_args() +config = vars(args) +#print(config) + +if args.keyword: + searchKeyword=args.keyword + searchPage=args.pageidx +else: + searchKeyword = "googleit" + searchPage="0" + +print("SearchKeyword is " + searchKeyword + " Search Page is " + searchPage ) +\end{python} + +\section{Time and Date} +\subsection{Get current date } +\begin{python} +##Get the current date in DD-MM-YYYY-HR-MM-SS format: +from datetime import datetime +now = datetime.now() +curDate = now.strftime("%d-%m-%Y-%H-%M-%S") +print(curDate) +# 18-06-2022-10-40-59 +\end{python} + +\subsection{Convert Unix time to datetime} +\begin{python} +from datetime import datetime +x = 1656100252345 +d = datetime.utcfromtimestamp( x / 1000 ).strftime('%Y-%m-%d %H:%M:%S') +#2022-06-24 19:50:52 +\end{python} + +\section{Algorithms} +\subsection{Remove elements} + +\subsection{Find middle coordinates of a coordinate array} +\begin{python} +[ (linesProc2[i] + linesProc2[i+1]) / 2 for i,x in enumerate( linesProc2[:-1] ) ] +\end{python} + +\section{Regex} +\subsection{Nongreedy regex search} +Default behaviour of regex is to greedy matching (searches the longest sequence up to the end). To search nongreedy: +\begin{python} +text="From: test: test", +regex="^F.+:" -> match="From: test:" +regex="^F.+?:" -> match="From:" +\end{python} + +\section{Network}\label{sect:network} + +\subsection{Single threaded to multi threaded} +Python programs are by default single threaded. This source is a multi-threaded example: +\begin{python} +### ---------------------- ### +### The following program is single threaded, it takes approximately six seconds. +### ---------------------- ### + +from time import sleep, perf_counter + +def task(): + print('Starting a task...') + sleep(3) + print('done') + + +start_time = perf_counter() + +task() +task() + +end_time = perf_counter() + +print(f'It took {end_time- start_time: 0.2f} second(s) to complete.') +# result depends on your cpu. please run the code! + +### ---------------------- ### +### The following program is multi-threaded and it takes approximately 3 seconds. +### ---------------------- ### +from time import sleep, perf_counter +from threading import Thread + +def task(): + print('Starting a task...') + sleep(3) + print('done') + + +start_time = perf_counter() + +# create two new threads +t1 = Thread(target=task) +t2 = Thread(target=task) + +# start the threads +t1.start() +t2.start() + +# wait for the threads to complete +t1.join() +t2.join() + +end_time = perf_counter() + +print(f'It took {end_time- start_time: 0.2f} second(s) to complete.') +# result depends on your cpu. please run the code! +\end{python} + +\subsection{Multi-thread with argument} +\begin{python} +from time import sleep, perf_counter +from threading import Thread +def task(id): + print(f'Starting the task {id}...') + sleep(1) + print(f'The task {id} completed') + +start_time = perf_counter() +## create and start 10 threads +threads = [] +for n in range(1, 11): + t = Thread(target=task, args=(n,)) + threads.append(t) + t.start() + +## wait for the threads to complete +for t in threads: + t.join() + +end_time = perf_counter() +print(f'It took {end_time- start_time: 0.2f} second(s) to complete.') +# Please run the program on your computer to see the output! +\end{python} + + +\section{Web}\label{sect:web} + +\subsection{Scrape HTML with Beautiful Soup} +This example code scrapes an HTML page and searches for HTML div tags inside it. +\begin{python} +import requests +from bs4 import BeautifulSoup + +URL = "https://edition.cnn.com/" +page = requests.get(URL) + +soup = BeautifulSoup(page.content, "html.parser") + +## print the HTML content +print(soup.prettify()) + +## find first div element in the page +myDiv = soup.find("div") + +## find all div elements in the page +myDivs = soup.findAll("div") + +## find all divs with class equal to the following string. +job_elements = results.find_all("div", attrs={"class":"card-content"} ) + +## get tag of an "a" element. +r.find('a')['href'] + +\end{python} + +\subsection{Make request until success} +\begin{python} +def retryResponseGetSoup(url): + response = get(url) + bs = BeautifulSoup(response.content) + while bs.text == 'Baglanti hatasi.' or response.status_code != 200: + print('retrying...') + time.sleep(5) + response = get(url) + bs = BeautifulSoup(response.content) + return bs + +url = "www.google.com" +s = retryResponseGetSoup(url) + +\end{python} + +\subsection{Selenium} + +\subsubsection{Access attribute of an element} +\begin{python} +### selenium python scroll to element's location +elements = driver.find_elements(By.XPATH, "//div[contains(@class, 'navigationPane')]/a") +for e in elements: + e.get_attribute("outerHTML") +\end{python} + + +\subsubsection{Scroll to element} +\begin{python} +### selenium python scroll to element's location +desired_y = element.location['y'] +current_y = (driver.execute_script('return window.innerHeight') / 2) + driver.execute_script('return window.pageYOffset') +scroll_y_by = desired_y +driver.execute_script("window.scrollBy(0, arguments[0]);", scroll_y_by) +\end{python} + +\subsubsection{Access pure HTML of the element} +\begin{python} +tableElems = driver.find_element(By.XPATH, "//table[contains(@class, 'morphologyTable')]//tbody") +tableElems.get_attribute("outerHTML") +\end{python} + +\subsubsection{Save cropped screenshot} +\begin{python} +driver.save_screenshot('shot.png') +im = Image.open('shot.png') +im = im.crop((int(x1-5),int(0), int(x1+w1+5), int(y2-y1+h2))) +im.save('shot.png') +\end{python} + +\subsection{Download files} +\begin{python} +import requests +image_url = "https://www.python.org/static/community_logos/python-logo-master-v3-TM.png" + +r = requests.get(image_url) +with open("python_logo.png",'wb') as f: + f.write(r.content) + +\end{python} + + +\section{Pandas} +[describe pandas library with 1-2 sentences. Then why its useful with 1-2 sentences.] + +\subsection{read CSV } +We can use Pandas library to read CSV's easily. The content goes to a DataFrame type of the Pandas library. +\begin{python} +with open('employee_file.csv', mode='w+') as employee_file: + employee_writer = csv.writer(employee_file, delimiter=',', quotechar='"') + employee_writer.writerow(['name', 'department', 'birthday month']) + employee_writer.writerow(['John Smith', 'Accounting', 'November']) + employee_writer.writerow(['Erica Meyers', 'IT', 'March']) + employee_writer.writerow(['Monica Barker', 'HR', 'December']) + +import pandas as pd +data= pd.read_csv("employee_file.csv") +print(data) +# name department birthday month +#0 John Smith Accounting November +#1 Erica Meyers IT March +#2 Monica Barker HR December +\end{python} + +\subsection{analyze and clean data } +\begin{python} +with open('employee_file.csv', mode='w+') as employee_file: + employee_writer = csv.writer(employee_file, delimiter=',', quotechar='"') + employee_writer.writerow(['name', 'department', 'birthday month','salary','gender']) + employee_writer.writerow(['John Smith', 'Accounting', 'November', '100', 'm']) + employee_writer.writerow(['Erica Meyers', 'IT', 'March', '200', 'f']) + employee_writer.writerow(['Monica Barker', '', '', '400', 'f']) + +import pandas as pd +df= pd.read_csv("employee_file.csv") + +## print head of the data +print(df.head(10)) +## print tail of the data +print(df.tail()) +## info about the data +print(df.info()) + +## get column data types +df.dtypes + +## drop empty rows +new_df = df.dropna() +print(new_df.to_string()) + +## drop unnecessary columns +df.drop(columns=['gender']) + +## replace empty places +df.fillna(130, inplace = True) + +## only replace specific columns +df["salary"].fillna(130, inplace = True) + +## substitute column mean to the empty places +x = df["salary"].mean() +df["salary"].fillna(x, inplace = True) + +## substitute column median to the empty places +x = df["salary"].median() +df["salary"].fillna(x, inplace = True) + +## substitute column mode to the empty places +x = df["salary"].mode()[0] +df["salary"].fillna(x, inplace = True) + +## remove rows with +df.dropna(subset=['department'], inplace = True) + + +\end{python} + +\subsection{basic functionality: access, sampling, filtering} +\begin{python} +import pandas as pd +df = pd.read_csv("../pokemon_data.txt", delimiter="\t") +## Read headers +df.columns + +## list the frequency of each Generation field +df['Generation'].value_counts() + +## give how many uniques are in the dataset +df["Generation"].nunique() + +## Read each column +df["Speed"] +df["Speed"][0:5] +df.ColumnName +df[ ["Speed", "HP"] ] + +## Read each row +df.iloc[1] +df.iloc[1:4] +[row for index, row in df.iterrows()] + +## Read a specific location (R,C) +df.iloc[2,1] + +## Select rows +df.loc[ df["Type 1" == "Fire"] + +## Sorting data +df.sort_values("Speed") +df.sort_values("Speed", ascending=False) +df.sort_values(["HP", "Speed"], ascending[1,0]) + +## Making changes to the data +df['Total'] = df['Total'] - 5 +df['Total'] = df[ ['CA','CB','CC'].mean() + +def f(x,y): + return x+y + +## Iterating over one column +result = [x for x in df['End']] + +## Iterating over two columns, use `zip` +result = [f(x, y) for x, y in zip(df['Start'], df['End'])] + +## Iterating over multiple columns - same data type +result = [f(row[0], row[1]) for row in df[['Start', 'End']].to_numpy()] + +## Iterating over multiple columns - differing data type +result = [f(row[0], row[1]) for row in zip(df['Start'], df['End'])] + +## worst and very slow solutions. Avoid. +for row in df.itertuples(): + print(row) + +##Removing columns +df.drop( columns=['Total'], in_place=True) + +##Removing columns conditionally +df.query("salary > 20") + +## Summing a dataframe +df.sum(axis=1) + +## Drop repeating entries +df.drop_duplicates(inplace = True) + +## save results to csv +df.to_csv("myCsvFile.csv", index=False) + +\end{python} + +\subsection{advanced: multi column access, contains, groupby} +\begin{python} +##################### +### Advanced +import pandas as pd +df = pd.read_csv("../pokemon_data.txt", delimiter="\t") + +df.loc[ df["Type 1" == "Grass" ] + +## Sample using multiple condition +new_df = (df.loc[ df["Type 1" == "Grass" ]) & df.loc[ df["Type 2" == "Poison" ] + +## After filtering, index stays. You have to reset index then. +new_df.reset_index(in_place=True) +new_df.reset_index(drop=True, in_place=True) # removes old idx + +## Using contains +df.loc[ df["Name"].str.contains("Mega") ] +df.loc[ ~df["Name"].str.contains("Mega") ] # take other set +df.loc[ df["Name"].str.contains("Fire|Grass", regex=True) ] +df.loc[ df["Name"].str.contains("pi[a-z]*", regex=True) ] + +#### Conditional Changes +## Change Type1 column having entry "fire" to "flamer" +df.loc[ df["Type 1"] ] == "Fire", "Type 1"] = "Flamer" + +## Change two columns at the same time. +df.loc[ df["Total"] > 500, ["Generation", "Legendary"] ] = ["Test 1", "Test2"] + +## Aggregate data using groupby +df.groupby( ["Type 1"] ).mean() +df.groupby("Type 1")['HP'].sum() +df.groupby( ["Type 1"] ).mean().sort_values("Defense", ascending=False) +df.groupby( ["Type 1"] ).count() + +### Working with large data +for df in pd.read_csv("modified.csv", chunksize=5000) + print(df) + +\end{python} + +\subsection{calculate column cumulatives} +\begin{python} +import pandas as pd +df = pd.DataFrame(data=[[1, 2, 7, 10], [10, 22, 1, 30], + [30, 42, 2, 10], [100,142, 22,1]], + columns=['Start','End','Value1','Value2']) + +df2 = df[['Value1', 'Value2']].cumsum() +df2.rename(columns={'Value1': 'Cumulative Value1', 'Value2': 'Cumulative Value2'}, +inplace=True) +print(df2) +\end{python} + +\subsection{operations on two data frames} +\begin{python} +import numpy as np +import pandas as pd + +df = pd.DataFrame(data=[[1, 2, 7, 10], [10, 22, 1, 30], + [30, 42, 2, 10], [100,142, 22,1]], + columns=['Value1','Value2','Value3','Value4']) + +df2 = pd.DataFrame(data=[[10, 20, 30, 40], [5, 1, 6, 32], + [143, 152, 2, 10], [np.nan, 162, 12, 11]], + columns=['Value1','Value2','Value3','Value4']) + +## add dataframes +df + df2 + +## replaces missing values with 0 while adding +df.add(df2, fill_value=0) + +## check whether df > df2. Result is a boolean filled data frame. +## eq, ne, lt, gt, le, and ge are the functions here. +## their usage is the same. +df.gt(df2) +\end{python} + +\subsubsection{Concat join rows} +\begin{python} +import pandas as pd +df = pd.DataFrame(data=[[10, 20, 30], [11, 21, 31]], columns=['Key1','Key2', 'Key3'] ) +df2 = pd.DataFrame(data=[[5, 6, 7], [5, 8, 12]], columns=['Key1','Key2', 'Key3'] ) + +df3 = pd.concat([df, df2], axis=0) +df3.reset_index(drop=True) # otherwise indexes get mixed +# Key1 Key2 Key3 +#0 10 20 30 +#1 11 21 31 +#2 5 6 7 +#3 5 8 12 +\end{python} + +\subsubsection{Concat join rows with different columns} +\begin{python} +import pandas as pd +df = pd.DataFrame(data=[[10, 20, 30], [11, 21, 31]], columns=['Key1','Key2', 'Key3'] ) +df2 = pd.DataFrame(data=[[5, "Lazy"], [5, "Hardworking"]],columns=['Key4','Key5'] ) +pd.concat([df, df2], axis=0) +# Key1 Key2 Key3 Key4 Key5 +#0 10.0 20.0 30.0 NaN NaN +#1 11.0 21.0 31.0 NaN NaN +#0 NaN NaN NaN 5.0 Lazy +#1 NaN NaN NaN 5.0 Hardworking +\end{python} + +\subsubsection{Concat join columns} +\begin{python} +import pandas as pd +df = pd.DataFrame(data=[[10, 20, 30], [11, 21, 31]], columns=['Key1','Key2', 'Key3'] ) +df2 = pd.DataFrame(data=[[5, "Lazy"], [5, "Hardworking"]], columns=['Key4','Key5'] ) + +pd.concat([df, df2], axis=1) +# Key1 Key2 Key3 Key4 Key5 +#0 10 20 30 5 Lazy +#1 11 21 31 5 Hardworking +\end{python} + +\subsection{applying a function to dataFrame rows or columns} +\begin{python} +import numpy as np +df = pd.DataFrame(data=[["Kevin", 2, 6.], ["Frank", 22, 8.], + ["Sarah", 4, 5.], ["Galvin", 3, 10.]], + columns=['Name','Years','Ability']) +print(df) +# Name Years Ability +#0 Kevin 2 6 +#1 Frank 22 8 +#2 Sarah 4 5 +#3 Galvin 3 10 + +## sum rows of the frame +df1 = df.apply(np.sum, axis=0) +print(df1) +#Name KevinFrankSarahGalvin +#Years 31 +#Ability 29 + +## sum columns of the frame +df2 = df[["Years", "Ability"]].apply(np.sum, axis=1) +print(df2) +#0 8.0 +#1 30.0 +#2 9.0 +#3 13.0 +\end{python} + +\subsection{plot values with dates on x axis} +\begin{python} +import pandas as pd +import matplotlib.pyplot as plt +df = pd.DataFrame(data=[["10-06-2022", 5], ["09-06-2022", 3], ["11-06-2022", 20], +["13-06-2022", 12],["12-06-2022", 15], ["14-06-2022", 7]], columns=['Date','Sales']) + +df["time"] = pd.to_datetime(df['Date'], format='%d-%m-%Y') +##df["time"] = pd.to_datetime(df['Date'], format='%Y-%m-%d %H:%M:%S.%f') + +df.set_index(['time'],inplace=True) +df.plot() +\end{python} + +\subsection{Example code 1:} +\begin{python} +import pandas as pd +import seaborn as sns +import matplotlib.pyplot as plt + +df = pd.read_csv("examples/4weeks_date.csv") + +##see the columns +df.columns + +##strip the column names to remove extra whitespaces +df = df.rename(columns=lambda x: x.strip()) + +##check dataset +df.describe() +df.info() +print("initial length of dataset %d " % len(df) ) + +##drop rows when ENTRIES or EXITS is zero +df_clean = df.query("ENTRIES > 0") +df_clean = df_clean.query("EXITS > 0") +print("length after cleaning 1 %d " % len(df_clean) ) + +##drop entries bigger than 5M +df_clean = df_clean.query("ENTRIES < 5000000") +df_clean = df_clean.query("EXITS < 5000000") +df_clean.reset_index(drop = True, inplace = True) +print("length after cleaning 2 %d " % len(df_clean) ) + +##compute total activity : ENTRIES + EXITS +df_clean["TA"] = df_clean["ENTRIES"] + df_clean["EXITS"] + +##combine date and time columns. Then convert to pdDate +df_clean["DT"] = df_clean["DATE"] + " " + df_clean["TIME"] +df_clean["DATETIME"] = pd.to_datetime(df_clean['DT'], format='%m/%d/%Y %H:%M:%S') + +##select a station and sum same day activities +df_clean["LINENAME"].value_counts() +usedLineName = "1237ACENQRS" +myLineDF = df_clean[ df_clean["LINENAME"] == usedLineName] +myLineDF.reset_index(drop = True, inplace = True) + +##sort rows with DATE + TIME +myLineDF = myLineDF.sort_values( ["DATE","TIME"] ) +myLineDF.reset_index(drop = True, inplace = True) + +##add rows with identical DATETIME +myLineDFGrouped = myLineDF.groupby("DATETIME").mean() +myLineDFGrouped.reset_index(drop = True, inplace = True) + +## Create figure and plot space +fig, ax = plt.subplots(figsize=(10, 10)) +ax.plot(myLineDFGrouped.index , myLineDFGrouped["TA"], color='purple') +ax.set(xlabel="Date", ylabel="Total activity", title="Total entries for line: %s" % usedLineName ) +plt.show() + +## Alternatively use default Plotter +myLineDFGrouped.plot() +\end{python} + +\section{Matplotlib Visualization} +\subsection{Basics} + +\subsubsection{Basic plotting} +\begin{python} +from matplotlib import pyplot as plt +plt.figure(figsize = (20,9)) +plt.plot() +\end{python} + + + + +\section{Seaborn Visualization} +Seaborn is a visualization library on top of Matplotlib. Seaborn is more comfortable in handling Pandas data frames. + +\subsection{Plotting an histogram} +\begin{python} +import matplotlib.pyplot as plt +import seaborn as sns +## plot only density +sns.distplot([0, 1, 2, 3, 4, 5], hist=False) +plt.show() +## plot density + histogram +sns.distplot([0, 1, 2, 3, 3, 3, 3, 4, 5, 7]) +plt.show() +\end{python} + +\subsection{Lineplot} +\begin{python} +import matplotlib.pyplot as plt +import seaborn as sns + +## loading dataset +data = sns.load_dataset("iris") +# [150 rows x 5 columns] + +### draw lineplot +sns.lineplot(x="sepal_length", y="sepal_width", data=data) + +## setting the x limit of the plot +plt.xlim(5) + +\end{python} + +\subsection{Scatterplot} +\begin{python} +# importing packages +import seaborn as sns +import matplotlib.pyplot as plt + +# loading dataset +data = sns.load_dataset("iris") + +sns.scatterplot(x='sepal_length', y='sepal_width', data=data) +plt.show() +\end{python} + +\section{OpenCV} + +\subsection{Basics} + +\subsubsection{Typecase PIL Image to OpenCV image} +\begin{python} +from PIL import Image +import cv2 +import matplotlib.pyplot as plt +pillowImage = Image.open("kiz-kulesi.jpg") +rgb_image_float= np.asarray(pillowImage,dtype=float)/255.0 +plt.imshow(rgb_image_float) +\end{python} + +\subsubsection{Flip, resize, rotate, crop images} +\begin{python} +import cv2 +import scipy.ndimage +import numpy as np +import matplotlib.pyplot as plt +original_image = cv2.imread("kiz-kulesi.jpg", cv2.IMREAD_GRAYSCALE) + +flipud_image=np.flipud(original_image) +fliplr_image=np.fliplr(original_image) +rotated_image=scipy.ndimage.rotate(original_image,45) +resized_image=scipy.misc.imresize(original_image, 0.5, interp='bilinear', mode=None) +rows,cols=original_image.shape +croped_image = original_image[int(rows / 3): -int(rows / 3), int(cols / 4): - int(cols / 4)] +fig1, axes_array = plt.subplots(2, 3) +fig1.set_size_inches(9,6) +image_plot = axes_array[0][0].imshow(original_image ,cmap=plt.cm.gray) +axes_array[0][0].set(title='Original') +image_plot = axes_array[0][1].imshow(flipud_image,cmap=plt.cm.gray) +axes_array[0][1].set(title='Flipped up-down') +image_plot = axes_array[0][2].imshow(fliplr_image,cmap=plt.cm.gray) +axes_array[0][2].set(title='Flipped left-right') +image_plot = axes_array[1][0].imshow(rotated_image,cmap=plt.cm.gray) +axes_array[1][0].set(title='Rotated') +image_plot = axes_array[1][1].imshow(resized_image,cmap=plt.cm.gray) +axes_array[1][1].set(title='Resized') +image_plot = axes_array[1][2].imshow(croped_image,cmap=plt.cm.gray) +axes_array[1][2].set(title='Cropped') +plt.show() +\end{python} + +\subsubsection{Operating on HSV colorspace} +\begin{python} +import matplotlib +import matplotlib.pyplot as plt +def demo_rgb_to_hsv(original_image,reduce_intensity_factor=0.5): + original_rgb_float= np.asarray(original_image,dtype=float)/255.0 + original_rgb_float = original_rgb_float[:,:,:3] + hsv_image=matplotlib.colors.rgb_to_hsv(original_rgb_float) + hsv_image_processed=hsv_image.copy() + hsv_image_processed[:,: ,2]=hsv_image[:,: ,2]*reduce_intensity_factor + rgb_image_processed=matplotlib.colors.hsv_to_rgb(hsv_image_processed) + fig1, axes_array = plt.subplots(1, 2) + fig1.set_size_inches(8,4) + image_plot = axes_array[0].imshow(original_rgb_float) # Show the RGB image + axes_array[0].axis('off') + axes_array[0].set(title='RGB Image') + image_plot = axes_array[1].imshow(rgb_image_processed) # Show the gray image + axes_array[1].axis('off') + axes_array[1].set(title='Intensity Reduced Image') + plt.show() +rgb_image_int = Image.open("kiz-kulesi.jpg") +demo_rgb_to_hsv(rgb_image_int) +\end{python} + +\subsubsection{1d Gaussian Kernel} +\begin{python} +def display_1d_gaussian(mean=0.0,sigma=0.5): + x=np.linspace(-10,10,1000) + y= (1/np.sqrt(2*np.pi*sigma**2))*np.exp(-((x-mean)**2)/(2*sigma**2)) + fig, axes1 = plt.subplots(1, 1) + fig.set_size_inches(6,3) + axes1.set(xlabel="X",ylabel="Y",title='Gaussian Curve',ylim=(0,1)) + plt.grid(True) + axes1.plot(x,y,color='gray') + plt.fill_between(x,y,0,color='#c0f0c0') + plt.show() + +\end{python} + +\subsubsection{2d Gaussian Kernel Image} +\begin{python} +import scipy.stats +import numpy as np +import matplotlib.pyplot as plt +from mpl_toolkits.mplot3d import Axes3D +from matplotlib.ticker import LinearLocator, FormatStrFormatter +def display_gaussian_kernel(sigma=1.0): + X = np.linspace(-5, 5, 400) + Y = np.linspace(-5, 5, 400) + X, Y = np.meshgrid(X, Y) + R = np.sqrt(X**2 + Y**2) + Z = np.sin(R) + mu = np.array([0.0, 0.0]) + covariance = np.diag(np.array([sigma, sigma])**2) + XY = np.column_stack([X.flat, Y.flat]) + z = scipy.stats.multivariate_normal.pdf(XY, mean=mu, cov=covariance) + Z = z.reshape(X.shape) + + # Plot the surface. + fig = plt.figure() + fig.set_size_inches(8,4) + ax1 = fig.add_subplot(121) + ax1.imshow(Z) + ax2 = fig.add_subplot(122, projection='3d') + + surf = ax2.plot_surface(X, Y, Z, cmap=plt.cm.coolwarm, linewidth=0, antialiased=False) + # Customize the z axis. + ax2.set_zlim(0, .2) + ax2.zaxis.set_major_locator(LinearLocator(10)) + ax2.zaxis.set_major_formatter(FormatStrFormatter('%.02f')) + + # Add a color bar which maps values to colors. + fig.colorbar(surf, shrink=0.5, aspect=5) + plt.show() + +display_gaussian_kernel() + +\end{python} + +\subsubsection{find horizontal lines} +\begin{python} +import cv2 +# Load image, convert to grayscale, Otsu's threshold +image = cv2.imread('kiz-kulesi.jpg') +result = image.copy() +gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) +thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1] + +# Detect horizontal lines +horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (40,1)) +detect_horizontal = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2) +cnts = cv2.findContours(detect_horizontal, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) +cnts = cnts[0] if len(cnts) == 2 else cnts[1] +for c in cnts: + cv2.drawContours(result, [c], -1, (36,255,12), 2) +plt.figure(figsize = (20,9)); plt.imshow(result) +\end{python} + +\subsubsection{Drawing text on image} +\begin{python} +import cv2 + +# path +path = r'kiz-kulesi.jpg' + +# Reading an image in default mode +image = cv2.imread(path) + +# Window name in which image is displayed +window_name = 'Image' + +# font +font = cv2.FONT_HERSHEY_SIMPLEX +# position +org = (40, 40) +# fontScale +fontScale = 1 +# Green color in BGR +color = (0, 255, 0) +# Line thickness of 2 px +thickness = 2 + +image = cv2.putText(image, 'Hello', org, font, fontScale, color, thickness, cv2.LINE_AA) + +# Displaying the image +plt.figure(figsize = (20,9)); plt.imshow(img_rgb) +\end{python} + +\subsection{Template Matching} +\begin{python} +from matplotlib import pyplot as plt +import numpy as np +import cv2 +import imutils + +def multiscaleTemplateMatching(imFileToLoad,templateFileToLoad): + template = cv2.imread(templateFileToLoad) + template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY) + template = cv2.Canny(template, 50, 200) + (tH, tW) = template.shape[:2] + # loop over the images to find the template in + image = cv2.imread(imFileToLoad) + gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) + found = None + # loop over the scales of the image + for scale in np.linspace(0.2, 1.0, 20)[::-1]: + # resize the image according to the scale, and keep track + # of the ratio of the resizing + resized = imutils.resize(gray, width = int(gray.shape[1] * scale)) + r = gray.shape[1] / float(resized.shape[1]) + # if the resized image is smaller than the template, then break + # from the loop + if resized.shape[0] < tH or resized.shape[1] < tW: + break + + # detect edges in the resized, grayscale image and apply template + # matching to find the template in the image + edged = cv2.Canny(resized, 50, 200) + result = cv2.matchTemplate(edged, template, cv2.TM_CCOEFF) + (_, maxVal, _, maxLoc) = cv2.minMaxLoc(result) + # check to see if the iteration should be visualized + if True: + # draw a bounding box around the detected region + clone = np.dstack([edged, edged, edged]) + cv2.rectangle(clone, (maxLoc[0], maxLoc[1]), + (maxLoc[0] + tW, maxLoc[1] + tH), (0, 0, 255), 2) + # if we have found a new maximum correlation value, then update + # the bookkeeping variable + if found is None or maxVal > found[0]: + found = (maxVal, maxLoc, r) + # unpack the bookkeeping variable and compute the (x, y) coordinates + # of the bounding box based on the resized ratio + (_, maxLoc, r) = found + (startX, startY) = (int(maxLoc[0] * r), int(maxLoc[1] * r)) + (endX, endY) = (int((maxLoc[0] + tW) * r), int((maxLoc[1] + tH) * r)) + # draw a bounding box around the detected result and display the image + + return [startX, startY, endX, endY] + +img_rgb = cv2.imread(shot) +startX, startY, endX, endY = multiscaleTemplateMatching(shot,templateFileToLoad) +cv2.rectangle(img_rgb, (startX, startY), (endX, endY), (0, 0, 255), 2) +plt.figure(figsize = (20,9)) +plt.imshow(img_rgb) +\end{python} + +\subsection{Overlapping bounding box removal: nonmaxima suppression} +\begin{python} +def NMS(boxes, overlapThresh = 0.4): + # Return an empty list, if no boxes given + if len(boxes) == 0: + return [] + x1 = boxes[:, 0] # x coordinate of the top-left corner + y1 = boxes[:, 1] # y coordinate of the top-left corner + x2 = boxes[:, 2] # x coordinate of the bottom-right corner + y2 = boxes[:, 3] # y coordinate of the bottom-right corner + # Compute the area of the bounding boxes and sort the bounding + # Boxes by the bottom-right y-coordinate of the bounding box + areas = (x2 - x1 + 1) * (y2 - y1 + 1) # We add 1, because the pixel at the start as well as at the end counts + # The indices of all boxes at start. We will redundant indices one by one. + indices = np.arange(len(x1)) + for i,box in enumerate(boxes): + # Create temporary indices + temp_indices = indices[indices!=i] + # Find out the coordinates of the intersection box + xx1 = np.maximum(box[0], boxes[temp_indices,0]) + yy1 = np.maximum(box[1], boxes[temp_indices,1]) + xx2 = np.minimum(box[2], boxes[temp_indices,2]) + yy2 = np.minimum(box[3], boxes[temp_indices,3]) + # Find out the width and the height of the intersection box + w = np.maximum(0, xx2 - xx1 + 1) + h = np.maximum(0, yy2 - yy1 + 1) + # compute the ratio of overlap + overlap = (w * h) / areas[temp_indices] + # if the actual boungding box has an overlap bigger than threshold with any other box, remove it's index + if np.any(overlap) > overlapThresh: + indices = indices[indices != i] + #return only the boxes at the remaining indices + return boxes[indices].astype(int) +\end{python} + +\subsection{SingleScale Multiple Template Matching} +\begin{python} +import cv2 +def singleScaleMultipleTemplateMatching(imageFileName, templateFileName): + print("[INFO] loading images...") + image = cv2.imread(imageFileName) + img_rgb = image.copy() + template = cv2.imread(templateFileName) + (tH, tW) = template.shape[:2] + + # convert both the image and template to grayscale + imageGray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) + templateGray = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY) + # perform template matching + print("[INFO] performing template matching...") + result = cv2.matchTemplate(imageGray, templateGray, + cv2.TM_CCOEFF_NORMED) + + (yCoords, xCoords) = np.where(result >= 0.75) + clone = image.copy() + print("[INFO] {} matched locations *before* NMS".format(len(yCoords))) + # loop over our starting (x, y)-coordinates + for (x, y) in zip(xCoords, yCoords): + # draw the bounding box on the image + cv2.rectangle(clone, (x, y), (x + tW, y + tH), + (255, 0, 0), 3) + + # initialize our list of rectangles + rects = [] + # loop over the starting (x, y)-coordinates again + for (x, y) in zip(xCoords, yCoords): + # update our list of rectangles + rects.append((x, y, x + tW, y + tH)) + # apply non-maxima suppression to the rectangles + pick = NMS(np.array(rects)) +# pick = rects + print("[INFO] {} matched locations *after* NMS".format(len(pick))) + + # loop over the final bounding boxes + for (startX, startY, endX, endY) in pick: + # draw the bounding box on the image + cv2.rectangle(img_rgb, (startX, startY), (endX, endY), + (0, 255, 0), 2) + return pick, img_rgb + +pick , img_rgb = singleScaleMultipleTemplateMatching("cropped2.png","template.png") + +plt.figure(figsize = (20,9)) +plt.imshow(img_rgb) +\end{python} + +\subsection{Finding and Plotting Contours} +\begin{python} +def findAndPlotContours(fileName, blob_area_thresh=20): + img = cv2.imread(fileName, cv2.IMREAD_COLOR) + gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) + thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 101, 3) + + ### following morphology open and close can be applied. + #kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5)) + #blob = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel) + #kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (9,9)) + #blob = cv2.morphologyEx(blob, cv2.MORPH_CLOSE, kernel) + blob = thresh + + # invert blob + blob = (255 - blob) + + # Get contours + cnts = cv2.findContours(blob, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) + cnts = cnts[0] if len(cnts) == 2 else cnts[1] + + ## select the contours larger than having area 20 + cnts = [c for c in cnts if cv2.contourArea(c) > blob_area_thresh] + #big_contour = max(cnts, key=cv2.contourArea) + + ## return contours and buffer image + result = img.copy() + result[:,:,0] = 255 + result[:,:,1] = 255 + result[:,:,2] = 255 + for c in cnts: + cv2.drawContours(result, [c], -1, (0,0,255), 1) + return result, c + +result, c = findAndPlotContours("kiz-kulesi.jpg",20) +\end{python} + +\subsection{Circle Detection} +\begin{python} +import matplotlib.pyplot as plt +import cv2 + +img = cv2.imread("cropped2.png", cv2.IMREAD_COLOR) +gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) + +detected_circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 20, param1 = 50, param2 = 30, minRadius = 1, maxRadius = 400) + +for pt in detected_circles[0, :]: + a, b, r = pt[0], pt[1], pt[2] + # Draw the circumference of the circle. + cv2.circle(img, (a, b), r, (0, 255, 0), 2) + # Draw a small circle (of radius 1) to show the center. + cv2.circle(img, (a, b), 1, (0, 0, 255), 3) + +plt.figure(figsize = (20,9)) +plt.imshow(img) +\end{python} + +\subsection{Connected Components Analysis} +\begin{python} +import matplotlib.pyplot as plt +import cv2 + +img = cv2.imread("cropped2.png", cv2.IMREAD_COLOR) +gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) +threshold = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1] +analysis = cv2.connectedComponentsWithStats(threshold, 4, cv2.CV_32S) +(totalLabels, label_ids, values, centroid) = analysis + +#plt.figure(figsize = (20,9)) +#plt.imshow(threshold) + +# Loop through each component +output = np.zeros(gray.shape, dtype="uint8") +for i in range(1, totalLabels): + area = values[i, cv2.CC_STAT_AREA] + + if (area > 110) and (area < 900): + + # Labels stores all the IDs of the components on the each pixel + # It has the same dimension as the threshold + # So we'll check the component + # then convert it to 255 value to mark it white + componentMask = (label_ids == i).astype("uint8") * 255 + + # Creating the Final output mask + output = cv2.bitwise_or(output, componentMask) + +plt.figure(figsize = (20,9)) +plt.imshow(output) + +\end{python} + +\subsection{Fit ellipses to objects} +\begin{python} +img = cv2.imread("cropped2.png", cv2.IMREAD_COLOR) +gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) +gray = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, s, 7.0) +cnts, hier = cv2.findContours(gray,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) + +ellipses = [] +if len(cnts) != 0: + for i in range(len(cnts)): + if len(cnts[i]) >= 5: + ellipse=cv2.fitEllipse(cnts[i]) + print(ellipse) + ellipses.append(ellipse) + centCoord = ( int(ellipse[0][0]), int(ellipse[0][1]) ) + axisLen = ( int(ellipse[1][0]), int(ellipse[1][1]) ) + angle = ellipse[2] + + ## angle filtering + #offSet = np.min( np.fabs( [angle, angle-90, angle-180, angle-270, angle-360]) ) + #if offSet < 5: + + img = cv2.ellipse(img, centCoord, axisLen, angle, 0, 360, (0,0,255)) + +# cv2.drawContours(img,cnts,-1,(150,10,255),2) + +plt.figure(figsize = (20,9)) +plt.imshow(img) +\end{python} + +\section{Numpy} + +\subsection{Fitting} + +\subsubsection{Curve fitting} +\begin{python} +import pandas as pd +import numpy as np +import matplotlib.pyplot as plt +from sklearn.preprocessing import PolynomialFeatures +from sklearn.linear_model import LinearRegression +from sklearn.metrics import r2_score +from sklearn.metrics import mean_squared_error + +def generateQuadraticData(): + x = np.random.rand(100) - 0.5 + u = 0.1 * np.random.rand(100) + + a = 1 + b = 0.0 + c = 0.1 + + y = a * np.multiply(x,x) + np.multiply(x,b) + c + u + #plt.scatter(x,y) + return x,y + +x,y = generateQuadraticData() +X = x.reshape(-1,1) # for one feature problems + +###We compare nonlinear regression here with different power +regr = LinearRegression() +quadratic = PolynomialFeatures(degree=2) +cubic = PolynomialFeatures(degree=3) +X_quad = quadratic.fit_transform(X) +X_cubic = cubic.fit_transform(X) + +X_fit = np.arange(X.min(), X.max(), 0.05)[:, np.newaxis] + +regr = regr.fit(X, y) +y_lin_fit = regr.predict(X_fit) +linear_r2 = r2_score(y, regr.predict(X)) + +regr = regr.fit(X_quad, y) +y_quad_fit = regr.predict(quadratic.fit_transform(X_fit)) +quadratic_r2 = r2_score(y, regr.predict(X_quad)) + +regr = regr.fit(X_cubic, y) +y_cubic_fit = regr.predict(cubic.fit_transform(X_fit)) +cubic_r2 = r2_score(y, regr.predict(X_cubic)) + +plt.scatter(X, y, label='training points', color='lightgray') + +plt.plot(X_fit, y_lin_fit, + label='linear (d=1), $R^2=%.2f$' % linear_r2, + color='blue', + lw=2, + linestyle=':') + +plt.plot(X_fit, y_quad_fit, + label='quadratic (d=2), $R^2=%.2f$' % quadratic_r2, + color='red', + lw=2, + linestyle='-') + +plt.plot(X_fit, y_cubic_fit, + label='cubic (d=3), $R^2=%.2f$' % cubic_r2, + color='green', + lw=2, + linestyle='--') + +plt.legend(loc='upper right') +plt.tight_layout() +plt.show() +\end{python} + +\subsubsection{Ransac curve fitting} +\begin{python} +import pandas as pd +import numpy as np +import matplotlib.pyplot as plt +from sklearn.preprocessing import PolynomialFeatures +from sklearn.linear_model import LinearRegression +from sklearn.metrics import r2_score +from sklearn.metrics import mean_squared_error +from sklearn import linear_model, datasets + +def generateQuadraticData(noiseFraction = 0.2): + nDataPoints = 100 + nNoisePoints = int(nDataPoints * noiseFraction) + ## data + a, b, c = 1, 0.0, 0.1 + x = np.random.rand(nDataPoints) - 0.5 + y = a * np.multiply(x,x) + np.multiply(x,b) + c + ## outliers + u = np.random.rand(nNoisePoints, 2) + + x = np.concatenate( (x,u[:,0]), axis=0) + y = np.concatenate( (y,u[:,1]), axis=0) +# plt.scatter(x,y) + + return x,y + +noiseFraction = 0.7 +x,y = generateQuadraticData(noiseFraction) + +## 1D data reshape. +X = x.reshape(-1,1) # for one feature problems +quadratic = PolynomialFeatures(degree=2) +X_quad = quadratic.fit_transform(X) +X_fit = np.arange(2*np.min(X), 2*np.max(X), 0.05)[:, np.newaxis] #evaluation interval +regr = linear_model.RANSACRegressor() +regr = regr.fit(X_quad, y) +y_quad_fit = regr.predict(quadratic.fit_transform(X_fit)) +quadratic_r2 = r2_score(y, regr.predict(X_quad)) +inlier_mask = regr.inlier_mask_ +outlier_mask = np.logical_not(inlier_mask) + +plt.figure(figsize = (10,9)) +plt.plot(X_fit, y_quad_fit, label='quadratic (d=2), $R^2=%.2f$' % quadratic_r2,color='blue', lw=1,linestyle='-') +plt.scatter(X[inlier_mask], y[inlier_mask], color="green", marker=".", label="Inliers") +plt.scatter(X[outlier_mask], y[outlier_mask], color="red", marker=".", label="Outliers") +plt.legend(loc='upper right') +plt.tight_layout() +plt.show() +\end{python} + +\section{Scikit-Learn} +Scikit learn supports many machine learning models. + +\subsection{Linear Regression} +\begin{python} +import matplotlib.pyplot as plt +import numpy as np +from sklearn import datasets, linear_model +from sklearn.metrics import mean_squared_error, r2_score + +# Load the diabetes dataset +diabetes_X, diabetes_y = datasets.load_diabetes(return_X_y=True) + +# Use only one feature +diabetes_X = diabetes_X[:, np.newaxis, 2] + +# Split the data into training/testing sets +diabetes_X_train = diabetes_X[:-20] +diabetes_X_test = diabetes_X[-20:] + +# Split the targets into training/testing sets +diabetes_y_train = diabetes_y[:-20] +diabetes_y_test = diabetes_y[-20:] + +# Create linear regression object +regr = linear_model.LinearRegression() + +# Train the model using the training sets +regr.fit(diabetes_X_train, diabetes_y_train) + +# Make predictions using the testing set +diabetes_y_pred = regr.predict(diabetes_X_test) + +# The coefficients +print("Coefficients: \n", regr.coef_) +# The mean squared error +print("Mean squared error: %.2f" % mean_squared_error(diabetes_y_test, diabetes_y_pred)) +# The coefficient of determination: 1 is perfect prediction +print("Coefficient of determination: %.2f" % r2_score(diabetes_y_test, diabetes_y_pred)) + +# Plot outputs +plt.scatter(diabetes_X_test, diabetes_y_test, color="black") +plt.plot(diabetes_X_test, diabetes_y_pred, color="blue", linewidth=3) + +plt.xticks(()) +plt.yticks(()) + +plt.show() + +\end{python} + +%\section*{Appendix} +%\bibliographystyle{plain} +%\bibliography{references} + +\end{document} diff --git a/taypack.tex b/taypack.tex new file mode 100644 index 0000000..0e9b09d --- /dev/null +++ b/taypack.tex @@ -0,0 +1,29 @@ +\usepackage{color} +\usepackage[makeroom]{cancel} + +%-------------- Environment for Mathematics -------------------% +\usepackage{bm} +\newcommand*{\B}[1]{\ifmmode\bm{#1}\else\textbf{#1}\fi} +\usepackage{amssymb} +\usepackage{amsmath} +%-------------- Graphical Model Macros -------------------% +\newcommand{\gmcsize}{5mm} +\newcommand{\gmcoffset}{15mm} +%-------------- Operators -------------------% +\DeclareMathOperator*{\E}{\mathbb{E}} +\DeclareMathOperator*{\argmin}{arg\,min} +\DeclareMathOperator{\Tr}{Tr} + +\newcommand{\taygun}[1]{\textcolor[rgb]{0,0.4,0.8}{\textbf{[TA] #1}}} +\newcommand{\tax}[1]{\textcolor[rgb]{0,0.5,0.5}{\textbf{[DTX] #1}}} +\newcommand{\mimno}[1]{\textcolor[rgb]{0.3,0.3,0.7}{\textbf{[MI] #1}}} + +%----------------- Theorems, lemmas, proofs, ----------------------% +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{claim}[theorem]{Claim} +\newtheorem{corollary}{Corollary} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{concept}[theorem]{Concept} +\newenvironment{proof}{{\bf Proof:}}{\hfill\rule{2mm}{2mm}} \ No newline at end of file