|
25 | 25 | GMTInvalidInput,
|
26 | 26 | GMTVersionError,
|
27 | 27 | )
|
| 28 | +from pygmt.helpers import data_kind, dummy_context |
28 | 29 |
|
29 | 30 | FAMILIES = [
|
30 | 31 | "GMT_IS_DATASET",
|
@@ -1359,6 +1360,90 @@ def virtualfile_from_grid(self, grid):
|
1359 | 1360 | with self.open_virtual_file(*args) as vfile:
|
1360 | 1361 | yield vfile
|
1361 | 1362 |
|
| 1363 | + def virtualfile_from_data(self, check_kind=None, data=None, x=None, y=None, z=None): |
| 1364 | + """ |
| 1365 | + Store any data inside a virtual file. |
| 1366 | +
|
| 1367 | + This convenience function automatically detects the kind of data passed |
| 1368 | + into it, and produces a virtualfile that can be passed into GMT later |
| 1369 | + on. |
| 1370 | +
|
| 1371 | + Parameters |
| 1372 | + ---------- |
| 1373 | + check_kind : str |
| 1374 | + Used to validate the type of data that can be passed in. Choose |
| 1375 | + from 'raster', 'vector' or None. Default is None (no validation). |
| 1376 | + data : str, xarray.DataArray, 2d array, or None |
| 1377 | + Any raster or vector data format. This could be a file name, a |
| 1378 | + raster grid, a vector matrix/arrays, or other supported data input. |
| 1379 | + x/y/z : 1d arrays or None |
| 1380 | + x, y and z columns as numpy arrays. |
| 1381 | +
|
| 1382 | + Returns |
| 1383 | + ------- |
| 1384 | + file_context : contextlib._GeneratorContextManager |
| 1385 | + The virtual file stored inside a context manager. Access the file |
| 1386 | + name of this virtualfile using ``with file_context as fname: ...``. |
| 1387 | +
|
| 1388 | + Examples |
| 1389 | + -------- |
| 1390 | + >>> from pygmt.helpers import GMTTempFile |
| 1391 | + >>> import xarray as xr |
| 1392 | + >>> data = xr.Dataset( |
| 1393 | + ... coords={"index": [0, 1, 2]}, |
| 1394 | + ... data_vars={ |
| 1395 | + ... "x": ("index", [9, 8, 7]), |
| 1396 | + ... "y": ("index", [6, 5, 4]), |
| 1397 | + ... "z": ("index", [3, 2, 1]), |
| 1398 | + ... }, |
| 1399 | + ... ) |
| 1400 | + >>> with Session() as ses: |
| 1401 | + ... with ses.virtualfile_from_data( |
| 1402 | + ... check_kind="vector", data=data |
| 1403 | + ... ) as fin: |
| 1404 | + ... # Send the output to a file so that we can read it |
| 1405 | + ... with GMTTempFile() as fout: |
| 1406 | + ... ses.call_module("info", f"{fin} ->{fout.name}") |
| 1407 | + ... print(fout.read().strip()) |
| 1408 | + ... |
| 1409 | + <vector memory>: N = 3 <7/9> <4/6> <1/3> |
| 1410 | + """ |
| 1411 | + kind = data_kind(data, x, y, z) |
| 1412 | + |
| 1413 | + if check_kind == "raster" and kind not in ("file", "grid"): |
| 1414 | + raise GMTInvalidInput(f"Unrecognized data type: {type(data)}") |
| 1415 | + if check_kind == "vector" and kind not in ("file", "matrix", "vectors"): |
| 1416 | + raise GMTInvalidInput(f"Unrecognized data type: {type(data)}") |
| 1417 | + |
| 1418 | + # Decide which virtualfile_from_ function to use |
| 1419 | + _virtualfile_from = { |
| 1420 | + "file": dummy_context, |
| 1421 | + "grid": self.virtualfile_from_grid, |
| 1422 | + # Note: virtualfile_from_matrix is not used because a matrix can be |
| 1423 | + # converted to vectors instead, and using vectors allows for better |
| 1424 | + # handling of string type inputs (e.g. for datetime data types) |
| 1425 | + "matrix": self.virtualfile_from_vectors, |
| 1426 | + "vectors": self.virtualfile_from_vectors, |
| 1427 | + }[kind] |
| 1428 | + |
| 1429 | + # Ensure the data is an iterable (Python list or tuple) |
| 1430 | + if kind in ("file", "grid"): |
| 1431 | + _data = (data,) |
| 1432 | + elif kind == "vectors": |
| 1433 | + _data = (x, y, z) |
| 1434 | + elif kind == "matrix": # turn 2D arrays into list of vectors |
| 1435 | + try: |
| 1436 | + # pandas.DataFrame and xarray.Dataset types |
| 1437 | + _data = [array for _, array in data.items()] |
| 1438 | + except AttributeError: |
| 1439 | + # Python lists, tuples, and numpy ndarray types |
| 1440 | + _data = np.atleast_2d(np.asanyarray(data).T) |
| 1441 | + |
| 1442 | + # Finally create the virtualfile from the data, to be passed into GMT |
| 1443 | + file_context = _virtualfile_from(*_data) |
| 1444 | + |
| 1445 | + return file_context |
| 1446 | + |
1362 | 1447 | def extract_region(self):
|
1363 | 1448 | """
|
1364 | 1449 | Extract the WESN bounding box of the currently active figure.
|
|
0 commit comments