qmenta-client 1.1.dev1507__py3-none-any.whl → 2.1__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.
- qmenta/client/Account.py +43 -11
- qmenta/client/File.py +44 -12
- qmenta/client/Project.py +908 -441
- qmenta/client/Subject.py +10 -3
- qmenta/client/utils.py +6 -2
- {qmenta_client-1.1.dev1507.dist-info → qmenta_client-2.1.dist-info}/METADATA +3 -2
- qmenta_client-2.1.dist-info/RECORD +10 -0
- {qmenta_client-1.1.dev1507.dist-info → qmenta_client-2.1.dist-info}/WHEEL +1 -1
- qmenta_client-1.1.dev1507.dist-info/RECORD +0 -10
qmenta/client/Account.py
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
from __future__ import print_function
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
-
from urllib3.exceptions import HTTPError
|
|
5
|
-
|
|
6
|
-
from qmenta.core import platform
|
|
7
4
|
from qmenta.core import errors
|
|
5
|
+
from qmenta.core import platform
|
|
6
|
+
from urllib3.exceptions import HTTPError
|
|
8
7
|
|
|
9
8
|
from .Project import Project
|
|
10
9
|
from .utils import load_json
|
|
@@ -35,7 +34,13 @@ class Account:
|
|
|
35
34
|
The Auth object used for communication with the platform
|
|
36
35
|
"""
|
|
37
36
|
|
|
38
|
-
def __init__(
|
|
37
|
+
def __init__(
|
|
38
|
+
self,
|
|
39
|
+
username,
|
|
40
|
+
password,
|
|
41
|
+
base_url="https://platform.qmenta.com",
|
|
42
|
+
verify_certificates=True,
|
|
43
|
+
):
|
|
39
44
|
|
|
40
45
|
self._cookie = None
|
|
41
46
|
self.username = username
|
|
@@ -62,7 +67,12 @@ class Account:
|
|
|
62
67
|
"""
|
|
63
68
|
logger = logging.getLogger(logger_name)
|
|
64
69
|
try:
|
|
65
|
-
auth = platform.Auth.login(
|
|
70
|
+
auth = platform.Auth.login(
|
|
71
|
+
self.username,
|
|
72
|
+
self.password,
|
|
73
|
+
base_url=self.baseurl,
|
|
74
|
+
ask_for_2fa_input=True,
|
|
75
|
+
)
|
|
66
76
|
except errors.PlatformError as e:
|
|
67
77
|
logger.error("Failed to log in: {}".format(e))
|
|
68
78
|
self.auth = None
|
|
@@ -109,10 +119,16 @@ class Account:
|
|
|
109
119
|
return Project(self, int(project_id))
|
|
110
120
|
elif type(project_id) is str:
|
|
111
121
|
projects = self.projects
|
|
112
|
-
projects_match = [
|
|
122
|
+
projects_match = [
|
|
123
|
+
proj for proj in projects if proj["name"] == project_id
|
|
124
|
+
]
|
|
113
125
|
if not projects_match:
|
|
114
|
-
raise Exception(
|
|
126
|
+
raise Exception(
|
|
127
|
+
f"Project {project_id} does not exist or is not available "
|
|
128
|
+
f"for this user."
|
|
129
|
+
)
|
|
115
130
|
return Project(self, int(projects_match[0]["id"]))
|
|
131
|
+
return None
|
|
116
132
|
|
|
117
133
|
@property
|
|
118
134
|
def projects(self):
|
|
@@ -127,7 +143,11 @@ class Account:
|
|
|
127
143
|
logger = logging.getLogger(logger_name)
|
|
128
144
|
|
|
129
145
|
try:
|
|
130
|
-
data = platform.parse_response(
|
|
146
|
+
data = platform.parse_response(
|
|
147
|
+
platform.post(
|
|
148
|
+
self.auth, "projectset_manager/get_projectset_list"
|
|
149
|
+
)
|
|
150
|
+
)
|
|
131
151
|
except errors.PlatformError as e:
|
|
132
152
|
logger.error("Failed to get project list: {}".format(e))
|
|
133
153
|
raise
|
|
@@ -137,7 +157,15 @@ class Account:
|
|
|
137
157
|
titles.append({"name": project["name"], "id": project["_id"]})
|
|
138
158
|
return titles
|
|
139
159
|
|
|
140
|
-
def add_project(
|
|
160
|
+
def add_project(
|
|
161
|
+
self,
|
|
162
|
+
project_abbreviation,
|
|
163
|
+
project_name,
|
|
164
|
+
description="",
|
|
165
|
+
users=None,
|
|
166
|
+
from_date="",
|
|
167
|
+
to_date="",
|
|
168
|
+
):
|
|
141
169
|
"""
|
|
142
170
|
Add a new project to the user account.
|
|
143
171
|
|
|
@@ -256,7 +284,9 @@ class Account:
|
|
|
256
284
|
preload_content=not stream,
|
|
257
285
|
)
|
|
258
286
|
if response.status >= 400:
|
|
259
|
-
raise HTTPError(
|
|
287
|
+
raise HTTPError(
|
|
288
|
+
"STATUS {}: {}".format(response.status, response.reason)
|
|
289
|
+
)
|
|
260
290
|
except Exception as e:
|
|
261
291
|
error = "Could not send request. ERROR: {0}".format(e)
|
|
262
292
|
logger.error(error)
|
|
@@ -278,7 +308,9 @@ class Account:
|
|
|
278
308
|
try:
|
|
279
309
|
parsed_content = load_json(response.data)
|
|
280
310
|
except Exception:
|
|
281
|
-
error = "Could not parse the response as JSON data: {}".format(
|
|
311
|
+
error = "Could not parse the response as JSON data: {}".format(
|
|
312
|
+
response.data
|
|
313
|
+
)
|
|
282
314
|
logger.error(error)
|
|
283
315
|
raise
|
|
284
316
|
|
qmenta/client/File.py
CHANGED
|
@@ -32,12 +32,21 @@ class File:
|
|
|
32
32
|
`ff_container = File(project, "MRB", "1", "gre_field_mapping_3.zip")`
|
|
33
33
|
"""
|
|
34
34
|
|
|
35
|
-
def __init__(
|
|
35
|
+
def __init__(
|
|
36
|
+
self,
|
|
37
|
+
project: qmenta.client.Project,
|
|
38
|
+
subject_name: str,
|
|
39
|
+
ssid: str,
|
|
40
|
+
file_name: str,
|
|
41
|
+
):
|
|
36
42
|
self.file_name = file_name
|
|
37
43
|
self.project = project
|
|
38
44
|
self._container_id = None
|
|
39
45
|
for cont in self.project.list_input_containers():
|
|
40
|
-
if
|
|
46
|
+
if (
|
|
47
|
+
cont["patient_secret_name"] == subject_name
|
|
48
|
+
and cont["ssid"] == ssid
|
|
49
|
+
):
|
|
41
50
|
self._container_id = cont["container_id"]
|
|
42
51
|
break
|
|
43
52
|
if self.file_name.endswith(".zip"):
|
|
@@ -50,7 +59,9 @@ class File:
|
|
|
50
59
|
def __str__(self):
|
|
51
60
|
return self.file_name
|
|
52
61
|
|
|
53
|
-
def pull_scan_sequence_info(
|
|
62
|
+
def pull_scan_sequence_info(
|
|
63
|
+
self, specify_dicom_tags=None, output_format: str = "csv"
|
|
64
|
+
):
|
|
54
65
|
"""
|
|
55
66
|
Pulling scan sequence information (e.g. series number, series type,
|
|
56
67
|
series description, number of files, file formats available)
|
|
@@ -74,11 +85,18 @@ class File:
|
|
|
74
85
|
if specify_dicom_tags is None:
|
|
75
86
|
specify_dicom_tags = list()
|
|
76
87
|
valid_output_formats = ["csv", "tsv", "json", "dict"]
|
|
77
|
-
assert
|
|
88
|
+
assert (
|
|
89
|
+
output_format in valid_output_formats
|
|
90
|
+
), f"Output format not valid. Choose one of {valid_output_formats}"
|
|
78
91
|
|
|
79
92
|
with TemporaryDirectory() as temp_dir:
|
|
80
93
|
local_file_name = mkstemp(dir=temp_dir) + ".zip"
|
|
81
|
-
self.project.download_file(
|
|
94
|
+
self.project.download_file(
|
|
95
|
+
self._container_id,
|
|
96
|
+
self.file_name,
|
|
97
|
+
local_file_name,
|
|
98
|
+
overwrite=False,
|
|
99
|
+
)
|
|
82
100
|
if self._file_type == "DICOM":
|
|
83
101
|
unzip_dicoms(local_file_name, temp_dir, exclude_members=None)
|
|
84
102
|
dicoms = glob.glob(os.path.join(temp_dir, "*"))
|
|
@@ -92,11 +110,21 @@ class File:
|
|
|
92
110
|
# only needed for one file, all have the same data.
|
|
93
111
|
for attribute in specify_dicom_tags:
|
|
94
112
|
# error handling of attributes send by the user
|
|
95
|
-
assert
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
113
|
+
assert (
|
|
114
|
+
len(attribute) == 2
|
|
115
|
+
), "Invalid length of DICOM Attribute"
|
|
116
|
+
assert isinstance(
|
|
117
|
+
attribute[0], int
|
|
118
|
+
), "Invalid type of DICOM Attribute"
|
|
119
|
+
output_data["dicom tag"].append(
|
|
120
|
+
open_file[attribute].tag
|
|
121
|
+
)
|
|
122
|
+
output_data["attribute"].append(
|
|
123
|
+
open_file[attribute].name
|
|
124
|
+
)
|
|
125
|
+
output_data["value"].append(
|
|
126
|
+
open_file[attribute].value
|
|
127
|
+
)
|
|
100
128
|
except Exception as e:
|
|
101
129
|
print(str(e))
|
|
102
130
|
pass
|
|
@@ -106,10 +134,14 @@ class File:
|
|
|
106
134
|
output_data["value"].append(number_files)
|
|
107
135
|
|
|
108
136
|
if output_format == "csv":
|
|
109
|
-
pd.DataFrame(output_data).to_csv(
|
|
137
|
+
pd.DataFrame(output_data).to_csv(
|
|
138
|
+
f"scan_sequence_info.{output_format}", index=False
|
|
139
|
+
)
|
|
110
140
|
|
|
111
141
|
elif output_format == "tsv":
|
|
112
|
-
pd.DataFrame(output_data).to_csv(
|
|
142
|
+
pd.DataFrame(output_data).to_csv(
|
|
143
|
+
f"scan_sequence_info.{output_format}", sep="\t", index=False
|
|
144
|
+
)
|
|
113
145
|
|
|
114
146
|
elif output_format == "json":
|
|
115
147
|
with open(f"scan_sequence_info.{output_format}", "w") as fp:
|