wxPython 4.3.2__cp315-cp315-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (472) hide show
  1. wx/WebView2Loader.dll +0 -0
  2. wx/__init__.py +22 -0
  3. wx/__init__.pyi +10 -0
  4. wx/__version__.py +9 -0
  5. wx/__version__.pyi +15 -0
  6. wx/_adv.cp315-win_amd64.pyd +0 -0
  7. wx/_aui.cp315-win_amd64.pyd +0 -0
  8. wx/_core.cp315-win_amd64.pyd +0 -0
  9. wx/_dataview.cp315-win_amd64.pyd +0 -0
  10. wx/_glcanvas.cp315-win_amd64.pyd +0 -0
  11. wx/_grid.cp315-win_amd64.pyd +0 -0
  12. wx/_html.cp315-win_amd64.pyd +0 -0
  13. wx/_html2.cp315-win_amd64.pyd +0 -0
  14. wx/_media.cp315-win_amd64.pyd +0 -0
  15. wx/_msw.cp315-win_amd64.pyd +0 -0
  16. wx/_propgrid.cp315-win_amd64.pyd +0 -0
  17. wx/_ribbon.cp315-win_amd64.pyd +0 -0
  18. wx/_richtext.cp315-win_amd64.pyd +0 -0
  19. wx/_stc.cp315-win_amd64.pyd +0 -0
  20. wx/_xml.cp315-win_amd64.pyd +0 -0
  21. wx/_xrc.cp315-win_amd64.pyd +0 -0
  22. wx/adv.py +127 -0
  23. wx/adv.pyi +5931 -0
  24. wx/aui.py +70 -0
  25. wx/aui.pyi +4805 -0
  26. wx/core.py +3417 -0
  27. wx/core.pyi +62949 -0
  28. wx/dataview.py +176 -0
  29. wx/dataview.pyi +3828 -0
  30. wx/gizmos.py +18 -0
  31. wx/glcanvas.py +13 -0
  32. wx/glcanvas.pyi +544 -0
  33. wx/grid.py +237 -0
  34. wx/grid.pyi +5678 -0
  35. wx/html.py +38 -0
  36. wx/html.pyi +3283 -0
  37. wx/html2.py +46 -0
  38. wx/html2.pyi +1301 -0
  39. wx/include/wxPython/sip.h +1938 -0
  40. wx/include/wxPython/wxpy_api.h +418 -0
  41. wx/lib/CDate.py +201 -0
  42. wx/lib/ClickableHtmlWindow.py +57 -0
  43. wx/lib/__init__.py +0 -0
  44. wx/lib/activex.py +178 -0
  45. wx/lib/activexwrapper.py +153 -0
  46. wx/lib/agw/__init__.py +128 -0
  47. wx/lib/agw/advancedsplash.py +563 -0
  48. wx/lib/agw/aquabutton.py +1127 -0
  49. wx/lib/agw/artmanager.py +2110 -0
  50. wx/lib/agw/aui/__init__.py +295 -0
  51. wx/lib/agw/aui/aui_constants.py +2616 -0
  52. wx/lib/agw/aui/aui_switcherdialog.py +1232 -0
  53. wx/lib/agw/aui/aui_utilities.py +648 -0
  54. wx/lib/agw/aui/auibar.py +4045 -0
  55. wx/lib/agw/aui/auibook.py +6288 -0
  56. wx/lib/agw/aui/dockart.py +1198 -0
  57. wx/lib/agw/aui/framemanager.py +10485 -0
  58. wx/lib/agw/aui/tabart.py +2749 -0
  59. wx/lib/agw/aui/tabmdi.py +679 -0
  60. wx/lib/agw/balloontip.py +1157 -0
  61. wx/lib/agw/buttonpanel.py +2787 -0
  62. wx/lib/agw/cubecolourdialog.py +3529 -0
  63. wx/lib/agw/customtreectrl.py +9908 -0
  64. wx/lib/agw/data/ShortcutEditor_1.png +0 -0
  65. wx/lib/agw/data/ShortcutEditor_1_thumb.png +0 -0
  66. wx/lib/agw/data/ShortcutEditor_2.png +0 -0
  67. wx/lib/agw/data/ShortcutEditor_2_thumb.png +0 -0
  68. wx/lib/agw/data/ShortcutEditor_3.png +0 -0
  69. wx/lib/agw/data/ShortcutEditor_3_thumb.png +0 -0
  70. wx/lib/agw/data/ShortcutEditor_4.png +0 -0
  71. wx/lib/agw/data/ShortcutEditor_4_thumb.png +0 -0
  72. wx/lib/agw/data/default_help_text.html +105 -0
  73. wx/lib/agw/flatmenu.py +7392 -0
  74. wx/lib/agw/flatnotebook.py +6669 -0
  75. wx/lib/agw/floatspin.py +1820 -0
  76. wx/lib/agw/fmcustomizedlg.py +535 -0
  77. wx/lib/agw/fmresources.py +407 -0
  78. wx/lib/agw/foldpanelbar.py +2282 -0
  79. wx/lib/agw/fourwaysplitter.py +1130 -0
  80. wx/lib/agw/genericmessagedialog.py +1549 -0
  81. wx/lib/agw/gradientbutton.py +731 -0
  82. wx/lib/agw/hyperlink.py +664 -0
  83. wx/lib/agw/hypertreelist.py +5756 -0
  84. wx/lib/agw/infobar.py +885 -0
  85. wx/lib/agw/knobctrl.py +944 -0
  86. wx/lib/agw/labelbook.py +3028 -0
  87. wx/lib/agw/multidirdialog.py +581 -0
  88. wx/lib/agw/peakmeter.py +1028 -0
  89. wx/lib/agw/persist/__init__.py +188 -0
  90. wx/lib/agw/persist/persist_constants.py +283 -0
  91. wx/lib/agw/persist/persist_handlers.py +2614 -0
  92. wx/lib/agw/persist/persistencemanager.py +863 -0
  93. wx/lib/agw/piectrl.py +1082 -0
  94. wx/lib/agw/pybusyinfo.py +399 -0
  95. wx/lib/agw/pycollapsiblepane.py +940 -0
  96. wx/lib/agw/pygauge.py +570 -0
  97. wx/lib/agw/pyprogress.py +916 -0
  98. wx/lib/agw/ribbon/__init__.py +198 -0
  99. wx/lib/agw/ribbon/art.py +219 -0
  100. wx/lib/agw/ribbon/art_aui.py +1283 -0
  101. wx/lib/agw/ribbon/art_default.py +81 -0
  102. wx/lib/agw/ribbon/art_internal.py +248 -0
  103. wx/lib/agw/ribbon/art_msw.py +2735 -0
  104. wx/lib/agw/ribbon/art_osx.py +52 -0
  105. wx/lib/agw/ribbon/bar.py +1259 -0
  106. wx/lib/agw/ribbon/buttonbar.py +1317 -0
  107. wx/lib/agw/ribbon/control.py +205 -0
  108. wx/lib/agw/ribbon/gallery.py +973 -0
  109. wx/lib/agw/ribbon/page.py +946 -0
  110. wx/lib/agw/ribbon/panel.py +1170 -0
  111. wx/lib/agw/ribbon/toolbar.py +1441 -0
  112. wx/lib/agw/rulerctrl.py +1885 -0
  113. wx/lib/agw/scrolledthumbnail.py +2116 -0
  114. wx/lib/agw/shapedbutton.py +1809 -0
  115. wx/lib/agw/shortcuteditor.py +2642 -0
  116. wx/lib/agw/speedmeter.py +1800 -0
  117. wx/lib/agw/supertooltip.py +1443 -0
  118. wx/lib/agw/thumbnailctrl.py +529 -0
  119. wx/lib/agw/toasterbox.py +1327 -0
  120. wx/lib/agw/ultimatelistctrl.py +13671 -0
  121. wx/lib/agw/xlsgrid.py +2111 -0
  122. wx/lib/agw/zoombar.py +1336 -0
  123. wx/lib/analogclock/__init__.py +140 -0
  124. wx/lib/analogclock/analogclock.py +630 -0
  125. wx/lib/analogclock/helpers.py +986 -0
  126. wx/lib/analogclock/lib_setup/__init__.py +0 -0
  127. wx/lib/analogclock/lib_setup/buttontreectrlpanel.py +297 -0
  128. wx/lib/analogclock/lib_setup/fontselect.py +57 -0
  129. wx/lib/analogclock/setup.py +490 -0
  130. wx/lib/analogclock/styles.py +47 -0
  131. wx/lib/anchors.py +103 -0
  132. wx/lib/art/__init__.py +4 -0
  133. wx/lib/art/flagart.py +1583 -0
  134. wx/lib/art/img2pyartprov.py +56 -0
  135. wx/lib/busy.py +152 -0
  136. wx/lib/buttons.py +1140 -0
  137. wx/lib/calendar.py +1596 -0
  138. wx/lib/checkbox.py +837 -0
  139. wx/lib/colourchooser/__init__.py +36 -0
  140. wx/lib/colourchooser/canvas.py +145 -0
  141. wx/lib/colourchooser/intl.py +24 -0
  142. wx/lib/colourchooser/pycolourbox.py +89 -0
  143. wx/lib/colourchooser/pycolourchooser.py +626 -0
  144. wx/lib/colourchooser/pycolourslider.py +98 -0
  145. wx/lib/colourchooser/pypalette.py +208 -0
  146. wx/lib/colourdb.py +740 -0
  147. wx/lib/colourselect.py +385 -0
  148. wx/lib/colourutils.py +118 -0
  149. wx/lib/combotreebox.py +944 -0
  150. wx/lib/delayedresult.py +420 -0
  151. wx/lib/dialogs.py +510 -0
  152. wx/lib/docview.py +3210 -0
  153. wx/lib/dragscroller.py +79 -0
  154. wx/lib/editor/README.txt +77 -0
  155. wx/lib/editor/__init__.py +24 -0
  156. wx/lib/editor/editor.py +974 -0
  157. wx/lib/editor/images.py +15 -0
  158. wx/lib/editor/selection.py +44 -0
  159. wx/lib/embeddedimage.py +76 -0
  160. wx/lib/eventStack.py +136 -0
  161. wx/lib/eventwatcher.py +440 -0
  162. wx/lib/evtmgr.py +521 -0
  163. wx/lib/expando.py +393 -0
  164. wx/lib/fancytext.py +494 -0
  165. wx/lib/filebrowsebutton.py +461 -0
  166. wx/lib/flashwin.py +262 -0
  167. wx/lib/flashwin_old.py +651 -0
  168. wx/lib/floatcanvas/FCEvents.py +53 -0
  169. wx/lib/floatcanvas/FCObjects.py +2910 -0
  170. wx/lib/floatcanvas/FloatCanvas.py +1025 -0
  171. wx/lib/floatcanvas/GUIMode.py +396 -0
  172. wx/lib/floatcanvas/NavCanvas.py +162 -0
  173. wx/lib/floatcanvas/Resources.py +319 -0
  174. wx/lib/floatcanvas/ScreenShot.py +1788 -0
  175. wx/lib/floatcanvas/Utilities/BBox.py +313 -0
  176. wx/lib/floatcanvas/Utilities/Colors.py +137 -0
  177. wx/lib/floatcanvas/Utilities/GUI.py +91 -0
  178. wx/lib/floatcanvas/Utilities/__init__.py +7 -0
  179. wx/lib/floatcanvas/__init__.py +124 -0
  180. wx/lib/foldmenu.py +89 -0
  181. wx/lib/gestures.py +310 -0
  182. wx/lib/gizmos/__init__.py +18 -0
  183. wx/lib/gizmos/dynamicsash.py +1202 -0
  184. wx/lib/gizmos/ledctrl.py +299 -0
  185. wx/lib/gizmos/treelistctrl.py +87 -0
  186. wx/lib/graphics.py +1942 -0
  187. wx/lib/gridmovers.py +516 -0
  188. wx/lib/iewin.py +249 -0
  189. wx/lib/iewin_old.py +894 -0
  190. wx/lib/imagebrowser.py +853 -0
  191. wx/lib/imageutils.py +163 -0
  192. wx/lib/infoframe.py +490 -0
  193. wx/lib/inspection.py +1254 -0
  194. wx/lib/intctrl.py +990 -0
  195. wx/lib/itemspicker.py +256 -0
  196. wx/lib/langlistctrl.py +480 -0
  197. wx/lib/layoutf.py +271 -0
  198. wx/lib/masked/__init__.py +27 -0
  199. wx/lib/masked/combobox.py +839 -0
  200. wx/lib/masked/ctrl.py +108 -0
  201. wx/lib/masked/ipaddrctrl.py +241 -0
  202. wx/lib/masked/maskededit.py +7262 -0
  203. wx/lib/masked/numctrl.py +2000 -0
  204. wx/lib/masked/textctrl.py +465 -0
  205. wx/lib/masked/timectrl.py +1465 -0
  206. wx/lib/mixins/__init__.py +17 -0
  207. wx/lib/mixins/grid.py +47 -0
  208. wx/lib/mixins/gridlabelrenderer.py +277 -0
  209. wx/lib/mixins/imagelist.py +77 -0
  210. wx/lib/mixins/inspection.py +184 -0
  211. wx/lib/mixins/listctrl.py +893 -0
  212. wx/lib/mixins/rubberband.py +403 -0
  213. wx/lib/mixins/treemixin.py +678 -0
  214. wx/lib/msgpanel.py +95 -0
  215. wx/lib/multisash.py +746 -0
  216. wx/lib/myole4ax.idl +178 -0
  217. wx/lib/myole4ax.tlb +0 -0
  218. wx/lib/newevent.py +229 -0
  219. wx/lib/newevent.pyi +25 -0
  220. wx/lib/nvdlg.py +156 -0
  221. wx/lib/ogl/__init__.py +13 -0
  222. wx/lib/ogl/basic.py +3989 -0
  223. wx/lib/ogl/bmpshape.py +86 -0
  224. wx/lib/ogl/canvas.py +467 -0
  225. wx/lib/ogl/composit.py +1576 -0
  226. wx/lib/ogl/diagram.py +230 -0
  227. wx/lib/ogl/divided.py +482 -0
  228. wx/lib/ogl/drawn.py +898 -0
  229. wx/lib/ogl/lines.py +1809 -0
  230. wx/lib/ogl/oglmisc.py +607 -0
  231. wx/lib/pdfviewer/__init__.py +113 -0
  232. wx/lib/pdfviewer/bitmaps/ArrowLeft.png +0 -0
  233. wx/lib/pdfviewer/bitmaps/ArrowRight.png +0 -0
  234. wx/lib/pdfviewer/bitmaps/DirectionH.png +0 -0
  235. wx/lib/pdfviewer/bitmaps/DirectionV.png +0 -0
  236. wx/lib/pdfviewer/bitmaps/PlayerFirst.png +0 -0
  237. wx/lib/pdfviewer/bitmaps/PlayerLast.png +0 -0
  238. wx/lib/pdfviewer/bitmaps/PlayerNext.png +0 -0
  239. wx/lib/pdfviewer/bitmaps/PlayerPrev.png +0 -0
  240. wx/lib/pdfviewer/bitmaps/Printer.png +0 -0
  241. wx/lib/pdfviewer/bitmaps/ReadMe.txt +28 -0
  242. wx/lib/pdfviewer/bitmaps/Save.png +0 -0
  243. wx/lib/pdfviewer/bitmaps/ZoomIn.png +0 -0
  244. wx/lib/pdfviewer/bitmaps/ZoomOut.png +0 -0
  245. wx/lib/pdfviewer/bitmaps/encode_bitmaps.py +37 -0
  246. wx/lib/pdfviewer/buttonpanel.py +285 -0
  247. wx/lib/pdfviewer/images.py +240 -0
  248. wx/lib/pdfviewer/viewer.py +1118 -0
  249. wx/lib/pdfwin.py +295 -0
  250. wx/lib/pdfwin_old.py +789 -0
  251. wx/lib/platebtn.py +789 -0
  252. wx/lib/plot/CHANGELOG.md +150 -0
  253. wx/lib/plot/README.md +16 -0
  254. wx/lib/plot/__init__.py +46 -0
  255. wx/lib/plot/__main__.py +5 -0
  256. wx/lib/plot/examples/__init__.py +0 -0
  257. wx/lib/plot/examples/demo.py +1010 -0
  258. wx/lib/plot/examples/simple_example.py +56 -0
  259. wx/lib/plot/plotcanvas.py +2985 -0
  260. wx/lib/plot/polyobjects.py +1524 -0
  261. wx/lib/plot/utils.py +334 -0
  262. wx/lib/popupctl.py +251 -0
  263. wx/lib/printout.py +1155 -0
  264. wx/lib/progressindicator.py +151 -0
  265. wx/lib/pubsub/LICENSE_BSD_Simple.txt +23 -0
  266. wx/lib/pubsub/README_WxPython.txt +22 -0
  267. wx/lib/pubsub/RELEASE_NOTES.txt +71 -0
  268. wx/lib/pubsub/__init__.py +25 -0
  269. wx/lib/pubsub/core/__init__.py +92 -0
  270. wx/lib/pubsub/core/arg1/__init__.py +16 -0
  271. wx/lib/pubsub/core/arg1/listenerimpl.py +97 -0
  272. wx/lib/pubsub/core/arg1/publisher.py +40 -0
  273. wx/lib/pubsub/core/arg1/publishermixin.py +34 -0
  274. wx/lib/pubsub/core/arg1/topicargspecimpl.py +66 -0
  275. wx/lib/pubsub/core/arg1/topicmgrimpl.py +19 -0
  276. wx/lib/pubsub/core/callables.py +198 -0
  277. wx/lib/pubsub/core/imp2.py +62 -0
  278. wx/lib/pubsub/core/itopicdefnprovider.py +0 -0
  279. wx/lib/pubsub/core/kwargs/__init__.py +16 -0
  280. wx/lib/pubsub/core/kwargs/datamsg.py +27 -0
  281. wx/lib/pubsub/core/kwargs/listenerimpl.py +93 -0
  282. wx/lib/pubsub/core/kwargs/publisher.py +77 -0
  283. wx/lib/pubsub/core/kwargs/publishermixin.py +65 -0
  284. wx/lib/pubsub/core/kwargs/topicargspecimpl.py +216 -0
  285. wx/lib/pubsub/core/kwargs/topicmgrimpl.py +13 -0
  286. wx/lib/pubsub/core/listener.py +40 -0
  287. wx/lib/pubsub/core/listenerbase.py +185 -0
  288. wx/lib/pubsub/core/notificationmgr.py +185 -0
  289. wx/lib/pubsub/core/publisherbase.py +189 -0
  290. wx/lib/pubsub/core/topicargspec.py +77 -0
  291. wx/lib/pubsub/core/topicdefnprovider.py +631 -0
  292. wx/lib/pubsub/core/topicexc.py +72 -0
  293. wx/lib/pubsub/core/topicmgr.py +454 -0
  294. wx/lib/pubsub/core/topicobj.py +472 -0
  295. wx/lib/pubsub/core/topictreetraverser.py +143 -0
  296. wx/lib/pubsub/core/topicutils.py +119 -0
  297. wx/lib/pubsub/core/treeconfig.py +21 -0
  298. wx/lib/pubsub/core/validatedefnargs.py +29 -0
  299. wx/lib/pubsub/core/weakmethod.py +102 -0
  300. wx/lib/pubsub/policies.py +24 -0
  301. wx/lib/pubsub/pub.py +199 -0
  302. wx/lib/pubsub/setuparg1.py +47 -0
  303. wx/lib/pubsub/setupkwargs.py +29 -0
  304. wx/lib/pubsub/utils/__init__.py +27 -0
  305. wx/lib/pubsub/utils/exchandling.py +100 -0
  306. wx/lib/pubsub/utils/misc.py +99 -0
  307. wx/lib/pubsub/utils/notification.py +331 -0
  308. wx/lib/pubsub/utils/topictreeprinter.py +195 -0
  309. wx/lib/pubsub/utils/xmltopicdefnprovider.py +286 -0
  310. wx/lib/pydocview.py +3300 -0
  311. wx/lib/rcsizer.py +227 -0
  312. wx/lib/resizewidget.py +357 -0
  313. wx/lib/scrolledpanel.py +243 -0
  314. wx/lib/sheet.py +350 -0
  315. wx/lib/sized_controls.py +691 -0
  316. wx/lib/softwareupdate.py +355 -0
  317. wx/lib/splitter.py +925 -0
  318. wx/lib/statbmp.py +199 -0
  319. wx/lib/stattext.py +321 -0
  320. wx/lib/throbber.py +424 -0
  321. wx/lib/ticker.py +306 -0
  322. wx/lib/ticker_xrc.py +48 -0
  323. wx/lib/utils.py +89 -0
  324. wx/lib/wordwrap.py +97 -0
  325. wx/lib/wxcairo/__init__.py +139 -0
  326. wx/lib/wxcairo/wx_cairocffi.py +200 -0
  327. wx/lib/wxcairo/wx_pycairo.py +455 -0
  328. wx/lib/wxpTag.py +274 -0
  329. wx/libcairo-2.dll +0 -0
  330. wx/locale/af/LC_MESSAGES/wxstd.mo +0 -0
  331. wx/locale/an/LC_MESSAGES/wxstd.mo +0 -0
  332. wx/locale/ar/LC_MESSAGES/wxstd.mo +0 -0
  333. wx/locale/ca/LC_MESSAGES/wxstd.mo +0 -0
  334. wx/locale/ca@valencia/LC_MESSAGES/wxstd.mo +0 -0
  335. wx/locale/co/LC_MESSAGES/wxstd.mo +0 -0
  336. wx/locale/cs/LC_MESSAGES/wxstd.mo +0 -0
  337. wx/locale/da/LC_MESSAGES/wxstd.mo +0 -0
  338. wx/locale/de/LC_MESSAGES/wxstd.mo +0 -0
  339. wx/locale/el/LC_MESSAGES/wxstd.mo +0 -0
  340. wx/locale/es/LC_MESSAGES/wxstd.mo +0 -0
  341. wx/locale/eu/LC_MESSAGES/wxstd.mo +0 -0
  342. wx/locale/fa_IR/LC_MESSAGES/wxstd.mo +0 -0
  343. wx/locale/fi/LC_MESSAGES/wxstd.mo +0 -0
  344. wx/locale/fr/LC_MESSAGES/wxstd.mo +0 -0
  345. wx/locale/gl_ES/LC_MESSAGES/wxstd.mo +0 -0
  346. wx/locale/hi/LC_MESSAGES/wxstd.mo +0 -0
  347. wx/locale/hr/LC_MESSAGES/wxstd.mo +0 -0
  348. wx/locale/hu/LC_MESSAGES/wxstd.mo +0 -0
  349. wx/locale/id/LC_MESSAGES/wxstd.mo +0 -0
  350. wx/locale/it/LC_MESSAGES/wxstd.mo +0 -0
  351. wx/locale/ja/LC_MESSAGES/wxstd.mo +0 -0
  352. wx/locale/ka/LC_MESSAGES/wxstd.mo +0 -0
  353. wx/locale/ko_KR/LC_MESSAGES/wxstd.mo +0 -0
  354. wx/locale/lt/LC_MESSAGES/wxstd.mo +0 -0
  355. wx/locale/lv/LC_MESSAGES/wxstd.mo +0 -0
  356. wx/locale/ms/LC_MESSAGES/wxstd.mo +0 -0
  357. wx/locale/nb/LC_MESSAGES/wxstd.mo +0 -0
  358. wx/locale/ne/LC_MESSAGES/wxstd.mo +0 -0
  359. wx/locale/nl/LC_MESSAGES/wxstd.mo +0 -0
  360. wx/locale/pl/LC_MESSAGES/wxstd.mo +0 -0
  361. wx/locale/pt/LC_MESSAGES/wxstd.mo +0 -0
  362. wx/locale/pt_BR/LC_MESSAGES/wxstd.mo +0 -0
  363. wx/locale/ro/LC_MESSAGES/wxstd.mo +0 -0
  364. wx/locale/ru/LC_MESSAGES/wxstd.mo +0 -0
  365. wx/locale/sk/LC_MESSAGES/wxstd.mo +0 -0
  366. wx/locale/sl/LC_MESSAGES/wxstd.mo +0 -0
  367. wx/locale/sq/LC_MESSAGES/wxstd.mo +0 -0
  368. wx/locale/sr/LC_MESSAGES/wxstd.mo +0 -0
  369. wx/locale/sv/LC_MESSAGES/wxstd.mo +0 -0
  370. wx/locale/ta/LC_MESSAGES/wxstd.mo +0 -0
  371. wx/locale/tr/LC_MESSAGES/wxstd.mo +0 -0
  372. wx/locale/uk/LC_MESSAGES/wxstd.mo +0 -0
  373. wx/locale/vi/LC_MESSAGES/wxstd.mo +0 -0
  374. wx/locale/zh_CN/LC_MESSAGES/wxstd.mo +0 -0
  375. wx/locale/zh_TW/LC_MESSAGES/wxstd.mo +0 -0
  376. wx/media.py +30 -0
  377. wx/media.pyi +272 -0
  378. wx/msw.py +16 -0
  379. wx/msw.pyi +91 -0
  380. wx/propgrid.py +498 -0
  381. wx/propgrid.pyi +7427 -0
  382. wx/py/CHANGES.txt +796 -0
  383. wx/py/Py.ico +0 -0
  384. wx/py/PyAlaCarte.py +34 -0
  385. wx/py/PyAlaMode.py +34 -0
  386. wx/py/PyAlaModeTest.py +33 -0
  387. wx/py/PyCrust.ico +0 -0
  388. wx/py/PyCrust.py +78 -0
  389. wx/py/PyCrust_16.png +0 -0
  390. wx/py/PyCrust_32.png +0 -0
  391. wx/py/PyFilling.py +35 -0
  392. wx/py/PyShell.py +78 -0
  393. wx/py/PySlices.ico +0 -0
  394. wx/py/PySlices.py +98 -0
  395. wx/py/PySlicesShell.py +94 -0
  396. wx/py/PySlices_16.png +0 -0
  397. wx/py/PySlices_32.png +0 -0
  398. wx/py/PyWrap.py +52 -0
  399. wx/py/README.txt +77 -0
  400. wx/py/__init__.py +20 -0
  401. wx/py/buffer.py +136 -0
  402. wx/py/crust.py +403 -0
  403. wx/py/crustslices.py +403 -0
  404. wx/py/dispatcher.py +259 -0
  405. wx/py/document.py +37 -0
  406. wx/py/editor.py +844 -0
  407. wx/py/editwindow.py +316 -0
  408. wx/py/filling.py +358 -0
  409. wx/py/frame.py +976 -0
  410. wx/py/images.py +212 -0
  411. wx/py/interpreter.py +161 -0
  412. wx/py/introspect.py +402 -0
  413. wx/py/magic.py +98 -0
  414. wx/py/parse.py +134 -0
  415. wx/py/path.py +36 -0
  416. wx/py/pseudo.py +99 -0
  417. wx/py/shell.py +1579 -0
  418. wx/py/sliceshell.py +3805 -0
  419. wx/py/tests/test_interpreter.py +71 -0
  420. wx/py/tests/test_introspect.py +810 -0
  421. wx/py/tests/test_pseudo.py +70 -0
  422. wx/py/tests/test_version.py +36 -0
  423. wx/py/tests/testall.py +22 -0
  424. wx/py/version.py +7 -0
  425. wx/py.typed +0 -0
  426. wx/ribbon.py +48 -0
  427. wx/ribbon.pyi +3099 -0
  428. wx/richtext.py +141 -0
  429. wx/richtext.pyi +13581 -0
  430. wx/siplib.cp315-win_amd64.pyd +0 -0
  431. wx/siplib.pyi +19 -0
  432. wx/stc.py +59 -0
  433. wx/stc.pyi +9918 -0
  434. wx/svg/__init__.py +363 -0
  435. wx/svg/_nanosvg.cp315-win_amd64.pyd +0 -0
  436. wx/tools/__init__.py +18 -0
  437. wx/tools/dbg.py +268 -0
  438. wx/tools/genaxmodule.py +50 -0
  439. wx/tools/helpviewer.py +92 -0
  440. wx/tools/img2img.py +85 -0
  441. wx/tools/img2png.py +54 -0
  442. wx/tools/img2py.py +306 -0
  443. wx/tools/img2xpm.py +54 -0
  444. wx/tools/pywxrc.py +951 -0
  445. wx/tools/wxget.py +254 -0
  446. wx/tools/wxget_docs_demo.py +183 -0
  447. wx/wxbase334u_net_vc140_x64.dll +0 -0
  448. wx/wxbase334u_vc140_x64.dll +0 -0
  449. wx/wxbase334u_xml_vc140_x64.dll +0 -0
  450. wx/wxmsw334u_adv_vc140_x64.dll +0 -0
  451. wx/wxmsw334u_aui_vc140_x64.dll +0 -0
  452. wx/wxmsw334u_core_vc140_x64.dll +0 -0
  453. wx/wxmsw334u_gl_vc140_x64.dll +0 -0
  454. wx/wxmsw334u_html_vc140_x64.dll +0 -0
  455. wx/wxmsw334u_media_vc140_x64.dll +0 -0
  456. wx/wxmsw334u_propgrid_vc140_x64.dll +0 -0
  457. wx/wxmsw334u_qa_vc140_x64.dll +0 -0
  458. wx/wxmsw334u_ribbon_vc140_x64.dll +0 -0
  459. wx/wxmsw334u_richtext_vc140_x64.dll +0 -0
  460. wx/wxmsw334u_stc_vc140_x64.dll +0 -0
  461. wx/wxmsw334u_webview_vc140_x64.dll +0 -0
  462. wx/wxmsw334u_xrc_vc140_x64.dll +0 -0
  463. wx/xml.py +18 -0
  464. wx/xml.pyi +728 -0
  465. wx/xrc.py +68 -0
  466. wx/xrc.pyi +896 -0
  467. wxpython-4.3.2.dist-info/METADATA +71 -0
  468. wxpython-4.3.2.dist-info/RECORD +472 -0
  469. wxpython-4.3.2.dist-info/WHEEL +5 -0
  470. wxpython-4.3.2.dist-info/entry_points.txt +13 -0
  471. wxpython-4.3.2.dist-info/licenses/LICENSE.txt +610 -0
  472. wxpython-4.3.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1524 @@
1
+ # -*- coding: utf-8 -*-
2
+ # pylint: disable=E1101, C0330, C0103
3
+ # E1101: Module X has no Y member
4
+ # C0330: Wrong continued indentation
5
+ # C0103: Invalid attribute/variable/method name
6
+ """
7
+ polyobjects.py
8
+ ==============
9
+
10
+ This contains all of the PolyXXX objects used by :mod:`wx.lib.plot`.
11
+
12
+ """
13
+ __docformat__ = "restructuredtext en"
14
+
15
+ # Standard Library
16
+ import time as _time
17
+ import wx
18
+ import warnings
19
+ from collections import namedtuple
20
+
21
+ # Third-Party
22
+ try:
23
+ import numpy as np
24
+ except:
25
+ msg = """
26
+ This module requires the NumPy module, which could not be
27
+ imported. It probably is not installed (it's not part of the
28
+ standard Python distribution). See the Numeric Python site
29
+ (http://numpy.scipy.org) for information on downloading source or
30
+ binaries."""
31
+ raise ImportError("NumPy not found.\n" + msg)
32
+
33
+ # Package
34
+ from .utils import pendingDeprecation
35
+ from .utils import TempStyle
36
+ from .utils import pairwise
37
+
38
+
39
+ class PolyPoints(object):
40
+ """
41
+ Base Class for lines and markers.
42
+
43
+ :param points: The points to plot
44
+ :type points: list of ``(x, y)`` pairs
45
+ :param attr: Additional attributes
46
+ :type attr: dict
47
+
48
+ .. warning::
49
+ All methods are private.
50
+ """
51
+
52
+ def __init__(self, points, attr):
53
+ self._points = np.array(points).astype(np.float64)
54
+ self._logscale = (False, False)
55
+ self._absScale = (False, False)
56
+ self._symlogscale = (False, False)
57
+ self._pointSize = (1.0, 1.0)
58
+ self.currentScale = (1, 1)
59
+ self.currentShift = (0, 0)
60
+ self.scaled = self.points
61
+ self.attributes = {}
62
+ self.attributes.update(self._attributes)
63
+ for name, value in attr.items():
64
+ if name not in self._attributes:
65
+ err_txt = "Style attribute incorrect. Should be one of {}"
66
+ raise KeyError(err_txt.format(self._attributes.keys()))
67
+ self.attributes[name] = value
68
+
69
+ @property
70
+ def logScale(self):
71
+ """
72
+ A tuple of ``(x_axis_is_log10, y_axis_is_log10)`` booleans. If a value
73
+ is ``True``, then that axis is plotted on a logarithmic base 10 scale.
74
+
75
+ :getter: Returns the current value of logScale
76
+ :setter: Sets the value of logScale
77
+ :type: tuple of bool, length 2
78
+ :raises ValueError: when setting an invalid value
79
+ """
80
+ return self._logscale
81
+
82
+ @logScale.setter
83
+ def logScale(self, logscale):
84
+ if not isinstance(logscale, tuple) or len(logscale) != 2:
85
+ raise ValueError("`logscale` must be a 2-tuple of bools")
86
+ self._logscale = logscale
87
+
88
+ def setLogScale(self, logscale):
89
+ """
90
+ Set to change the axes to plot Log10(values)
91
+
92
+ Value must be a tuple of booleans (x_axis_bool, y_axis_bool)
93
+
94
+ .. deprecated:: Feb 27, 2016
95
+
96
+ Use the :attr:`~wx.lib.plot.polyobjects.PolyPoints.logScale`
97
+ property instead.
98
+ """
99
+ pendingDeprecation("self.logScale property")
100
+ self._logscale = logscale
101
+
102
+ @property
103
+ def symLogScale(self):
104
+ """
105
+ .. warning::
106
+
107
+ Not yet implemented.
108
+
109
+ A tuple of ``(x_axis_is_SymLog10, y_axis_is_SymLog10)`` booleans.
110
+ If a value is ``True``, then that axis is plotted on a symmetric
111
+ logarithmic base 10 scale.
112
+
113
+ A Symmetric Log10 scale means that values can be positive and
114
+ negative. Any values less than
115
+ :attr:`~wx.lig.plot.PolyPoints.symLogThresh` will be plotted on
116
+ a linear scale to avoid the plot going to infinity near 0.
117
+
118
+ :getter: Returns the current value of symLogScale
119
+ :setter: Sets the value of symLogScale
120
+ :type: tuple of bool, length 2
121
+ :raises ValueError: when setting an invalid value
122
+
123
+ .. note::
124
+
125
+ This is a simplified example of how SymLog works::
126
+
127
+ if x >= thresh:
128
+ x = Log10(x)
129
+ elif x =< thresh:
130
+ x = -Log10(Abs(x))
131
+ else:
132
+ x = x
133
+
134
+ .. seealso::
135
+
136
+ + :attr:`~wx.lib.plot.PolyPoints.symLogThresh`
137
+ + See http://matplotlib.org/examples/pylab_examples/symlog_demo.html
138
+ for an example.
139
+ """
140
+ return self._symlogscale
141
+
142
+ # TODO: Implement symmetric log scale
143
+ @symLogScale.setter
144
+ def symLogScale(self, symlogscale, thresh):
145
+ raise NotImplementedError("Symmetric Log Scale not yet implemented")
146
+
147
+ if not isinstance(symlogscale, tuple) or len(symlogscale) != 2:
148
+ raise ValueError("`symlogscale` must be a 2-tuple of bools")
149
+ self._symlogscale = symlogscale
150
+
151
+ @property
152
+ def symLogThresh(self):
153
+ """
154
+ .. warning::
155
+
156
+ Not yet implemented.
157
+
158
+ A tuple of ``(x_thresh, y_thresh)`` floats that define where the plot
159
+ changes to linear scale when using a symmetric log scale.
160
+
161
+ :getter: Returns the current value of symLogThresh
162
+ :setter: Sets the value of symLogThresh
163
+ :type: tuple of float, length 2
164
+ :raises ValueError: when setting an invalid value
165
+
166
+ .. note::
167
+
168
+ This is a simplified example of how SymLog works::
169
+
170
+ if x >= thresh:
171
+ x = Log10(x)
172
+ elif x =< thresh:
173
+ x = -Log10(Abs(x))
174
+ else:
175
+ x = x
176
+
177
+ .. seealso::
178
+
179
+ + :attr:`~wx.lib.plot.PolyPoints.symLogScale`
180
+ + See http://matplotlib.org/examples/pylab_examples/symlog_demo.html
181
+ for an example.
182
+ """
183
+ return self._symlogscale
184
+
185
+ # TODO: Implement symmetric log scale threshold
186
+ @symLogThresh.setter
187
+ def symLogThresh(self, symlogscale, thresh):
188
+ raise NotImplementedError("Symmetric Log Scale not yet implemented")
189
+
190
+ if not isinstance(symlogscale, tuple) or len(symlogscale) != 2:
191
+ raise ValueError("`symlogscale` must be a 2-tuple of bools")
192
+ self._symlogscale = symlogscale
193
+
194
+ @property
195
+ def absScale(self):
196
+ """
197
+ A tuple of ``(x_axis_is_abs, y_axis_is_abs)`` booleans. If a value
198
+ is ``True``, then that axis is plotted on an absolute value scale.
199
+
200
+ :getter: Returns the current value of absScale
201
+ :setter: Sets the value of absScale
202
+ :type: tuple of bool, length 2
203
+ :raises ValueError: when setting an invalid value
204
+ """
205
+ return self._absScale
206
+
207
+ @absScale.setter
208
+ def absScale(self, absscale):
209
+
210
+ if not isinstance(absscale, tuple) and len(absscale) == 2:
211
+ raise ValueError("`absscale` must be a 2-tuple of bools")
212
+ self._absScale = absscale
213
+
214
+ @property
215
+ def points(self):
216
+ """
217
+ Get or set the plotted points.
218
+
219
+ :getter: Returns the current value of points, adjusting for the
220
+ various scale options such as Log, Abs, or SymLog.
221
+ :setter: Sets the value of points.
222
+ :type: list of `(x, y)` pairs
223
+
224
+ .. note::
225
+
226
+ Only set unscaled points - do not perform the log, abs, or symlog
227
+ adjustments yourself.
228
+ """
229
+ data = np.array(self._points, copy=True) # need the copy
230
+ # TODO: get rid of the
231
+ # need for copy
232
+
233
+ # work on X:
234
+ if self.absScale[0]:
235
+ data = self._abs(data, 0)
236
+ if self.logScale[0]:
237
+ data = self._log10(data, 0)
238
+
239
+ if self.symLogScale[0]:
240
+ # TODO: implement symLogScale
241
+ # Should symLogScale override absScale? My vote is no.
242
+ # Should symLogScale override logScale? My vote is yes.
243
+ # - symLogScale could be a parameter passed to logScale...
244
+ pass
245
+
246
+ # work on Y:
247
+ if self.absScale[1]:
248
+ data = self._abs(data, 1)
249
+ if self.logScale[1]:
250
+ data = self._log10(data, 1)
251
+
252
+ if self.symLogScale[1]:
253
+ # TODO: implement symLogScale
254
+ pass
255
+
256
+ return data
257
+
258
+ @points.setter
259
+ def points(self, points):
260
+ self._points = points
261
+
262
+ def _log10(self, data, index):
263
+ """ Take the Log10 of the data, dropping any negative values """
264
+ data = np.compress(data[:, index] > 0, data, 0)
265
+ data[:, index] = np.log10(data[:, index])
266
+ return data
267
+
268
+ def _abs(self, data, index):
269
+ """ Take the Abs of the data """
270
+ data[:, index] = np.abs(data[:, index])
271
+ return data
272
+
273
+ def boundingBox(self):
274
+ """
275
+ Returns the bounding box for the entire dataset as a tuple with this
276
+ format::
277
+
278
+ ((minX, minY), (maxX, maxY))
279
+
280
+ :returns: boundingbox
281
+ :rtype: numpy array of ``[[minX, minY], [maxX, maxY]]``
282
+ """
283
+ if len(self.points) == 0:
284
+ # no curves to draw
285
+ # defaults to (-1,-1) and (1,1) but axis can be set in Draw
286
+ minXY = np.array([-1.0, -1.0])
287
+ maxXY = np.array([1.0, 1.0])
288
+ else:
289
+ minXY = np.minimum.reduce(self.points)
290
+ maxXY = np.maximum.reduce(self.points)
291
+ return minXY, maxXY
292
+
293
+ def scaleAndShift(self, scale=(1, 1), shift=(0, 0)):
294
+ """
295
+ Scales and shifts the data for plotting.
296
+
297
+ :param scale: The values to scale the data by.
298
+ :type scale: list of floats: ``[x_scale, y_scale]``
299
+ :param shift: The value to shift the data by. This should be in scaled
300
+ units
301
+ :type shift: list of floats: ``[x_shift, y_shift]``
302
+ :returns: None
303
+ """
304
+ if len(self.points) == 0:
305
+ # no curves to draw
306
+ return
307
+
308
+ # TODO: Can we remove the if statement altogether? Does
309
+ # scaleAndShift ever get called when the current value equals
310
+ # the new value?
311
+
312
+ # cast everything to list: some might be np.ndarray objects
313
+ if (list(scale) != list(self.currentScale)
314
+ or list(shift) != list(self.currentShift)):
315
+ # update point scaling
316
+ self.scaled = scale * self.points + shift
317
+ self.currentScale = scale
318
+ self.currentShift = shift
319
+ # else unchanged use the current scaling
320
+
321
+ def getLegend(self):
322
+ return self.attributes['legend']
323
+
324
+ def getClosestPoint(self, pntXY, pointScaled=True):
325
+ """
326
+ Returns the index of closest point on the curve, pointXY,
327
+ scaledXY, distance x, y in user coords.
328
+
329
+ if pointScaled == True, then based on screen coords
330
+ if pointScaled == False, then based on user coords
331
+ """
332
+ if pointScaled:
333
+ # Using screen coords
334
+ p = self.scaled
335
+ pxy = self.currentScale * np.array(pntXY) + self.currentShift
336
+ else:
337
+ # Using user coords
338
+ p = self.points
339
+ pxy = np.array(pntXY)
340
+ # determine distance for each point
341
+ d = np.sqrt(np.add.reduce((p - pxy) ** 2, 1)) # sqrt(dx^2+dy^2)
342
+ pntIndex = np.argmin(d)
343
+ dist = d[pntIndex]
344
+ return [pntIndex,
345
+ self.points[pntIndex],
346
+ self.scaled[pntIndex] / self._pointSize,
347
+ dist]
348
+
349
+
350
+ class PolyLine(PolyPoints):
351
+ """
352
+ Creates PolyLine object
353
+
354
+ :param points: The points that make up the line
355
+ :type points: list of ``[x, y]`` values
356
+ :param **attr: keyword attributes
357
+
358
+ =========================== ============= ====================
359
+ Keyword and Default Description Type
360
+ =========================== ============= ====================
361
+ ``colour='black'`` Line color :class:`wx.Colour`
362
+ ``width=1`` Line width float
363
+ ``style=wx.PENSTYLE_SOLID`` Line style :class:`wx.PenStyle`
364
+ ``legend=''`` Legend string str
365
+ ``drawstyle='line'`` see below str
366
+ =========================== ============= ====================
367
+
368
+ ================== ==================================================
369
+ Draw style Description
370
+ ================== ==================================================
371
+ ``'line'`` Draws an straight line between consecutive points
372
+ ``'steps-pre'`` Draws a line down from point A and then right to
373
+ point B
374
+ ``'steps-post'`` Draws a line right from point A and then down
375
+ to point B
376
+ ``'steps-mid-x'`` Draws a line horizontally to half way between A
377
+ and B, then draws a line vertically, then again
378
+ horizontally to point B.
379
+ ``'steps-mid-y'`` Draws a line vertically to half way between A
380
+ and B, then draws a line horizonatally, then
381
+ again vertically to point B.
382
+ *Note: This typically does not look very good*
383
+ ================== ==================================================
384
+
385
+ .. warning::
386
+
387
+ All methods except ``__init__`` are private.
388
+ """
389
+
390
+ _attributes = {'colour': 'black',
391
+ 'width': 1,
392
+ 'style': wx.PENSTYLE_SOLID,
393
+ 'legend': '',
394
+ 'drawstyle': 'line',
395
+ }
396
+ _drawstyles = ("line", "steps-pre", "steps-post",
397
+ "steps-mid-x", "steps-mid-y")
398
+
399
+ def __init__(self, points, **attr):
400
+ PolyPoints.__init__(self, points, attr)
401
+
402
+ def draw(self, dc, printerScale, coord=None):
403
+ """
404
+ Draw the lines.
405
+
406
+ :param dc: The DC to draw on.
407
+ :type dc: :class:`wx.DC`
408
+ :param printerScale:
409
+ :type printerScale: float
410
+ :param coord: The legend coordinate?
411
+ :type coord: ???
412
+ """
413
+ colour = self.attributes['colour']
414
+ width = self.attributes['width'] * printerScale * self._pointSize[0]
415
+ style = self.attributes['style']
416
+ drawstyle = self.attributes['drawstyle']
417
+
418
+ if not isinstance(colour, wx.Colour):
419
+ colour = wx.Colour(colour)
420
+ pen = wx.Pen(colour, int(width), style)
421
+ pen.SetCap(wx.CAP_BUTT)
422
+ dc.SetPen(pen)
423
+ if coord is None:
424
+ if len(self.scaled): # bugfix for Mac OS X
425
+ for c1, c2 in zip(self.scaled, self.scaled[1:]):
426
+ self._path(dc, c1, c2, drawstyle)
427
+ else:
428
+ coord = [(int(c[0]), int(c[1])) for c in coord]
429
+ dc.DrawLines(coord) # draw legend line
430
+
431
+ def getSymExtent(self, printerScale):
432
+ """
433
+ Get the Width and Height of the symbol.
434
+
435
+ :param printerScale:
436
+ :type printerScale: float
437
+ """
438
+ h = self.attributes['width'] * printerScale * self._pointSize[0]
439
+ w = 5 * h
440
+ return (w, h)
441
+
442
+ def _path(self, dc, coord1, coord2, drawstyle):
443
+ """
444
+ Calculates the path from coord1 to coord 2 along X and Y
445
+
446
+ :param dc: The DC to draw on.
447
+ :type dc: :class:`wx.DC`
448
+ :param coord1: The first coordinate in the coord pair
449
+ :type coord1: list, length 2: ``[x, y]``
450
+ :param coord2: The second coordinate in the coord pair
451
+ :type coord2: list, length 2: ``[x, y]``
452
+ :param drawstyle: The type of connector to use
453
+ :type drawstyle: str
454
+ """
455
+ if drawstyle == 'line':
456
+ # Straight line between points.
457
+ line = [coord1, coord2]
458
+ elif drawstyle == 'steps-pre':
459
+ # Up/down to next Y, then right to next X
460
+ intermediate = [coord1[0], coord2[1]]
461
+ line = [coord1, intermediate, coord2]
462
+ elif drawstyle == 'steps-post':
463
+ # Right to next X, then up/down to Y
464
+ intermediate = [coord2[0], coord1[1]]
465
+ line = [coord1, intermediate, coord2]
466
+ elif drawstyle == 'steps-mid-x':
467
+ # need 3 lines between points: right -> up/down -> right
468
+ mid_x = ((coord2[0] - coord1[0]) / 2) + coord1[0]
469
+ intermediate1 = [mid_x, coord1[1]]
470
+ intermediate2 = [mid_x, coord2[1]]
471
+ line = [coord1, intermediate1, intermediate2, coord2]
472
+ elif drawstyle == 'steps-mid-y':
473
+ # need 3 lines between points: up/down -> right -> up/down
474
+ mid_y = ((coord2[1] - coord1[1]) / 2) + coord1[1]
475
+ intermediate1 = [coord1[0], mid_y]
476
+ intermediate2 = [coord2[0], mid_y]
477
+ line = [coord1, intermediate1, intermediate2, coord2]
478
+ else:
479
+ err_txt = "Invalid drawstyle '{}'. Must be one of {}."
480
+ raise ValueError(err_txt.format(drawstyle, self._drawstyles))
481
+
482
+ line = [(int(p[0]), int(p[1])) for p in line]
483
+ dc.DrawLines(line)
484
+
485
+
486
+ class PolySpline(PolyLine):
487
+ """
488
+ Creates PolySpline object
489
+
490
+ :param points: The points that make up the spline
491
+ :type points: list of ``[x, y]`` values
492
+ :param **attr: keyword attributes
493
+
494
+ =========================== ============= ====================
495
+ Keyword and Default Description Type
496
+ =========================== ============= ====================
497
+ ``colour='black'`` Line color :class:`wx.Colour`
498
+ ``width=1`` Line width float
499
+ ``style=wx.PENSTYLE_SOLID`` Line style :class:`wx.PenStyle`
500
+ ``legend=''`` Legend string str
501
+ =========================== ============= ====================
502
+
503
+ .. warning::
504
+
505
+ All methods except ``__init__`` are private.
506
+ """
507
+
508
+ _attributes = {'colour': 'black',
509
+ 'width': 1,
510
+ 'style': wx.PENSTYLE_SOLID,
511
+ 'legend': ''}
512
+
513
+ def __init__(self, points, **attr):
514
+ PolyLine.__init__(self, points, **attr)
515
+
516
+ def draw(self, dc, printerScale, coord=None):
517
+ """ Draw the spline """
518
+ colour = self.attributes['colour']
519
+ width = self.attributes['width'] * printerScale * self._pointSize[0]
520
+ style = self.attributes['style']
521
+ if not isinstance(colour, wx.Colour):
522
+ colour = wx.Colour(colour)
523
+ pen = wx.Pen(colour, int(width), style)
524
+ pen.SetCap(wx.CAP_ROUND)
525
+ dc.SetPen(pen)
526
+ if coord is None:
527
+ if len(self.scaled) >= 3:
528
+ dc.DrawSpline(self.scaled.astype(np.int32))
529
+ else:
530
+ coord = [(int(c[0]), int(c[1])) for c in coord]
531
+ dc.DrawLines(coord) # draw legend line
532
+
533
+
534
+ class PolyMarker(PolyPoints):
535
+ """
536
+ Creates a PolyMarker object.
537
+
538
+ :param points: The marker coordinates.
539
+ :type points: list of ``[x, y]`` values
540
+ :param **attr: keyword attributes
541
+
542
+ ================================= ============= ====================
543
+ Keyword and Default Description Type
544
+ ================================= ============= ====================
545
+ ``marker='circle'`` see below str
546
+ ``size=2`` Marker size float
547
+ ``colour='black'`` Outline color :class:`wx.Colour`
548
+ ``width=1`` Outline width float
549
+ ``style=wx.PENSTYLE_SOLID`` Outline style :class:`wx.PenStyle`
550
+ ``fillcolour=colour`` fill color :class:`wx.Colour`
551
+ ``fillstyle=wx.BRUSHSTYLE_SOLID`` fill style :class:`wx.BrushStyle`
552
+ ``legend=''`` Legend string str
553
+ ================================= ============= ====================
554
+
555
+ =================== ==================================
556
+ Marker Description
557
+ =================== ==================================
558
+ ``'circle'`` A circle of diameter ``size``
559
+ ``'dot'`` A dot. Does not have a size.
560
+ ``'square'`` A square with side length ``size``
561
+ ``'triangle'`` An upward-pointed triangle
562
+ ``'triangle_down'`` A downward-pointed triangle
563
+ ``'cross'`` An "X" shape
564
+ ``'plus'`` A "+" shape
565
+ =================== ==================================
566
+
567
+ .. warning::
568
+
569
+ All methods except ``__init__`` are private.
570
+ """
571
+ _attributes = {'colour': 'black',
572
+ 'width': 1,
573
+ 'size': 2,
574
+ 'fillcolour': None,
575
+ 'fillstyle': wx.BRUSHSTYLE_SOLID,
576
+ 'marker': 'circle',
577
+ 'legend': ''}
578
+
579
+ def __init__(self, points, **attr):
580
+ PolyPoints.__init__(self, points, attr)
581
+
582
+ def draw(self, dc, printerScale, coord=None):
583
+ """ Draw the points """
584
+ colour = self.attributes['colour']
585
+ width = self.attributes['width'] * printerScale * self._pointSize[0]
586
+ size = self.attributes['size'] * printerScale * self._pointSize[0]
587
+ fillcolour = self.attributes['fillcolour']
588
+ fillstyle = self.attributes['fillstyle']
589
+ marker = self.attributes['marker']
590
+
591
+ if colour and not isinstance(colour, wx.Colour):
592
+ colour = wx.Colour(colour)
593
+ if fillcolour and not isinstance(fillcolour, wx.Colour):
594
+ fillcolour = wx.Colour(fillcolour)
595
+
596
+ dc.SetPen(wx.Pen(colour, int(width)))
597
+ if fillcolour:
598
+ dc.SetBrush(wx.Brush(fillcolour, fillstyle))
599
+ else:
600
+ dc.SetBrush(wx.Brush(colour, fillstyle))
601
+ if coord is None:
602
+ if len(self.scaled): # bugfix for Mac OS X
603
+ self._drawmarkers(dc, self.scaled, marker, size)
604
+ else:
605
+ self._drawmarkers(dc, coord, marker, size) # draw legend marker
606
+
607
+ def getSymExtent(self, printerScale):
608
+ """Width and Height of Marker"""
609
+ s = 5 * self.attributes['size'] * printerScale * self._pointSize[0]
610
+ return (s, s)
611
+
612
+ def _drawmarkers(self, dc, coords, marker, size=1):
613
+ f = getattr(self, "_{}".format(marker))
614
+ f(dc, coords, size)
615
+
616
+ def _circle(self, dc, coords, size=1):
617
+ fact = 2.5 * size
618
+ wh = 5.0 * size
619
+ rect = np.zeros((len(coords), 4), float) + [0.0, 0.0, wh, wh]
620
+ rect[:, 0:2] = coords - [fact, fact]
621
+ dc.DrawEllipseList(rect.astype(np.int32))
622
+
623
+ def _dot(self, dc, coords, size=1):
624
+ coords = [(int(c[0]), int(c[1])) for c in coords]
625
+ dc.DrawPointList(coords)
626
+
627
+ def _square(self, dc, coords, size=1):
628
+ fact = 2.5 * size
629
+ wh = 5.0 * size
630
+ rect = np.zeros((len(coords), 4), float) + [0.0, 0.0, wh, wh]
631
+ rect[:, 0:2] = coords - [fact, fact]
632
+ dc.DrawRectangleList(rect.astype(np.int32))
633
+
634
+ def _triangle(self, dc, coords, size=1):
635
+ shape = [(-2.5 * size, 1.44 * size),
636
+ (2.5 * size, 1.44 * size), (0.0, -2.88 * size)]
637
+ poly = np.repeat(coords, 3, 0)
638
+ poly = poly.reshape(len(coords), 3, 2)
639
+ poly += shape
640
+ dc.DrawPolygonList(poly.astype(np.int32))
641
+
642
+ def _triangle_down(self, dc, coords, size=1):
643
+ shape = [(-2.5 * size, -1.44 * size),
644
+ (2.5 * size, -1.44 * size), (0.0, 2.88 * size)]
645
+ poly = np.repeat(coords, 3, 0)
646
+ poly = poly.reshape(len(coords), 3, 2)
647
+ poly += shape
648
+ dc.DrawPolygonList(poly.astype(np.int32))
649
+
650
+ def _cross(self, dc, coords, size=1):
651
+ fact = 2.5 * size
652
+ for f in [[-fact, -fact, fact, fact], [-fact, fact, fact, -fact]]:
653
+ lines = np.concatenate((coords, coords), axis=1) + f
654
+ dc.DrawLineList(lines.astype(np.int32))
655
+
656
+ def _plus(self, dc, coords, size=1):
657
+ fact = 2.5 * size
658
+ for f in [[-fact, 0, fact, 0], [0, -fact, 0, fact]]:
659
+ lines = np.concatenate((coords, coords), axis=1) + f
660
+ dc.DrawLineList(lines.astype(np.int32))
661
+
662
+
663
+ class PolyBarsBase(PolyPoints):
664
+ """
665
+ Base class for PolyBars and PolyHistogram.
666
+
667
+ .. warning::
668
+
669
+ All methods are private.
670
+ """
671
+ _attributes = {'edgecolour': 'black',
672
+ 'edgewidth': 2,
673
+ 'edgestyle': wx.PENSTYLE_SOLID,
674
+ 'legend': '',
675
+ 'fillcolour': 'red',
676
+ 'fillstyle': wx.BRUSHSTYLE_SOLID,
677
+ 'barwidth': 1.0
678
+ }
679
+
680
+ def __init__(self, points, attr):
681
+ """
682
+ """
683
+ PolyPoints.__init__(self, points, attr)
684
+
685
+ def _scaleAndShift(self, data, scale=(1, 1), shift=(0, 0)):
686
+ """same as override method, but returns a value."""
687
+ scaled = scale * data + shift
688
+ return scaled
689
+
690
+ def getSymExtent(self, printerScale):
691
+ """Width and Height of Marker"""
692
+ h = self.attributes['edgewidth'] * printerScale * self._pointSize[0]
693
+ w = 5 * h
694
+ return (w, h)
695
+
696
+ def set_pen_and_brush(self, dc, printerScale):
697
+ pencolour = self.attributes['edgecolour']
698
+ penwidth = (self.attributes['edgewidth']
699
+ * printerScale * self._pointSize[0])
700
+ penstyle = self.attributes['edgestyle']
701
+ fillcolour = self.attributes['fillcolour']
702
+ fillstyle = self.attributes['fillstyle']
703
+
704
+ if not isinstance(pencolour, wx.Colour):
705
+ pencolour = wx.Colour(pencolour)
706
+ pen = wx.Pen(pencolour, int(penwidth), penstyle)
707
+ pen.SetCap(wx.CAP_BUTT)
708
+
709
+ if not isinstance(fillcolour, wx.Colour):
710
+ fillcolour = wx.Colour(fillcolour)
711
+ brush = wx.Brush(fillcolour, fillstyle)
712
+
713
+ dc.SetPen(pen)
714
+ dc.SetBrush(brush)
715
+
716
+ def scale_rect(self, rect):
717
+ # Scale the points to the plot area
718
+ scaled_rect = self._scaleAndShift(rect,
719
+ self.currentScale,
720
+ self.currentShift)
721
+
722
+ # Convert to (left, top, width, height) for drawing
723
+ wx_rect = [scaled_rect[0][0], # X (left)
724
+ scaled_rect[0][1], # Y (top)
725
+ scaled_rect[1][0] - scaled_rect[0][0], # Width
726
+ scaled_rect[1][1] - scaled_rect[0][1]] # Height
727
+
728
+ return wx_rect
729
+
730
+ def draw(self, dc, printerScale, coord=None):
731
+ pass
732
+
733
+
734
+ class PolyBars(PolyBarsBase):
735
+ """
736
+ Creates a PolyBars object.
737
+
738
+ :param points: The data to plot.
739
+ :type points: sequence of ``(center, height)`` points
740
+ :param **attr: keyword attributes
741
+
742
+ ================================= ============= =======================
743
+ Keyword and Default Description Type
744
+ ================================= ============= =======================
745
+ ``barwidth=1.0`` bar width float or list of floats
746
+ ``edgecolour='black'`` edge color :class:`wx.Colour`
747
+ ``edgewidth=1`` edge width float
748
+ ``edgestyle=wx.PENSTYLE_SOLID`` edge style :class:`wx.PenStyle`
749
+ ``fillcolour='red'`` fill color :class:`wx.Colour`
750
+ ``fillstyle=wx.BRUSHSTYLE_SOLID`` fill style :class:`wx.BrushStyle`
751
+ ``legend=''`` legend string str
752
+ ================================= ============= =======================
753
+
754
+ .. important::
755
+
756
+ If ``barwidth`` is a list of floats:
757
+
758
+ + each bar will have a separate width
759
+ + ``len(barwidth)`` must equal ``len(points)``.
760
+
761
+ .. warning::
762
+
763
+ All methods except ``__init__`` are private.
764
+ """
765
+ def __init__(self, points, **attr):
766
+ PolyBarsBase.__init__(self, points, attr)
767
+
768
+ def calc_rect(self, x, y, w):
769
+ """ Calculate the rectangle for plotting. """
770
+ return self.scale_rect([[x - w / 2, y], # left, top
771
+ [x + w / 2, 0]]) # right, bottom
772
+
773
+ def draw(self, dc, printerScale, coord=None):
774
+ """ Draw the bars """
775
+ self.set_pen_and_brush(dc, printerScale)
776
+ barwidth = self.attributes['barwidth']
777
+
778
+ if coord is None:
779
+ if isinstance(barwidth, (int, float)):
780
+ # use a single width for all bars
781
+ pts = ((x, y, barwidth) for x, y in self.points)
782
+ elif isinstance(barwidth, (list, tuple)):
783
+ # use a separate width for each bar
784
+ if len(barwidth) != len(self.points):
785
+ err_str = ("Barwidth ({} items) and Points ({} items) do "
786
+ "not have the same length!")
787
+ err_str = err_str.format(len(barwidth), len(self.points))
788
+ raise ValueError(err_str)
789
+ pts = ((x, y, w) for (x, y), w in zip(self.points, barwidth))
790
+ else:
791
+ # invalid attribute type
792
+ err_str = ("Invalid type for 'barwidth'. Expected float, "
793
+ "int, or list or tuple of (int or float). Got {}.")
794
+ raise TypeError(err_str.format(type(barwidth)))
795
+
796
+ rects = [self.calc_rect(x, y, w) for x, y, w in pts]
797
+ rects = [(int(r[0]), int(r[1]), int(r[2]), int(r[3])) for r in rects]
798
+ dc.DrawRectangleList(rects)
799
+ else:
800
+ dc.DrawLines(coord) # draw legend line
801
+
802
+
803
+ class PolyHistogram(PolyBarsBase):
804
+ """
805
+ Creates a PolyHistogram object.
806
+
807
+ :param hist: The histogram data.
808
+ :type hist: sequence of ``y`` values that define the heights of the bars
809
+ :param binspec: The bin specification.
810
+ :type binspec: sequence of ``x`` values that define the edges of the bins
811
+ :param **attr: keyword attributes
812
+
813
+ ================================= ============= =======================
814
+ Keyword and Default Description Type
815
+ ================================= ============= =======================
816
+ ``edgecolour='black'`` edge color :class:`wx.Colour`
817
+ ``edgewidth=3`` edge width float
818
+ ``edgestyle=wx.PENSTYLE_SOLID`` edge style :class:`wx.PenStyle`
819
+ ``fillcolour='blue'`` fill color :class:`wx.Colour`
820
+ ``fillstyle=wx.BRUSHSTYLE_SOLID`` fill style :class:`wx.BrushStyle`
821
+ ``legend=''`` legend string str
822
+ ================================= ============= =======================
823
+
824
+ .. tip::
825
+
826
+ Use ``np.histogram()`` to easily create your histogram parameters::
827
+
828
+ hist_data, binspec = np.histogram(data)
829
+ hist_plot = PolyHistogram(hist_data, binspec)
830
+
831
+ .. important::
832
+
833
+ ``len(binspec)`` must equal ``len(hist) + 1``.
834
+
835
+ .. warning::
836
+
837
+ All methods except ``__init__`` are private.
838
+ """
839
+ def __init__(self, hist, binspec, **attr):
840
+ if len(binspec) != len(hist) + 1:
841
+ raise ValueError("Len(binspec) must equal len(hist) + 1")
842
+
843
+ self.hist = hist
844
+ self.binspec = binspec
845
+
846
+ # define the bins and center x locations
847
+ self.bins = list(pairwise(self.binspec))
848
+ bar_center_x = (pair[0] + (pair[1] - pair[0])/2 for pair in self.bins)
849
+
850
+ points = list(zip(bar_center_x, self.hist))
851
+ PolyBarsBase.__init__(self, points, attr)
852
+
853
+ def calc_rect(self, y, low, high):
854
+ """ Calculate the rectangle for plotting. """
855
+ return self.scale_rect([[low, y], # left, top
856
+ [high, 0]]) # right, bottom
857
+
858
+ def draw(self, dc, printerScale, coord=None):
859
+ """ Draw the bars """
860
+ self.set_pen_and_brush(dc, printerScale)
861
+
862
+ if coord is None:
863
+ rects = [self.calc_rect(y, low, high)
864
+ for y, (low, high)
865
+ in zip(self.hist, self.bins)]
866
+ rects = [(int(r[0]), int(r[1]), int(r[2]), int(r[3]))
867
+ for r in rects]
868
+
869
+ dc.DrawRectangleList(rects)
870
+ else:
871
+ dc.DrawLines(coord) # draw legend line
872
+
873
+
874
+ class PolyBoxPlot(PolyPoints):
875
+ """
876
+ Creates a PolyBoxPlot object.
877
+
878
+ :param data: Raw data to create a box plot from.
879
+ :type data: sequence of int or float
880
+ :param **attr: keyword attributes
881
+
882
+ ================================= ============= =======================
883
+ Keyword and Default Description Type
884
+ ================================= ============= =======================
885
+ ``colour='black'`` edge color :class:`wx.Colour`
886
+ ``width=1`` edge width float
887
+ ``style=wx.PENSTYLE_SOLID`` edge style :class:`wx.PenStyle`
888
+ ``legend=''`` legend string str
889
+ ================================= ============= =======================
890
+
891
+ .. note::
892
+
893
+ ``np.NaN`` and ``np.inf`` values are ignored.
894
+
895
+ .. admonition:: TODO
896
+
897
+ + [ ] Figure out a better way to get multiple box plots side-by-side
898
+ (current method is a hack).
899
+ + [ ] change the X axis to some labels.
900
+ + [ ] Change getClosestPoint to only grab box plot items and outlers?
901
+ Currently grabs every data point.
902
+ + [ ] Add more customization such as Pens/Brushes, outlier shapes/size,
903
+ and box width.
904
+ + [ ] Figure out how I want to handle log-y: log data then calcBP? Or
905
+ should I calc the BP first then the plot it on a log scale?
906
+ """
907
+ _attributes = {'colour': 'black',
908
+ 'width': 1,
909
+ 'style': wx.PENSTYLE_SOLID,
910
+ 'legend': '',
911
+ }
912
+
913
+ def __init__(self, points, **attr):
914
+ # Set various attributes
915
+ self.box_width = 0.5
916
+
917
+ # Determine the X position and create a 1d dataset.
918
+ self.xpos = points[0, 0]
919
+ points = points[:, 1]
920
+
921
+ # Calculate the box plot points and the outliers
922
+ self._bpdata = self.calcBpData(points)
923
+ self._outliers = self.calcOutliers(points)
924
+ points = np.concatenate((self._bpdata, self._outliers))
925
+ points = np.array([(self.xpos, x) for x in points])
926
+
927
+ # Create a jitter for the outliers
928
+ self.jitter = (0.05 * np.random.random_sample(len(self._outliers))
929
+ + self.xpos - 0.025)
930
+
931
+ # Init the parent class
932
+ PolyPoints.__init__(self, points, attr)
933
+
934
+ def _clean_data(self, data=None):
935
+ """
936
+ Removes NaN and Inf from the data.
937
+ """
938
+ if data is None:
939
+ data = self.points
940
+
941
+ # clean out NaN and infinity values.
942
+ data = data[~np.isnan(data)]
943
+ data = data[~np.isinf(data)]
944
+
945
+ return data
946
+
947
+ def boundingBox(self):
948
+ """
949
+ Returns bounding box for the plot.
950
+
951
+ Override method.
952
+ """
953
+ xpos = self.xpos
954
+
955
+ minXY = np.array([xpos - self.box_width / 2, self._bpdata.min * 0.95])
956
+ maxXY = np.array([xpos + self.box_width / 2, self._bpdata.max * 1.05])
957
+ return minXY, maxXY
958
+
959
+ def getClosestPoint(self, pntXY, pointScaled=True):
960
+ """
961
+ Returns the index of closest point on the curve, pointXY,
962
+ scaledXY, distance x, y in user coords.
963
+
964
+ Override method.
965
+
966
+ if pointScaled == True, then based on screen coords
967
+ if pointScaled == False, then based on user coords
968
+ """
969
+
970
+ xpos = self.xpos
971
+
972
+ # combine the outliers with the box plot data
973
+ data_to_use = np.concatenate((self._bpdata, self._outliers))
974
+ data_to_use = np.array([(xpos, x) for x in data_to_use])
975
+
976
+ if pointScaled:
977
+ # Use screen coords
978
+ p = self.scaled
979
+ pxy = self.currentScale * np.array(pntXY) + self.currentShift
980
+ else:
981
+ # Using user coords
982
+ p = self._points
983
+ pxy = np.array(pntXY)
984
+
985
+ # determine distance for each point
986
+ d = np.sqrt(np.add.reduce((p - pxy) ** 2, 1)) # sqrt(dx^2+dy^2)
987
+ pntIndex = np.argmin(d)
988
+ dist = d[pntIndex]
989
+ return [pntIndex,
990
+ self.points[pntIndex],
991
+ self.scaled[pntIndex] / self._pointSize,
992
+ dist]
993
+
994
+ def getSymExtent(self, printerScale):
995
+ """Width and Height of Marker"""
996
+ # TODO: does this need to be updated?
997
+ h = self.attributes['width'] * printerScale * self._pointSize[0]
998
+ w = 5 * h
999
+ return (w, h)
1000
+
1001
+ def calcBpData(self, data=None):
1002
+ """
1003
+ Box plot points:
1004
+
1005
+ Median (50%)
1006
+ 75%
1007
+ 25%
1008
+ low_whisker = lowest value that's >= (25% - (IQR * 1.5))
1009
+ high_whisker = highest value that's <= 75% + (IQR * 1.5)
1010
+
1011
+ outliers are outside of 1.5 * IQR
1012
+
1013
+ :param array-like data: The data to plot
1014
+ :return bpdata: Descriptive statistics for data:
1015
+ (min_data, low_whisker, q25, median, q75, high_whisker, max_data)
1016
+ :rtype: collections.namedtuple
1017
+ """
1018
+ data = self._clean_data(data)
1019
+
1020
+ min_data = float(np.min(data))
1021
+ max_data = float(np.max(data))
1022
+ q25 = float(np.percentile(data, 25))
1023
+ q75 = float(np.percentile(data, 75))
1024
+
1025
+ iqr = q75 - q25
1026
+
1027
+ low_whisker = float(data[data >= q25 - 1.5 * iqr].min())
1028
+ high_whisker = float(data[data <= q75 + 1.5 * iqr].max())
1029
+
1030
+ median = float(np.median(data))
1031
+
1032
+ BPData = namedtuple("bpdata", ("min", "low_whisker", "q25", "median",
1033
+ "q75", "high_whisker", "max"))
1034
+
1035
+ bpdata = BPData(min_data, low_whisker, q25, median,
1036
+ q75, high_whisker, max_data)
1037
+
1038
+ return bpdata
1039
+
1040
+ def calcOutliers(self, data=None):
1041
+ """
1042
+ Calculates the outliers. Must be called after calcBpData.
1043
+ """
1044
+ data = self._clean_data(data)
1045
+
1046
+ outliers = data
1047
+ outlier_bool = np.logical_or(outliers > self._bpdata.high_whisker,
1048
+ outliers < self._bpdata.low_whisker)
1049
+ outliers = outliers[outlier_bool]
1050
+ return outliers
1051
+
1052
+ def _scaleAndShift(self, data, scale=(1, 1), shift=(0, 0)):
1053
+ """same as override method, but returns a value."""
1054
+ scaled = scale * data + shift
1055
+ return scaled
1056
+
1057
+ @TempStyle('pen')
1058
+ def draw(self, dc, printerScale, coord=None):
1059
+ """
1060
+ Draws a box plot on the DC.
1061
+
1062
+ .. note::
1063
+
1064
+ The following draw order is required:
1065
+
1066
+ 1. First the whisker line
1067
+ 2. Then the IQR box
1068
+ 3. Lasly the median line.
1069
+
1070
+ This is because
1071
+
1072
+ + The whiskers are drawn as single line rather than two lines
1073
+ + The median line must be visible over the box if the box has a fill.
1074
+
1075
+ Other than that, the draw order can be changed.
1076
+ """
1077
+ self._draw_whisker(dc, printerScale)
1078
+ self._draw_iqr_box(dc, printerScale)
1079
+ self._draw_median(dc, printerScale) # median after box
1080
+ self._draw_whisker_ends(dc, printerScale)
1081
+ self._draw_outliers(dc, printerScale)
1082
+
1083
+ @TempStyle('pen')
1084
+ def _draw_whisker(self, dc, printerScale):
1085
+ """Draws the whiskers as a single line"""
1086
+ xpos = self.xpos
1087
+
1088
+ # We draw it as one line and then hide the middle part with
1089
+ # the IQR rectangle
1090
+ whisker_line = np.array([[xpos, self._bpdata.low_whisker],
1091
+ [xpos, self._bpdata.high_whisker]])
1092
+
1093
+ whisker_line = self._scaleAndShift(whisker_line,
1094
+ self.currentScale,
1095
+ self.currentShift)
1096
+
1097
+ whisker_pen = wx.Pen(wx.BLACK, 2, wx.PENSTYLE_SOLID)
1098
+ whisker_pen.SetCap(wx.CAP_BUTT)
1099
+ dc.SetPen(whisker_pen)
1100
+ dc.DrawLines(whisker_line)
1101
+
1102
+ @TempStyle('pen')
1103
+ def _draw_iqr_box(self, dc, printerScale):
1104
+ """Draws the Inner Quartile Range box"""
1105
+ xpos = self.xpos
1106
+ box_w = self.box_width
1107
+
1108
+ iqr_box = [[xpos - box_w / 2, self._bpdata.q75], # left, top
1109
+ [xpos + box_w / 2, self._bpdata.q25]] # right, bottom
1110
+
1111
+ # Scale it to the plot area
1112
+ iqr_box = self._scaleAndShift(iqr_box,
1113
+ self.currentScale,
1114
+ self.currentShift)
1115
+
1116
+ # rectangles are drawn (left, top, width, height) so adjust
1117
+ iqr_box = [int(iqr_box[0][0]), # X (left)
1118
+ int(iqr_box[0][1]), # Y (top)
1119
+ int(iqr_box[1][0] - iqr_box[0][0]), # Width
1120
+ int(iqr_box[1][1] - iqr_box[0][1])] # Height
1121
+
1122
+ box_pen = wx.Pen(wx.BLACK, 3, wx.PENSTYLE_SOLID)
1123
+ box_brush = wx.Brush(wx.GREEN, wx.BRUSHSTYLE_SOLID)
1124
+ dc.SetPen(box_pen)
1125
+ dc.SetBrush(box_brush)
1126
+
1127
+ dc.DrawRectangleList([iqr_box])
1128
+
1129
+ @TempStyle('pen')
1130
+ def _draw_median(self, dc, printerScale, coord=None):
1131
+ """Draws the median line"""
1132
+ xpos = self.xpos
1133
+
1134
+ median_line = np.array(
1135
+ [[xpos - self.box_width / 2, self._bpdata.median],
1136
+ [xpos + self.box_width / 2, self._bpdata.median]]
1137
+ )
1138
+
1139
+ median_line = self._scaleAndShift(median_line,
1140
+ self.currentScale,
1141
+ self.currentShift)
1142
+
1143
+ median_pen = wx.Pen(wx.BLACK, 4, wx.PENSTYLE_SOLID)
1144
+ median_pen.SetCap(wx.CAP_BUTT)
1145
+ dc.SetPen(median_pen)
1146
+ dc.DrawLines(median_line)
1147
+
1148
+ @TempStyle('pen')
1149
+ def _draw_whisker_ends(self, dc, printerScale):
1150
+ """Draws the end caps of the whiskers"""
1151
+ xpos = self.xpos
1152
+ fence_top = np.array(
1153
+ [[xpos - self.box_width * 0.2, self._bpdata.high_whisker],
1154
+ [xpos + self.box_width * 0.2, self._bpdata.high_whisker]]
1155
+ )
1156
+
1157
+ fence_top = self._scaleAndShift(fence_top,
1158
+ self.currentScale,
1159
+ self.currentShift)
1160
+
1161
+ fence_bottom = np.array(
1162
+ [[xpos - self.box_width * 0.2, self._bpdata.low_whisker],
1163
+ [xpos + self.box_width * 0.2, self._bpdata.low_whisker]]
1164
+ )
1165
+
1166
+ fence_bottom = self._scaleAndShift(fence_bottom,
1167
+ self.currentScale,
1168
+ self.currentShift)
1169
+
1170
+ fence_pen = wx.Pen(wx.BLACK, 2, wx.PENSTYLE_SOLID)
1171
+ fence_pen.SetCap(wx.CAP_BUTT)
1172
+ dc.SetPen(fence_pen)
1173
+ dc.DrawLines(fence_top)
1174
+ dc.DrawLines(fence_bottom)
1175
+
1176
+ @TempStyle('pen')
1177
+ def _draw_outliers(self, dc, printerScale):
1178
+ """Draws dots for the outliers"""
1179
+ # Set the pen
1180
+ outlier_pen = wx.Pen(wx.BLUE, 5, wx.PENSTYLE_SOLID)
1181
+ dc.SetPen(outlier_pen)
1182
+
1183
+ outliers = self._outliers
1184
+
1185
+ # Scale the data for plotting
1186
+ pt_data = np.array([self.jitter, outliers]).T
1187
+ pt_data = self._scaleAndShift(pt_data,
1188
+ self.currentScale,
1189
+ self.currentShift)
1190
+
1191
+ # Draw the outliers
1192
+ size = 0.5
1193
+ fact = 2.5 * size
1194
+ wh = 5.0 * size
1195
+ rect = np.zeros((len(pt_data), 4), float) + [0.0, 0.0, wh, wh]
1196
+ rect[:, 0:2] = pt_data - [fact, fact]
1197
+ dc.DrawRectangleList(rect.astype(np.int32))
1198
+
1199
+
1200
+ class PlotGraphics(object):
1201
+ """
1202
+ Creates a PlotGraphics object.
1203
+
1204
+ :param objects: The Poly objects to plot.
1205
+ :type objects: list of :class:`~wx.lib.plot.PolyPoints` objects
1206
+ :param title: The title shown at the top of the graph.
1207
+ :type title: str
1208
+ :param xLabel: The x-axis label.
1209
+ :type xLabel: str
1210
+ :param yLabel: The y-axis label.
1211
+ :type yLabel: str
1212
+
1213
+ .. warning::
1214
+
1215
+ All methods except ``__init__`` are private.
1216
+ """
1217
+ def __init__(self, objects, title='', xLabel='', yLabel=''):
1218
+ if type(objects) not in [list, tuple]:
1219
+ raise TypeError("objects argument should be list or tuple")
1220
+ self.objects = objects
1221
+ self._title = title
1222
+ self._xLabel = xLabel
1223
+ self._yLabel = yLabel
1224
+ self._pointSize = (1.0, 1.0)
1225
+
1226
+ @property
1227
+ def logScale(self):
1228
+ if len(self.objects) == 0:
1229
+ return
1230
+ return [obj.logScale for obj in self.objects]
1231
+
1232
+ @logScale.setter
1233
+ def logScale(self, logscale):
1234
+ # XXX: error checking done by PolyPoints class
1235
+ # if not isinstance(logscale, tuple) and len(logscale) != 2:
1236
+ # raise TypeError("logscale must be a 2-tuple of bools")
1237
+ if len(self.objects) == 0:
1238
+ return
1239
+ for obj in self.objects:
1240
+ obj.logScale = logscale
1241
+
1242
+ def setLogScale(self, logscale):
1243
+ """
1244
+ Set the log scale boolean value.
1245
+
1246
+ .. deprecated:: Feb 27, 2016
1247
+
1248
+ Use the :attr:`~wx.lib.plot.polyobjects.PlotGraphics.logScale`
1249
+ property instead.
1250
+ """
1251
+ pendingDeprecation("self.logScale property")
1252
+ self.logScale = logscale
1253
+
1254
+ @property
1255
+ def absScale(self):
1256
+ if len(self.objects) == 0:
1257
+ return
1258
+ return [obj.absScale for obj in self.objects]
1259
+
1260
+ @absScale.setter
1261
+ def absScale(self, absscale):
1262
+ # XXX: error checking done by PolyPoints class
1263
+ # if not isinstance(absscale, tuple) and len(absscale) != 2:
1264
+ # raise TypeError("absscale must be a 2-tuple of bools")
1265
+ if len(self.objects) == 0:
1266
+ return
1267
+ for obj in self.objects:
1268
+ obj.absScale = absscale
1269
+
1270
+ def boundingBox(self):
1271
+ p1, p2 = self.objects[0].boundingBox()
1272
+ for o in self.objects[1:]:
1273
+ p1o, p2o = o.boundingBox()
1274
+ p1 = np.minimum(p1, p1o)
1275
+ p2 = np.maximum(p2, p2o)
1276
+ return p1, p2
1277
+
1278
+ def scaleAndShift(self, scale=(1, 1), shift=(0, 0)):
1279
+ for o in self.objects:
1280
+ o.scaleAndShift(scale, shift)
1281
+
1282
+ def setPrinterScale(self, scale):
1283
+ """
1284
+ Thickens up lines and markers only for printing
1285
+
1286
+ .. deprecated:: Feb 27, 2016
1287
+
1288
+ Use the :attr:`~wx.lib.plot.polyobjects.PlotGraphics.printerScale`
1289
+ property instead.
1290
+ """
1291
+ pendingDeprecation("self.printerScale property")
1292
+ self.printerScale = scale
1293
+
1294
+ def setXLabel(self, xLabel=''):
1295
+ """
1296
+ Set the X axis label on the graph
1297
+
1298
+ .. deprecated:: Feb 27, 2016
1299
+
1300
+ Use the :attr:`~wx.lib.plot.polyobjects.PlotGraphics.xLabel`
1301
+ property instead.
1302
+ """
1303
+ pendingDeprecation("self.xLabel property")
1304
+ self.xLabel = xLabel
1305
+
1306
+ def setYLabel(self, yLabel=''):
1307
+ """
1308
+ Set the Y axis label on the graph
1309
+
1310
+ .. deprecated:: Feb 27, 2016
1311
+
1312
+ Use the :attr:`~wx.lib.plot.polyobjects.PlotGraphics.yLabel`
1313
+ property instead.
1314
+ """
1315
+ pendingDeprecation("self.yLabel property")
1316
+ self.yLabel = yLabel
1317
+
1318
+ def setTitle(self, title=''):
1319
+ """
1320
+ Set the title at the top of graph
1321
+
1322
+ .. deprecated:: Feb 27, 2016
1323
+
1324
+ Use the :attr:`~wx.lib.plot.polyobjects.PlotGraphics.title`
1325
+ property instead.
1326
+ """
1327
+ pendingDeprecation("self.title property")
1328
+ self.title = title
1329
+
1330
+ def getXLabel(self):
1331
+ """
1332
+ Get X axis label string
1333
+
1334
+ .. deprecated:: Feb 27, 2016
1335
+
1336
+ Use the :attr:`~wx.lib.plot.polyobjects.PlotGraphics.xLabel`
1337
+ property instead.
1338
+ """
1339
+ pendingDeprecation("self.xLabel property")
1340
+ return self.xLabel
1341
+
1342
+ def getYLabel(self):
1343
+ """
1344
+ Get Y axis label string
1345
+
1346
+ .. deprecated:: Feb 27, 2016
1347
+
1348
+ Use the :attr:`~wx.lib.plot.polyobjects.PlotGraphics.yLabel`
1349
+ property instead.
1350
+ """
1351
+ pendingDeprecation("self.yLabel property")
1352
+ return self.yLabel
1353
+
1354
+ def getTitle(self, title=''):
1355
+ """
1356
+ Get the title at the top of graph
1357
+
1358
+ .. deprecated:: Feb 27, 2016
1359
+
1360
+ Use the :attr:`~wx.lib.plot.polyobjects.PlotGraphics.title`
1361
+ property instead.
1362
+ """
1363
+ pendingDeprecation("self.title property")
1364
+ return self.title
1365
+
1366
+ @property
1367
+ def printerScale(self):
1368
+ return self._printerScale
1369
+
1370
+ @printerScale.setter
1371
+ def printerScale(self, scale):
1372
+ """Thickens up lines and markers only for printing"""
1373
+ self._printerScale = scale
1374
+
1375
+ @property
1376
+ def xLabel(self):
1377
+ """Get the X axis label on the graph"""
1378
+ return self._xLabel
1379
+
1380
+ @xLabel.setter
1381
+ def xLabel(self, text):
1382
+ self._xLabel = text
1383
+
1384
+ @property
1385
+ def yLabel(self):
1386
+ """Get the Y axis label on the graph"""
1387
+ return self._yLabel
1388
+
1389
+ @yLabel.setter
1390
+ def yLabel(self, text):
1391
+ self._yLabel = text
1392
+
1393
+ @property
1394
+ def title(self):
1395
+ """Get the title at the top of graph"""
1396
+ return self._title
1397
+
1398
+ @title.setter
1399
+ def title(self, text):
1400
+ self._title = text
1401
+
1402
+ def draw(self, dc):
1403
+ for o in self.objects:
1404
+ # t=_time.perf_counter() # profile info
1405
+ o._pointSize = self._pointSize
1406
+ o.draw(dc, self._printerScale)
1407
+ # print(o, "time=", _time.perf_counter()-t)
1408
+
1409
+ def getSymExtent(self, printerScale):
1410
+ """Get max width and height of lines and markers symbols for legend"""
1411
+ self.objects[0]._pointSize = self._pointSize
1412
+ symExt = self.objects[0].getSymExtent(printerScale)
1413
+ for o in self.objects[1:]:
1414
+ o._pointSize = self._pointSize
1415
+ oSymExt = o.getSymExtent(printerScale)
1416
+ symExt = np.maximum(symExt, oSymExt)
1417
+ return symExt
1418
+
1419
+ def getLegendNames(self):
1420
+ """Returns list of legend names"""
1421
+ lst = [None] * len(self)
1422
+ for i in range(len(self)):
1423
+ lst[i] = self.objects[i].getLegend()
1424
+ return lst
1425
+
1426
+ def __len__(self):
1427
+ return len(self.objects)
1428
+
1429
+ def __getitem__(self, item):
1430
+ return self.objects[item]
1431
+
1432
+
1433
+ # -------------------------------------------------------------------------
1434
+ # Used to layout the printer page
1435
+
1436
+
1437
+ class PlotPrintout(wx.Printout):
1438
+ """Controls how the plot is made in printing and previewing"""
1439
+ # Do not change method names in this class,
1440
+ # we have to override wx.Printout methods here!
1441
+
1442
+ def __init__(self, graph):
1443
+ """graph is instance of plotCanvas to be printed or previewed"""
1444
+ wx.Printout.__init__(self)
1445
+ self.graph = graph
1446
+
1447
+ def HasPage(self, page):
1448
+ if page == 1:
1449
+ return True
1450
+ else:
1451
+ return False
1452
+
1453
+ def GetPageInfo(self):
1454
+ return (1, 1, 1, 1) # disable page numbers
1455
+
1456
+ def OnPrintPage(self, page):
1457
+ dc = self.GetDC() # allows using floats for certain functions
1458
+ # print("PPI Printer",self.GetPPIPrinter())
1459
+ # print("PPI Screen", self.GetPPIScreen())
1460
+ # print("DC GetSize", dc.GetSize())
1461
+ # print("GetPageSizePixels", self.GetPageSizePixels())
1462
+ # Note PPIScreen does not give the correct number
1463
+ # Calculate everything for printer and then scale for preview
1464
+ PPIPrinter = self.GetPPIPrinter() # printer dots/inch (w,h)
1465
+ # PPIScreen= self.GetPPIScreen() # screen dots/inch (w,h)
1466
+ dcSize = dc.GetSize() # DC size
1467
+ if self.graph._antiAliasingEnabled and not isinstance(dc, wx.GCDC):
1468
+ try:
1469
+ dc = wx.GCDC(dc)
1470
+ except Exception:
1471
+ pass
1472
+ else:
1473
+ if self.graph._hiResEnabled:
1474
+ # high precision - each logical unit is 1/20 of a point
1475
+ dc.SetMapMode(wx.MM_TWIPS)
1476
+ pageSize = self.GetPageSizePixels() # page size in terms of pixcels
1477
+ clientDcSize = self.graph.GetClientSize()
1478
+
1479
+ # find what the margins are (mm)
1480
+ pgSetupData = self.graph.pageSetupData
1481
+ margLeftSize, margTopSize = pgSetupData.GetMarginTopLeft()
1482
+ margRightSize, margBottomSize = pgSetupData.GetMarginBottomRight()
1483
+
1484
+ # calculate offset and scale for dc
1485
+ pixLeft = margLeftSize * PPIPrinter[0] / 25.4 # mm*(dots/in)/(mm/in)
1486
+ pixRight = margRightSize * PPIPrinter[0] / 25.4
1487
+ pixTop = margTopSize * PPIPrinter[1] / 25.4
1488
+ pixBottom = margBottomSize * PPIPrinter[1] / 25.4
1489
+
1490
+ plotAreaW = pageSize[0] - (pixLeft + pixRight)
1491
+ plotAreaH = pageSize[1] - (pixTop + pixBottom)
1492
+
1493
+ # ratio offset and scale to screen size if preview
1494
+ if self.IsPreview():
1495
+ ratioW = float(dcSize[0]) / pageSize[0]
1496
+ ratioH = float(dcSize[1]) / pageSize[1]
1497
+ pixLeft *= ratioW
1498
+ pixTop *= ratioH
1499
+ plotAreaW *= ratioW
1500
+ plotAreaH *= ratioH
1501
+
1502
+ # rescale plot to page or preview plot area
1503
+ self.graph._setSize(plotAreaW, plotAreaH)
1504
+
1505
+ # Set offset and scale
1506
+ dc.SetDeviceOrigin(int(pixLeft), int(pixTop))
1507
+
1508
+ # Thicken up pens and increase marker size for printing
1509
+ ratioW = float(plotAreaW) / clientDcSize[0]
1510
+ ratioH = float(plotAreaH) / clientDcSize[1]
1511
+ aveScale = (ratioW + ratioH) / 2
1512
+ if self.graph._antiAliasingEnabled and not self.IsPreview():
1513
+ scale = dc.GetUserScale()
1514
+ dc.SetUserScale(scale[0] / self.graph._pointSize[0],
1515
+ scale[1] / self.graph._pointSize[1])
1516
+ self.graph._setPrinterScale(aveScale) # tickens up pens for printing
1517
+
1518
+ self.graph._printDraw(dc)
1519
+ # rescale back to original
1520
+ self.graph._setSize()
1521
+ self.graph._setPrinterScale(1)
1522
+ self.graph.Redraw() # to get point label scale and shift correct
1523
+
1524
+ return True