Source code for csdmpy
# -*- coding: utf-8 -*-
"""CSDM."""
from __future__ import division
from __future__ import print_function
import json
from urllib.parse import urlparse
from csdmpy.csdm import CSDM
from csdmpy.dependent_variables import DependentVariable
from csdmpy.dependent_variables.download import download_file_from_url
from csdmpy.dimensions import Dimension
from csdmpy.helper_functions import _preview
from csdmpy.utils import validate
__author__ = "Deepansh J. Srivastava"
__email__ = "srivastava.89@osu.edu"
__version__ = "0.1.5"
__all__ = ["load", "new", "plot"]
def _import_json(filename):
res = urlparse(filename)
if res[0] not in ["file", ""]:
filename = download_file_from_url(filename)
with open(filename, "rb") as f:
content = f.read()
return json.loads(str(content, encoding="UTF-8"))
[docs]def load(filename=None, application=False):
r"""
Load a .csdf/.csdfe file and return an instance of :ref:`csdm_api` class.
The file must be a JSON serialization of the CSD Model.
Example:
>>> data1 = cp.load('local_address/file.csdf') # doctest: +SKIP
>>> data2 = cp.load('url_address/file.csdf') # doctest: +SKIP
Args:
filename (str): A local or remote address to the `.csdf or `.csdfe` file.
application (bool): If true, the application metadata from application that
last serialized the file will be imported. Default is False.
sort_fft_order (bool): If true, the coordinates and the components
corresponding to the dimension with `complex_fft` as True will be
sorted upon import and the corresponding `complex_fft` key-value
will be set to False. Default is True.
Returns:
A CSDM instance.
"""
if filename is None:
raise Exception("Missing a required data file address.")
# if isdir(filename):
# csdm_files = [f for f in listdir(filename) if f.endswith((".csdf", ".csdfe"))]
# if len(csdm_files) > 1:
# raise Exception(
# ("The given path is a folder. More that one csdf(e) files found in this folder")
# )
# if len(csdm_files) == 0:
# raise Exception(
# ("The given path is a folder. No csdf(e) file found in the folder.")
# )
# csd_file = join(filename, csdm_files[0])
# else:
# csd_file = filename
try:
dictionary = _import_json(filename)
except Exception as e:
raise Exception(e)
dictionary["filename"] = filename
csdm_object = parse_dict(dictionary)
if application is False:
csdm_object.application = {}
for dim in csdm_object.dimensions:
dim.application = {}
if hasattr(dim, "reciprocal") and dim.type != "label":
dim.reciprocal.application = {}
for dim in csdm_object.dependent_variables:
dim.application = {}
# if hasattr(dim., 'dimension indexes'):
# dim.reciprocal.application = {}
# csdm_objects = []
# for file_ in csdm_files:
# csdm_objects.append(_load(file_, application=application))
return csdm_object
[docs]def parse_dict(dictionary):
"""Parse a CSDM compliant python dictionary and return a CSDM object.
Args:
dictionary: A CSDM compliant python dictionary.
"""
key_list_root = dictionary.keys()
if "CSDM" in key_list_root:
raise KeyError("'CSDM' is not a valid keyword. Did you mean 'csdm'?")
if "csdm" not in key_list_root:
raise KeyError("Missing a required `csdm` key.")
# inside csdm object
optional_keys = [
"read_only",
"timestamp",
"geographic_coordinate",
"application",
"tags",
"description",
]
required_keys = ["version"]
all_keys = optional_keys + required_keys
key_list_csdm = list(dictionary["csdm"].keys())
key_list_csdm_lower_case = [item.lower() for item in key_list_csdm]
for i in range(len(key_list_csdm)):
if key_list_csdm[i] not in all_keys and key_list_csdm_lower_case[i] in all_keys:
raise KeyError(
(
f"{key_list_csdm[i]} is not a valid keyword. "
f"Did you mean '{key_list_csdm_lower_case[i]}'?"
)
)
for item in required_keys:
if item not in key_list_csdm:
raise KeyError(f"Missing a required `{item}` key.")
_version = dictionary["csdm"]["version"]
validate(_version, "version", str)
if "filename" in dictionary.keys():
filename = dictionary["filename"]
else:
filename = None
csdm = CSDM(filename=filename, version=_version)
if "timestamp" in dictionary["csdm"].keys():
_timestamp = dictionary["csdm"]["timestamp"]
validate(_timestamp, "timestamp", str)
csdm._timestamp = _timestamp
if "dimensions" in key_list_csdm:
for dim in dictionary["csdm"]["dimensions"]:
csdm.add_dimension(dim)
if "dependent_variables" in key_list_csdm:
for dat in dictionary["csdm"]["dependent_variables"]:
csdm.add_dependent_variable(dat)
n_points = [item.count for item in csdm.dimensions]
if n_points != []:
csdm._reshape(n_points[::-1])
for key in optional_keys:
if key in key_list_csdm:
setattr(csdm, "_" + key, dictionary["csdm"][key])
return csdm
[docs]def loads(string):
"""
Loads a JSON serialized string as a CSDM object.
Args:
string: A JSON serialized CSDM string.
Returns:
A CSDM object
Example:
>>> object_from_string = cp.loads(cp.new('A test dump').dumps())
>>> print(object_from_string.data_structure) # doctest: +SKIP
{
"csdm": {
"version": "1.0",
"timestamp": "2019-10-21T20:33:17Z",
"description": "A test dump",
"dimensions": [],
"dependent_variables": []
}
}
"""
dictionary = json.loads(string)
csdm_object = parse_dict(dictionary)
return csdm_object
[docs]def new(description=""):
r"""
Create a new instance of the :ref:`csdm_api` class containing a 0D{0} dataset.
Args:
description (str): A string describing the the csdm object. This is optional.
Example:
>>> import csdmpy as cp
>>> emptydata = cp.new(description='Testing Testing 1 2 3')
>>> print(emptydata.data_structure)
{
"csdm": {
"version": "1.0",
"description": "Testing Testing 1 2 3",
"dimensions": [],
"dependent_variables": []
}
}
Returns:
A CSDM instance.
"""
return CSDM(description=description)
[docs]def plot(data_object, **kwargs):
"""
Helper function for plotting basic 1D and 2D datasets.
Args:
data_object: The csdm object
reverse_axis: An array of boolean specifying which dimensions will be
displayed in reverse.
kwargs: Additional kwargs which are passed to the matplotlib plot or
imshow functions.
Example:
>>> cp.plot(data_object) # doctest: +SKIP
"""
_preview(data_object, **kwargs)