jupyter-analysis-tools 1.1.0__py3-none-any.whl → 1.2.0__py3-none-any.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.
@@ -1,11 +1,11 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  # __init__.py
3
3
 
4
- __version__ = "1.1.0"
4
+ __version__ = "1.2.0"
5
5
 
6
6
  from .binning import reBin
7
7
  from .git import checkRepo, isNBstripoutActivated, isNBstripoutInstalled, isRepo
8
- from .readdata import readdata
8
+ from .readdata import readdata, readPDHmeta, readSSF
9
9
  from .readdata import readdata as readPDH
10
10
  from .utils import setLocaleUTF8
11
11
  from .widgets import PathSelector, showBoolStatus
@@ -1,18 +1,22 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  # readdata.py
3
3
 
4
- import os
4
+ import json
5
+ import warnings
6
+ import xml.etree.ElementTree as et
7
+ from pathlib import Path
5
8
 
6
9
  import pandas as pd
7
10
 
8
11
 
9
- def readdata(fn, q_range=None, read_csv_args=None, print_filename=True):
12
+ def readdata(fpath, q_range=None, read_csv_args=None, print_filename=True):
10
13
  """Read a datafile pandas Dataframe
11
14
  extract a file_name
12
15
  select q-range: q_min <= q <= q_max
13
16
  """
17
+ fpath = Path(fpath)
14
18
  if print_filename:
15
- print(f"Reading file '{fn}'")
19
+ print(f"Reading file '{str(fpath)}'")
16
20
  if read_csv_args is None:
17
21
  read_csv_args = dict()
18
22
  if "sep" not in read_csv_args:
@@ -23,10 +27,10 @@ def readdata(fn, q_range=None, read_csv_args=None, print_filename=True):
23
27
  read_csv_args.update(index_col=False)
24
28
  # print("f_read_data, read_csv_args:", read_csv_args) # for debugging
25
29
 
26
- _, file_ext = os.path.splitext(fn)
30
+ file_ext = fpath.suffix
27
31
  if file_ext.lower() == ".pdh": # for PDH files
28
32
  nrows = pd.read_csv(
29
- fn,
33
+ fpath,
30
34
  skiprows=2,
31
35
  nrows=1,
32
36
  usecols=[
@@ -36,12 +40,117 @@ def readdata(fn, q_range=None, read_csv_args=None, print_filename=True):
36
40
  header=None,
37
41
  ).values[0, 0]
38
42
  read_csv_args.update(skiprows=5, nrows=nrows)
39
- df_data = pd.read_csv(fn, **read_csv_args)
43
+ df = pd.read_csv(fpath, **read_csv_args)
40
44
 
41
45
  # select q-range
42
46
  if q_range is not None:
43
47
  q_min, q_max = q_range
44
- df_data = df_data[(df_data.q > q_min) & (df_data.q < q_max)]
48
+ df = df[(df.q > q_min) & (df.q < q_max)]
45
49
 
46
- file_name = os.path.basename(fn).split("[")[0]
47
- return df_data, file_name
50
+ filename = fpath.stem.split("[")[0]
51
+ return df, filename
52
+
53
+
54
+ def convertValue(val):
55
+ val = val.strip()
56
+ try:
57
+ return int(val)
58
+ except ValueError:
59
+ try:
60
+ return float(val)
61
+ except ValueError:
62
+ pass
63
+ return val
64
+
65
+ def xmlPDHToDict(root):
66
+ result = {}
67
+ stack = [(root, result)]
68
+ while stack:
69
+ elem, parentCont = stack.pop()
70
+ elemCont = {}
71
+ key = elem.attrib.pop("key", None)
72
+ idx = -1
73
+ if (not len(list(elem)) and not len(elem.attrib)
74
+ and not (elem.text and len(elem.text.strip()))):
75
+ continue # skip empty elements with a key only early
76
+ if elem.tag == "list":
77
+ elemCont = []
78
+ else: # add attributes & values to dict
79
+ # Attach text, if any
80
+ if elem.text and len(elem.text.strip()):
81
+ if elem.tag in ("value", "reference"):
82
+ elemCont["value"] = convertValue(elem.text)
83
+ else:
84
+ elemCont["#text"] = convertValue(elem.text)
85
+ # Attach attributes, if any
86
+ if elem.attrib:
87
+ elemCont.update({k: convertValue(v) for k, v in elem.attrib.items() if len(v.strip())})
88
+ if key == "unit" and "value" in elemCont: # fix some units
89
+ elemCont["value"] = elemCont["value"].replace("_", "")
90
+ if "unit" in elemCont:
91
+ elemCont["unit"] = elemCont["unit"].replace("_", "")
92
+ # reduce the extracted dict&attributes
93
+ idx = elemCont.get("index", -1) # insert last/append if no index given
94
+ value = elemCont.get("value", None)
95
+ if value is not None and (len(elemCont) == 1
96
+ or (len(elemCont) == 2 and "index" in elemCont)):
97
+ elemCont = value # contains value only
98
+ parentKey = elem.tag
99
+ if key is not None and parentKey in ("list", "value", "group"):
100
+ # skip one level in hierarchy for these generic containers
101
+ parentKey = key
102
+ key = None
103
+ try:
104
+ if isinstance(parentCont, list):
105
+ parentCont.insert(idx, elemCont)
106
+ elif parentKey not in parentCont: # add as new list
107
+ if key is None: # make a list
108
+ parentCont[parentKey] = elemCont
109
+ else: # have a key
110
+ parentCont[parentKey] = {key: elemCont}
111
+ else: # parentKey exists already
112
+ if (not isinstance(parentCont[parentKey], list) and
113
+ not isinstance(parentCont[parentKey], dict)):
114
+ # if its a plain value before, make a list out of it and append in next step
115
+ parentCont[parentKey] = [parentCont[parentKey]]
116
+ if isinstance(parentCont[parentKey], list):
117
+ parentCont[parentKey].append(elemCont)
118
+ elif key is not None:
119
+ parentCont[parentKey].update({key: elemCont})
120
+ else: # key is None
121
+ parentCont[parentKey].update(elemCont)
122
+ except AttributeError:
123
+ raise
124
+ # reversed for correct order
125
+ stack += [(child, elemCont) for child in reversed(list(elem))]
126
+ # fix some entry values, weird Anton Paar PDH format
127
+ try:
128
+ oldts = result["fileinfo"]["parameter"]["DateTime"]["value"]
129
+ delta = (39*365+10)*24*3600 # timestamp seems to be based on around 2009-01-01 (a day give or take)
130
+ # make it compatible to datetime.datetime routines
131
+ result["fileinfo"]["parameter"]["DateTime"]["value"] = oldts+delta
132
+ except KeyError:
133
+ pass
134
+ return result
135
+
136
+ def readPDHmeta(fp):
137
+ fp = Path(fp)
138
+ if fp.suffix.lower() != ".pdh":
139
+ warnings.warn("readPDHmeta() supports .pdh files only!")
140
+ return # for PDH files
141
+ lines = ""
142
+ with open(fp) as fd:
143
+ lines = fd.readlines()
144
+ nrows = int(lines[2].split()[0])
145
+ xml = "".join(lines[nrows+5:])
146
+ return xmlPDHToDict(et.fromstring(xml))
147
+
148
+ def readSSF(fp):
149
+ fp = Path(fp)
150
+ if fp.suffix.lower() != ".ssf":
151
+ warnings.warn("readSession() supports .ssf files only!")
152
+ return # for PDH files
153
+ data = ""
154
+ with open(fp, encoding='utf-8-sig') as fd:
155
+ data = fd.read()
156
+ return xmlPDHToDict(et.fromstring(data))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jupyter-analysis-tools
3
- Version: 1.1.0
3
+ Version: 1.2.0
4
4
  Summary: Yet another Python library with helpers and utilities for data analysis and processing.
5
5
  Author-email: Ingo Breßler <dev@ingobressler.net>
6
6
  License: MIT license
@@ -53,8 +53,8 @@ Yet another Python library with helpers and utilities for data analysis and proc
53
53
  :target: https://pypi.org/project/jupyter-analysis-tools
54
54
  :alt: PyPI Package latest release
55
55
 
56
- .. |commits-since| image:: https://img.shields.io/github/commits-since/BAMresearch/jupyter-analysis-tools/v1.1.0.svg
57
- :target: https://github.com/BAMresearch/jupyter-analysis-tools/compare/v1.1.0...main
56
+ .. |commits-since| image:: https://img.shields.io/github/commits-since/BAMresearch/jupyter-analysis-tools/v1.2.0.svg
57
+ :target: https://github.com/BAMresearch/jupyter-analysis-tools/compare/v1.2.0...main
58
58
  :alt: Commits since latest release
59
59
 
60
60
  .. |license| image:: https://img.shields.io/pypi/l/jupyter-analysis-tools.svg
@@ -127,6 +127,20 @@ Note, to combine the coverage data from all the tox environments run:
127
127
 
128
128
  # CHANGELOG
129
129
 
130
+ ## v1.2.0 (2025-07-11)
131
+
132
+ ### Features
133
+
134
+ * readdata: readSSF() renamed from readSession(), tests added with expected JSON output ([`e2197f6`](https://github.com/BAMresearch/jupyter-analysis-tools/commit/e2197f6bcb032c1bc1a9a7435e024dda763228c4))
135
+
136
+ * readPDHmeta: routine for reading metadata part from .PDH and .SSF files ([`ea6a1d5`](https://github.com/BAMresearch/jupyter-analysis-tools/commit/ea6a1d554f3763fc05022ae8e4e8909f0993cd43))
137
+
138
+ ### Testing
139
+
140
+ * readdata: path separator depends on platform ([`1b2866f`](https://github.com/BAMresearch/jupyter-analysis-tools/commit/1b2866f13307c2cf2dedc59f36d7372442ddbfd8))
141
+
142
+ * readdata: testdata files and testing, using pathlib instead of old os.path ([`aeacfa4`](https://github.com/BAMresearch/jupyter-analysis-tools/commit/aeacfa4a949d7293f2cd3ce5e3004fddf20ecc02))
143
+
130
144
  ## v1.1.0 (2025-07-10)
131
145
 
132
146
  ### Bug fixes
@@ -1,16 +1,16 @@
1
- jupyter_analysis_tools/__init__.py,sha256=I4Vdvl5uMDvIcs12ZZlMYaFzLrCrUerH5ZkWzgSKhUs,343
1
+ jupyter_analysis_tools/__init__.py,sha256=qwt3D2fugc238WYSAYOpSmy9EqAxHIq45WkHLCgqjGQ,365
2
2
  jupyter_analysis_tools/analysis.py,sha256=AiAvUO648f0PYXqLfal1kDH926neasE5c1RYFu9wtYg,1768
3
3
  jupyter_analysis_tools/binning.py,sha256=d6eXRC3IOnnJIF25OfEASyWedT71EX2nF7jAgGJ9suQ,14536
4
4
  jupyter_analysis_tools/datalocations.py,sha256=BakfiZOMcBwp-_DAn7l57lGWZmZGNnk0j73V75nLBUA,4322
5
5
  jupyter_analysis_tools/distrib.py,sha256=uyh2jXDdXR6dfd36CAoE5_psoFF0bfA6l1wletPD7Xo,16515
6
6
  jupyter_analysis_tools/git.py,sha256=mqSk5nnAFrmk1_2KFuKVrDWOkRbGbAQOq2N1DfxhNpg,2216
7
7
  jupyter_analysis_tools/plotting.py,sha256=L2gwSjlBVK8OneAfSuna3vCJIg2rSEdvd9TfEbM2Als,1183
8
- jupyter_analysis_tools/readdata.py,sha256=Z0LCAYKEauItdDF6H0gJYR74EKgR2-XFHo5gKlTz7cw,1348
8
+ jupyter_analysis_tools/readdata.py,sha256=zqFYK21ckmogVgsEYNVeqvNvkGVzcHzdCT-I_n0n_uw,5702
9
9
  jupyter_analysis_tools/utils.py,sha256=cwbviD1YP06rVhtItdORHEbp8fQ7JfhcrYDONRM336Y,5315
10
10
  jupyter_analysis_tools/widgets.py,sha256=rA8qPvY9nS1OtykZwXtCTG29K-N_MYFVb5Aj8yK40_s,2996
11
- jupyter_analysis_tools-1.1.0.dist-info/licenses/AUTHORS.rst,sha256=SUxxgElDBm6WdCbBBFfcr0ZE3SolWL0T0aS5Fym1198,100
12
- jupyter_analysis_tools-1.1.0.dist-info/licenses/LICENSE,sha256=SrbIwXA1ZLTO6uwZneJMpvdgiC-3fhNl0vwb3ALoY4g,1107
13
- jupyter_analysis_tools-1.1.0.dist-info/METADATA,sha256=34HMf-Q8hrdj1SemL1o8-eJEAyhLBz--BX3c2B_6GUM,35291
14
- jupyter_analysis_tools-1.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
15
- jupyter_analysis_tools-1.1.0.dist-info/top_level.txt,sha256=ei_0x-BF85FLoJ_h67ySwDFowtqus_gI4_0GR466PEU,23
16
- jupyter_analysis_tools-1.1.0.dist-info/RECORD,,
11
+ jupyter_analysis_tools-1.2.0.dist-info/licenses/AUTHORS.rst,sha256=SUxxgElDBm6WdCbBBFfcr0ZE3SolWL0T0aS5Fym1198,100
12
+ jupyter_analysis_tools-1.2.0.dist-info/licenses/LICENSE,sha256=SrbIwXA1ZLTO6uwZneJMpvdgiC-3fhNl0vwb3ALoY4g,1107
13
+ jupyter_analysis_tools-1.2.0.dist-info/METADATA,sha256=gBi2EdNB6XZP1RC5bls8EepnVGiVMf0HVoXD5D3svZ0,36100
14
+ jupyter_analysis_tools-1.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
15
+ jupyter_analysis_tools-1.2.0.dist-info/top_level.txt,sha256=ei_0x-BF85FLoJ_h67ySwDFowtqus_gI4_0GR466PEU,23
16
+ jupyter_analysis_tools-1.2.0.dist-info/RECORD,,