qmenta-client 1.1.dev1230__py3-none-any.whl → 1.1.dev1289__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
@@ -11,7 +11,6 @@ from enum import Enum
11
11
  from qmenta.client import Account
12
12
  from qmenta.core import errors
13
13
  from qmenta.core import platform
14
- from .Subject import Subject
15
14
 
16
15
  if sys.version_info[0] == 3:
17
16
  # Note: this branch & variable is only needed for python 2/3 compatibility
@@ -161,45 +160,137 @@ class Project:
161
160
  dict
162
161
  A list of dictionary of {"metadata_name": "metadata_value"}
163
162
  """
164
- return self.get_subjects_metadata(cache=False)
163
+ return self.get_subjects_metadata()
165
164
 
166
- def get_subjects_metadata(self, cache=True, search_criteria=None):
165
+ def get_subjects_metadata(self, search_criteria={}, items=(0, 9999)):
167
166
  """
168
- List all subject data from the selected project.
167
+ List all subjects data from the selected project that meet the defined
168
+ search criteria.
169
+
169
170
  Parameters
170
171
  ----------
171
- cache: bool
172
- Whether to use the cached metadata or not
173
-
174
172
  search_criteria: dict
175
173
  Each element is a string and is built using the formatting
176
- "type;value", or "type;operation|value"
174
+ "type;value", or "type;operation|value"
175
+
176
+ Complete search_criteria Dictionary Explanation:
177
+
178
+ search_criteria = {
179
+ "pars_patient_secret_name": "string;SUBJECTID",
180
+ "pars_ssid": "integer;OPERATOR|SSID",
181
+ "pars_modalities": "string;MODALITY",
182
+ "pars_tags": "tags;TAGS",
183
+ "pars_age_at_scan": "integer;OPERATOR|AGE_AT_SCAN",
184
+ "pars_[dicom]_KEY": "KEYTYPE;KEYVALUE",
185
+ "pars_PROJECTMETADATA": "METADATATYPE;METADATAVALUE",
186
+ }
187
+
188
+ Where:
189
+ "pars_patient_secret_name": Applies the search to the 'Subject ID'.
190
+ SUBJECTID is a comma separated list of strings.
191
+ "pars_ssid": Applies the search to the 'Session ID'.
192
+ SSID is an integer.
193
+ OPERATOR is the operator to apply. One of:
194
+ - Equal: eq
195
+ - Different Than: ne
196
+ - Greater Than: gt
197
+ - Greater/Equal To: gte
198
+ - Lower Than: lt
199
+ - Lower/Equal To: lte
200
+
201
+ "pars_modalities": Applies the search to the file 'Modalities'
202
+ available within each Subject ID.
203
+ MODALITY is a comma separated list of string.
204
+ "pars_tags": Applies the search to the file 'Tags' available within
205
+ each Subject ID and to the subject-level 'Tags'.
206
+ TAGS is a comma separated list of strings.
207
+ "pars_age_at_scan": Applies the search to the 'age_at_scan' metadata
208
+ field.
209
+ AGE_AT_SCAN is an integer.
210
+ "pars_[dicom]_KEY": Applies the search to the metadata fields
211
+ available within each file. KEY must be one of the
212
+ metadata keys of the files. The full list of KEYS is shown above via
213
+ 'file_m["metadata"]["info"].keys()'.
214
+ KEYTYPE is the type of the KEY. One of:
215
+ - integer
216
+ - string
217
+ - list
218
+
219
+ if 'integer' you must also include an OPERATOR
220
+ (i.e., "integer;OPERATOR|KEYVALUE").
221
+ KEYVALUE is the expected value of the KEY.
222
+ "pars_[dicom]_PROJECTMETADATA": Applies to the metadata defined
223
+ within the 'Metadata Manager' of the project.
224
+ PROJECTMETADATA is the ID of the metadata field.
225
+ METADATATYPE is the type of the metadata field. One of:
226
+ - string
227
+ - integer
228
+ - list
229
+ - decimal
230
+ - single_option
231
+ - multiple_option
232
+
233
+ if 'integer' or 'decimal' you must also include an OPERATOR
234
+ (i.e., "integer;OPERATOR|METADATAVALUE").
235
+ KEYVALUE is the expected value of the metadata.
236
+
237
+ 1) Example:
238
+ search_criteria = {
239
+ "pars_patient_secret_name": "string;abide",
240
+ "pars_ssid": "integer;eq|2"
241
+ }
242
+
243
+ 2) Example:
244
+ search_criteria = {
245
+ "pars_modalities": "string;T1",
246
+ "pars_tags": "tags;flair",
247
+ "pars_[dicom]_Manufacturer": "string;ge",
248
+ "pars_[dicom]_FlipAngle": "integer;gt|5",
249
+ }
177
250
 
178
- Example:
179
- search_criteria = {"pars_patient_secret_name": "string;abide",
180
- "pars_ssid": "integer;eq|2"}
251
+ Note the search criteria applies to all the files included within a
252
+ session. Hence, it does not imply that all the criteria conditions
253
+ are applied to the same files. In example 2) above, it means that
254
+ any Subject ID/Session ID that has a file classified with a 'T1'
255
+ modality, a file with a 'flair' tag, a file whose Manufacturer
256
+ contains 'ge', and a file whose FlipAngle is greater than '5º' will
257
+ be selected.
181
258
 
182
259
  Returns
183
260
  -------
184
261
  dict
185
262
  A list of dictionary of {"metadata_name": "metadata_value"}
263
+
186
264
  """
187
265
 
188
- if not cache or not self._subjects_metadata:
189
- content = platform.parse_response(platform.post(
190
- self._account.auth, "patient_manager/get_patient_list",
191
- data=search_criteria,
192
- headers={"X-Range": "items=0-9999"}
193
- ))
194
- self._subjects_metadata = content
195
- else:
196
- content = self._subjects_metadata
266
+ assert len(items) == 2, f"The number of elements in items " \
267
+ f"'{len(items)}' should be equal to two."
268
+ assert all([isinstance(item, int) for item in items]), \
269
+ f"All items elements '{items}' should be integers."
270
+
271
+ assert all([key[:5] == "pars_" for key in search_criteria.keys()]), \
272
+ f"All keys of the search_criteria dictionary " \
273
+ f"'{search_criteria.keys()}' must start with 'pars_'."
274
+
275
+ operator_list = ["eq", "ne", "gt", "gte", "lt", "lte"]
276
+ for key, value in search_criteria.items():
277
+ if value.split(";")[0] in ["integer", "decimal"]:
278
+ assert value.split(";")[1].split("|")[0] in operator_list, \
279
+ f"Search criteria of type '{value.split(';')[0]}' must " \
280
+ f"include an operator ({', '.join(operator_list)})."
281
+
282
+ content = platform.parse_response(platform.post(
283
+ self._account.auth, "patient_manager/get_patient_list",
284
+ data=search_criteria,
285
+ headers={"X-Range": f"items={items[0]}-{items[1]}"}
286
+ ))
197
287
  return content
198
288
 
199
289
  @property
200
290
  def subjects(self):
201
291
  """
202
- Return the list of subject names from the selected project.
292
+ Return the list of subject names (Subject ID) from the selected
293
+ project.
203
294
 
204
295
  :return: a list of subject names
205
296
  :rtype: List(Strings)
@@ -211,12 +302,13 @@ class Project:
211
302
 
212
303
  def check_subject_name(self, subject_name):
213
304
  """
214
- Check if a given subject name exists in the selected project.
305
+ Check if a given subject name (Subject ID) exists in the selected
306
+ project.
215
307
 
216
308
  Parameters
217
309
  ----------
218
310
  subject_name : str
219
- name of the subject to check
311
+ Subject ID of the subject to check
220
312
 
221
313
  Returns
222
314
  -------
@@ -329,12 +421,32 @@ class Project:
329
421
  else:
330
422
  return None
331
423
 
332
- def list_analysis(self, limit=10000000):
424
+ def list_analysis(self, search_condition={}, items=(0, 9999)):
333
425
  """
334
426
  List the analysis available to the user.
427
+ search condition example:
428
+ search_condition = {
429
+ "secret_name":"014_S_6920",
430
+ "from_d": "06.02.2025",
431
+ "with_child_analysis": 1,
432
+ "state": "completed"
433
+ }
335
434
 
336
435
  Parameters
337
436
  ----------
437
+ search_condition : dict
438
+ p_n: str # analysis_name
439
+ type: str # analysis_type
440
+ from_d: str # dd.mm.yyyy
441
+ to_d: str # dd.mm.yyyy
442
+ qa_status: str # pass/fail/nd
443
+ secret_name: str # Subject_ID
444
+ tags: str #
445
+ with_child_analysis: 1
446
+ # if 1, child analysis of workflows will appear
447
+ id: str # container_id
448
+ state: # running, completed, pending, exception
449
+ username: str #
338
450
  limit : int
339
451
  Max number of results
340
452
 
@@ -343,55 +455,121 @@ class Project:
343
455
  dict
344
456
  List of analysis, each a dictionary
345
457
  """
346
- req_headers = {"X-Range": "items=0-" + str(limit - 1)}
458
+ assert len(items) == 2, f"The number of elements in items " \
459
+ f"'{len(items)}' should be equal to two."
460
+ assert all([isinstance(item, int) for item in items]), \
461
+ f"All items elements '{items}' should be integers."
462
+ search_keys = {
463
+ "p_n": str,
464
+ "type": str,
465
+ "from_d": str,
466
+ "to_d": str,
467
+ "qa_status": str,
468
+ "secret_name": str,
469
+ "tags": str,
470
+ "with_child_analysis": int,
471
+ "id": int,
472
+ "state": str,
473
+ "username": str,
474
+ }
475
+ for key in search_condition.keys():
476
+ if key not in search_keys.keys():
477
+ raise Exception(
478
+ (
479
+ f"This key '{key}' is not accepted by this"
480
+ "search condition"
481
+ )
482
+ )
483
+ if not isinstance(search_condition[key], search_keys[key]):
484
+ raise Exception(
485
+ (
486
+ f"The key {key} in the search condition"
487
+ f"is not type {search_keys[key]}"
488
+ )
489
+ )
490
+ req_headers = {"X-Range": f"items={items[0]}-{items[1] - 1}"}
347
491
  return platform.parse_response(platform.post(
348
492
  auth=self._account.auth,
349
493
  endpoint="analysis_manager/get_analysis_list",
350
- headers=req_headers
494
+ headers=req_headers,
495
+ data=search_condition
351
496
  ))
352
497
 
353
- def get_container(self, subject_name):
354
- search_condition = {
498
+ def get_subject_container_id(self, subject_name, ssid):
499
+ """
500
+ Given a Subject ID and Session ID, return its Container ID.
501
+
502
+ Parameters
503
+ ----------
504
+ subject_name : str
505
+ Subject ID of the subject in the project.
506
+ ssid : str
507
+ Session ID of the subject in the project.
508
+
509
+ Returns
510
+ -------
511
+ int or bool
512
+ The Container ID of the subject in the project, or False if
513
+ the subject is not found.
514
+ """
515
+
516
+ search_criteria = {
355
517
  "s_n": subject_name,
518
+ "ssid": ssid
356
519
  }
357
520
  response = self.list_input_containers(
358
- search_condition=search_condition
521
+ search_criteria=search_criteria
359
522
  )
360
523
 
361
- if len(response) > 1:
362
- raise Exception(f"multiple containers for subject {subject_name} "
363
- f"found")
364
- elif len(response) == 1:
365
- return response[0]
366
- else:
367
- return None
524
+ for subject in response:
525
+ if subject["patient_secret_name"] == subject_name and \
526
+ subject["ssid"] == ssid:
527
+ return subject["container_id"]
528
+ return False
368
529
 
369
- def list_input_containers(self, search_condition=None, limit=1000):
530
+ def list_input_containers(self, search_criteria={}, items=(0, 9999)):
370
531
  """
371
- List the containers available to the user.
532
+ Retrieve the list of input containers available to the user under a
533
+ certain search criteria.
372
534
 
373
535
  Parameters
374
536
  ----------
375
- search_condition : dict
376
- d_n: container_name
377
- s_n: subject_id
378
- from_d: from date
379
- to_d: to date
380
- sets: data sets (modalities)
381
- limit : int
382
- Max number of results
537
+ search_criteria : dict
538
+ Each element is a string and is built using the formatting
539
+ "type;value".
540
+
541
+ List of possible keys:
542
+ d_n: container_name # TODO: WHAT IS THIS???
543
+ s_n: subject_id
544
+ Subject ID of the subject in the platform.
545
+ ssid: session_id
546
+ Session ID of the subejct in the platform.
547
+ from_d: from date
548
+ Starting date in which perform the search. Format: DD.MM.YYYY
549
+ to_d: to date
550
+ End date in which perform the search. Format: DD.MM.YYYY
551
+ sets: data sets (modalities) # TODO: WHAT IS THIS???
552
+
553
+ items: Tuple(int, int)
554
+ Starting and ending element of the search.
383
555
 
384
556
  Returns
385
557
  -------
386
558
  dict
387
- List of containers, each a dictionary
388
- {"name": "container-name", "id": "container_id"}
559
+ List of containers, each a dictionary containing the following
560
+ information:
561
+ {"container_name", "container_id", "patient_secret_name", "ssid"}
389
562
  """
390
563
 
391
- req_headers = {"X-Range": "items=0-" + str(limit - 1)}
564
+ assert len(items) == 2, f"The number of elements in items " \
565
+ f"'{len(items)}' should be equal to two."
566
+ assert all([isinstance(item, int) for item in items]), \
567
+ f"All items elements '{items}' should be integers."
568
+
392
569
  response = platform.parse_response(platform.post(
393
570
  self._account.auth, "file_manager/get_container_list",
394
- data=search_condition, headers=req_headers
571
+ data=search_criteria,
572
+ headers={"X-Range": f"items={items[0]}-{items[1]}"}
395
573
  ))
396
574
  containers = [
397
575
  {
@@ -492,12 +670,15 @@ class Project:
492
670
  Returns
493
671
  -------
494
672
  dict
495
- Dictionary with the metadata.
673
+ Dictionary with the metadata. False otherwise.
496
674
  """
497
675
  all_metadata = self.list_container_files_metadata(container_id)
498
- for file_meta in all_metadata:
499
- if file_meta["name"] == filename:
500
- return file_meta
676
+ if all_metadata:
677
+ for file_meta in all_metadata:
678
+ if file_meta["name"] == filename:
679
+ return file_meta
680
+ else:
681
+ return False
501
682
 
502
683
  def change_file_metadata(self, container_id, filename, modality, tags):
503
684
  """
@@ -620,16 +801,17 @@ class Project:
620
801
  container_id, zip_name))
621
802
  return True
622
803
 
623
- def get_subject_id(self, subject_name, cache=False):
804
+ def get_subject_id(self, subject_name, ssid):
624
805
  """
625
- Given a subject name, return its ID in the project.
806
+ Given a Subject ID and Session ID, return its Patient ID in the
807
+ project.
626
808
 
627
809
  Parameters
628
810
  ----------
629
811
  subject_name : str
630
- Name of the subject in the project.
631
- cache : bool
632
- Whether to use the cached metadata or not
812
+ Subject ID of the subject in the project.
813
+ ssid : str
814
+ Session ID of the subject in the project.
633
815
 
634
816
  Returns
635
817
  -------
@@ -638,37 +820,12 @@ class Project:
638
820
  the subject is not found.
639
821
  """
640
822
 
641
- for user in self.get_subjects_metadata(cache):
642
- if user["patient_secret_name"] == subject_name:
823
+ for user in self.get_subjects_metadata():
824
+ if user["patient_secret_name"] == str(subject_name) and \
825
+ user["ssid"] == str(ssid):
643
826
  return int(user["_id"])
644
827
  return False
645
828
 
646
- def get_subject(self, subject_name, cache=True):
647
- """
648
- Return a subject object, representing a subject from the project.
649
-
650
- Parameters
651
- ----------
652
- subject_name : str
653
- Name of the subject.
654
- cache: bool
655
- Whether to use the cached metadata or not
656
-
657
- Returns
658
- -------
659
- Subject or bool
660
- A Subject instance representing the desired subject, or
661
- False if the subject was not found.
662
-
663
- """
664
- subject_id = self.get_subject_id(subject_name, cache=cache)
665
- if subject_id is False:
666
- return False
667
- subj = Subject(subject_name)
668
- subj.subject_id = subject_id
669
- subj.project = self
670
- return subj
671
-
672
829
  def add_subject(self, subject):
673
830
  """
674
831
  Add a subject to the project.
@@ -704,18 +861,114 @@ class Project:
704
861
  "Subject {0} was successfully created".format(subject.name))
705
862
  return True
706
863
 
707
- def delete_session(self, subject_name, session_id, cache=False):
864
+ def change_subject_metadata(self, patient_id, subject_name, ssid, tags,
865
+ age_at_scan, metadata):
708
866
  """
709
- Delete a session from a subject within a project.
867
+ Change the Subject ID, Session ID, Tags, Age at Scan and Metadata of
868
+ the session with Patient ID
869
+
870
+ Parameters
871
+ ----------
872
+ patient_id : Integer
873
+ Patient ID representing the session to modify.
874
+ subject_name : String
875
+ Represents the new Subject ID.
876
+ ssid : String
877
+ Represents the new Session ID.
878
+ tags : list of strings in lowercase
879
+ Represents the new tags of the session.
880
+ age_at_scan : Integer
881
+ Represents the new Age at Scan of the Session.
882
+ metadata : Dictionary
883
+ Each pair key/value representing the new metadata values.
884
+
885
+ The keys must either all start with "md\\_" or none start
886
+ with "md\\_".
887
+
888
+ The key represents the ID of the metadata field.
889
+
890
+ Returns
891
+ -------
892
+ bool
893
+ True if correctly modified, False otherwise
894
+ """
895
+ logger = logging.getLogger(logger_name)
896
+
897
+ try:
898
+ patient_id = str(int(patient_id))
899
+ except ValueError:
900
+ raise ValueError(f"'patient_id': '{patient_id}' not valid. "
901
+ f"Must be convertible to int.")
902
+
903
+ assert isinstance(tags, list) and \
904
+ all(isinstance(item, str) for item in tags), \
905
+ f"tags: '{tags}' should be a list of strings."
906
+ tags = [tag.lower() for tag in tags]
907
+
908
+ assert subject_name is not None and subject_name != "", \
909
+ "subject_name must be a non empty string."
910
+ assert ssid is not None and ssid != "", \
911
+ "ssid must be a non empty string."
912
+
913
+ try:
914
+ age_at_scan = str(int(age_at_scan)) if age_at_scan else None
915
+ except ValueError:
916
+ raise ValueError(f"age_at_scan: '{age_at_scan}' not valid. "
917
+ f"Must be an integer.")
918
+
919
+ assert isinstance(metadata, dict), \
920
+ f"metadata: '{metadata}' should be a dictionary."
921
+
922
+ assert all("md_" == key[:3] for key in metadata.keys()) or \
923
+ all("md_" != key[:3] for key in metadata.keys()), \
924
+ f"metadata: '{metadata}' must be a dictionary whose keys " \
925
+ f"are either all starting with 'md_' or none."
926
+
927
+ metadata_keys = self.metadata_parameters.keys()
928
+ assert \
929
+ all([key[3:] in metadata_keys
930
+ if "md_" == key[:3] else key in metadata_keys
931
+ for key in metadata.keys()]), \
932
+ f"Some metadata keys provided ({', '.join(metadata.keys())}) " \
933
+ f"are not available in the project. They can be added via the " \
934
+ f"Metadata Manager via the QMENTA Platform graphical user " \
935
+ f"interface (GUI)."
936
+
937
+ post_data = {
938
+ "patient_id": patient_id,
939
+ "secret_name": str(subject_name),
940
+ "ssid": str(ssid),
941
+ "tags": ",".join(tags),
942
+ "age_at_scan": age_at_scan,
943
+ }
944
+ for key, value in metadata.items():
945
+ id = key[3:] if "md_" == key[:3] else key
946
+ post_data[f"last_vals.{id}"] = value
947
+
948
+ try:
949
+ platform.parse_response(platform.post(
950
+ self._account.auth,
951
+ "patient_manager/upsert_patient",
952
+ data=post_data
953
+ ))
954
+ except errors.PlatformError:
955
+ logger.error(f"Patient ID '{patient_id}' could not be modified.")
956
+ return False
957
+
958
+ logger.info(f"Patient ID '{patient_id}' successfully modified.")
959
+ return True
960
+
961
+ def delete_session(self, subject_name, session_id):
962
+ """
963
+ Delete a session from a subject within a project providing the
964
+ Subject ID and Session ID.
710
965
 
711
966
  Parameters
712
967
  ----------
713
968
  subject_name : str
714
- Name of the subject
969
+ Subject ID of the subject
715
970
  session_id : int
716
- The SSID of the session that will be deleted
717
- cache : bool
718
- Whether to use the cached metadata or not
971
+ The Session ID of the session that will be deleted
719
972
 
720
973
  Returns
721
974
  -------
@@ -723,31 +976,31 @@ class Project:
723
976
  True if correctly deleted, False otherwise.
724
977
  """
725
978
  logger = logging.getLogger(logger_name)
726
- all_sessions = self.get_subjects_metadata(cache)
979
+ all_sessions = self.get_subjects_metadata()
727
980
 
728
- sessions_to_del = [
981
+ session_to_del = [
729
982
  s for s in all_sessions if
730
- s["patient_secret_name"] == subject_name and int(
731
- s["ssid"]
732
- ) == session_id
983
+ s["patient_secret_name"] == subject_name and
984
+ s["ssid"] == session_id
733
985
  ]
734
986
 
735
- if not sessions_to_del:
987
+ if not session_to_del:
736
988
  logger.error(
737
989
  f"Session {subject_name}/{session_id} could not be found "
738
990
  f"in this project."
739
991
  )
740
992
  return False
741
- elif len(sessions_to_del) > 1:
993
+ elif len(session_to_del) > 1:
742
994
  raise RuntimeError(
743
- "Multiple sessions with same SID and SSID. Contact support."
995
+ "Multiple sessions with same Subject ID and Session ID."
996
+ " Contact support."
744
997
  )
745
998
  else:
746
999
  logger.info("{}/{} found (id {})".format(
747
- subject_name, session_id, sessions_to_del[0]["_id"]
1000
+ subject_name, session_id, session_to_del[0]["_id"]
748
1001
  ))
749
1002
 
750
- session = sessions_to_del[0]
1003
+ session = session_to_del[0]
751
1004
 
752
1005
  try:
753
1006
  platform.parse_response(platform.post(
@@ -767,14 +1020,46 @@ class Project:
767
1020
  )
768
1021
  return True
769
1022
 
1023
+ def delete_session_by_patientid(self, patient_id):
1024
+ """
1025
+ Delete a session from a subject within a project providing the
1026
+ Patient ID.
1027
+
1028
+ Parameters
1029
+ ----------
1030
+ patient_id : str
1031
+ Patient ID of the Session ID/Subject ID
1032
+
1033
+ Returns
1034
+ -------
1035
+ bool
1036
+ True if correctly deleted, False otherwise.
1037
+ """
1038
+ logger = logging.getLogger(logger_name)
1039
+
1040
+ try:
1041
+ platform.parse_response(platform.post(
1042
+ self._account.auth, "patient_manager/delete_patient",
1043
+ data={
1044
+ "patient_id": str(int(patient_id)), "delete_files": 1
1045
+ }
1046
+ ))
1047
+ except errors.PlatformError:
1048
+ logger.error(f"Patient ID {patient_id} could not be deleted.")
1049
+ return False
1050
+
1051
+ logger.info(f"Patient ID {patient_id} successfully deleted.")
1052
+ return True
1053
+
770
1054
  def delete_subject(self, subject_name):
771
1055
  """
772
- Delete a subject from the project.
1056
+ Delete a subject from the project. It deletes all its available
1057
+ sessions only providing the Subject ID.
773
1058
 
774
1059
  Parameters
775
1060
  ----------
776
1061
  subject_name : str
777
- Name of the subject to be deleted.
1062
+ Subject ID of the subject to be deleted.
778
1063
 
779
1064
  Returns
780
1065
  -------
@@ -784,7 +1069,7 @@ class Project:
784
1069
 
785
1070
  logger = logging.getLogger(logger_name)
786
1071
  # Always fetch the session IDs from the platform before deleting them
787
- all_sessions = self.get_subjects_metadata(False)
1072
+ all_sessions = self.get_subjects_metadata()
788
1073
 
789
1074
  sessions_to_del = [
790
1075
  s for s in all_sessions if s["patient_secret_name"] == subject_name
@@ -799,7 +1084,7 @@ class Project:
799
1084
  return False
800
1085
 
801
1086
  for ssid in [s["ssid"] for s in sessions_to_del]:
802
- if not self.delete_session(subject_name, ssid, cache=True):
1087
+ if not self.delete_session(subject_name, ssid):
803
1088
  return False
804
1089
  return True
805
1090
 
@@ -884,16 +1169,16 @@ class Project:
884
1169
  add_to_container_id=0, chunk_size=2 ** 9,
885
1170
  split_data=False):
886
1171
  """
887
- Upload a file to the platform, associated with the current user.
1172
+ Upload a ZIP file to the platform.
888
1173
 
889
1174
  Parameters
890
1175
  ----------
891
1176
  file_path : str
892
- Path to the file to upload.
1177
+ Path to the ZIP file to upload.
893
1178
  subject_name : str
894
- Subject to which this file will belong
1179
+ Subject ID of the data to upload in the project in QMENTA Platform.
895
1180
  ssid : str
896
- The ID of the timepoint
1181
+ Session ID of the Subject ID (i.e., ID of the timepoint).
897
1182
  date_of_scan : str
898
1183
  Date of scan/creation of the file
899
1184
  description : str
@@ -903,7 +1188,7 @@ class Project:
903
1188
  name : str
904
1189
  Name of the file in the platform
905
1190
  input_data_type : str
906
- mri_brain_data:1.0 or gametection:1.0
1191
+ qmenta_medical_image_data:3.11
907
1192
  add_to_container_id : int
908
1193
  ID of the container to which this file should be added (if id > 0)
909
1194
  chunk_size : int
@@ -1,8 +1,7 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: qmenta-client
3
- Version: 1.1.dev1230
3
+ Version: 1.1.dev1289
4
4
  Summary: Python client lib to interact with the QMENTA platform.
5
- Home-page: https://www.qmenta.com/
6
5
  Author: QMENTA
7
6
  Author-email: dev@qmenta.com
8
7
  Requires-Python: >=3.10,<4.0
@@ -12,5 +11,7 @@ Classifier: Programming Language :: Python :: 3
12
11
  Classifier: Programming Language :: Python :: 3.10
13
12
  Classifier: Programming Language :: Python :: 3.11
14
13
  Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
15
  Requires-Dist: future (>=0.18.2,<0.19.0)
16
16
  Requires-Dist: qmenta-core (>=4.0.1,<5.0.0)
17
+ Project-URL: Homepage, https://www.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=rxOd03sZXCrZjHbxQlgV7qbEXc2STX-sTSXprBKkIOA,48357
4
+ qmenta/client/Project.py,sha256=Y0G5vSVODThAL8kGwmtkcZrE49vB2LVlNf2eRrqr8dg,59767
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.dev1230.dist-info/METADATA,sha256=GVsXH4eCCog-jbYRrB-vthtUbOnvsemdnc-yAmeNdak,609
9
- qmenta_client-1.1.dev1230.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
10
- qmenta_client-1.1.dev1230.dist-info/RECORD,,
8
+ qmenta_client-1.1.dev1289.dist-info/METADATA,sha256=khcRoMKuV0hhGvxc-9tjMy9RRIXugkzyE5sKZ_PuF4M,672
9
+ qmenta_client-1.1.dev1289.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
10
+ qmenta_client-1.1.dev1289.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.0
2
+ Generator: poetry-core 2.0.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any