mapdata 3.19.0__tar.gz → 3.21.0__tar.gz
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.
- {mapdata-3.19.0/mapdata.egg-info → mapdata-3.21.0}/PKG-INFO +2 -17
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/mapdata.py +362 -20
- {mapdata-3.19.0 → mapdata-3.21.0/mapdata.egg-info}/PKG-INFO +2 -17
- {mapdata-3.19.0 → mapdata-3.21.0}/setup.py +2 -2
- {mapdata-3.19.0 → mapdata-3.21.0}/LICENSE.txt +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/MANIFEST.in +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/README.md +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/configfile/mapdata.conf +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/0.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/1.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/2.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/3.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/4.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/5.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/6.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/7.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/8.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/9.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/A.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/B.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/C.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/D.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/E.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/F.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/G.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/H.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/I.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/J.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/K.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/L.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/M.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/N.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/O.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/P.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/Q.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/R.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/S.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/T.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/U.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/V.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/W.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/X.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/Y.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/Z.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/airplane.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/anchor.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/ball.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/ball_small.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/bar.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/bars.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/binoculars.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/bird.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/block.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/block_small.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/bookmark.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/box_stack.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/camera.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/cancel.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/car.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/car2.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/center8.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/check.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/check_circle.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/checkbox.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/checkerboard.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/chevrons.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/circle.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/circle_bar.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/circle_plus.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/circle_stipple.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/circle_triangle.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/circle_wedge.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/circle_x.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/clock.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/columns.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/contract.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/cross.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/darkeye.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/decrease.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/deposition.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/diag_ll.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/diag_lr.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/diag_ul.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/diag_ur.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/dialog.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/diamond.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/donkey.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/dot.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/down.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/drop.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/elephant.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/expand.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/eye.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/fire.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/fish.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/flag.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/flag2.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/four_arrows.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/graph.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/hand.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/hash.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/heart.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/hidden.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/hourglass.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/house.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/increase.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/info.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/leaf.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/left.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/lightbulb.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/lightning.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/lightning2.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/location_ptr.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/mine.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/nested_boxes.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/pennant.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/pennant2.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/people.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/person.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/person2.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/person3.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/phone.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/photo.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/picnic.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/plus.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/point_down.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/point_left.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/point_right.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/point_up.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/pointer_ne.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/pointer_nw.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/pointer_se.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/pointer_sw.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/puzzle.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/q1.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/q1_notch.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/q2.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/q2_notch.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/q3.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/q3_notch.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/q4.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/q4_notch.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/qmark_circle.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/qmark_circle2.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/raincloud.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/right.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/rocket.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/rocket2.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/rose.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/rows.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/scales.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/search.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/search2.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/skull.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/square.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/star.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/stipple.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/stop.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/surprise_circle.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/swamp.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/target.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/target2.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/ten.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/trash.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/tree.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/tree2.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/tree3.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/triangle.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/triangle_open.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/triangle_sm.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/up.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/vapor.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/warning.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/wave.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/wave2.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/wave3.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/weather.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/wedge.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/wedge_sm.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/wedges_3.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/well.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/whale.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/whale2.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/wheelchair.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/zigzags.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/16x16/zigzags2.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/20x20/ball20.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/20x20/block20.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/20x20/circle20.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/20x20/q1_20.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/20x20/q2_20.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/20x20/q3_20.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/20x20/q4_20.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/20x20/square20.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/24x24/ball24.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/24x24/block24.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/24x24/circle24.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/24x24/square24.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/28x28/ball28.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/28x28/block28.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/28x28/circle28.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata/symbols/28x28/square28.xbm +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata.egg-info/SOURCES.txt +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata.egg-info/dependency_links.txt +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata.egg-info/requires.txt +9 -9
- {mapdata-3.19.0 → mapdata-3.21.0}/mapdata.egg-info/top_level.txt +0 -0
- {mapdata-3.19.0 → mapdata-3.21.0}/setup.cfg +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: mapdata
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.21.0
|
|
4
4
|
Summary: An interactive map and table explorer for geographic coordinates in a spreadsheet, CSV file, or database that includes data plotting and statistical summaries
|
|
5
5
|
Home-page: https:/hg.sr.ht/~rdnielsen/mapdata
|
|
6
6
|
Author: Dreas Nielsen
|
|
7
7
|
Author-email: cortice@tutanota.com
|
|
8
8
|
License: GPL
|
|
9
|
-
Keywords: Map,Locations,CRS,CSV,Spreadsheet,Database,PNG,JPG,Postscript
|
|
9
|
+
Keywords: Map,Locations,CRS,CSV,Spreadsheet,Database,Statistics,Plotting,PNG,JPG,Postscript
|
|
10
10
|
Classifier: Development Status :: 5 - Production/Stable
|
|
11
11
|
Classifier: Environment :: Console
|
|
12
12
|
Classifier: Environment :: X11 Applications
|
|
@@ -24,21 +24,6 @@ Classifier: Topic :: Scientific/Engineering
|
|
|
24
24
|
Requires-Python: >=3.8
|
|
25
25
|
Description-Content-Type: text/markdown
|
|
26
26
|
License-File: LICENSE.txt
|
|
27
|
-
Requires-Dist: tkintermapview
|
|
28
|
-
Requires-Dist: pyproj
|
|
29
|
-
Requires-Dist: jenkspy
|
|
30
|
-
Requires-Dist: odfpy
|
|
31
|
-
Requires-Dist: openpyxl
|
|
32
|
-
Requires-Dist: xlrd
|
|
33
|
-
Requires-Dist: matplotlib
|
|
34
|
-
Requires-Dist: seaborn
|
|
35
|
-
Requires-Dist: loess
|
|
36
|
-
Requires-Dist: statsmodels
|
|
37
|
-
Requires-Dist: scipy
|
|
38
|
-
Requires-Dist: scikit-learn
|
|
39
|
-
Requires-Dist: pymannkendall
|
|
40
|
-
Requires-Dist: umap-learn
|
|
41
|
-
Requires-Dist: pynndescent
|
|
42
27
|
|
|
43
28
|
|
|
44
29
|
*mapdata.py* is a data explorer for data sets containing geographic coordinates. Data can be read from a CSV file, spreadsheet, or database. Both a map and a data
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
#
|
|
25
25
|
# ==================================================================
|
|
26
26
|
|
|
27
|
-
version = "3.
|
|
28
|
-
vdate = "2026-
|
|
27
|
+
version = "3.21.0"
|
|
28
|
+
vdate = "2026-03-17"
|
|
29
29
|
|
|
30
30
|
copyright = "2023-2026"
|
|
31
31
|
|
|
@@ -1332,12 +1332,14 @@ def enable_if(widget, tf_val):
|
|
|
1332
1332
|
widget["state"] = tk.NORMAL if tf_val else tk.DISABLED
|
|
1333
1333
|
|
|
1334
1334
|
def chosen_dataset(maingui, column_list, selected_only):
|
|
1335
|
+
# Returns the dataset as a column-oriented list of lists.
|
|
1335
1336
|
if selected_only:
|
|
1336
1337
|
return maingui.get_sel_data(column_list)
|
|
1337
1338
|
else:
|
|
1338
1339
|
return maingui.get_all_data(column_list)
|
|
1339
1340
|
|
|
1340
1341
|
def chosen_dataset_and_ids(maingui, column_list, selected_only):
|
|
1342
|
+
# Returns the dataset as a column-oriented list of lists.
|
|
1341
1343
|
if selected_only:
|
|
1342
1344
|
return maingui.get_sel_data(column_list), maingui.get_sel_rowids()
|
|
1343
1345
|
else:
|
|
@@ -3401,7 +3403,7 @@ class MapUI(object):
|
|
|
3401
3403
|
def get_all_rowids(self):
|
|
3402
3404
|
return self.tbl.get_children()
|
|
3403
3405
|
def get_sel_data(self, column_list):
|
|
3404
|
-
# Plotting and statistics support. Return data from selected rows for the specified columns, as a list of lists.
|
|
3406
|
+
# Plotting and statistics support. Return data from selected rows for the specified columns, as a list of column-oriented lists.
|
|
3405
3407
|
res = [[] for _ in column_list]
|
|
3406
3408
|
indices = [self.headers.index(c) for c in column_list]
|
|
3407
3409
|
for sel_row in self.tbl.selection():
|
|
@@ -4015,6 +4017,14 @@ class MapUI(object):
|
|
|
4015
4017
|
dlg = UniqueValuesDialog(self, self.data_types)
|
|
4016
4018
|
dlg.show()
|
|
4017
4019
|
|
|
4020
|
+
def show_missing_byrow(self, args=None):
|
|
4021
|
+
dlg = MissingByRowDialog(self, self.data_types)
|
|
4022
|
+
dlg.show()
|
|
4023
|
+
|
|
4024
|
+
def show_missing_byvariable(self, args=None):
|
|
4025
|
+
dlg = MissingByVariableDialog(self, self.data_types)
|
|
4026
|
+
dlg.show()
|
|
4027
|
+
|
|
4018
4028
|
def add_rowid(self, args=None):
|
|
4019
4029
|
dlg = AddRowIDDialog(self, self.data_types)
|
|
4020
4030
|
colname, prefix = dlg.show()
|
|
@@ -4523,6 +4533,8 @@ class MapUI(object):
|
|
|
4523
4533
|
tbl_menu.add_command(label="Hide/show columns", command = self.hide_columns, underline=0)
|
|
4524
4534
|
tbl_menu.add_command(label="Counts by location", command=self.counts_by_loc, underline=0)
|
|
4525
4535
|
tbl_menu.add_command(label="Unique values", command=self.unique_data_values, underline=3)
|
|
4536
|
+
tbl_menu.add_command(label="Missing by row", command=self.show_missing_byrow, underline=0)
|
|
4537
|
+
tbl_menu.add_command(label="Missing by variable", command=self.show_missing_byvariable, underline=11)
|
|
4526
4538
|
tbl_menu.add_command(label="Find candidate keys", command=self.find_candkeys, underline=0)
|
|
4527
4539
|
tbl_menu.add_command(label="Find duplicate rows", command=self.find_duprows, underline=3)
|
|
4528
4540
|
tbl_menu.add_command(label="Test cardinality", command=self.cardinality_test, underline=10)
|
|
@@ -6733,6 +6745,15 @@ class UniqueValuesDialog(Dialog):
|
|
|
6733
6745
|
self.data_labels = None
|
|
6734
6746
|
self.dlg.bind("<Control-s>")
|
|
6735
6747
|
|
|
6748
|
+
# Top controls
|
|
6749
|
+
self.sel_only_var, self.sel_only_ck = add_sel_only(self.ctrl_frame, 0, 0, self.q_recalc)
|
|
6750
|
+
self.indiv_var = tk.StringVar(self.ctrl_frame, "0")
|
|
6751
|
+
indiv_ck = ttk.Checkbutton(self.ctrl_frame, text="Individually", command=self.q_recalc, variable=self.indiv_var,
|
|
6752
|
+
onvalue="1", offvalue="0")
|
|
6753
|
+
indiv_ck.grid(row=0, column=1, sticky=tk.W, padx=(6,3), pady=(3,3), columnspan=None)
|
|
6754
|
+
self.ctrl_frame.columnconfigure(0, weight=0)
|
|
6755
|
+
self.ctrl_frame.columnconfigure(1, weight=1)
|
|
6756
|
+
|
|
6736
6757
|
# The content_frame encompasses the two panes of the variable frame and the content frame
|
|
6737
6758
|
frame_panes = ttk.PanedWindow(self.content_frame, orient=tk.HORIZONTAL, width=600)
|
|
6738
6759
|
frame_panes.grid(row=0, column=0, sticky=tk.NSEW)
|
|
@@ -6741,7 +6762,7 @@ class UniqueValuesDialog(Dialog):
|
|
|
6741
6762
|
var_frame = tk.Frame(frame_panes, width=250, borderwidth=2, relief=tk.RIDGE)
|
|
6742
6763
|
var_frame.grid(row=0, column=0, sticky=tk.NSEW)
|
|
6743
6764
|
var_frame.rowconfigure(0, weight=1)
|
|
6744
|
-
var_frame.columnconfigure(0, weight=1)
|
|
6765
|
+
var_frame.columnconfigure(0, weight=1, minsize=200)
|
|
6745
6766
|
frame_panes.add(var_frame, weight=1)
|
|
6746
6767
|
# Add multi-select list of variables to the leftmost pane
|
|
6747
6768
|
varvals = [[v] for v in self.variables]
|
|
@@ -6775,20 +6796,48 @@ class UniqueValuesDialog(Dialog):
|
|
|
6775
6796
|
|
|
6776
6797
|
def q_recalc(self, *event, get_data=True):
|
|
6777
6798
|
self.clear_output()
|
|
6778
|
-
if len(self.column_table.selection()) > 0
|
|
6779
|
-
self.
|
|
6799
|
+
if len(self.column_table.selection()) > 0:
|
|
6800
|
+
self.get_data()
|
|
6801
|
+
if self.rawdataset is not None and len(self.rawdataset[0]) > 0:
|
|
6802
|
+
self.recalc()
|
|
6780
6803
|
|
|
6781
|
-
def
|
|
6782
|
-
|
|
6804
|
+
def get_data(self):
|
|
6805
|
+
# Get the selected data into 'dataset'
|
|
6806
|
+
self.rawdataset = None
|
|
6807
|
+
self.colnames = []
|
|
6783
6808
|
for sel_row in self.column_table.selection():
|
|
6784
6809
|
datarow = self.column_table.item(sel_row)["values"]
|
|
6785
|
-
|
|
6786
|
-
|
|
6787
|
-
|
|
6788
|
-
|
|
6789
|
-
|
|
6790
|
-
|
|
6791
|
-
|
|
6810
|
+
self.colnames.append(datarow[0])
|
|
6811
|
+
if len(self.colnames) > 0:
|
|
6812
|
+
# Get either only the selected data or all data.
|
|
6813
|
+
dataset = chosen_dataset(self.parent, self.colnames, self.sel_only_var.get()=='1')
|
|
6814
|
+
if dataset is None or len(dataset[0]) == 0:
|
|
6815
|
+
self.rawdataset = None
|
|
6816
|
+
self.colnames = None
|
|
6817
|
+
else:
|
|
6818
|
+
self.rawdataset = dataset
|
|
6819
|
+
|
|
6820
|
+
def recalc(self):
|
|
6821
|
+
if self.indiv_var.get()=='1':
|
|
6822
|
+
counts = dict(zip(self.colnames, [0 for _ in range(len(self.colnames))]))
|
|
6823
|
+
for i,col in enumerate(self.colnames):
|
|
6824
|
+
counts[col] = len(set([x for x in self.rawdataset[i] if x is not None and str(x) != '']))
|
|
6825
|
+
self.dataset = list(counts.items())
|
|
6826
|
+
self.data_labels = ["Variable", "Count"]
|
|
6827
|
+
else:
|
|
6828
|
+
counts = {}
|
|
6829
|
+
ds = columns_to_rows(self.rawdataset)
|
|
6830
|
+
for row in ds:
|
|
6831
|
+
trow = tuple(row)
|
|
6832
|
+
if trow not in counts.keys():
|
|
6833
|
+
counts[trow] = 1
|
|
6834
|
+
else:
|
|
6835
|
+
counts[trow] += 1
|
|
6836
|
+
self.dataset = [list(k) for k in counts.keys()]
|
|
6837
|
+
vals = list(counts.values())
|
|
6838
|
+
for i in range(len(counts)):
|
|
6839
|
+
self.dataset[i].append(vals[i])
|
|
6840
|
+
self.data_labels = self.colnames + ["Count"]
|
|
6792
6841
|
tframe, tdata = treeview_table(self.values_frame, self.dataset, self.data_labels)
|
|
6793
6842
|
tframe.grid(row=0, column=0, sticky=tk.NSEW)
|
|
6794
6843
|
self.dlg.bind("<Control-s>", self.save_data)
|
|
@@ -6798,6 +6847,277 @@ class UniqueValuesDialog(Dialog):
|
|
|
6798
6847
|
self.dlg.wait_window(self.dlg)
|
|
6799
6848
|
|
|
6800
6849
|
|
|
6850
|
+
class MissingByRowDialog(Dialog):
|
|
6851
|
+
def __init__(self, parent, column_specs):
|
|
6852
|
+
self.parent = parent
|
|
6853
|
+
self.column_specs = column_specs
|
|
6854
|
+
self.auto_update = True
|
|
6855
|
+
super().__init__("Rows with Missing Values",
|
|
6856
|
+
"Select one or more variables from the left to see how many rows have 0, 1, 2, or more missing values for these variables. A grouping variable may optionally be used. Use Ctrl-click or Shift-click to select multiple rows.",
|
|
6857
|
+
help_url="https://mapdata.readthedocs.io/en/latest/missing_by_row.html")
|
|
6858
|
+
# Data
|
|
6859
|
+
self.dataset = None
|
|
6860
|
+
self.data_labels = None
|
|
6861
|
+
self.all_columns = sorted([c[0] for c in self.column_specs])
|
|
6862
|
+
self.categ_columns = sorted([c[0] for c in self.column_specs if c[1] in ("string", "boolean", "date", "timestamp")])
|
|
6863
|
+
self.dnames = ["Group", "Missing values", "Number of rows"]
|
|
6864
|
+
self.dlg.bind("<Control-s>")
|
|
6865
|
+
|
|
6866
|
+
# Top controls
|
|
6867
|
+
self.sel_only_var, self.sel_only_ck = add_sel_only(self.ctrl_frame, 0, 0, self.q_recalc)
|
|
6868
|
+
self.autoupdate_var = add_autoupdate(self.ctrl_frame, 0, 1, self.set_autoupdate)
|
|
6869
|
+
self.ctrl_frame.columnconfigure(0, weight=0)
|
|
6870
|
+
self.ctrl_frame.columnconfigure(1, weight=1)
|
|
6871
|
+
|
|
6872
|
+
# Two panes for the variable frame and the content frame
|
|
6873
|
+
frame_panes = ttk.PanedWindow(self.content_frame, orient=tk.HORIZONTAL)
|
|
6874
|
+
frame_panes.grid(row=0, column=0, sticky=tk.NSEW, padx=3, pady=3)
|
|
6875
|
+
|
|
6876
|
+
# Variable frame for list of columns/variables
|
|
6877
|
+
var_frame = tk.Frame(frame_panes, borderwidth=2, relief=tk.RIDGE)
|
|
6878
|
+
var_frame.grid(row=0, column=0, sticky=tk.NSEW)
|
|
6879
|
+
var_frame.rowconfigure(0, weight=1)
|
|
6880
|
+
var_frame.columnconfigure(0, weight=1)
|
|
6881
|
+
frame_panes.add(var_frame, weight=1)
|
|
6882
|
+
# Add multi-select list of variables to the leftmost pane
|
|
6883
|
+
self.column_frame, self.column_table = treeview_table(var_frame, rowset=[[v] for v in self.all_columns], \
|
|
6884
|
+
column_headers=['Variable'], select_mode=tk.EXTENDED, nrows=min(10, len(self.all_columns)))
|
|
6885
|
+
self.column_frame.grid(row=0, column=0, sticky=tk.NSEW)
|
|
6886
|
+
self.column_table.bind('<ButtonRelease-1>', self.q_recalc)
|
|
6887
|
+
|
|
6888
|
+
# Add an optional 'group by' variable selection
|
|
6889
|
+
self.groupby_var = tk.StringVar(var_frame, "")
|
|
6890
|
+
groupby_lbl = ttk.Label(var_frame, text="Group by:")
|
|
6891
|
+
groupby_lbl.grid(row=1, column=0, sticky=tk.W, padx=(6,3), pady=(3,3))
|
|
6892
|
+
self.groupby_sel = ttk.Combobox(var_frame, state="readonly", textvariable=self.groupby_var,
|
|
6893
|
+
values= [''] + self.categ_columns, width=24)
|
|
6894
|
+
self.groupby_sel.grid(row=2, column=0, sticky=tk.W, padx=(12,3), pady=(3,3))
|
|
6895
|
+
self.groupby_sel.bind("<<ComboboxSelected>>", self.q_recalc)
|
|
6896
|
+
|
|
6897
|
+
# output frame. This contains a Treeview table with the counts of missing values.
|
|
6898
|
+
self.output_frame = tk.Frame(frame_panes, borderwidth=3, relief=tk.RIDGE)
|
|
6899
|
+
self.output_frame.grid(row=0, column=0, sticky=tk.NSEW)
|
|
6900
|
+
self.output_frame.rowconfigure(0, weight=1)
|
|
6901
|
+
self.output_frame.columnconfigure(0, weight=1)
|
|
6902
|
+
frame_panes.add(self.output_frame, weight=12)
|
|
6903
|
+
|
|
6904
|
+
# initialize content frame with headings, no data
|
|
6905
|
+
self.clear_output()
|
|
6906
|
+
|
|
6907
|
+
# Buttons
|
|
6908
|
+
add_help_close_buttons(self.dlg, self.btn_frame, self.do_help, self.do_close)
|
|
6909
|
+
|
|
6910
|
+
def clear_output(self):
|
|
6911
|
+
for ctl in self.output_frame.winfo_children():
|
|
6912
|
+
ctl.destroy()
|
|
6913
|
+
clear_dlg_hotkeys(self.dlg)
|
|
6914
|
+
self.dataset = None
|
|
6915
|
+
self.missingdata = None
|
|
6916
|
+
tframe, tdata = treeview_table(self.output_frame, [], self.dnames)
|
|
6917
|
+
tframe.grid(row=0, column=0, sticky=tk.NSEW)
|
|
6918
|
+
|
|
6919
|
+
def q_recalc(self, *args):
|
|
6920
|
+
if len(self.column_table.selection()) > 0:
|
|
6921
|
+
self.clear_output()
|
|
6922
|
+
self.get_data()
|
|
6923
|
+
if self.dataset is not None and len(self.dataset[0]) > 0:
|
|
6924
|
+
self.recalc()
|
|
6925
|
+
|
|
6926
|
+
def get_data(self):
|
|
6927
|
+
# Get the selected data into 'dataset'
|
|
6928
|
+
self.dataset = None
|
|
6929
|
+
self.n_dataset_columns = 0
|
|
6930
|
+
column_list = []
|
|
6931
|
+
for sel_row in self.column_table.selection():
|
|
6932
|
+
datarow = self.column_table.item(sel_row)["values"]
|
|
6933
|
+
column_list.append(datarow[0])
|
|
6934
|
+
if len(column_list) > 0:
|
|
6935
|
+
self.n_dataset_columns = len(column_list)
|
|
6936
|
+
if self.groupby_var.get() != "":
|
|
6937
|
+
column_list.append(self.groupby_var.get())
|
|
6938
|
+
# Get either only the selected data or all data.
|
|
6939
|
+
dataset = chosen_dataset(self.parent, column_list, self.sel_only_var.get() == "1")
|
|
6940
|
+
if dataset is None or len(dataset[0]) == 0:
|
|
6941
|
+
self.dataset = None
|
|
6942
|
+
self.data_labels = None
|
|
6943
|
+
else:
|
|
6944
|
+
self.dataset = dataset
|
|
6945
|
+
self.data_labels = column_list
|
|
6946
|
+
|
|
6947
|
+
def recalc(self):
|
|
6948
|
+
# Find the numbers of missing values of all selected rows. This is accumulated as a dictionary
|
|
6949
|
+
# with keys equal to numbers of missing values in a row and values of the number of rows with
|
|
6950
|
+
# that number of missing values.
|
|
6951
|
+
def incmissing(dic, n_missing):
|
|
6952
|
+
if n_missing not in dic.keys():
|
|
6953
|
+
dic[n_missing] = 0
|
|
6954
|
+
dic[n_missing] = dic[n_missing] + 1
|
|
6955
|
+
|
|
6956
|
+
if self.data_labels is not None:
|
|
6957
|
+
if self.groupby_var.get() == "":
|
|
6958
|
+
missings = {}
|
|
6959
|
+
for datarow in columns_to_rows(self.dataset):
|
|
6960
|
+
incmissing(missings, sum(val == '' for val in datarow))
|
|
6961
|
+
self.missingdata = sorted(list(zip(missings.keys(), missings.values())))
|
|
6962
|
+
self.dnames = ["Missing", "Rows"]
|
|
6963
|
+
else:
|
|
6964
|
+
datasetdict = subset_by_groups(self.dataset[0:self.n_dataset_columns], self.dataset[self.n_dataset_columns])
|
|
6965
|
+
self.missingdata = []
|
|
6966
|
+
for grp in datasetdict.keys():
|
|
6967
|
+
ds = columns_to_rows(datasetdict[grp])
|
|
6968
|
+
missings = {}
|
|
6969
|
+
for datarow in ds:
|
|
6970
|
+
incmissing(missings, sum(val == '' for val in datarow))
|
|
6971
|
+
self.missingdata.extend(sorted(list(zip([grp]*len(missings.keys()), missings.keys(), missings.values())), key=lambda x: x[1]))
|
|
6972
|
+
self.dnames = ["Group", "Missing", "Rows"]
|
|
6973
|
+
tframe, tdata = treeview_table(self.output_frame, self.missingdata, self.dnames)
|
|
6974
|
+
tframe.grid(row=0, column=0, sticky=tk.NSEW)
|
|
6975
|
+
self.dlg.bind("<Control-s>", self.save_data)
|
|
6976
|
+
def set_autoupdate(self):
|
|
6977
|
+
self.auto_update = self.autoupdate_var.get() == "1"
|
|
6978
|
+
if self.auto_update:
|
|
6979
|
+
self.q_recalc(None)
|
|
6980
|
+
def save_data(self, *args):
|
|
6981
|
+
export_data_table(self.dnames, self.missingdata, sheetname="Numbers of missing values")
|
|
6982
|
+
def do_close(self, *args):
|
|
6983
|
+
self.parent.remove_univar(self)
|
|
6984
|
+
super().do_cancel(args)
|
|
6985
|
+
|
|
6986
|
+
|
|
6987
|
+
|
|
6988
|
+
class MissingByVariableDialog(Dialog):
|
|
6989
|
+
def __init__(self, parent, column_specs):
|
|
6990
|
+
self.parent = parent
|
|
6991
|
+
self.column_specs = column_specs
|
|
6992
|
+
self.auto_update = True
|
|
6993
|
+
super().__init__("Variables with Missing Values",
|
|
6994
|
+
"Select one or more variables from the left to see how many missing values each has. A grouping variable may optionally be used. Use Ctrl-click or Shift-click to select multiple rows.",
|
|
6995
|
+
help_url="https://mapdata.readthedocs.io/en/latest/missing_by_variable.html")
|
|
6996
|
+
# Data
|
|
6997
|
+
self.dataset = None
|
|
6998
|
+
self.data_labels = None
|
|
6999
|
+
self.all_columns = sorted([c[0] for c in self.column_specs])
|
|
7000
|
+
self.categ_columns = sorted([c[0] for c in self.column_specs if c[1] in ("string", "boolean", "date", "timestamp")])
|
|
7001
|
+
self.dnames = ["Variable", "Missing"]
|
|
7002
|
+
self.dlg.bind("<Control-s>")
|
|
7003
|
+
|
|
7004
|
+
# Top controls
|
|
7005
|
+
self.sel_only_var, self.sel_only_ck = add_sel_only(self.ctrl_frame, 0, 0, self.q_recalc)
|
|
7006
|
+
self.autoupdate_var = add_autoupdate(self.ctrl_frame, 0, 1, self.set_autoupdate)
|
|
7007
|
+
self.ctrl_frame.columnconfigure(0, weight=0)
|
|
7008
|
+
self.ctrl_frame.columnconfigure(1, weight=1)
|
|
7009
|
+
|
|
7010
|
+
# Two panes for the variable frame and the content frame
|
|
7011
|
+
frame_panes = ttk.PanedWindow(self.content_frame, orient=tk.HORIZONTAL)
|
|
7012
|
+
frame_panes.grid(row=0, column=0, sticky=tk.NSEW, padx=3, pady=3)
|
|
7013
|
+
|
|
7014
|
+
# Variable frame for list of all columns/variables
|
|
7015
|
+
var_frame = tk.Frame(frame_panes, borderwidth=2, relief=tk.RIDGE)
|
|
7016
|
+
var_frame.grid(row=0, column=0, sticky=tk.NSEW)
|
|
7017
|
+
var_frame.rowconfigure(0, weight=1)
|
|
7018
|
+
var_frame.columnconfigure(0, weight=1)
|
|
7019
|
+
frame_panes.add(var_frame, weight=1)
|
|
7020
|
+
# Add multi-select list of variables to the leftmost pane
|
|
7021
|
+
self.column_frame, self.column_table = treeview_table(var_frame, rowset=[[v] for v in self.all_columns], \
|
|
7022
|
+
column_headers=['Variable'], select_mode=tk.EXTENDED, nrows=min(10, len(self.all_columns)))
|
|
7023
|
+
self.column_frame.grid(row=0, column=0, sticky=tk.NSEW)
|
|
7024
|
+
self.column_table.bind('<ButtonRelease-1>', self.q_recalc)
|
|
7025
|
+
|
|
7026
|
+
# Add an optional 'group by' variable selection
|
|
7027
|
+
self.groupby_var = tk.StringVar(var_frame, "")
|
|
7028
|
+
groupby_lbl = ttk.Label(var_frame, text="Group by:")
|
|
7029
|
+
groupby_lbl.grid(row=1, column=0, sticky=tk.W, padx=(6,3), pady=(3,3))
|
|
7030
|
+
self.groupby_sel = ttk.Combobox(var_frame, state="readonly", textvariable=self.groupby_var,
|
|
7031
|
+
values= [''] + self.categ_columns, width=24)
|
|
7032
|
+
self.groupby_sel.grid(row=2, column=0, sticky=tk.W, padx=(12,3), pady=(3,3))
|
|
7033
|
+
self.groupby_sel.bind("<<ComboboxSelected>>", self.q_recalc)
|
|
7034
|
+
|
|
7035
|
+
# Output frame. This contains a Treeview table with the counts of missing values.
|
|
7036
|
+
self.output_frame = tk.Frame(frame_panes, borderwidth=3, relief=tk.RIDGE)
|
|
7037
|
+
self.output_frame.grid(row=0, column=0, sticky=tk.NSEW)
|
|
7038
|
+
self.output_frame.rowconfigure(0, weight=1)
|
|
7039
|
+
self.output_frame.columnconfigure(0, weight=1)
|
|
7040
|
+
frame_panes.add(self.output_frame, weight=12)
|
|
7041
|
+
|
|
7042
|
+
# initialize content frame with headings, no data
|
|
7043
|
+
self.clear_output()
|
|
7044
|
+
|
|
7045
|
+
# Buttons
|
|
7046
|
+
add_help_close_buttons(self.dlg, self.btn_frame, self.do_help, self.do_close)
|
|
7047
|
+
|
|
7048
|
+
def clear_output(self):
|
|
7049
|
+
for ctl in self.output_frame.winfo_children():
|
|
7050
|
+
ctl.destroy()
|
|
7051
|
+
clear_dlg_hotkeys(self.dlg)
|
|
7052
|
+
self.dataset = None
|
|
7053
|
+
self.missingdata = None
|
|
7054
|
+
tframe, tdata = treeview_table(self.output_frame, [], self.dnames)
|
|
7055
|
+
tframe.grid(row=0, column=0, sticky=tk.NSEW)
|
|
7056
|
+
|
|
7057
|
+
def q_recalc(self, *args):
|
|
7058
|
+
if len(self.column_table.selection()) > 0:
|
|
7059
|
+
self.clear_output()
|
|
7060
|
+
self.get_data()
|
|
7061
|
+
if self.dataset is not None and len(self.dataset[0]) > 0:
|
|
7062
|
+
self.recalc()
|
|
7063
|
+
|
|
7064
|
+
def get_data(self):
|
|
7065
|
+
# Get the selected data into 'dataset'
|
|
7066
|
+
self.dataset = None
|
|
7067
|
+
self.n_dataset_columns = 0
|
|
7068
|
+
column_list = []
|
|
7069
|
+
for sel_row in self.column_table.selection():
|
|
7070
|
+
datarow = self.column_table.item(sel_row)["values"]
|
|
7071
|
+
column_list.append(datarow[0])
|
|
7072
|
+
if len(column_list) > 0:
|
|
7073
|
+
self.n_dataset_columns = len(column_list)
|
|
7074
|
+
if self.groupby_var.get() != "":
|
|
7075
|
+
column_list.append(self.groupby_var.get())
|
|
7076
|
+
# Get either only the selected data or all data.
|
|
7077
|
+
dataset = chosen_dataset(self.parent, column_list, self.sel_only_var.get() == "1")
|
|
7078
|
+
if dataset is None or len(dataset[0]) == 0:
|
|
7079
|
+
self.dataset = None
|
|
7080
|
+
self.data_labels = None
|
|
7081
|
+
else:
|
|
7082
|
+
self.dataset = dataset
|
|
7083
|
+
self.data_labels = column_list
|
|
7084
|
+
|
|
7085
|
+
def recalc(self):
|
|
7086
|
+
# Find the numbers of missing values of all selected variables.
|
|
7087
|
+
if self.data_labels is not None:
|
|
7088
|
+
if self.groupby_var.get() == "":
|
|
7089
|
+
# Output is two columns, one with the variable name and one with the number of missing values.
|
|
7090
|
+
n_missing = []
|
|
7091
|
+
for col in self.dataset:
|
|
7092
|
+
n_missing.append(sum(val == '' for val in col))
|
|
7093
|
+
self.missingdata = sorted(list(zip(self.data_labels, n_missing)))
|
|
7094
|
+
self.dnames = ["Variable", "Missing"]
|
|
7095
|
+
else:
|
|
7096
|
+
# Output is a table with groups in rows, variables in columns, missing values in cells
|
|
7097
|
+
datasetdict = subset_by_groups(self.dataset[0:self.n_dataset_columns], self.dataset[self.n_dataset_columns])
|
|
7098
|
+
self.missingdata = []
|
|
7099
|
+
for grp in datasetdict.keys():
|
|
7100
|
+
ds = datasetdict[grp]
|
|
7101
|
+
n_missing = [grp]
|
|
7102
|
+
for col in ds:
|
|
7103
|
+
n_missing.append(sum(val == '' for val in col))
|
|
7104
|
+
self.missingdata.append(n_missing)
|
|
7105
|
+
self.dnames = ["Group"] + self.data_labels[:-1]
|
|
7106
|
+
tframe, tdata = treeview_table(self.output_frame, self.missingdata, self.dnames)
|
|
7107
|
+
tframe.grid(row=0, column=0, sticky=tk.NSEW)
|
|
7108
|
+
self.dlg.bind("<Control-s>", self.save_data)
|
|
7109
|
+
def set_autoupdate(self):
|
|
7110
|
+
self.auto_update = self.autoupdate_var.get() == "1"
|
|
7111
|
+
if self.auto_update:
|
|
7112
|
+
self.q_recalc(None)
|
|
7113
|
+
def save_data(self, *args):
|
|
7114
|
+
export_data_table(self.dnames, self.missingdata, sheetname="Numbers of missing values")
|
|
7115
|
+
def do_close(self, *args):
|
|
7116
|
+
self.parent.remove_univar(self)
|
|
7117
|
+
super().do_cancel(args)
|
|
7118
|
+
|
|
7119
|
+
|
|
7120
|
+
|
|
6801
7121
|
class SelNonMissingDialog(Dialog):
|
|
6802
7122
|
def __init__(self, column_specs):
|
|
6803
7123
|
super().__init__("Select Non-Missing Values",
|
|
@@ -6948,7 +7268,7 @@ class PlotDialog(Dialog):
|
|
|
6948
7268
|
plot_types.append("Date range by category")
|
|
6949
7269
|
plot_types.extend(["Empirical CDF", "Histogram", "Kernel density (KD) plot", "Line plot", "Mean by category",
|
|
6950
7270
|
"Min-max by bin", "Min-max by category", "Normal Q-Q plot", "Pareto chart", "Scatter plot", "Stripchart",
|
|
6951
|
-
"Total by category", "Violin plot", "Y range plot"])
|
|
7271
|
+
"Total by category", "Violin plot", "Y range plot", "Zipf's Law"])
|
|
6952
7272
|
self.type_sel = ttk.Combobox(self.ctrl_frame, state="readonly", textvariable=self.type_var, width=20, height=21, values=plot_types)
|
|
6953
7273
|
self.type_sel.grid(row=0, column=1, columnspan=2, sticky=tk.W, padx=(3,6), pady=(3,3))
|
|
6954
7274
|
self.type_sel["state"] = tk.NORMAL
|
|
@@ -7174,9 +7494,11 @@ class PlotDialog(Dialog):
|
|
|
7174
7494
|
elif plot_type == "Min-max by category":
|
|
7175
7495
|
self.x_sel["state"] = "readonly"
|
|
7176
7496
|
self.x_sel["values"] = self.quant_columns
|
|
7177
|
-
self.xlog_ck["state"] = tk.NORMAL
|
|
7178
7497
|
self.y_sel["state"] = "readonly"
|
|
7179
7498
|
self.y_sel["values"] = self.categ_columns2
|
|
7499
|
+
elif plot_type == "Zipf's Law":
|
|
7500
|
+
self.x_sel["state"] = "readonly"
|
|
7501
|
+
self.x_sel["values"] = sorted([c[0] for c in self.column_specs if c[1] == "string"])
|
|
7180
7502
|
else:
|
|
7181
7503
|
self.x_sel["state"] = "readonly"
|
|
7182
7504
|
self.x_sel["values"] = self.quant_columns
|
|
@@ -7197,7 +7519,7 @@ class PlotDialog(Dialog):
|
|
|
7197
7519
|
# Conditionally (re)draw the plot.
|
|
7198
7520
|
plot_type = self.type_var.get()
|
|
7199
7521
|
can_redraw = (plot_type in ("Count by category", "Empirical CDF", "Normal Q-Q plot", "Breaks groups", "Breaks optimum", \
|
|
7200
|
-
"Histogram", "Pareto chart") and self.x_var.get() != '') \
|
|
7522
|
+
"Histogram", "Pareto chart", "Zipf's Law") and self.x_var.get() != '') \
|
|
7201
7523
|
or (plot_type in ("Scatter plot", "Line plot", "Min-max by bin", "Min-max by category", "Y range plot") and \
|
|
7202
7524
|
self.x_var.get() != '' and self.y_var.get() != '') \
|
|
7203
7525
|
or (plot_type in ("Box plot", "Kernel density (KD) plot", "Stripchart", "Violin plot") and self.x_var.get() != '') \
|
|
@@ -7293,6 +7615,19 @@ class PlotDialog(Dialog):
|
|
|
7293
7615
|
x_counts = [counter[k] for k in x_vals]
|
|
7294
7616
|
self.plot_data = [x_vals, x_counts]
|
|
7295
7617
|
self.plot_data_labels = [self.data_labels[0], "Count"]
|
|
7618
|
+
elif plot_type == "Zipf's Law":
|
|
7619
|
+
counter = collections.Counter(self.dataset[0])
|
|
7620
|
+
zcts = sorted(list(zip(counter.values(), counter.keys())), key=lambda x: x[0], reverse=True)
|
|
7621
|
+
zd = list(zip(*zcts))
|
|
7622
|
+
zdata = [list(zd[1]), list(zd[0])]
|
|
7623
|
+
zdata.append(list(range(1, len(zdata[0])+1)))
|
|
7624
|
+
tot = sum(zdata[1])
|
|
7625
|
+
zdata.append([x/tot for x in zdata[1]])
|
|
7626
|
+
zdata.append([math.log10(x) for x in zdata[2]])
|
|
7627
|
+
zdata.append([math.log10(x) for x in zdata[3]])
|
|
7628
|
+
self.plot_data = zdata
|
|
7629
|
+
self.plot_data_labels = [self.data_labels[0], "Count", "Rank", "Frequency", "Log10_Rank", "Log10_Frequency"]
|
|
7630
|
+
self.xlog_ck["state"] = tk.DISABLED
|
|
7296
7631
|
elif plot_type in ("Box plot", "Histogram", "Kernel density (KD) plot", "Stripchart", "Violin plot"):
|
|
7297
7632
|
if self.groupby_var.get() != '':
|
|
7298
7633
|
self.plot_data_labels, self.plot_data = spread_by_groups(self.dataset[1], self.dataset[0])
|
|
@@ -7869,7 +8204,7 @@ class PlotDialog(Dialog):
|
|
|
7869
8204
|
self.plot.axes.plot([pmin, pmax], [pmin, pmax])
|
|
7870
8205
|
self.plot.set_axis_labels(self.xlabel or self.plot_data_labels[2], self.ylabel or self.plot_data_labels[1])
|
|
7871
8206
|
elif plot_type == "Pareto chart":
|
|
7872
|
-
groups = self.plot_data[0]
|
|
8207
|
+
groups = [str(g) for g in self.plot_data[0]]
|
|
7873
8208
|
grp_lbls = []
|
|
7874
8209
|
for g in groups:
|
|
7875
8210
|
if wrap_at_underscores:
|
|
@@ -7983,6 +8318,13 @@ class PlotDialog(Dialog):
|
|
|
7983
8318
|
else:
|
|
7984
8319
|
sns.violinplot({self.x_var.get(): self.dataset[0]}, x=self.x_var.get(), alpha=self.alpha, ax=self.plot_axes)
|
|
7985
8320
|
self.plot.set_axis_labels(self.ylabel or self.data_labels[0], self.xlabel or self.x_var.get())
|
|
8321
|
+
elif plot_type == "Zipf's Law":
|
|
8322
|
+
self.plot.axes.set_xscale('log')
|
|
8323
|
+
self.plot.axes.set_yscale('log')
|
|
8324
|
+
self.plot.axes.grid(visible=True, color="0.8", linestyle="dotted", which='both', axis='both')
|
|
8325
|
+
self.plot.axes.plot(self.plot_data[2], self.plot_data[3], alpha=self.alpha)
|
|
8326
|
+
self.plot.set_axis_labels(self.plot_data_labels[2], self.xlabel or self.plot_data_labels[3])
|
|
8327
|
+
self.plot_title = self.data_labels[0]
|
|
7986
8328
|
if self.plot_title is not None:
|
|
7987
8329
|
self.plot.axes.set_title(self.plot_title)
|
|
7988
8330
|
self.plot.axes.title.set_visible(True)
|
|
@@ -13351,7 +13693,7 @@ class NMFUnmixingDialog(Dialog):
|
|
|
13351
13693
|
frame_panes.grid(row=0, column=0, sticky=tk.NSEW)
|
|
13352
13694
|
|
|
13353
13695
|
# Variable frame for list of quantitative columns/variables
|
|
13354
|
-
var_frame = tk.Frame(frame_panes, borderwidth=2, relief=tk.RIDGE)
|
|
13696
|
+
var_frame = tk.Frame(frame_panes, width=250, borderwidth=2, relief=tk.RIDGE)
|
|
13355
13697
|
var_frame.grid(row=0, column=0, sticky=tk.NSEW)
|
|
13356
13698
|
var_frame.rowconfigure(0, weight=1)
|
|
13357
13699
|
var_frame.columnconfigure(0, weight=1, minsize=200)
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: mapdata
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.21.0
|
|
4
4
|
Summary: An interactive map and table explorer for geographic coordinates in a spreadsheet, CSV file, or database that includes data plotting and statistical summaries
|
|
5
5
|
Home-page: https:/hg.sr.ht/~rdnielsen/mapdata
|
|
6
6
|
Author: Dreas Nielsen
|
|
7
7
|
Author-email: cortice@tutanota.com
|
|
8
8
|
License: GPL
|
|
9
|
-
Keywords: Map,Locations,CRS,CSV,Spreadsheet,Database,PNG,JPG,Postscript
|
|
9
|
+
Keywords: Map,Locations,CRS,CSV,Spreadsheet,Database,Statistics,Plotting,PNG,JPG,Postscript
|
|
10
10
|
Classifier: Development Status :: 5 - Production/Stable
|
|
11
11
|
Classifier: Environment :: Console
|
|
12
12
|
Classifier: Environment :: X11 Applications
|
|
@@ -24,21 +24,6 @@ Classifier: Topic :: Scientific/Engineering
|
|
|
24
24
|
Requires-Python: >=3.8
|
|
25
25
|
Description-Content-Type: text/markdown
|
|
26
26
|
License-File: LICENSE.txt
|
|
27
|
-
Requires-Dist: tkintermapview
|
|
28
|
-
Requires-Dist: pyproj
|
|
29
|
-
Requires-Dist: jenkspy
|
|
30
|
-
Requires-Dist: odfpy
|
|
31
|
-
Requires-Dist: openpyxl
|
|
32
|
-
Requires-Dist: xlrd
|
|
33
|
-
Requires-Dist: matplotlib
|
|
34
|
-
Requires-Dist: seaborn
|
|
35
|
-
Requires-Dist: loess
|
|
36
|
-
Requires-Dist: statsmodels
|
|
37
|
-
Requires-Dist: scipy
|
|
38
|
-
Requires-Dist: scikit-learn
|
|
39
|
-
Requires-Dist: pymannkendall
|
|
40
|
-
Requires-Dist: umap-learn
|
|
41
|
-
Requires-Dist: pynndescent
|
|
42
27
|
|
|
43
28
|
|
|
44
29
|
*mapdata.py* is a data explorer for data sets containing geographic coordinates. Data can be read from a CSV file, spreadsheet, or database. Both a map and a data
|
|
@@ -9,7 +9,7 @@ symbol_files = glob.glob("mapdata/symbols/16x16/*.xbm") + glob.glob("mapdata/sym
|
|
|
9
9
|
glob.glob("mapdata/symbols/24x24/*.xbm") + glob.glob("mapdata/symbols/28x28/*.xbm")
|
|
10
10
|
|
|
11
11
|
setuptools.setup(name='mapdata',
|
|
12
|
-
version='3.
|
|
12
|
+
version='3.21.0',
|
|
13
13
|
description="An interactive map and table explorer for geographic coordinates in a spreadsheet, CSV file, or database that includes data plotting and statistical summaries",
|
|
14
14
|
author='Dreas Nielsen',
|
|
15
15
|
author_email='cortice@tutanota.com',
|
|
@@ -36,7 +36,7 @@ setuptools.setup(name='mapdata',
|
|
|
36
36
|
'Topic :: Office/Business',
|
|
37
37
|
'Topic :: Scientific/Engineering'
|
|
38
38
|
],
|
|
39
|
-
keywords=['Map', 'Locations', 'CRS', 'CSV', 'Spreadsheet', 'Database', 'PNG', 'JPG', 'Postscript'],
|
|
39
|
+
keywords=['Map', 'Locations', 'CRS', 'CSV', 'Spreadsheet', 'Database', 'Statistics', 'Plotting', 'PNG', 'JPG', 'Postscript'],
|
|
40
40
|
long_description_content_type="text/markdown",
|
|
41
41
|
long_description=long_description
|
|
42
42
|
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|