qmenta-client 1.1.dev1373__py3-none-any.whl → 1.1.dev1382__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/Project.py CHANGED
@@ -20,186 +20,6 @@ logger_name = "qmenta.client"
20
20
  OPERATOR_LIST = ["eq", "ne", "gt", "gte", "lt", "lte"]
21
21
 
22
22
 
23
- def show_progress(done, total, finish=False):
24
- bytes_in_mb = 1024 * 1024
25
- progress_message = "\r[{:.2f} %] Uploaded {:.2f} of {:.2f} Mb".format(
26
- done / float(total) * 100, done / bytes_in_mb, total / bytes_in_mb
27
- )
28
- sys.stdout.write(progress_message)
29
- sys.stdout.flush()
30
- if not finish:
31
- pass
32
- # sys.stdout.write("")
33
- # sys.stdout.flush()
34
- else:
35
- sys.stdout.write("\n")
36
-
37
-
38
- def get_session_id(file_path):
39
- m = hashlib.md5()
40
- m.update(file_path.encode("utf-8"))
41
- return str(time.time()).replace(".", "") + "_" + m.hexdigest()
42
-
43
-
44
- def check_upload_file(file_path):
45
- """
46
- Check whether a file has the correct extension to upload.
47
-
48
- Parameters
49
- ----------
50
- file_path : str
51
- Path to the file
52
-
53
- Returns
54
- -------
55
- bool
56
- True if correct extension, False otherwise.
57
- """
58
-
59
- # TODO: Add a file zipper here so zips files in a folder
60
-
61
- file_parts = file_path.split(".")
62
- extension = file_parts[-1]
63
-
64
- if extension != "zip":
65
- logging.getLogger(logger_name).error("You must upload a zip.")
66
- return False
67
- else:
68
- return True
69
-
70
-
71
- def operation(reference_value, operator, input_value):
72
- """
73
- The method performs an operation by comparing the two input values.
74
- The Operation is applied to the Input Value in comparison to the Reference
75
- Value.
76
-
77
- Parameters
78
- ----------
79
- reference_value : str, list, or int
80
- Reference value.
81
- operator : str
82
- Operation.
83
- input_value : str, list, or int
84
- Input value.
85
-
86
- Returns
87
- -------
88
- bool
89
- True if the operation is satisfied, False otherwise.
90
- """
91
- if input_value is None or input_value == "":
92
- return False
93
-
94
- if operator == "in":
95
- return reference_value in input_value
96
-
97
- elif operator == "in-list":
98
- return all([el in input_value for el in reference_value])
99
-
100
- elif operator == "eq":
101
- return input_value == reference_value
102
-
103
- elif operator == "gt":
104
- return input_value > reference_value
105
-
106
- elif operator == "gte":
107
- return input_value >= reference_value
108
-
109
- elif operator == "lt":
110
- return input_value < reference_value
111
-
112
- elif operator == "lte":
113
- return input_value <= reference_value
114
- else:
115
- return False
116
-
117
-
118
- def wrap_search_criteria(search_criteria={}):
119
- """
120
- Wraps the conditions specified within the Search Criteria in order for
121
- other methods to handle it easily. The conditions are grouped only into
122
- three groups: Modality, Tags and the File Metadata (if DICOM it corresponds
123
- to the DICOM information), and each of them is output in a different
124
- variable.
125
-
126
- Parameters
127
- ----------
128
- search_criteria : dict
129
- Each element is a string and is built using the formatting
130
- "KEYTYPE;VALUE", or "KEYTYPE;OPERATOR|VALUE".
131
-
132
- Full list of keys avaiable for the dictionary:
133
-
134
- search_criteria = {
135
- "pars_patient_secret_name": "string;SUBJECTID",
136
- "pars_ssid": "integer;OPERATOR|SSID",
137
- "pars_modalities": "string;MODALITY",
138
- "pars_tags": "tags;TAGS",
139
- "pars_age_at_scan": "integer;OPERATOR|AGE_AT_SCAN",
140
- "pars_[dicom]_KEY": "KEYTYPE;KEYVALUE",
141
- "pars_PROJECTMETADATA": "METADATATYPE;METADATAVALUE",
142
- }
143
-
144
- See documentation for a complete definition.
145
-
146
- Returns
147
- -------
148
- modality : str
149
- String containing the modality of the search criteria extracted from
150
- 'pars_modalities'
151
-
152
- tags : list of str
153
- List of strings containing the tags of the search criteria extracted
154
- 'from pars_tags'
155
-
156
- file_metadata : Dict
157
- Dictionary containing the file metadata of the search criteria
158
- extracted from 'pars_[dicom]_KEY'
159
- """
160
-
161
- # The keys not included bellow apply to the whole session.
162
- modality, tags, file_metadata = "", list(), dict()
163
- for key, value in search_criteria.items():
164
- if key == "pars_modalities":
165
- modalities = value.split(";")[1].split(",")
166
- if len(modalities) != 1:
167
- raise ValueError(f"A file can only have one modality. "
168
- f"Provided Modalities: "
169
- f"{', '.join(modalities)}.")
170
- modality = modalities[0]
171
- elif key == "pars_tags":
172
- tags = value.split(";")[1].split(",")
173
- elif "pars_[dicom]_" in key:
174
- d_tag = key.split("pars_[dicom]_")[1]
175
- d_type = value.split(";")[0]
176
- if d_type == "string":
177
- file_metadata[d_tag] = {
178
- "operation": "in",
179
- "value": value.replace(d_type + ";", "")
180
- }
181
- elif d_type == "integer":
182
- d_operator = value.split(";")[1].split("|")[0]
183
- d_value = value.split(";")[1].split("|")[1]
184
- file_metadata[d_tag] = {
185
- "operation": d_operator,
186
- "value": int(d_value)}
187
- elif d_type == "decimal":
188
- d_operator = value.split(";")[1].split("|")[0]
189
- d_value = value.split(";")[1].split("|")[1]
190
- file_metadata[d_tag] = {
191
- "operation": d_operator,
192
- "value": float(d_value)
193
- }
194
- elif d_type == "list":
195
- value.replace(d_type + ";", "")
196
- file_metadata[d_tag] = {
197
- "operation": "in-list",
198
- "value": value.replace(d_type + ";", "").split(";")
199
- }
200
- return modality, tags, file_metadata
201
-
202
-
203
23
  def convert_qc_value_to_qcstatus(value):
204
24
  """
205
25
  Convert input string to QCStatus class.
@@ -577,7 +397,7 @@ class Project:
577
397
  content = self.get_subjects_metadata(search_criteria, items=(0, 9999))
578
398
 
579
399
  # Wrap search criteria.
580
- modality, tags, dicoms = wrap_search_criteria(search_criteria)
400
+ modality, tags, dicoms = self.__wrap_search_criteria(search_criteria)
581
401
 
582
402
  # Iterate over the files of each subject selected to include/exclude
583
403
  # them from the results.
@@ -602,7 +422,7 @@ class Project:
602
422
  d_operator = dict_value["operation"]
603
423
  d_value = dict_value["value"]
604
424
  result_values.append(
605
- operation(d_value, d_operator, f_value)
425
+ self.__operation(d_value, d_operator, f_value)
606
426
  )
607
427
 
608
428
  if not all(result_values):
@@ -731,17 +551,17 @@ class Project:
731
551
  Parameters
732
552
  ----------
733
553
  search_condition : dict
734
- - p_n: str Analysis name
735
- - type: str Type
736
- - from_d: str dd.mm.yyyy Date from
737
- - to_d: str dd.mm.yyyy Date to
738
- - qa_status: str pass/fail/nd QC status
739
- - secret_name: str Subject ID
740
- - tags: str
741
- - with_child_analysis: 1 if 1, child analysis of workflows will appear
742
- - id: str ID
743
- - state: running, completed, pending, exception
744
- - username: str
554
+ - p_n: str or None Analysis name
555
+ - type: str or None Type
556
+ - from_d: str or None dd.mm.yyyy Date from
557
+ - to_d: str or None dd.mm.yyyy Date to
558
+ - qa_status: str or None pass/fail/nd QC status
559
+ - secret_name: str or None Subject ID
560
+ - tags: str or None
561
+ - with_child_analysis: 1 or None if 1, child analysis of workflows will appear
562
+ - id: str or None ID
563
+ - state: running, completed, pending, exception or None
564
+ - username: str or None
745
565
 
746
566
  items : List[int]
747
567
  list containing two elements [min, max] that correspond to the
@@ -770,7 +590,7 @@ class Project:
770
590
  for key in search_condition.keys():
771
591
  if key not in search_keys.keys():
772
592
  raise Exception((f"This key '{key}' is not accepted by this" "search condition"))
773
- if not isinstance(search_condition[key], search_keys[key]):
593
+ if not isinstance(search_condition[key], search_keys[key]) and search_condition[key] is not None:
774
594
  raise Exception((f"The key {key} in the search condition" f"is not type {search_keys[key]}"))
775
595
  req_headers = {"X-Range": f"items={items[0]}-{items[1] - 1}"}
776
596
  return platform.parse_response(
@@ -881,17 +701,17 @@ class Project:
881
701
  Parameters
882
702
  ----------
883
703
  search_condition : dict
884
- - p_n: str Analysis name
885
- - type: str Type
886
- - from_d: str dd.mm.yyyy Date from
887
- - to_d: str dd.mm.yyyy Date to
888
- - qa_status: str pass/fail/nd QC status
889
- - secret_name: str Subject ID
890
- - tags: str
891
- - with_child_analysis: 1 if 1, child analysis of workflows will appear
892
- - id: str ID
893
- - state: running, completed, pending, exception
894
- - username: str
704
+ - p_n: str or None Analysis name
705
+ - type: str or None Type
706
+ - from_d: str or None dd.mm.yyyy Date from
707
+ - to_d: str or None dd.mm.yyyy Date to
708
+ - qa_status: str or None pass/fail/nd QC status
709
+ - secret_name: str or None Subject ID
710
+ - tags: str or None
711
+ - with_child_analysis: 1 or None if 1, child analysis of workflows will appear
712
+ - id: str or None ID
713
+ - state: running, completed, pending, exception or None
714
+ - username: str or None
895
715
  items : List[int]
896
716
  list containing two elements [min, max] that correspond to the
897
717
  mininum and maximum range of analysis listed
@@ -1533,7 +1353,7 @@ class Project:
1533
1353
  logger.error("Cannot upload empty file {}".format(file_path))
1534
1354
  return False
1535
1355
  uploaded = 0
1536
- session_id = get_session_id(file_path)
1356
+ session_id = self.__get_session_id(file_path)
1537
1357
  chunk_num = 0
1538
1358
  retries_count = 0
1539
1359
  uploaded_bytes = 0
@@ -1592,7 +1412,7 @@ class Project:
1592
1412
  retries_count = 0
1593
1413
  uploaded_bytes += chunk_size
1594
1414
  elif int(response.status_code) == 200:
1595
- show_progress(file_size, file_size, finish=True)
1415
+ self.__show_progress(file_size, file_size, finish=True)
1596
1416
  break
1597
1417
  elif int(response.status_code) == 416:
1598
1418
  retries_count += 1
@@ -1610,7 +1430,7 @@ class Project:
1610
1430
  break
1611
1431
 
1612
1432
  uploaded += chunk_size
1613
- show_progress(uploaded, file_size)
1433
+ self.__show_progress(uploaded, file_size)
1614
1434
 
1615
1435
  try:
1616
1436
  platform.parse_response(response)
@@ -1639,7 +1459,7 @@ class Project:
1639
1459
  True if upload was correctly done, False otherwise.
1640
1460
  """
1641
1461
 
1642
- if check_upload_file(file_path):
1462
+ if self.__check_upload_file(file_path):
1643
1463
  return self.upload_file(file_path, subject_name)
1644
1464
 
1645
1465
  def upload_gametection(self, file_path, subject_name):
@@ -1658,7 +1478,7 @@ class Project:
1658
1478
  True if upload was correctly done, False otherwise.
1659
1479
  """
1660
1480
 
1661
- if check_upload_file(file_path):
1481
+ if self.__check_upload_file(file_path):
1662
1482
  return self.upload_file(file_path, subject_name, input_data_type="parkinson_gametection")
1663
1483
  return False
1664
1484
 
@@ -1678,7 +1498,7 @@ class Project:
1678
1498
  True if upload was correctly done, False otherwise.
1679
1499
  """
1680
1500
 
1681
- if check_upload_file(file_path):
1501
+ if self.__check_upload_file(file_path):
1682
1502
  return self.upload_file(file_path, subject_name, result=True)
1683
1503
  return False
1684
1504
 
@@ -2183,3 +2003,178 @@ class Project:
2183
2003
  return False
2184
2004
 
2185
2005
  return res["guidance_text"]
2006
+
2007
+ def __show_progress(self, done, total, finish=False):
2008
+ bytes_in_mb = 1024 * 1024
2009
+ progress_message = "\r[{:.2f} %] Uploaded {:.2f} of {:.2f} Mb".format(
2010
+ done / float(total) * 100, done / bytes_in_mb, total / bytes_in_mb
2011
+ )
2012
+ sys.stdout.write(progress_message)
2013
+ sys.stdout.flush()
2014
+ if not finish:
2015
+ pass
2016
+ # sys.stdout.write("")
2017
+ # sys.stdout.flush()
2018
+ else:
2019
+ sys.stdout.write("\n")
2020
+
2021
+ def __get_session_id(self, file_path):
2022
+ m = hashlib.md5()
2023
+ m.update(file_path.encode("utf-8"))
2024
+ return str(time.time()).replace(".", "") + "_" + m.hexdigest()
2025
+
2026
+ def __check_upload_file(self, file_path):
2027
+ """
2028
+ Check whether a file has the correct extension to upload.
2029
+
2030
+ Parameters
2031
+ ----------
2032
+ file_path : str
2033
+ Path to the file
2034
+
2035
+ Returns
2036
+ -------
2037
+ bool
2038
+ True if correct extension, False otherwise.
2039
+ """
2040
+
2041
+ # TODO: Add a file zipper here so zips files in a folder
2042
+
2043
+ file_parts = file_path.split(".")
2044
+ extension = file_parts[-1]
2045
+
2046
+ if extension != "zip":
2047
+ logging.getLogger(logger_name).error("You must upload a zip.")
2048
+ return False
2049
+ else:
2050
+ return True
2051
+
2052
+ def __operation(self, reference_value, operator, input_value):
2053
+ """
2054
+ The method performs an operation by comparing the two input values.
2055
+ The Operation is applied to the Input Value in comparison to the Reference
2056
+ Value.
2057
+
2058
+ Parameters
2059
+ ----------
2060
+ reference_value : str, list, or int
2061
+ Reference value.
2062
+ operator : str
2063
+ Operation.
2064
+ input_value : str, list, or int
2065
+ Input value.
2066
+
2067
+ Returns
2068
+ -------
2069
+ bool
2070
+ True if the operation is satisfied, False otherwise.
2071
+ """
2072
+ if input_value is None or input_value == "":
2073
+ return False
2074
+
2075
+ if operator == "in":
2076
+ return reference_value in input_value
2077
+
2078
+ elif operator == "in-list":
2079
+ return all([el in input_value for el in reference_value])
2080
+
2081
+ elif operator == "eq":
2082
+ return input_value == reference_value
2083
+
2084
+ elif operator == "gt":
2085
+ return input_value > reference_value
2086
+
2087
+ elif operator == "gte":
2088
+ return input_value >= reference_value
2089
+
2090
+ elif operator == "lt":
2091
+ return input_value < reference_value
2092
+
2093
+ elif operator == "lte":
2094
+ return input_value <= reference_value
2095
+ else:
2096
+ return False
2097
+
2098
+ def __wrap_search_criteria(self, search_criteria={}):
2099
+ """
2100
+ Wraps the conditions specified within the Search Criteria in order for
2101
+ other methods to handle it easily. The conditions are grouped only into
2102
+ three groups: Modality, Tags and the File Metadata (if DICOM it corresponds
2103
+ to the DICOM information), and each of them is output in a different
2104
+ variable.
2105
+
2106
+ Parameters
2107
+ ----------
2108
+ search_criteria : dict
2109
+ Each element is a string and is built using the formatting
2110
+ "KEYTYPE;VALUE", or "KEYTYPE;OPERATOR|VALUE".
2111
+
2112
+ Full list of keys avaiable for the dictionary:
2113
+
2114
+ search_criteria = {
2115
+ "pars_patient_secret_name": "string;SUBJECTID",
2116
+ "pars_ssid": "integer;OPERATOR|SSID",
2117
+ "pars_modalities": "string;MODALITY",
2118
+ "pars_tags": "tags;TAGS",
2119
+ "pars_age_at_scan": "integer;OPERATOR|AGE_AT_SCAN",
2120
+ "pars_[dicom]_KEY": "KEYTYPE;KEYVALUE",
2121
+ "pars_PROJECTMETADATA": "METADATATYPE;METADATAVALUE",
2122
+ }
2123
+
2124
+ See documentation for a complete definition.
2125
+
2126
+ Returns
2127
+ -------
2128
+ modality : str
2129
+ String containing the modality of the search criteria extracted from
2130
+ 'pars_modalities'
2131
+
2132
+ tags : list of str
2133
+ List of strings containing the tags of the search criteria extracted
2134
+ 'from pars_tags'
2135
+
2136
+ file_metadata : Dict
2137
+ Dictionary containing the file metadata of the search criteria
2138
+ extracted from 'pars_[dicom]_KEY'
2139
+ """
2140
+
2141
+ # The keys not included bellow apply to the whole session.
2142
+ modality, tags, file_metadata = "", list(), dict()
2143
+ for key, value in search_criteria.items():
2144
+ if key == "pars_modalities":
2145
+ modalities = value.split(";")[1].split(",")
2146
+ if len(modalities) != 1:
2147
+ raise ValueError(f"A file can only have one modality. "
2148
+ f"Provided Modalities: "
2149
+ f"{', '.join(modalities)}.")
2150
+ modality = modalities[0]
2151
+ elif key == "pars_tags":
2152
+ tags = value.split(";")[1].split(",")
2153
+ elif "pars_[dicom]_" in key:
2154
+ d_tag = key.split("pars_[dicom]_")[1]
2155
+ d_type = value.split(";")[0]
2156
+ if d_type == "string":
2157
+ file_metadata[d_tag] = {
2158
+ "operation": "in",
2159
+ "value": value.replace(d_type + ";", "")
2160
+ }
2161
+ elif d_type == "integer":
2162
+ d_operator = value.split(";")[1].split("|")[0]
2163
+ d_value = value.split(";")[1].split("|")[1]
2164
+ file_metadata[d_tag] = {
2165
+ "operation": d_operator,
2166
+ "value": int(d_value)}
2167
+ elif d_type == "decimal":
2168
+ d_operator = value.split(";")[1].split("|")[0]
2169
+ d_value = value.split(";")[1].split("|")[1]
2170
+ file_metadata[d_tag] = {
2171
+ "operation": d_operator,
2172
+ "value": float(d_value)
2173
+ }
2174
+ elif d_type == "list":
2175
+ value.replace(d_type + ";", "")
2176
+ file_metadata[d_tag] = {
2177
+ "operation": "in-list",
2178
+ "value": value.replace(d_type + ";", "").split(";")
2179
+ }
2180
+ return modality, tags, file_metadata
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: qmenta-client
3
- Version: 1.1.dev1373
3
+ Version: 1.1.dev1382
4
4
  Summary: Python client lib to interact with the QMENTA platform.
5
5
  Author: QMENTA
6
6
  Author-email: dev@qmenta.com
@@ -1,10 +1,10 @@
1
1
  qmenta/__init__.py,sha256=jv2YF__bseklT3OWEzlqJ5qE24c4aWd5F4r0TTjOrWQ,65
2
2
  qmenta/client/Account.py,sha256=MEljEy9cmg2uP2FG1d3TZAgfj66EE2_3PQAZ9rvpCXY,9647
3
3
  qmenta/client/File.py,sha256=ZgvSqejIosUt4uoX7opUnPnp5XGEaJNMRwFC0mQVB8k,5344
4
- qmenta/client/Project.py,sha256=xk-C4kf2i7RLsIp3fiwHQzlEOZpb1sL-KqxGqDex8Mc,76953
4
+ qmenta/client/Project.py,sha256=-Smnh6NCv-N-xF07f1OtTH1VpqVEMLl7fbemwK3Aayk,77848
5
5
  qmenta/client/Subject.py,sha256=lhxxVdQ6d-GNoQC8mrJwa4L1f44nJc4PcJtDspmKN7I,8756
6
6
  qmenta/client/__init__.py,sha256=AjTojBhZeW5nl0i605KS8S1Gl5tPNc1hdzD47BGNfoI,147
7
7
  qmenta/client/utils.py,sha256=5DK2T_HQprrCwLS0Ycm2CjseaYmAUKaJkJvYoW-Rqzc,2479
8
- qmenta_client-1.1.dev1373.dist-info/METADATA,sha256=TYlTOCDsSr_eH8mjJ8RQ_F91JQQYmlLHVCMbZDkn0r4,672
9
- qmenta_client-1.1.dev1373.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
10
- qmenta_client-1.1.dev1373.dist-info/RECORD,,
8
+ qmenta_client-1.1.dev1382.dist-info/METADATA,sha256=E0qXlYKpgxu_Uh-1tuvWKs_FHUrbn6Kcy9YqXyCN82Y,672
9
+ qmenta_client-1.1.dev1382.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
10
+ qmenta_client-1.1.dev1382.dist-info/RECORD,,