diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..6f59070 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,25 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v2.4.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-added-large-files + +- repo: https://github.com/asottile/reorder_python_imports + rev: v2.3.0 + hooks: + - id: reorder-python-imports + +- repo: https://gitlab.com/pycqa/flake8 + rev: 3.8.3 + hooks: + - id: flake8 + +- repo: https://github.com/psf/black + rev: 19.10b0 + hooks: + - id: black diff --git a/Pipfile b/Pipfile deleted file mode 100644 index 291a246..0000000 --- a/Pipfile +++ /dev/null @@ -1,12 +0,0 @@ -[[source]] -url = "https://pypi.org/simple" -verify_ssl = true -name = "pypi" - -[packages] -numpy = "*" -matplotlib = "*" -pandas = "*" - -[dev-packages] - diff --git a/Pipfile.lock b/Pipfile.lock deleted file mode 100644 index a18722f..0000000 --- a/Pipfile.lock +++ /dev/null @@ -1,161 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "80c4a565375d554200bf6e7cf08b9c808ba44a022d01a47ad46f617a18f1d3fc" - }, - "pipfile-spec": 6, - "requires": {}, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "cycler": { - "hashes": [ - "sha256:1d8a5ae1ff6c5cf9b93e8811e581232ad8920aeec647c37316ceac982b08cb2d", - "sha256:cd7b2d1018258d7247a71425e9f26463dfb444d411c39569972f4ce586b0c9d8" - ], - "version": "==0.10.0" - }, - "kiwisolver": { - "hashes": [ - "sha256:0ee4ed8b3ae8f5f712b0aa9ebd2858b5b232f1b9a96b0943dceb34df2a223bc3", - "sha256:0f7f532f3c94e99545a29f4c3f05637f4d2713e7fd91b4dd8abfc18340b86cd5", - "sha256:1a078f5dd7e99317098f0e0d490257fd0349d79363e8c923d5bb76428f318421", - "sha256:1aa0b55a0eb1bd3fa82e704f44fb8f16e26702af1a073cc5030eea399e617b56", - "sha256:2874060b91e131ceeff00574b7c2140749c9355817a4ed498e82a4ffa308ecbc", - "sha256:379d97783ba8d2934d52221c833407f20ca287b36d949b4bba6c75274bcf6363", - "sha256:3b791ddf2aefc56382aadc26ea5b352e86a2921e4e85c31c1f770f527eb06ce4", - "sha256:4329008a167fac233e398e8a600d1b91539dc33c5a3eadee84c0d4b04d4494fa", - "sha256:45813e0873bbb679334a161b28cb9606d9665e70561fd6caa8863e279b5e464b", - "sha256:53a5b27e6b5717bdc0125338a822605084054c80f382051fb945d2c0e6899a20", - "sha256:574f24b9805cb1c72d02b9f7749aa0cc0b81aa82571be5201aa1453190390ae5", - "sha256:66f82819ff47fa67a11540da96966fb9245504b7f496034f534b81cacf333861", - "sha256:79e5fe3ccd5144ae80777e12973027bd2f4f5e3ae8eb286cabe787bed9780138", - "sha256:83410258eb886f3456714eea4d4304db3a1fc8624623fc3f38a487ab36c0f653", - "sha256:8b6a7b596ce1d2a6d93c3562f1178ebd3b7bb445b3b0dd33b09f9255e312a965", - "sha256:9576cb63897fbfa69df60f994082c3f4b8e6adb49cccb60efb2a80a208e6f996", - "sha256:95a25d9f3449046ecbe9065be8f8380c03c56081bc5d41fe0fb964aaa30b2195", - "sha256:a424f048bebc4476620e77f3e4d1f282920cef9bc376ba16d0b8fe97eec87cde", - "sha256:aaec1cfd94f4f3e9a25e144d5b0ed1eb8a9596ec36d7318a504d813412563a85", - "sha256:acb673eecbae089ea3be3dcf75bfe45fc8d4dcdc951e27d8691887963cf421c7", - "sha256:b15bc8d2c2848a4a7c04f76c9b3dc3561e95d4dabc6b4f24bfabe5fd81a0b14f", - "sha256:b1c240d565e977d80c0083404c01e4d59c5772c977fae2c483f100567f50847b", - "sha256:c595693de998461bcd49b8d20568c8870b3209b8ea323b2a7b0ea86d85864694", - "sha256:ce3be5d520b4d2c3e5eeb4cd2ef62b9b9ab8ac6b6fedbaa0e39cdb6f50644278", - "sha256:e0f910f84b35c36a3513b96d816e6442ae138862257ae18a0019d2fc67b041dc", - "sha256:ea36e19ac0a483eea239320aef0bd40702404ff8c7e42179a2d9d36c5afcb55c", - "sha256:efabbcd4f406b532206b8801058c8bab9e79645b9880329253ae3322b7b02cd5", - "sha256:f923406e6b32c86309261b8195e24e18b6a8801df0cfc7814ac44017bfcb3939" - ], - "version": "==1.0.1" - }, - "matplotlib": { - "hashes": [ - "sha256:1ae6549976b6ceb6ee426272a28c0fc9715b3e3669694d560c8f661c5b39e2c5", - "sha256:4d4250bf508dd07cca3b43888097f873cadb66eec6ac63dbbfb798798ec07af2", - "sha256:53af2e01d7f1700ed2b64a9091bc865360c9c4032f625451c4589a826854c787", - "sha256:63e498067d32d627111cd1162cae1621f1221f9d4c6a9745dd7233f29de581b6", - "sha256:7169a34971e398dd58e87e173f97366fd88a3fa80852704530433eb224a8ca57", - "sha256:91c54d6bb9eeaaff965656c5ea6cbdcbf780bad8462ac99b30b451548194746f", - "sha256:aeef177647bb3fccfe09065481989d7dfc5ac59e9367d6a00a3481062cf651e4", - "sha256:cf8ae10559a78aee0409ede1e9d4fda03895433eeafe609dd9ed67e45f552db0", - "sha256:d51d0889d1c4d51c51a9822265c0494ea3e70a52bdd88358e0863daca46fa23a", - "sha256:de5ccd3500247f85fe4f9fad90f80a8bd397e4f110a4c33fabf95f07403e8372", - "sha256:e1d33589e32f482d0a7d1957bf473d43341115d40d33f578dad44432e47df7b7", - "sha256:e8d1939262aa6b36d0c51f50a50a43a04b9618d20db31e6c0192b1463067aeef", - "sha256:e918d51b1fda82a65fdf52d2f3914b2246481cc2a9cd10e223e6be6078916ff3" - ], - "index": "pypi", - "version": "==3.0.3" - }, - "numpy": { - "hashes": [ - "sha256:1980f8d84548d74921685f68096911585fee393975f53797614b34d4f409b6da", - "sha256:22752cd809272671b273bb86df0f505f505a12368a3a5fc0aa811c7ece4dfd5c", - "sha256:23cc40313036cffd5d1873ef3ce2e949bdee0646c5d6f375bf7ee4f368db2511", - "sha256:2b0b118ff547fecabc247a2668f48f48b3b1f7d63676ebc5be7352a5fd9e85a5", - "sha256:3a0bd1edf64f6a911427b608a894111f9fcdb25284f724016f34a84c9a3a6ea9", - "sha256:3f25f6c7b0d000017e5ac55977a3999b0b1a74491eacb3c1aa716f0e01f6dcd1", - "sha256:4061c79ac2230594a7419151028e808239450e676c39e58302ad296232e3c2e8", - "sha256:560ceaa24f971ab37dede7ba030fc5d8fa173305d94365f814d9523ffd5d5916", - "sha256:62be044cd58da2a947b7e7b2252a10b42920df9520fc3d39f5c4c70d5460b8ba", - "sha256:6c692e3879dde0b67a9dc78f9bfb6f61c666b4562fd8619632d7043fb5b691b0", - "sha256:6f65e37b5a331df950ef6ff03bd4136b3c0bbcf44d4b8e99135d68a537711b5a", - "sha256:7a78cc4ddb253a55971115f8320a7ce28fd23a065fc33166d601f51760eecfa9", - "sha256:80a41edf64a3626e729a62df7dd278474fc1726836552b67a8c6396fd7e86760", - "sha256:893f4d75255f25a7b8516feb5766c6b63c54780323b9bd4bc51cdd7efc943c73", - "sha256:972ea92f9c1b54cc1c1a3d8508e326c0114aaf0f34996772a30f3f52b73b942f", - "sha256:9f1d4865436f794accdabadc57a8395bd3faa755449b4f65b88b7df65ae05f89", - "sha256:9f4cd7832b35e736b739be03b55875706c8c3e5fe334a06210f1a61e5c2c8ca5", - "sha256:adab43bf657488300d3aeeb8030d7f024fcc86e3a9b8848741ea2ea903e56610", - "sha256:bd2834d496ba9b1bdda3a6cf3de4dc0d4a0e7be306335940402ec95132ad063d", - "sha256:d20c0360940f30003a23c0adae2fe50a0a04f3e48dc05c298493b51fd6280197", - "sha256:d3b3ed87061d2314ff3659bb73896e622252da52558f2380f12c421fbdee3d89", - "sha256:dc235bf29a406dfda5790d01b998a1c01d7d37f449128c0b1b7d1c89a84fae8b", - "sha256:fb3c83554f39f48f3fa3123b9c24aecf681b1c289f9334f8215c1d3c8e2f6e5b" - ], - "index": "pypi", - "version": "==1.16.2" - }, - "pandas": { - "hashes": [ - "sha256:071e42b89b57baa17031af8c6b6bbd2e9a5c68c595bc6bf9adabd7a9ed125d3b", - "sha256:17450e25ae69e2e6b303817bdf26b2cd57f69595d8550a77c308be0cd0fd58fa", - "sha256:17916d818592c9ec891cbef2e90f98cc85e0f1e89ed0924c9b5220dc3209c846", - "sha256:2538f099ab0e9f9c9d09bbcd94b47fd889bad06dc7ae96b1ed583f1dc1a7a822", - "sha256:366f30710172cb45a6b4f43b66c220653b1ea50303fbbd94e50571637ffb9167", - "sha256:42e5ad741a0d09232efbc7fc648226ed93306551772fc8aecc6dce9f0e676794", - "sha256:4e718e7f395ba5bfe8b6f6aaf2ff1c65a09bb77a36af6394621434e7cc813204", - "sha256:4f919f409c433577a501e023943e582c57355d50a724c589e78bc1d551a535a2", - "sha256:4fe0d7e6438212e839fc5010c78b822664f1a824c0d263fd858f44131d9166e2", - "sha256:5149a6db3e74f23dc3f5a216c2c9ae2e12920aa2d4a5b77e44e5b804a5f93248", - "sha256:627594338d6dd995cfc0bacd8e654cd9e1252d2a7c959449228df6740d737eb8", - "sha256:83c702615052f2a0a7fb1dd289726e29ec87a27272d775cb77affe749cca28f8", - "sha256:8c872f7fdf3018b7891e1e3e86c55b190e6c5cee70cab771e8f246c855001296", - "sha256:90f116086063934afd51e61a802a943826d2aac572b2f7d55caaac51c13db5b5", - "sha256:a3352bacac12e1fc646213b998bce586f965c9d431773d9e91db27c7c48a1f7d", - "sha256:bcdd06007cca02d51350f96debe51331dec429ac8f93930a43eb8fb5639e3eb5", - "sha256:c1bd07ebc15285535f61ddd8c0c75d0d6293e80e1ee6d9a8d73f3f36954342d0", - "sha256:c9a4b7c55115eb278c19aa14b34fcf5920c8fe7797a09b7b053ddd6195ea89b3", - "sha256:cc8fc0c7a8d5951dc738f1c1447f71c43734244453616f32b8aa0ef6013a5dfb", - "sha256:d7b460bc316064540ce0c41c1438c416a40746fd8a4fb2999668bf18f3c4acf1" - ], - "index": "pypi", - "version": "==0.24.2" - }, - "pyparsing": { - "hashes": [ - "sha256:66c9268862641abcac4a96ba74506e594c884e3f57690a696d21ad8210ed667a", - "sha256:f6c5ef0d7480ad048c054c37632c67fca55299990fff127850181659eea33fc3" - ], - "version": "==2.3.1" - }, - "python-dateutil": { - "hashes": [ - "sha256:7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb", - "sha256:c89805f6f4d64db21ed966fda138f8a5ed7a4fdbc1a8ee329ce1b74e3c74da9e" - ], - "version": "==2.8.0" - }, - "pytz": { - "hashes": [ - "sha256:32b0891edff07e28efe91284ed9c31e123d84bea3fd98e1f72be2508f43ef8d9", - "sha256:d5f05e487007e29e03409f9398d074e158d920d36eb82eaf66fb1136b0c5374c" - ], - "version": "==2018.9" - }, - "six": { - "hashes": [ - "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", - "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" - ], - "version": "==1.12.0" - } - }, - "develop": {} -} diff --git a/README.rst b/README.rst index 74ed9d0..64622b4 100644 --- a/README.rst +++ b/README.rst @@ -229,7 +229,7 @@ no_rows): z_val = z_obj.z_values print('Z-values shape: ', z_val.shape) - new_zgrid = ZMAPGrid(z_values=z_val, min_x=-630000.0000, max_x=672000.0000, + new_zgrid = ZMAPGrid(z_values=z_val, min_x=-630000.0000, max_x=672000.0000, min_y=2000000.0000, max_y=2621000.0000) @@ -283,5 +283,3 @@ References * https://lists.osgeo.org/pipermail/gdal-dev/2011-June/029173.html * https://gist.github.com/wassname/526d5fde3f3cbeb67da8 * Saltus, R.W. and Bird, K.J., 2003. Digital depth horizon compilations of the Alaskan North Slope and adjacent arctic regions. U.S. Geological Survey data release: https://doi.org/10.3133/ofr03230 - - diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..a795491 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,6 @@ +[flake8] +ignore = E203 +max-line-length = 119 + +[pep8] +ignore = E265,E501,W504 diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..1e9543d --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,28 @@ +import pytest + +from zmapio import ZMAPGrid + +z_text = """! File created by DMBTools2.GridFileFormats.ZmapPlusFile +! +@GRID FILE, GRID, 4 +20, -9999.0000000, , 7, 1 +6, 4, 0, 200, 0, 300 +0.0, 0.0, 0.0 +@ + -9999.0000000 -9999.0000000 3.0000000 32.0000000 + 88.0000000 13.0000000 + -9999.0000000 20.0000000 8.0000000 42.0000000 + 75.0000000 5.0000000 + 5.0000000 100.0000000 35.0000000 50.0000000 + 27.0000000 1.0000000 + 2.0000000 36.0000000 10.0000000 6.0000000 + 9.0000000 -9999.0000000 +""" + + +@pytest.fixture +def zmap_object(tmpdir): + x = tmpdir.join("test.dat") + x.write(z_text) + z_obj = ZMAPGrid(x.strpath) + yield z_obj diff --git a/tests/test_export.py b/tests/test_export.py new file mode 100644 index 0000000..a1cd8cc --- /dev/null +++ b/tests/test_export.py @@ -0,0 +1,35 @@ +import json + + +def test_export_to_csv(zmap_object, tmpdir): + x = tmpdir.join("output.csv") + zmap_object.to_csv(x.strpath) + lines = x.readlines() + assert len(lines) == 24 + assert lines[0] == "0.0,300.0,nan\n" + + +def test_export_to_geojson(zmap_object, tmpdir): + x = tmpdir.join("output.json") + zmap_object.to_geojson(x.strpath) + d = json.load(x) + assert sorted(list(d.keys())) == ["coordinates", "type"] + assert d.get("type") == "MultiPoint" + assert len(d.get("coordinates")) == 24 + assert [0.0, 60.0, 88.0] in d.get("coordinates") + + +def test_export_to_wkt(zmap_object, tmpdir): + x = tmpdir.join("output.wkt") + zmap_object.to_wkt(x.strpath) + with open(x.strpath) as f: + line = f.readline() + assert line.startswith("MULTIPOINT ((0.0000000 300.0000000 nan),") + + +def test_export_to_wkt_with_precision(zmap_object, tmpdir): + x = tmpdir.join("output.wkt") + zmap_object.to_wkt(x.strpath, precision=2) + with open(x.strpath) as f: + line = f.readline() + assert line.startswith("MULTIPOINT ((0.00 300.00 nan),") diff --git a/tests/test_read.py b/tests/test_read.py new file mode 100644 index 0000000..c3a2b75 --- /dev/null +++ b/tests/test_read.py @@ -0,0 +1,50 @@ +def test_read_comments_section(zmap_object): + assert len(zmap_object.comments) == 2 + assert zmap_object.comments[0].startswith( + " File created by DMBTools2.GridFileFormats" + ) + + +def test_columns_rows_count(zmap_object): + assert zmap_object.no_cols == 4 + assert zmap_object.no_rows == 6 + + +def test_max_min_values(zmap_object): + assert zmap_object.max_x == 200.0 + assert zmap_object.min_x == 0.0 + assert zmap_object.max_y == 300.0 + assert zmap_object.min_y == 0.0 + + +def test_decimal_places(zmap_object): + assert zmap_object.decimal_places == 7 + + +def test_nodes_per_line(zmap_object): + assert zmap_object.nodes_per_line == 4 + + +def test_null_values(zmap_object): + assert zmap_object.null_value == -9999 + assert zmap_object.null_value_2 == "" + + +def test_start_column(zmap_object): + assert zmap_object.start_column == 1 + + +def test_x_values(zmap_object): + assert zmap_object.x_values.shape == (6, 4) + + +def test_y_values(zmap_object): + assert zmap_object.y_values.shape == (6, 4) + + +def test_z_values(zmap_object): + assert zmap_object.z_values.shape == (4, 6) + + +def test_z_type(zmap_object): + assert zmap_object.z_type == "GRID" diff --git a/tests/test_write.py b/tests/test_write.py new file mode 100644 index 0000000..896c1ce --- /dev/null +++ b/tests/test_write.py @@ -0,0 +1,36 @@ +from zmapio import ZMAPGrid + +z_text = """!this is +!a test +@test, GRID, 4 +20, -9999.0, , 7, 1 +6, 4, 0.0, 200.0, 0.0, 300.0 +0.0, 0.0, 0.0 +@ + -9999.0000000 -9999.0000000 3.0000000 32.0000000 + 88.0000000 13.0000000 + -9999.0000000 20.0000000 8.0000000 42.0000000 + 75.0000000 5.0000000 + 5.0000000 100.0000000 35.0000000 50.0000000 + 27.0000000 1.0000000 + 2.0000000 36.0000000 10.0000000 6.0000000 + 9.0000000 -9999.0000000 +""" + + +def test_write_zmap_file(zmap_object, tmpdir): + x = tmpdir.join("output.dat") + z = ZMAPGrid( + z_values=zmap_object.z_values, min_x=0.0, max_x=200.0, min_y=0.0, max_y=300.0 + ) + z.comments = ["this is", "a test"] + z.nodes_per_line = 4 + z.field_width = 20 + z.decimal_places = 7 + z.name = "test" + z.null_value = -9999.0 + z.write(x.strpath) + + with open(x.strpath) as f: + data = f.read() + assert data == z_text diff --git a/zmapio/__init__.py b/zmapio/__init__.py index cbb4729..4c06bae 100644 --- a/zmapio/__init__.py +++ b/zmapio/__init__.py @@ -1,2 +1,2 @@ -from .zmap import ZMAPGrid -from .__version__ import __version__ +from .__version__ import __version__ # noqa: F401 +from .zmap import ZMAPGrid # noqa: F401 diff --git a/zmapio/__version__.py b/zmapio/__version__.py index abeeedb..3d18726 100644 --- a/zmapio/__version__.py +++ b/zmapio/__version__.py @@ -1 +1 @@ -__version__ = '0.4.0' +__version__ = "0.5.0" diff --git a/zmapio/reader.py b/zmapio/reader.py index f762ddb..9e70c6e 100644 --- a/zmapio/reader.py +++ b/zmapio/reader.py @@ -21,7 +21,7 @@ def open_file(file_ref): file_ref = StringIO(file_ref) else: - file_ref = open(lines[0], 'r') + file_ref = open(lines[0], "r") return file_ref @@ -32,21 +32,21 @@ def read_file_contents(file_obj): data = None data_flag = False lines = file_obj.readlines() - lines = [line for line in lines if not line.startswith('+')] + lines = [line for line in lines if not line.startswith("+")] for i in range(len(lines)): line = lines[i].strip() if not line: continue - if line.startswith('!'): + if line.startswith("!"): comments.append(line[1:]) - elif line.startswith('@') and not data_flag: + elif line.startswith("@") and not data_flag: data_flag = True headers = read_headers(i, lines) - elif line.startswith('@') and data_flag: + elif line.startswith("@") and data_flag: data = read_data(i, lines) break @@ -58,32 +58,33 @@ def read_file_contents(file_obj): def read_headers(index, lines): rows = [] - for line in lines[index: index + 4]: + for line in lines[index : index + 4]: line = line.strip() - rows.append(line.split(',')) - - header = {"name": rows[0][0].strip()[1:], - "z_type": rows[0][1].strip(), - "nodes_per_line": int(rows[0][2]), - "field_width": int(rows[1][0]), - "null_value": rows[1][1].strip(), - "null_value_2": rows[1][2].strip(), - "decimal_places": int(rows[1][3]), - "start_column": int(rows[1][4]), - "no_rows": int(rows[2][0]), - "no_cols": int(rows[2][1]), - "min_x": np.float64(rows[2][2]), - "max_x": np.float64(rows[2][3]), - "min_y": np.float64(rows[2][4]), - "max_y": np.float64(rows[2][5]) - } + rows.append(line.split(",")) + + header = { + "name": rows[0][0].strip()[1:], + "z_type": rows[0][1].strip(), + "nodes_per_line": int(rows[0][2]), + "field_width": int(rows[1][0]), + "null_value": rows[1][1].strip(), + "null_value_2": rows[1][2].strip(), + "decimal_places": int(rows[1][3]), + "start_column": int(rows[1][4]), + "no_rows": int(rows[2][0]), + "no_cols": int(rows[2][1]), + "min_x": np.float64(rows[2][2]), + "max_x": np.float64(rows[2][3]), + "min_y": np.float64(rows[2][4]), + "max_y": np.float64(rows[2][5]), + } return header def read_data(index, lines): data = [] - for line in lines[index + 1:]: + for line in lines[index + 1 :]: line = line.strip() data.append(line) diff --git a/zmapio/writer.py b/zmapio/writer.py index 0c09674..bf08dff 100644 --- a/zmapio/writer.py +++ b/zmapio/writer.py @@ -1,26 +1,35 @@ import math -def chunks(l, n): - for i in range(0, len(l), n): - yield l[i:i+n] +def chunks(x, n): + for i in range(0, len(x), n): + yield x[i : i + n] def write(zmap, file_object, nodes_per_line): lines = [] if not zmap.null_value_2: - zmap.null_value_2 = '' + zmap.null_value_2 = "" for c in zmap.comments: - lines.append('!' + c) + lines.append("!" + c) lines.append("@{}, {}, {}".format(zmap.name, zmap.z_type, nodes_per_line)) - lines.append("{}, {}, {}, {}, {}".format(zmap.field_width, zmap.null_value, zmap.null_value_2, - zmap.decimal_places, zmap.start_column)) - lines.append("{}, {}, {}, {}, {}, {}".format(zmap.no_rows, zmap.no_cols, - zmap.min_x, zmap.max_x, - zmap.min_y, zmap.max_y)) + lines.append( + "{}, {}, {}, {}, {}".format( + zmap.field_width, + zmap.null_value, + zmap.null_value_2, + zmap.decimal_places, + zmap.start_column, + ) + ) + lines.append( + "{}, {}, {}, {}, {}, {}".format( + zmap.no_rows, zmap.no_cols, zmap.min_x, zmap.max_x, zmap.min_y, zmap.max_y + ) + ) lines.append("0.0, 0.0, 0.0") lines.append("@") @@ -28,9 +37,14 @@ def write(zmap, file_object, nodes_per_line): for j in chunks(i, nodes_per_line): j_fmt = "0.{}f".format(zmap.decimal_places) j_fmt = "{0:" + j_fmt + "}" - j = [j_fmt.format(float(x)) if not math.isnan(x) else j_fmt.format(float(zmap.null_value)) for x in j] + j = [ + j_fmt.format(float(x)) + if not math.isnan(x) + else j_fmt.format(float(zmap.null_value)) + for x in j + ] line = "{:>" + "{}".format(zmap.field_width) + "}" - lines.append(''.join([line] * len(j)).format(*tuple(j))) + lines.append("".join([line] * len(j)).format(*tuple(j))) - file_object.write('\n'.join(lines)) - file_object.write('\n') + file_object.write("\n".join(lines)) + file_object.write("\n") diff --git a/zmapio/zmap.py b/zmapio/zmap.py index 529639a..8b34f79 100644 --- a/zmapio/zmap.py +++ b/zmapio/zmap.py @@ -1,21 +1,38 @@ import csv import json + import numpy as np -from . import reader, writer +from . import reader +from . import writer -class ZMAPGrid(object): - def __init__(self, file_ref=None, comments=None, name=None, z_type='GRID', nodes_per_line=None, field_width=None, - null_value=1e+30, decimal_places=None, start_column=1, min_x=None, max_x=None, min_y=None, max_y=None, - z_values=None, **kwargs): +class ZMAPGrid(object): + def __init__( + self, + file_ref=None, + comments=None, + name=None, + z_type="GRID", + nodes_per_line=None, + field_width=None, + null_value=1e30, + decimal_places=None, + start_column=1, + min_x=None, + max_x=None, + min_y=None, + max_y=None, + z_values=None, + **kwargs + ): self.comments = comments self.name = name self.z_type = z_type self.nodes_per_line = nodes_per_line self.field_width = field_width self.null_value = null_value - self.null_value_2 = '' + self.null_value_2 = "" self.decimal_places = decimal_places self.start_column = start_column self.z_values = z_values @@ -30,7 +47,10 @@ def __init__(self, file_ref=None, comments=None, name=None, z_type='GRID', nodes self.y_values = y self.z_values = z - elif all(v is not None for v in [self.z_values, self.min_x, self.max_x, self.min_y, self.max_y]): + elif all( + v is not None + for v in [self.z_values, self.min_x, self.max_x, self.min_y, self.max_y] + ): self.no_cols, self.no_rows = self.z_values.shape x = np.linspace(self.min_x, self.max_x, self.no_cols) y = np.linspace(self.max_y, self.min_y, self.no_rows) @@ -48,7 +68,7 @@ def read(self, file_ref, dtype=np.float64): self.comments = comments - if hasattr(file_obj, 'close'): + if hasattr(file_obj, "close"): file_obj.close() try: @@ -82,18 +102,20 @@ def plot(self, **kwargs): except ImportError: raise ImportError("matplotlib needs to be installed for plotting.") - ax = plt.pcolormesh(self.x_values, self.y_values, self.z_values.swapaxes(0, 1), **kwargs) + ax = plt.pcolormesh( + self.x_values, self.y_values, self.z_values.swapaxes(0, 1), **kwargs + ) return ax def to_csv(self, file_ref, **kwargs): opened_file = False - if isinstance(file_ref, str) and not hasattr(file_ref, 'write'): + if isinstance(file_ref, str) and not hasattr(file_ref, "write"): opened_file = True - file_ref = open(file_ref, 'w') + file_ref = open(file_ref, "w") - if 'lineterminator' not in kwargs: - kwargs['lineterminator'] = '\n' + if "lineterminator" not in kwargs: + kwargs["lineterminator"] = "\n" writer = csv.writer(file_ref, **kwargs) for j in range(self.no_cols): @@ -108,9 +130,9 @@ def to_csv(self, file_ref, **kwargs): def to_wkt(self, file_ref, precision=None): opened_file = False - if isinstance(file_ref, str) and not hasattr(file_ref, 'write'): + if isinstance(file_ref, str) and not hasattr(file_ref, "write"): opened_file = True - file_ref = open(file_ref, 'w') + file_ref = open(file_ref, "w") if not precision: if self.decimal_places: @@ -124,19 +146,29 @@ def to_wkt(self, file_ref, precision=None): x = self.x_values[i, j] y = self.y_values[i, j] z = self.z_values[j, i] - nodes.append('({} {} {})'.format(np.format_float_positional(x, precision=precision, unique=False), - np.format_float_positional(y, precision=precision, unique=False), - np.format_float_positional(z, precision=precision, unique=False))) - file_ref.write("MULTIPOINT (" + ', '.join(nodes) + ")") + nodes.append( + "({} {} {})".format( + np.format_float_positional( + x, precision=precision, unique=False + ), + np.format_float_positional( + y, precision=precision, unique=False + ), + np.format_float_positional( + z, precision=precision, unique=False + ), + ) + ) + file_ref.write("MULTIPOINT (" + ", ".join(nodes) + ")") if opened_file: file_ref.close() def to_geojson(self, file_ref): opened_file = False - if isinstance(file_ref, str) and not hasattr(file_ref, 'write'): + if isinstance(file_ref, str) and not hasattr(file_ref, "write"): opened_file = True - file_ref = open(file_ref, 'w') + file_ref = open(file_ref, "w") nodes = [] for j in range(self.no_cols): @@ -146,7 +178,7 @@ def to_geojson(self, file_ref): z = self.z_values[j, i] nodes.append([x, y, z]) - json.dump({'type': 'MultiPoint', 'coordinates': nodes}, file_ref) + json.dump({"type": "MultiPoint", "coordinates": nodes}, file_ref) if opened_file: file_ref.close() @@ -155,22 +187,25 @@ def to_dataframe(self): try: import pandas as pd except ImportError: - raise ImportError("pandas package needs to be installed for dataframe conversion.") + raise ImportError( + "pandas package needs to be installed for dataframe conversion." + ) from collections import defaultdict + nodes_dict = defaultdict(list) for j in range(self.no_cols): for i in range(self.no_rows): - nodes_dict['X'].append(self.x_values[i, j]) - nodes_dict['Y'].append(self.y_values[i, j]) - nodes_dict['Z'].append(self.z_values[j, i]) + nodes_dict["X"].append(self.x_values[i, j]) + nodes_dict["Y"].append(self.y_values[i, j]) + nodes_dict["Z"].append(self.z_values[j, i]) return pd.DataFrame(nodes_dict) def write(self, file_ref, nodes_per_line=None): opened_file = False - if isinstance(file_ref, str) and not hasattr(file_ref, 'write'): + if isinstance(file_ref, str) and not hasattr(file_ref, "write"): opened_file = True - file_ref = open(file_ref, 'w') + file_ref = open(file_ref, "w") if not nodes_per_line: nodes_per_line = self.nodes_per_line