mrio-toolbox 1.1.1__py3-none-any.whl → 1.1.3__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.
Potentially problematic release.
This version of mrio-toolbox might be problematic. Click here for more details.
- {mrio_toolbox-1.1.1.dist-info → mrio_toolbox-1.1.3.dist-info}/METADATA +2 -2
- mrio_toolbox-1.1.3.dist-info/RECORD +5 -0
- mrio_toolbox-1.1.3.dist-info/top_level.txt +1 -0
- mrio_toolbox/__init__.py +0 -21
- mrio_toolbox/_parts/_Axe.py +0 -539
- mrio_toolbox/_parts/_Part.py +0 -1698
- mrio_toolbox/_parts/__init__.py +0 -7
- mrio_toolbox/_parts/part_operations.py +0 -57
- mrio_toolbox/extractors/__init__.py +0 -20
- mrio_toolbox/extractors/downloaders.py +0 -36
- mrio_toolbox/extractors/emerging/__init__.py +0 -3
- mrio_toolbox/extractors/emerging/emerging_extractor.py +0 -117
- mrio_toolbox/extractors/eora/__init__.py +0 -3
- mrio_toolbox/extractors/eora/eora_extractor.py +0 -132
- mrio_toolbox/extractors/exiobase/__init__.py +0 -3
- mrio_toolbox/extractors/exiobase/exiobase_extractor.py +0 -270
- mrio_toolbox/extractors/extractors.py +0 -79
- mrio_toolbox/extractors/figaro/__init__.py +0 -3
- mrio_toolbox/extractors/figaro/figaro_downloader.py +0 -280
- mrio_toolbox/extractors/figaro/figaro_extractor.py +0 -187
- mrio_toolbox/extractors/gloria/__init__.py +0 -3
- mrio_toolbox/extractors/gloria/gloria_extractor.py +0 -202
- mrio_toolbox/extractors/gtap11/__init__.py +0 -7
- mrio_toolbox/extractors/gtap11/extraction/__init__.py +0 -3
- mrio_toolbox/extractors/gtap11/extraction/extractor.py +0 -129
- mrio_toolbox/extractors/gtap11/extraction/harpy_files/__init__.py +0 -6
- mrio_toolbox/extractors/gtap11/extraction/harpy_files/_header_sets.py +0 -279
- mrio_toolbox/extractors/gtap11/extraction/harpy_files/har_file.py +0 -262
- mrio_toolbox/extractors/gtap11/extraction/harpy_files/har_file_io.py +0 -974
- mrio_toolbox/extractors/gtap11/extraction/harpy_files/header_array.py +0 -300
- mrio_toolbox/extractors/gtap11/extraction/harpy_files/sl4.py +0 -229
- mrio_toolbox/extractors/gtap11/gtap_mrio/__init__.py +0 -6
- mrio_toolbox/extractors/gtap11/gtap_mrio/mrio_builder.py +0 -158
- mrio_toolbox/extractors/icio/__init__.py +0 -3
- mrio_toolbox/extractors/icio/icio_extractor.py +0 -121
- mrio_toolbox/extractors/wiod/__init__.py +0 -3
- mrio_toolbox/extractors/wiod/wiod_extractor.py +0 -143
- mrio_toolbox/mrio.py +0 -899
- mrio_toolbox/msm/__init__.py +0 -6
- mrio_toolbox/msm/multi_scale_mapping.py +0 -863
- mrio_toolbox/utils/__init__.py +0 -3
- mrio_toolbox/utils/converters/__init__.py +0 -5
- mrio_toolbox/utils/converters/pandas.py +0 -247
- mrio_toolbox/utils/converters/xarray.py +0 -130
- mrio_toolbox/utils/formatting/__init__.py +0 -0
- mrio_toolbox/utils/formatting/formatter.py +0 -528
- mrio_toolbox/utils/loaders/__init__.py +0 -7
- mrio_toolbox/utils/loaders/_loader.py +0 -312
- mrio_toolbox/utils/loaders/_loader_factory.py +0 -96
- mrio_toolbox/utils/loaders/_nc_loader.py +0 -184
- mrio_toolbox/utils/loaders/_np_loader.py +0 -112
- mrio_toolbox/utils/loaders/_pandas_loader.py +0 -128
- mrio_toolbox/utils/loaders/_parameter_loader.py +0 -386
- mrio_toolbox/utils/savers/__init__.py +0 -11
- mrio_toolbox/utils/savers/_path_checker.py +0 -37
- mrio_toolbox/utils/savers/_to_folder.py +0 -165
- mrio_toolbox/utils/savers/_to_nc.py +0 -60
- mrio_toolbox-1.1.1.dist-info/RECORD +0 -59
- mrio_toolbox-1.1.1.dist-info/top_level.txt +0 -1
- {mrio_toolbox-1.1.1.dist-info → mrio_toolbox-1.1.3.dist-info}/WHEEL +0 -0
- {mrio_toolbox-1.1.1.dist-info → mrio_toolbox-1.1.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Extractor for GLORIA data.
|
|
3
|
-
|
|
4
|
-
This extractor loads GLORIA raw data files and converts them to NetCDF
|
|
5
|
-
files.
|
|
6
|
-
|
|
7
|
-
Supports GLORIA version 059
|
|
8
|
-
https://ielab.info/labs/ielab-gloria
|
|
9
|
-
|
|
10
|
-
Created on Fr Dez 20, 2024
|
|
11
|
-
@author: wirth, based on code of beaufils
|
|
12
|
-
|
|
13
|
-
"""
|
|
14
|
-
|
|
15
|
-
import os
|
|
16
|
-
import logging
|
|
17
|
-
import numpy as np
|
|
18
|
-
import pandas as pd
|
|
19
|
-
from mrio_toolbox import MRIO
|
|
20
|
-
from mrio_toolbox.utils.savers._to_nc import save_to_nc
|
|
21
|
-
|
|
22
|
-
log = logging.getLogger(__name__)
|
|
23
|
-
|
|
24
|
-
def extract_gloria(
|
|
25
|
-
year,
|
|
26
|
-
source,
|
|
27
|
-
markup = 1,
|
|
28
|
-
parts = "all",
|
|
29
|
-
precision=32):
|
|
30
|
-
"""
|
|
31
|
-
Extract GLORIA data.
|
|
32
|
-
|
|
33
|
-
Loads GLORIA tables and labels and store them as NetCDF for further use with
|
|
34
|
-
the mrio_toolbox library. Currrently, this extractor supports loading T, Y,
|
|
35
|
-
VA, Q, and QY tables.
|
|
36
|
-
|
|
37
|
-
Put all tables (including emission satellite accounts) as well as the
|
|
38
|
-
'GLORIA_ReadMe_059a.xlsx' file in the same source folder.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
Parameters
|
|
42
|
-
----------
|
|
43
|
-
year : str
|
|
44
|
-
Data year to load.
|
|
45
|
-
parts : str
|
|
46
|
-
Data blocks to load:
|
|
47
|
-
basic : T, Y
|
|
48
|
-
all : T, Y, VA, Q, QY
|
|
49
|
-
markup : int
|
|
50
|
-
Version of prices to load. Available versions:
|
|
51
|
-
1 : basic prices
|
|
52
|
-
2 : trade margins
|
|
53
|
-
3 : transport margins
|
|
54
|
-
4 : taxes on products
|
|
55
|
-
5 : subsidies on products
|
|
56
|
-
source : path-like
|
|
57
|
-
Path to folder where raw data is stored
|
|
58
|
-
precision : int
|
|
59
|
-
Floating point precision in bits. Default is 32.
|
|
60
|
-
This introduces some rounding error for large numbers.
|
|
61
|
-
"""
|
|
62
|
-
|
|
63
|
-
#Check source path
|
|
64
|
-
source = source + f"/GLORIA_MRIOs_59_{year}"
|
|
65
|
-
if not os.path.exists(source):
|
|
66
|
-
log.error(f"{os.path.abspath(source)} does not exist.")
|
|
67
|
-
raise NotADirectoryError(f"{os.path.abspath(source)} does not exist.")
|
|
68
|
-
|
|
69
|
-
# Gloria comes with 164 regions (160 countries + rest of americas,
|
|
70
|
-
# rest of europe, rest of africa, rest of asia-pacific) and 120 sectors.
|
|
71
|
-
|
|
72
|
-
if parts == "all":
|
|
73
|
-
parts = ["T","Y","V","TQ","YQ"]
|
|
74
|
-
elif parts == "basic":
|
|
75
|
-
parts = ["T","Y", "V"]
|
|
76
|
-
|
|
77
|
-
tables = {}
|
|
78
|
-
|
|
79
|
-
if precision == 32:
|
|
80
|
-
log.info("Data precision is 32 bits")
|
|
81
|
-
dt = np.float32
|
|
82
|
-
elif precision == 64:
|
|
83
|
-
log.info("Data precision is 64 bits")
|
|
84
|
-
dt = np.float64
|
|
85
|
-
|
|
86
|
-
log.info("Loading Gloria labels...")
|
|
87
|
-
labels = {}
|
|
88
|
-
countries = pd.read_excel(
|
|
89
|
-
io = os.path.join(source, "GLORIA_ReadMe_059a.xlsx"),
|
|
90
|
-
sheet_name = "Regions")
|
|
91
|
-
countries = countries["Region_acronyms"].tolist()
|
|
92
|
-
sectors = pd.read_excel(
|
|
93
|
-
io = os.path.join(source, "GLORIA_ReadMe_059a.xlsx"),
|
|
94
|
-
sheet_name = "Sectors")
|
|
95
|
-
sectors = sectors["Sector_names"].tolist()
|
|
96
|
-
va_and_y_labs = pd.read_excel(
|
|
97
|
-
io = os.path.join(source, "GLORIA_ReadMe_059a.xlsx"),
|
|
98
|
-
sheet_name = "Value added and final demand")
|
|
99
|
-
va_labs= va_and_y_labs["Value_added_names"].tolist()
|
|
100
|
-
y_labs = va_and_y_labs["Final_demand_names"].tolist()
|
|
101
|
-
q_labs = pd.read_excel(
|
|
102
|
-
io = os.path.join(source, "GLORIA_ReadMe_059a.xlsx"),
|
|
103
|
-
sheet_name = "Satellites")
|
|
104
|
-
q_labs["combined"] = q_labs["Sat_head_indicator"] + " - " + q_labs["Sat_indicator"] + " - " + q_labs["Sat_unit"]
|
|
105
|
-
q_labs = q_labs["combined"].tolist()
|
|
106
|
-
|
|
107
|
-
labels["countries"] = countries
|
|
108
|
-
labels["sectors"] = sectors
|
|
109
|
-
labels["y_labs"] = y_labs
|
|
110
|
-
labels["q_labs"] = q_labs
|
|
111
|
-
labels["va_labs"] = va_labs
|
|
112
|
-
log.info("Loaded Gloria labels")
|
|
113
|
-
|
|
114
|
-
log.info("Loading Gloria tables, this can take a while...")
|
|
115
|
-
for part in parts:
|
|
116
|
-
if part == "T" or part == "Y":
|
|
117
|
-
path = os.path.join(source, f'20240111_120secMother_AllCountries_002_{part}-Results_{year}_059_Markup00{markup}(full).csv')
|
|
118
|
-
elif part == "V":
|
|
119
|
-
path = os.path.join(source, f'20240419_120secMother_AllCountries_002_{part}-Results_{year}_059_Markup001(full).csv')
|
|
120
|
-
elif part == "TQ" or part == "YQ":
|
|
121
|
-
path = os.path.join(source, f'20240417_120secMother_AllCountries_002_{part}-Results_{year}_059_Markup00{markup}(full).csv')
|
|
122
|
-
log.info(f"Loading {part} table...")
|
|
123
|
-
tables[part] = load_and_transform_to_IO_structure(path, part, dt)
|
|
124
|
-
log.info(f"Loaded {part} table")
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
# build an MRIO object from labels and tables
|
|
128
|
-
m = MRIO()
|
|
129
|
-
m.add_dimensions(labels)
|
|
130
|
-
|
|
131
|
-
m.parts["T"] = m.new_part(name="t",
|
|
132
|
-
data= tables["T"],
|
|
133
|
-
dimensions = [["countries","sectors"],["countries", "sectors"]])
|
|
134
|
-
log.info("Added T table")
|
|
135
|
-
|
|
136
|
-
m.parts["Y"] = m.new_part(name="y",
|
|
137
|
-
data= tables["Y"],
|
|
138
|
-
dimensions = [["countries","sectors"],["countries", "y_labs"]])
|
|
139
|
-
log.info("Added Y table")
|
|
140
|
-
|
|
141
|
-
m.parts["VA"] = m.new_part(name="va",
|
|
142
|
-
data= tables["V"],
|
|
143
|
-
dimensions = ["va_labs",["countries","sectors"]])
|
|
144
|
-
log.info("Added VA table")
|
|
145
|
-
|
|
146
|
-
if parts == "all":
|
|
147
|
-
m.parts["Q"] = m.new_part(name="q",
|
|
148
|
-
data= tables["TQ"],
|
|
149
|
-
dimensions = ["q_labs",["countries","sectors"]])
|
|
150
|
-
log.info("Added Q table")
|
|
151
|
-
|
|
152
|
-
m.parts["QY"] = m.new_part(name="qy",
|
|
153
|
-
data= tables["YQ"],
|
|
154
|
-
dimensions = ["q_labs",["countries","y_labs"]])
|
|
155
|
-
log.info("Added QY table")
|
|
156
|
-
|
|
157
|
-
m.name = f"gloria_{year}_markup00{markup}"
|
|
158
|
-
return m
|
|
159
|
-
|
|
160
|
-
def load_and_transform_to_IO_structure(path, part, dt):
|
|
161
|
-
c = 164 # number of countries
|
|
162
|
-
s = 120 # number of sectors
|
|
163
|
-
|
|
164
|
-
table = np.loadtxt(path, dtype=dt, delimiter=',')
|
|
165
|
-
|
|
166
|
-
rows = np.arange(table.shape[0])
|
|
167
|
-
columns = np.arange(table.shape[1])
|
|
168
|
-
|
|
169
|
-
if part == "T":
|
|
170
|
-
selected_rows = (rows // s) % 2 == 1 # Starts with 120 off, then 120 on
|
|
171
|
-
selected_columns = (columns // s) % 2 == 0 # starts with 120 on, then 120 off
|
|
172
|
-
elif part == "Y":
|
|
173
|
-
selected_rows = (rows // s) % 2 == 1
|
|
174
|
-
selected_columns = columns
|
|
175
|
-
elif part == "V":
|
|
176
|
-
selected_rows = rows
|
|
177
|
-
selected_columns = (columns // s) % 2 == 0
|
|
178
|
-
elif part == "TQ":
|
|
179
|
-
selected_rows = rows
|
|
180
|
-
selected_columns = (columns // s) % 2 == 0
|
|
181
|
-
elif part == "YQ":
|
|
182
|
-
selected_rows = rows
|
|
183
|
-
selected_columns = columns
|
|
184
|
-
|
|
185
|
-
table = table[selected_rows][:, selected_columns]
|
|
186
|
-
|
|
187
|
-
if part == "V":
|
|
188
|
-
# Stack the entries to transform the pseudo-diagonalized 984x19680 shape into a 6x19680 shape
|
|
189
|
-
|
|
190
|
-
block_height = 6
|
|
191
|
-
block_width = 120
|
|
192
|
-
blocks = []
|
|
193
|
-
|
|
194
|
-
for i in range (0, int(table.shape[0]/block_height)):
|
|
195
|
-
block = table[i*block_height:(i+1)*block_height,
|
|
196
|
-
i*block_width:(i+1)*block_width]
|
|
197
|
-
blocks.append(block)
|
|
198
|
-
|
|
199
|
-
table = np.hstack(blocks)
|
|
200
|
-
|
|
201
|
-
return table
|
|
202
|
-
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Extracts the data from the .har file and saves it as .npy files.
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
import os
|
|
6
|
-
from mrio_toolbox.extractors.gtap11.extraction.harpy_files.har_file import HarFileObj
|
|
7
|
-
|
|
8
|
-
import xarray as xr
|
|
9
|
-
import logging
|
|
10
|
-
import mrio_toolbox.extractors.gtap11.gtap_mrio.mrio_builder as mrio_builder
|
|
11
|
-
|
|
12
|
-
log = logging.getLogger(__name__)
|
|
13
|
-
|
|
14
|
-
def extract_gtap11(
|
|
15
|
-
year = 2017,
|
|
16
|
-
source = "",
|
|
17
|
-
files = "all",
|
|
18
|
-
name = "gtap",
|
|
19
|
-
build_io = True,
|
|
20
|
-
save_raw = True
|
|
21
|
-
):
|
|
22
|
-
"""
|
|
23
|
-
Extract GTAP data from .har files and save it as .nc file.
|
|
24
|
-
|
|
25
|
-
Parameters
|
|
26
|
-
----------
|
|
27
|
-
source : str, optional
|
|
28
|
-
Location of the source files, by default the current directory
|
|
29
|
-
save_raw : str, optional
|
|
30
|
-
Where to save the raw files, by default the current directory
|
|
31
|
-
files : list, optional
|
|
32
|
-
List of files to extract, by default, all files in the source directory
|
|
33
|
-
name : str, optional
|
|
34
|
-
Name under which the files are saved, by default "gtap"
|
|
35
|
-
build_io : bool, optional
|
|
36
|
-
Whether to build the input-output table, by default False
|
|
37
|
-
|
|
38
|
-
Raises
|
|
39
|
-
------
|
|
40
|
-
NotADirectoryError
|
|
41
|
-
Exception raised when the source directory does not exist
|
|
42
|
-
FileNotFoundError
|
|
43
|
-
Exception raised when the destination directory does not contain any .har files
|
|
44
|
-
If only some files are missing, a warning is issued but the extraction continues
|
|
45
|
-
"""
|
|
46
|
-
#Check source path
|
|
47
|
-
if not os.path.exists(source):
|
|
48
|
-
log.error(f"{os.path.abspath(source)} does not exist.")
|
|
49
|
-
raise NotADirectoryError(f"{os.path.abspath(source)} does not exist.")
|
|
50
|
-
|
|
51
|
-
log.info(f"Extracting GTAP data from {os.path.abspath(source)}")
|
|
52
|
-
|
|
53
|
-
#List available har files
|
|
54
|
-
har_files = [f for f in os.listdir(source) if f.endswith(".har")]
|
|
55
|
-
if len(har_files) == 0:
|
|
56
|
-
log.error(f"No .har files found in {os.path.abspath(source)}")
|
|
57
|
-
raise FileNotFoundError(f"No .har files found in {os.path.abspath(source)}")
|
|
58
|
-
log.info(f"Found {len(har_files)} .har files in {os.path.abspath(source)}")
|
|
59
|
-
|
|
60
|
-
if isinstance(files, str) and files == "all":
|
|
61
|
-
files = har_files
|
|
62
|
-
|
|
63
|
-
ds = xr.Dataset()
|
|
64
|
-
for file in files:
|
|
65
|
-
if file not in har_files:
|
|
66
|
-
log.warning(f"{file} not found in {os.path.abspath(source)}")
|
|
67
|
-
continue
|
|
68
|
-
log.info(f" Extracting {file}")
|
|
69
|
-
filename = os.path.join(source, file)
|
|
70
|
-
data = HarFileObj(filename = filename)
|
|
71
|
-
variables = data.getHeaderArrayNames()
|
|
72
|
-
for variable in variables:
|
|
73
|
-
log.info(f" Extracting {variable}")
|
|
74
|
-
ds = convert_variable(data, variable, ds)
|
|
75
|
-
|
|
76
|
-
if save_raw:
|
|
77
|
-
log.info(f"Saving {name}_raw.nc")
|
|
78
|
-
if save_raw is True:
|
|
79
|
-
#By default, save in the source folder
|
|
80
|
-
save_raw = source
|
|
81
|
-
ds.to_netcdf(os.path.join(save_raw, f"{name}_raw.nc"))
|
|
82
|
-
if build_io:
|
|
83
|
-
log.info("Building input-output table")
|
|
84
|
-
mrio = mrio_builder.build_io(ds)
|
|
85
|
-
mrio.name = f"{name}_{year}"
|
|
86
|
-
return mrio
|
|
87
|
-
|
|
88
|
-
def convert_variable(file, variable, ds):
|
|
89
|
-
"""
|
|
90
|
-
Convert a variable from a .har file to a xarray DataArray.
|
|
91
|
-
|
|
92
|
-
Data descriptor variables are stored as attributes of the dataset.
|
|
93
|
-
|
|
94
|
-
Parameters
|
|
95
|
-
----------
|
|
96
|
-
file : harpy.HarFileObj
|
|
97
|
-
Representation of the .har file
|
|
98
|
-
variable : str
|
|
99
|
-
Name of the variable to extract
|
|
100
|
-
ds : xarray.Dataset
|
|
101
|
-
Dataset to which the variable is added
|
|
102
|
-
|
|
103
|
-
Returns
|
|
104
|
-
-------
|
|
105
|
-
ds : xarray.Dataset
|
|
106
|
-
Updated dataset
|
|
107
|
-
"""
|
|
108
|
-
data = file[variable]
|
|
109
|
-
coords = dict()
|
|
110
|
-
dims = []
|
|
111
|
-
for dim in data.sets.dims:
|
|
112
|
-
if dim.name is None:
|
|
113
|
-
#Intercepts descriptive variables
|
|
114
|
-
log.info(f" {variable} is a descriptive variable")
|
|
115
|
-
ds.attrs[variable] = str(data.array)
|
|
116
|
-
return ds
|
|
117
|
-
dims.append(dim.name)
|
|
118
|
-
coords[dim.name] = dim.dim_desc
|
|
119
|
-
ds[variable] = xr.DataArray(
|
|
120
|
-
data.array,
|
|
121
|
-
coords = coords,
|
|
122
|
-
dims = dims,
|
|
123
|
-
attrs = {
|
|
124
|
-
"long_name": data.long_name,
|
|
125
|
-
"name" : variable
|
|
126
|
-
}
|
|
127
|
-
)
|
|
128
|
-
return ds
|
|
129
|
-
|
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Created on Jun 29 14:46:48 2018
|
|
3
|
-
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
import numpy as np
|
|
7
|
-
from typing import List, Union
|
|
8
|
-
|
|
9
|
-
class _HeaderSet:
|
|
10
|
-
"""
|
|
11
|
-
This class is used to represent sets associated with header arrays.
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
# Status is unknown elements but set, element index, known set elements, no set just numeric
|
|
15
|
-
_valid_status = ["u", "e", "k", "n"]
|
|
16
|
-
_genSetID = 0
|
|
17
|
-
|
|
18
|
-
def __init__(self, name: 'Union[str,None]',
|
|
19
|
-
status: str,
|
|
20
|
-
dim_desc: 'Union[List[str],str,None]',
|
|
21
|
-
dim_size: int):
|
|
22
|
-
|
|
23
|
-
self.name = name
|
|
24
|
-
self.status = status
|
|
25
|
-
self.dim_desc = dim_desc
|
|
26
|
-
if not dim_desc is None:
|
|
27
|
-
if any([len(el) > 12 for el in dim_desc]):
|
|
28
|
-
raise ValueError("Set Element too long (maximum 12 Characters for set Elements)")
|
|
29
|
-
self.elemPosDict={} if self.dim_desc is None else dict(zip( [elem.strip().lower() for elem in dim_desc], range(0,len(self.dim_desc))))
|
|
30
|
-
self.dim_size = dim_size
|
|
31
|
-
|
|
32
|
-
def transform_index(self,index):
|
|
33
|
-
if isinstance(index,(str,int)):
|
|
34
|
-
return self.name_to_ind(index), None
|
|
35
|
-
|
|
36
|
-
elif isinstance(index,slice):
|
|
37
|
-
newslice=self.convertSlice(index)
|
|
38
|
-
npIndList=list(range(self.dim_size))[newslice]
|
|
39
|
-
SetName=self._newname() if not all(p is None for p in [newslice.start,newslice.stop,newslice.step]) else self.name
|
|
40
|
-
if self.dim_desc:
|
|
41
|
-
return npIndList, _HeaderSet(SetName, self.status, self.dim_desc[newslice], len(npIndList))
|
|
42
|
-
else:
|
|
43
|
-
return npIndList, _HeaderSet(SetName, self.status, dim_desc=None, dim_size=len(npIndList))
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
elif isinstance(index,list):
|
|
47
|
-
useElem=self.status in ["e","k"]
|
|
48
|
-
setElList=[] if useElem else None
|
|
49
|
-
npIndList=[]
|
|
50
|
-
for ind in index:
|
|
51
|
-
if isinstance(ind, (str,int) ):
|
|
52
|
-
idx=self.name_to_ind(ind)
|
|
53
|
-
npIndList.append(idx)
|
|
54
|
-
if useElem: setElList.append(self.dim_desc[idx])
|
|
55
|
-
elif isinstance(ind,slice):
|
|
56
|
-
newslice = self.convertSlice(ind)
|
|
57
|
-
npIndList.append(list(range(self.dim_size))[newslice])
|
|
58
|
-
if useElem: setElList.extend(self.dim_desc[newslice])
|
|
59
|
-
else:
|
|
60
|
-
raise TypeError("Only slice, str, int allowed in list indexing")
|
|
61
|
-
if useElem:
|
|
62
|
-
if len(set(setElList)) != len(setElList):
|
|
63
|
-
raise ValueError("Indexing leads to duplicate set elements which is not permitted")
|
|
64
|
-
if setElList != self.dim_desc:
|
|
65
|
-
return npIndList, _HeaderSet(self._newname(), self.status, setElList, len(npIndList))
|
|
66
|
-
else:
|
|
67
|
-
return npIndList, self
|
|
68
|
-
else:
|
|
69
|
-
return npIndList, _HeaderSet(self._newname(), self.status, None, len(npIndList))
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
def convertSlice(self,index):
|
|
73
|
-
if not isinstance(index.step, int) and not index.step is None:
|
|
74
|
-
raise ValueError("step in slice has to be integer")
|
|
75
|
-
start=self.name_to_ind(index.start)
|
|
76
|
-
start= None if start==0 else start
|
|
77
|
-
stop = self.name_to_ind(index.stop)
|
|
78
|
-
stop = None if stop==self.dim_size else stop
|
|
79
|
-
step= None if index.step == 1 else index.step
|
|
80
|
-
return slice(start, stop, step)
|
|
81
|
-
|
|
82
|
-
def name_to_ind(self,idx):
|
|
83
|
-
if idx is None:
|
|
84
|
-
return None
|
|
85
|
-
elif isinstance(idx,str):
|
|
86
|
-
if idx.strip().lower() in self.elemPosDict:
|
|
87
|
-
return self.elemPosDict[idx.strip().lower()]
|
|
88
|
-
else:
|
|
89
|
-
raise ValueError("Element not in set")
|
|
90
|
-
elif isinstance(idx,int):
|
|
91
|
-
if idx >= self.dim_size:
|
|
92
|
-
raise ValueError("Index Out Of bounds")
|
|
93
|
-
return idx
|
|
94
|
-
|
|
95
|
-
def _newname(self):
|
|
96
|
-
_HeaderSet._genSetID+=1
|
|
97
|
-
return "S@"+str(_HeaderSet._genSetID)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
class _HeaderDims:
|
|
101
|
-
|
|
102
|
-
def __init__(self, setList):
|
|
103
|
-
self._dims=setList
|
|
104
|
-
|
|
105
|
-
@staticmethod
|
|
106
|
-
def fromShape(shape):
|
|
107
|
-
setList=[_HeaderSet(None, 'n', None, dim) for dim in shape]
|
|
108
|
-
return _HeaderDims(setList)
|
|
109
|
-
|
|
110
|
-
@staticmethod
|
|
111
|
-
def fromSetShape(sets, setElDict, shape):
|
|
112
|
-
setObjList=[]
|
|
113
|
-
lowerDict=dict(zip([key.strip().lower() for key in setElDict.keys()], setElDict.keys() ))
|
|
114
|
-
for idim, setName in enumerate(sets):
|
|
115
|
-
lowSet=setName.strip().lower()
|
|
116
|
-
if lowSet in lowerDict:
|
|
117
|
-
setObjList.append(_HeaderSet(setName,'k',setElDict[lowerDict[lowSet]],shape[idim]))
|
|
118
|
-
else:
|
|
119
|
-
setObjList.append(_HeaderSet(setName, 'u', None, shape[idim]))
|
|
120
|
-
return _HeaderDims(setObjList)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
@property
|
|
124
|
-
def dims(self) -> List[_HeaderSet]:
|
|
125
|
-
return self._dims
|
|
126
|
-
|
|
127
|
-
@dims.setter
|
|
128
|
-
def dims(self, obj) -> None:
|
|
129
|
-
self._dims = obj
|
|
130
|
-
|
|
131
|
-
def ndim(self):
|
|
132
|
-
"""
|
|
133
|
-
Number of dimensions
|
|
134
|
-
"""
|
|
135
|
-
return len(self._dims)
|
|
136
|
-
|
|
137
|
-
def defined(self):
|
|
138
|
-
"""
|
|
139
|
-
Tells whether dimensensions have sets defined or are just array like
|
|
140
|
-
"""
|
|
141
|
-
return not all([dim.name is None for dim in self._dims])
|
|
142
|
-
|
|
143
|
-
@property
|
|
144
|
-
def setNames(self):
|
|
145
|
-
return [dim.name for dim in self.dims]
|
|
146
|
-
|
|
147
|
-
@setNames.setter
|
|
148
|
-
def setNames(self, sNames):
|
|
149
|
-
if not isinstance(sNames,list): raise TypeError("set Names needs to be given as a list of strings")
|
|
150
|
-
if len(sNames) != len(self.dims) : raise ValueError("wrong length of set List. Header is rank "+str(len(self.dims))+ "but received list size "+ len(sNames))
|
|
151
|
-
for name in sNames:
|
|
152
|
-
if not isinstance(name,str): raise TypeError("set Names contains a non string object: "+str(name))
|
|
153
|
-
if len(name.strip()) > 12 : raise ValueError("Set names are limited to 12 characters. received '"+name+"'")
|
|
154
|
-
for newName, dim in zip(sNames,self.dims):
|
|
155
|
-
dim.name=newName.strip()
|
|
156
|
-
|
|
157
|
-
@property
|
|
158
|
-
def setElements(self):
|
|
159
|
-
return [dim.dim_desc for dim in self.dims]
|
|
160
|
-
|
|
161
|
-
@property
|
|
162
|
-
def shape(self):
|
|
163
|
-
return tuple([sets.dim_size for sets in self._dims])
|
|
164
|
-
|
|
165
|
-
def __str__(self):
|
|
166
|
-
outputstr=""
|
|
167
|
-
for setDim in self._dims:
|
|
168
|
-
if setDim.status in "keu":
|
|
169
|
-
outputstr+=" " + setDim.name.ljust(12) + ": \n"
|
|
170
|
-
else:
|
|
171
|
-
outputstr+=" "+"Not Specified"
|
|
172
|
-
if setDim.status in "ke":
|
|
173
|
-
outputstr+=" " +", ".join(setDim.dim_desc) + "\n"
|
|
174
|
-
return outputstr
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
def compatible_shape(self,other):
|
|
179
|
-
return self.shape == other
|
|
180
|
-
|
|
181
|
-
def matchSets(self,sets=None, shape:tuple=None):
|
|
182
|
-
if sets is None and shape is None : raise KeyError("Only one argument allowed")
|
|
183
|
-
newSets = []
|
|
184
|
-
if not sets is None:
|
|
185
|
-
# Try to match the shape of the dimensions
|
|
186
|
-
iset=len(self.dims)-1; jset=len(sets.dims)-1
|
|
187
|
-
while iset >=0 and jset >=0:
|
|
188
|
-
if jset < 0 :
|
|
189
|
-
newSets.append(self.dims[iset])
|
|
190
|
-
iset -=1
|
|
191
|
-
elif iset < 0 :
|
|
192
|
-
newSets.append(sets.dims[jset])
|
|
193
|
-
jset -=1
|
|
194
|
-
if self.dims[iset].dim_size == sets.dims[jset].dim_size or self.dims[iset].dim_size == 1 or sets.dims[jset].dim_size == 1:
|
|
195
|
-
if self.dims[iset].status != 'n':
|
|
196
|
-
newSets.append(self.dims[iset])
|
|
197
|
-
else:
|
|
198
|
-
newSets.append(sets.dims[jset])
|
|
199
|
-
iset-= 1 ; jset -=1
|
|
200
|
-
newSets.reverse()
|
|
201
|
-
elif not shape is None:
|
|
202
|
-
iset = len(self.dims) - 1; jset=len(shape)-1
|
|
203
|
-
while iset >=0 and jset >=0:
|
|
204
|
-
if jset < 0 :
|
|
205
|
-
newSets.append(self.dims[iset])
|
|
206
|
-
iset -=1
|
|
207
|
-
elif iset < 0 :
|
|
208
|
-
newSets.append(_HeaderSet(None , 'n' , None, shape[jset]))
|
|
209
|
-
jset -=1
|
|
210
|
-
if self.dims[iset].dim_size == shape[jset] or self.dims[iset].dim_size == 1 or shape[jset] == 1:
|
|
211
|
-
newSets.append(self.dims[iset])
|
|
212
|
-
iset-= 1 ; jset -=1
|
|
213
|
-
newSets.reverse()
|
|
214
|
-
else:
|
|
215
|
-
return KeyError("Either sets o shape have to be defined")
|
|
216
|
-
|
|
217
|
-
return _HeaderDims(newSets)
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
def transform_index(self,index_tuple):
|
|
221
|
-
if not isinstance(index_tuple,tuple):
|
|
222
|
-
index_tuple=(index_tuple,)
|
|
223
|
-
|
|
224
|
-
trueLen=len([x for x in index_tuple if x is not None])
|
|
225
|
-
if trueLen != self.ndim() and not Ellipsis in index_tuple:
|
|
226
|
-
raise ValueError("Rank mismatch in indexing")
|
|
227
|
-
if index_tuple.count(Ellipsis)>1:
|
|
228
|
-
raise ValueError("Only single Ellipsis (...) allowed in indexing")
|
|
229
|
-
|
|
230
|
-
thisIndex=[]
|
|
231
|
-
for ind in index_tuple:
|
|
232
|
-
if ind == Ellipsis:
|
|
233
|
-
for i in range(0,self.ndim()-trueLen+1):
|
|
234
|
-
thisIndex.append(slice(None,None,None))
|
|
235
|
-
elif isinstance(ind,(list,str,int,slice)) or ind is None:
|
|
236
|
-
thisIndex.append(ind)
|
|
237
|
-
else:
|
|
238
|
-
raise TypeError("Only ...,list,str,int,slice and None allowed as indices")
|
|
239
|
-
|
|
240
|
-
npIndex=[]
|
|
241
|
-
newSets=[]
|
|
242
|
-
|
|
243
|
-
iset=0
|
|
244
|
-
for index in thisIndex:
|
|
245
|
-
if index is None:
|
|
246
|
-
npInd=np.newaxis
|
|
247
|
-
newSet=_HeaderSet(None , 'n' , None, 1)
|
|
248
|
-
else:
|
|
249
|
-
setDim=self._dims[iset]
|
|
250
|
-
npInd, newSet = setDim.transform_index(index)
|
|
251
|
-
iset+=1
|
|
252
|
-
npIndex.append(npInd)
|
|
253
|
-
newSets.append(newSet)
|
|
254
|
-
|
|
255
|
-
rankIndex=tuple([slice(None) if isinstance(ind,list) or ind is None else 0 for ind in npIndex])
|
|
256
|
-
newSets = [setDim for ri, setDim in zip(rankIndex,newSets) if ri != 0]
|
|
257
|
-
return self._makeNPIndex(npIndex), rankIndex, _HeaderDims(newSets)
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
@staticmethod
|
|
261
|
-
def _makeNPIndex(indexList):
|
|
262
|
-
newinds = []
|
|
263
|
-
for i, item in enumerate(indexList):
|
|
264
|
-
if isinstance(item, list):
|
|
265
|
-
newinds.append(item)
|
|
266
|
-
elif isinstance(item,int):
|
|
267
|
-
newinds.append([item])
|
|
268
|
-
|
|
269
|
-
numpyInd = list(np.ix_(*newinds))
|
|
270
|
-
newinds=[]
|
|
271
|
-
for item in indexList:
|
|
272
|
-
if not item is None:
|
|
273
|
-
newinds.append(numpyInd.pop(0))
|
|
274
|
-
else:
|
|
275
|
-
newinds.append(None)
|
|
276
|
-
|
|
277
|
-
return tuple(newinds)
|
|
278
|
-
|
|
279
|
-
|