logs-py 2.9.6__py3-none-any.whl → 3.0.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.

Potentially problematic release.


This version of logs-py might be problematic. Click here for more details.

Files changed (146) hide show
  1. LOGS/Auxiliary/DateTimeConverter.py +11 -1
  2. LOGS/Auxiliary/Exceptions.py +40 -4
  3. LOGS/Auxiliary/LOGSErrorResponse.py +4 -1
  4. LOGS/Auxiliary/MinimalModelGenerator.py +88 -28
  5. LOGS/Auxiliary/Tools.py +11 -0
  6. LOGS/Converter/Conversion.py +248 -0
  7. LOGS/Converter/Converter.py +96 -0
  8. LOGS/Converter/ConverterParameter.py +88 -0
  9. LOGS/Converter/ExportParamters.py +89 -0
  10. LOGS/Converter/__init__.py +13 -0
  11. LOGS/Entities/Bridge.py +6 -3
  12. LOGS/Entities/CustomField.py +96 -91
  13. LOGS/Entities/CustomFieldModels.py +57 -0
  14. LOGS/Entities/CustomFieldRelations.py +10 -0
  15. LOGS/Entities/CustomFieldRequestParameter.py +43 -15
  16. LOGS/Entities/CustomFieldValue.py +88 -0
  17. LOGS/Entities/CustomFieldValueConverter.py +66 -0
  18. LOGS/Entities/CustomType.py +187 -0
  19. LOGS/Entities/CustomTypeEntityType.py +11 -0
  20. LOGS/Entities/CustomTypeMinimal.py +8 -0
  21. LOGS/Entities/CustomTypeRelations.py +59 -0
  22. LOGS/Entities/CustomTypeRequestParameter.py +61 -0
  23. LOGS/Entities/CustomTypeSection.py +39 -0
  24. LOGS/Entities/CustomTypes.py +12 -0
  25. LOGS/Entities/DataSource.py +28 -14
  26. LOGS/Entities/Dataset.py +274 -136
  27. LOGS/Entities/DatasetCreator.py +23 -72
  28. LOGS/Entities/DatasetInfo.py +23 -2
  29. LOGS/Entities/DatasetModels.py +31 -0
  30. LOGS/Entities/DatasetRequestParameter.py +45 -32
  31. LOGS/Entities/Datatrack.py +74 -30
  32. LOGS/Entities/DatatrackFormattedTable.py +25 -0
  33. LOGS/Entities/DatatrackGeneric.py +34 -0
  34. LOGS/Entities/DatatrackImage.py +25 -0
  35. LOGS/Entities/DatatrackNumericArray.py +9 -39
  36. LOGS/Entities/DatatrackNumericMatrix.py +86 -0
  37. LOGS/Entities/DocumentRequestParameter.py +2 -2
  38. LOGS/Entities/EntitiesRequestParameter.py +2 -2
  39. LOGS/Entities/Experiment.py +3 -3
  40. LOGS/Entities/FileExcludePattern.py +8 -0
  41. LOGS/Entities/FormatFormat.py +22 -1
  42. LOGS/Entities/FormatFormatRequestParameter.py +2 -1
  43. LOGS/Entities/FormatFormats.py +1 -1
  44. LOGS/Entities/FormattedTable/DatatypeFormattedTable.py +135 -0
  45. LOGS/Entities/FormattedTable/DatatypeFormattedTableCell.py +108 -0
  46. LOGS/Entities/FormattedTable/DatatypeFormattedTableSettings.py +11 -0
  47. LOGS/Entities/FormattedTable/__init__.py +9 -0
  48. LOGS/Entities/ILiterarTypedEntity.py +19 -0
  49. LOGS/Entities/Instrument.py +3 -3
  50. LOGS/Entities/Inventories.py +12 -0
  51. LOGS/Entities/Inventory.py +95 -0
  52. LOGS/Entities/InventoryMinimal.py +20 -0
  53. LOGS/Entities/InventoryRelations.py +23 -0
  54. LOGS/Entities/InventoryRequestParameter.py +53 -0
  55. LOGS/Entities/LabNotebook.py +37 -0
  56. LOGS/Entities/LabNotebookEntry.py +47 -24
  57. LOGS/Entities/LabNotebookEntryContent/BasicAttribute.py +15 -0
  58. LOGS/Entities/LabNotebookEntryContent/EntityAttribute.py +85 -0
  59. LOGS/Entities/LabNotebookEntryContent/EntryContentBlockquote.py +13 -0
  60. LOGS/Entities/LabNotebookEntryContent/EntryContentBulletList.py +17 -0
  61. LOGS/Entities/LabNotebookEntryContent/EntryContentCallout.py +40 -0
  62. LOGS/Entities/LabNotebookEntryContent/EntryContentContentPlaceholderNode.py +31 -0
  63. LOGS/Entities/LabNotebookEntryContent/EntryContentConverter.py +207 -0
  64. LOGS/Entities/LabNotebookEntryContent/EntryContentDocument.py +8 -0
  65. LOGS/Entities/LabNotebookEntryContent/EntryContentEntity.py +13 -0
  66. LOGS/Entities/LabNotebookEntryContent/EntryContentEntityMention.py +31 -0
  67. LOGS/Entities/LabNotebookEntryContent/EntryContentHeading.py +33 -0
  68. LOGS/Entities/LabNotebookEntryContent/EntryContentHorizontalRule.py +12 -0
  69. LOGS/Entities/LabNotebookEntryContent/EntryContentItem.py +37 -0
  70. LOGS/Entities/LabNotebookEntryContent/EntryContentListItem.py +49 -0
  71. LOGS/Entities/LabNotebookEntryContent/EntryContentOrderedList.py +31 -0
  72. LOGS/Entities/LabNotebookEntryContent/EntryContentParagraph.py +13 -0
  73. LOGS/Entities/LabNotebookEntryContent/EntryContentTable.py +17 -0
  74. LOGS/Entities/LabNotebookEntryContent/EntryContentTableCell.py +40 -0
  75. LOGS/Entities/LabNotebookEntryContent/EntryContentTableRow.py +8 -0
  76. LOGS/Entities/LabNotebookEntryContent/EntryContentTaskList.py +17 -0
  77. LOGS/Entities/LabNotebookEntryContent/EntryContentTaskListItem.py +31 -0
  78. LOGS/Entities/LabNotebookEntryContent/EntryContentText.py +33 -0
  79. LOGS/Entities/LabNotebookEntryContent/IEntryContentWithAttribute.py +23 -0
  80. LOGS/Entities/LabNotebookEntryContent/IEntryContentWithContent.py +38 -0
  81. LOGS/Entities/LabNotebookEntryContent/IEntryContentWithTextAttribute.py +16 -0
  82. LOGS/Entities/LabNotebookEntryContent/TextAttribute.py +46 -0
  83. LOGS/Entities/LabNotebookEntryContent/TextMarkAtributes.py +64 -0
  84. LOGS/Entities/LabNotebookEntryContent/TextMarkConverter.py +45 -0
  85. LOGS/Entities/LabNotebookEntryContent/TextMarks.py +71 -0
  86. LOGS/Entities/LabNotebookEntryContent/__init__.py +34 -0
  87. LOGS/Entities/LabNotebookEntryRequestParameter.py +2 -0
  88. LOGS/Entities/LabNotebookExperiment.py +52 -0
  89. LOGS/Entities/LabNotebookExperimentMinimal.py +8 -0
  90. LOGS/Entities/LabNotebookExperimentRequestParameter.py +49 -0
  91. LOGS/Entities/LabNotebookExperiments.py +16 -0
  92. LOGS/Entities/LabNotebookMinimal.py +19 -0
  93. LOGS/Entities/LabNotebookModels.py +14 -0
  94. LOGS/Entities/LabNotebookRequestParameter.py +43 -0
  95. LOGS/Entities/LabNotebooks.py +12 -0
  96. LOGS/Entities/Method.py +3 -3
  97. LOGS/Entities/ParserLog.py +4 -0
  98. LOGS/Entities/Person.py +2 -2
  99. LOGS/Entities/Project.py +7 -7
  100. LOGS/Entities/{ProjectUserPermission.py → ProjectPersonPermission.py} +14 -4
  101. LOGS/Entities/Role.py +3 -3
  102. LOGS/Entities/RunState.py +1 -0
  103. LOGS/Entities/Sample.py +36 -57
  104. LOGS/Entities/SampleRequestParameter.py +30 -15
  105. LOGS/Entities/Track.py +8 -4
  106. LOGS/Entities/TrackData.py +11 -0
  107. LOGS/Entities/TrackImage.py +21 -0
  108. LOGS/Entities/TrackImageData.py +20 -0
  109. LOGS/Entities/TrackMatrix.py +28 -0
  110. LOGS/Entities/TrackMatrixData.py +22 -0
  111. LOGS/Entities/TrackTable.py +21 -0
  112. LOGS/Entities/TrackTableData.py +22 -0
  113. LOGS/Entities/TrackXY.py +5 -1
  114. LOGS/Entities/TrackXYComplex.py +1 -1
  115. LOGS/Entities/__init__.py +26 -7
  116. LOGS/Entity/ConnectedEntity.py +39 -1
  117. LOGS/Entity/Entity.py +9 -14
  118. LOGS/Entity/SerializeableContent.py +62 -5
  119. LOGS/Interfaces/IHierarchyType.py +63 -0
  120. LOGS/Interfaces/IPermissionedEntity.py +29 -5
  121. LOGS/Interfaces/IProjectBased.py +1 -1
  122. LOGS/Interfaces/ITypedEntity.py +69 -12
  123. LOGS/Interfaces/IVersionedEntity.py +39 -0
  124. LOGS/LOGS.py +137 -46
  125. LOGS/LOGSConnection.py +52 -24
  126. LOGS/LOGSOptions.py +8 -0
  127. LOGS/Parameters/Color.py +92 -0
  128. LOGS/Parameters/ParameterBase.py +55 -0
  129. LOGS/Parameters/ParameterConverter.py +24 -0
  130. LOGS/Parameters/ParameterElement.py +99 -0
  131. LOGS/Parameters/ParameterList.py +52 -0
  132. LOGS/Parameters/ParameterTable.py +64 -0
  133. LOGS/Parameters/__init__.py +13 -0
  134. LOGS/__init__.py +1 -0
  135. {logs_py-2.9.6.dist-info → logs_py-3.0.0.dist-info}/METADATA +2 -1
  136. logs_py-3.0.0.dist-info/RECORD +263 -0
  137. LOGS/Entities/CustomFieldEnums.py +0 -25
  138. LOGS/Entities/DatasetType.py +0 -7
  139. LOGS/Entities/DatasetTypeMinimal.py +0 -8
  140. LOGS/Entities/SampleType.py +0 -34
  141. LOGS/Entities/SampleTypeMinimal.py +0 -8
  142. LOGS/Entities/SampleTypeRequestParameter.py +0 -8
  143. LOGS/Entities/SampleTypes.py +0 -12
  144. logs_py-2.9.6.dist-info/RECORD +0 -183
  145. {logs_py-2.9.6.dist-info → logs_py-3.0.0.dist-info}/WHEEL +0 -0
  146. {logs_py-2.9.6.dist-info → logs_py-3.0.0.dist-info}/top_level.txt +0 -0
@@ -2,10 +2,17 @@ from typing import List, Optional, TypeVar, Union, cast
2
2
 
3
3
  from LOGS.Entities.DatasetRequestParameter import ParsingStates
4
4
  from LOGS.Entities.Datatrack import Datatrack
5
+ from LOGS.Entities.DatatrackFormattedTable import DatatrackFormattedTable
6
+ from LOGS.Entities.DatatrackGeneric import DatatrackGeneric
7
+ from LOGS.Entities.DatatrackImage import DatatrackImage
5
8
  from LOGS.Entities.DatatrackNumericArray import DatatrackNumericArray
9
+ from LOGS.Entities.DatatrackNumericMatrix import DatatrackNumericMatrix
6
10
  from LOGS.Entities.HierarchyNode import HierarchyNode
7
11
  from LOGS.Entities.ParserLog import ParserLog
8
12
  from LOGS.Entities.Track import Track
13
+ from LOGS.Entities.TrackImage import TrackImage
14
+ from LOGS.Entities.TrackMatrix import TrackMatrix
15
+ from LOGS.Entities.TrackTable import TrackTable
9
16
  from LOGS.Entities.TrackXY import TrackXY
10
17
  from LOGS.Entities.TrackXYComplex import TrackXYComplex
11
18
  from LOGS.Entity.SerializeableContent import SerializeableContent
@@ -72,10 +79,17 @@ class DatasetInfo(SerializeableContent):
72
79
  @classmethod
73
80
  def _trackConverter(cls, value: dict) -> TRACKS:
74
81
  if isinstance(value, dict) and "type" in value:
82
+ # print("_trackConverter", value["type"])
75
83
  if value["type"] == "XY_real":
76
84
  return TrackXY(value)
77
85
  elif value["type"] == "XY_complex":
78
86
  return TrackXYComplex(value)
87
+ elif value["type"] == "matrix_real":
88
+ return TrackMatrix(value)
89
+ elif value["type"] == "image":
90
+ return TrackImage(value)
91
+ elif value["type"] == "table":
92
+ return TrackTable(value)
79
93
  else:
80
94
  return Track(value)
81
95
  else:
@@ -84,12 +98,19 @@ class DatasetInfo(SerializeableContent):
84
98
  @classmethod
85
99
  def _datatrackConverter(cls, value: dict) -> DATATRACKS:
86
100
  if isinstance(value, dict) and "type" in value:
101
+ # print("_datatrackConverter", value["type"])
87
102
  if value["type"] == "numeric_array":
88
103
  return DatatrackNumericArray(value)
104
+ elif value["type"] == "numeric_matrix":
105
+ return DatatrackNumericMatrix(value)
106
+ elif value["type"] == "image":
107
+ return DatatrackImage(value)
108
+ elif value["type"] == "formatted_table":
109
+ return DatatrackFormattedTable(value)
89
110
  else:
90
- return Datatrack(value)
111
+ return DatatrackGeneric(value)
91
112
  else:
92
- return Datatrack(value)
113
+ return DatatrackGeneric(value)
93
114
 
94
115
  @property
95
116
  def tracks(self) -> Optional[List[Track]]:
@@ -0,0 +1,31 @@
1
+ from dataclasses import dataclass
2
+ from enum import Enum
3
+ from typing import List, Optional
4
+
5
+ from LOGS.Entity.SerializeableContent import SerializeableClass, SerializeableContent
6
+
7
+
8
+ class DatasetSourceType(Enum):
9
+ ManualUpload = 0
10
+ SFTPAutoload = 1
11
+ ClientAutoload = 2
12
+ APIUpload = 3
13
+
14
+
15
+ class ParsedMetadata(SerializeableContent):
16
+ Parameters: bool = False
17
+ Tracks: bool = False
18
+ TrackCount: int = False
19
+ TrackViewerTypes: List[str] = []
20
+
21
+
22
+ @dataclass
23
+ class DatasetSource(SerializeableClass):
24
+ id: Optional[int] = None
25
+ type: Optional[DatasetSourceType] = None
26
+ name: Optional[str] = None
27
+
28
+
29
+ class ViewableEntityTypes(Enum):
30
+ ELN = "ELN"
31
+ CustomField = "CustomField"
@@ -4,12 +4,16 @@ from enum import Enum
4
4
  from typing import Any, Dict, List, Literal, Optional, Sequence
5
5
 
6
6
  from LOGS.Auxiliary.Constants import Constants
7
+ from LOGS.Entities.DatasetModels import ViewableEntityTypes
7
8
  from LOGS.Entities.ICustomSchemaRequest import ICustomSchemaRequest
8
9
  from LOGS.Entities.IRelatedEntityRequest import IRelatedEntityRequest
9
10
  from LOGS.Entity.EntityRequestParameter import EntityRequestParameter
11
+ from LOGS.Interfaces.ICreationRecord import ICreationRecordRequest
12
+ from LOGS.Interfaces.IModificationRecord import IModificationRecordRequest
10
13
  from LOGS.Interfaces.INamedEntity import INamedEntityRequest
11
14
  from LOGS.Interfaces.IOwnedEntity import IOwnedEntityRequest
12
15
  from LOGS.Interfaces.IPermissionedEntity import IPermissionedEntityRequest
16
+ from LOGS.Interfaces.IProjectBased import IProjectBasedRequest
13
17
  from LOGS.Interfaces.ISoftDeletable import ISoftDeletableRequest
14
18
  from LOGS.Interfaces.ITypedEntity import ITypedEntityRequest
15
19
  from LOGS.Interfaces.IUniqueEntity import IUniqueEntityRequest
@@ -30,22 +34,24 @@ class DatasetOrder(Enum):
30
34
  METHOD_DESC = "METHOD_DESC"
31
35
  EXPERIMENT_ASC = "EXPERIMENT_ASC"
32
36
  EXPERIMENT_DESC = "EXPERIMENT_DESC"
33
- DATE_ADDED_ASC = "DATE_ADDED_ASC"
34
- DATE_ADDED_DESC = "DATE_ADDED_DESC"
37
+ CREATED_ON_ASC = "CREATED_ON_ASC"
38
+ CREATED_ON_DESC = "CREATED_ON_DESC"
39
+ CREATED_BY_ASC = "CREATED_BY_ASC"
40
+ CREATED_BY_DESC = "CREATED_BY_DESC"
41
+ MODIFIED_ON_ASC = "MODIFIED_ON_ASC"
42
+ MODIFIED_ON_DESC = "MODIFIED_ON_DESC"
43
+ MODIFIED_BY_ASC = "MODIFIED_BY_ASC"
44
+ MODIFIED_BY_DESC = "MODIFIED_BY_DESC"
35
45
  INSTRUMENT_ASC = "INSTRUMENT_ASC"
36
46
  INSTRUMENT_DESC = "INSTRUMENT_DESC"
37
47
  SAMPLE_ASC = "SAMPLE_ASC"
38
48
  SAMPLE_DESC = "SAMPLE_DESC"
39
- FACILITY_ASC = "FACILITY_ASC"
40
- FACILITY_DESC = "FACILITY_DESC"
41
49
  PARSING_STATE_ASC = "PARSING_STATE_ASC"
42
50
  PARSING_STATE_DESC = "PARSING_STATE_DESC"
43
- PARSERID_ASC = "PARSERID_ASC"
44
- PARSERID_DESC = "PARSERID_DESC"
45
51
  FORMAT_ID_ASC = "FORMAT_ID_ASC"
46
52
  FORMAT_ID_DESC = "FORMAT_ID_DESC"
47
53
  TYPE_ASC = "TYPE_ASC"
48
- TYPE_DESC = "YPE_DESC"
54
+ TYPE_DESC = "TYPE_DESC"
49
55
 
50
56
 
51
57
  @dataclass
@@ -55,42 +61,49 @@ class DatasetRequestParameter(
55
61
  ITypedEntityRequest,
56
62
  ISoftDeletableRequest,
57
63
  ICustomSchemaRequest,
64
+ IProjectBasedRequest,
58
65
  IOwnedEntityRequest,
59
66
  INamedEntityRequest,
60
67
  IUniqueEntityRequest,
68
+ ICreationRecordRequest,
69
+ IModificationRecordRequest,
61
70
  IPermissionedEntityRequest,
62
71
  ):
63
- includeParameters: Optional[bool] = None
64
- methodIds: Optional[List[int]] = None
65
- formatIds: Optional[List[str]] = None
66
- experimentIds: Optional[List[int]] = None
67
- sampleIds: Optional[List[int]] = None
72
+
68
73
  acquisitionDateFrom: Optional[datetime] = None
69
74
  acquisitionDateTo: Optional[datetime] = None
70
- dateAddedFrom: Optional[datetime] = None
71
- dateAddedTo: Optional[datetime] = None
72
- operatorIds: Optional[List[int]] = None
73
- instrumentIds: Optional[List[int]] = None
74
- hasExperiment: Optional[bool] = None
75
- hasOperator: Optional[bool] = None
76
- documentIds: Optional[List[int]] = None
77
- equipmentIds: Optional[List[int]] = None
78
- projectIds: Optional[List[int]] = None
79
- organizationIds: Optional[List[int]] = None
80
75
  autoloadServerIds: Optional[List[int]] = None
81
- participatedPersonIds: Optional[List[int]] = None
82
- pathContains: Optional[str] = None
83
- parsingState: Optional[List[ParsingStates]] = None
84
76
  bridgeIds: Optional[List[int]] = None
85
77
  dataSourceIds: Optional[List[int]] = None
86
- orderBy: Optional[DatasetOrder] = None
87
- typeIds: Optional[List[str]] = None
78
+ documentIds: Optional[List[int]] = None
79
+ equipmentIds: Optional[List[int]] = None
80
+ excludeUndeleted: Optional[bool] = None
81
+ experimentIds: Optional[List[int]] = None
82
+ files: Optional[Sequence[Constants.FILE_TYPE]] = None
83
+ formatIds: Optional[List[str]] = None
84
+ hasExperiment: Optional[bool] = None
88
85
  hashes: Optional[List[str]] = None
89
- includeSoftDeleted: Optional[Optional[bool]] = None
90
- isSoftDeleted: Optional[Optional[bool]] = None
86
+ hasOperator: Optional[bool] = None
87
+ includeParameters: Optional[bool] = None
91
88
  includeParsingInfo: Optional[bool] = None
92
- isClaimed: Optional[Optional[bool]] = None
89
+ includeSoftDeleted: Optional[Optional[bool]] = None
93
90
  includeUnclaimed: Optional[Optional[bool]] = None
94
- files: Optional[Sequence[Constants.FILE_TYPE]] = None
95
- parameters: Optional[Dict[str, Any]] = None
91
+ instrumentIds: Optional[List[int]] = None
92
+ isClaimed: Optional[Optional[bool]] = None
96
93
  isReferencedByLabNotebook: Optional[Optional[bool]] = None
94
+ isViewableEntity: Optional[bool] = None
95
+ methodIds: Optional[List[int]] = None
96
+ names: Optional[List[str]] = None
97
+ operatorIds: Optional[List[int]] = None
98
+ orderBy: Optional[DatasetOrder] = None
99
+ organizationIds: Optional[List[int]] = None
100
+ originIds: Optional[List[int]] = None
101
+ parameters: Optional[Dict[str, Any]] = None
102
+ parsingState: Optional[List[ParsingStates]] = None
103
+ participatedPersonIds: Optional[List[int]] = None
104
+ pathContains: Optional[str] = None
105
+ sampleIds: Optional[List[int]] = None
106
+ searchTermIncludeNotes: Optional[bool] = None
107
+ searchTermIncludeParameters: Optional[bool] = None
108
+ searchTermIncludePaths: Optional[bool] = None
109
+ viewableEntityTypes: Optional[List[ViewableEntityTypes]] = None
@@ -1,34 +1,37 @@
1
+ import os
1
2
  from typing import Any, List, Literal, Optional, cast
2
3
 
3
- import numpy as np
4
-
5
4
  from LOGS.Auxiliary.Exceptions import (
6
5
  EntityIncompleteException,
7
6
  LOGSException,
8
7
  formatErrorMessage,
9
8
  )
10
9
  from LOGS.Entity.ConnectedEntity import ConnectedEntity
11
- from LOGS.LOGSConnection import ResponseTypes
10
+ from LOGS.LOGSConnection import LOGSConnection, ResponseTypes
12
11
 
13
- NumberTypeType = Literal["int", "float", "double"]
14
- DatatrackType = Literal[
12
+ _NumberTypeType = Literal["int", "float", "double"]
13
+ _DatatrackType = Literal[
15
14
  "binary", "char", "formatted_table", "image", "numeric_array", "numeric_matrix"
16
15
  ]
17
- CodecType = Literal["char", "jpeg", "points", "generator"]
16
+ _CodecType = Literal["char", "jpeg", "points", "generator"]
18
17
 
19
18
 
20
19
  class Datatrack(ConnectedEntity):
21
- _type: Optional[DatatrackType] = None
22
- _codec: Optional[CodecType] = None
20
+ _type: Optional[_DatatrackType] = None
21
+ _codec: Optional[_CodecType] = None
23
22
  _id: Optional[str] = None
24
23
  _count: Optional[int] = None
25
24
  _size: Optional[List[int]] = None
26
25
  _min: Optional[List[float]] = None
27
26
  _max: Optional[List[float]] = None
28
- _numberType: Optional[NumberTypeType] = None
27
+ _numberType: Optional[_NumberTypeType] = None
29
28
  _data: Optional[Any] = None
30
29
  _incomplete = True
31
30
 
31
+ def __init__(self, ref=None, connection: Optional[LOGSConnection] = None):
32
+ self._noSerialize += ["data"]
33
+ super().__init__(ref=ref, connection=connection)
34
+
32
35
  def _getConnectionData(self):
33
36
  if not self._endpoint:
34
37
  raise NotImplementedError(
@@ -40,22 +43,60 @@ class Datatrack(ConnectedEntity):
40
43
 
41
44
  return self._getConnection(), self._endpoint, self.id
42
45
 
46
+ def _fetchDataFromCache(self):
47
+ cacheFile = self._getCacheFile()
48
+ if cacheFile is None:
49
+ raise LOGSException("Cache directory not defined.")
50
+
51
+ if not os.path.exists(cacheFile):
52
+ return None
53
+
54
+ with open(cacheFile, "rb") as f:
55
+ return f.read()
56
+
57
+ def _getCacheFile(self):
58
+ if self.cacheDir is None:
59
+ return None
60
+
61
+ return os.path.join(self.cacheDir, self.cacheId + ".cache")
62
+
63
+ def _storeDataInCache(self, data):
64
+ cacheFile = self._getCacheFile()
65
+ if cacheFile is None:
66
+ raise LOGSException("Cache directory not defined.")
67
+ with open(cacheFile, "wb") as f:
68
+ f.write(data)
69
+
70
+ def clearCache(self):
71
+ cacheFile = self._getCacheFile()
72
+ if cacheFile is not None:
73
+ if os.path.exists(cacheFile):
74
+ os.remove(cacheFile)
75
+
43
76
  def _fetchData(self):
44
- connection, endpoint, id = self._getConnectionData()
77
+ data = None
78
+ if self.cacheDir:
79
+ data = self._fetchDataFromCache()
45
80
 
46
- data, responseError = connection.getEndpoint(
47
- endpoint + [id], responseType=ResponseTypes.RAW
48
- )
49
- if responseError:
50
- raise LOGSException(
51
- "Could not fetch %s: %s"
52
- % (type(self).__name__, formatErrorMessage(responseError.errors)),
53
- responseError=responseError,
81
+ if data is None:
82
+ connection, endpoint, id = self._getConnectionData()
83
+
84
+ data, responseError = connection.getEndpoint(
85
+ endpoint + [id], responseType=ResponseTypes.RAW
54
86
  )
87
+ if responseError:
88
+ raise LOGSException(
89
+ "Could not fetch %s: %s"
90
+ % (type(self).__name__, formatErrorMessage(responseError.errors)),
91
+ responseError=responseError,
92
+ )
93
+
94
+ if self.cacheDir:
95
+ self._storeDataInCache(data)
55
96
 
56
97
  self._data = data
57
98
 
58
- def fetchFull(self):
99
+ def fetchFull(self, cacheDir: Optional[str] = None):
59
100
  self._fetchData()
60
101
  self._incomplete = False
61
102
 
@@ -67,15 +108,11 @@ class Datatrack(ConnectedEntity):
67
108
  yield x
68
109
 
69
110
  @property
70
- def type(self) -> Optional[DatatrackType]:
111
+ def type(self) -> Optional[_DatatrackType]:
71
112
  return self._type
72
113
 
73
- @type.setter
74
- def type(self, value):
75
- self._type = cast(Any, self.checkAndConvertNullable(value, str, "type"))
76
-
77
114
  @property
78
- def codec(self) -> Optional[CodecType]:
115
+ def codec(self) -> Optional[_CodecType]:
79
116
  return self._codec
80
117
 
81
118
  @codec.setter
@@ -123,7 +160,7 @@ class Datatrack(ConnectedEntity):
123
160
  self._max = self.checkListAndConvertNullable(value, float, "max")
124
161
 
125
162
  @property
126
- def numberType(self) -> Optional[NumberTypeType]:
163
+ def numberType(self) -> Optional[_NumberTypeType]:
127
164
  return self._numberType
128
165
 
129
166
  @numberType.setter
@@ -133,7 +170,14 @@ class Datatrack(ConnectedEntity):
133
170
  )
134
171
 
135
172
  @property
136
- def data(self) -> Optional[np.ndarray]:
137
- if self._incomplete:
138
- raise EntityIncompleteException(self)
139
- return self._data
173
+ def data(self) -> Optional[Any]:
174
+ raise NotImplementedError(
175
+ "Field 'data' of %a class not implemented." % type(self).__name__
176
+ )
177
+
178
+ @property
179
+ def cacheId(self) -> str:
180
+ if self._cacheId is None:
181
+ return f"{self.type}_{self.id}"
182
+ else:
183
+ return self._cacheId
@@ -0,0 +1,25 @@
1
+ import json
2
+ from typing import Optional, cast
3
+
4
+ from LOGS.Auxiliary.Exceptions import EntityIncompleteException
5
+ from LOGS.Entities.Datatrack import Datatrack
6
+ from LOGS.Entities.FormattedTable.DatatypeFormattedTable import DatatypeFormattedTable
7
+
8
+
9
+ class DatatrackFormattedTable(Datatrack):
10
+ _type = "formatted_table"
11
+ _data: Optional[DatatypeFormattedTable] = None
12
+
13
+ def _fetchData(self):
14
+ super()._fetchData()
15
+
16
+ if self._data is not None:
17
+ # s = cast(bytes, self._data).decode("utf-8")
18
+ b = cast(bytes, self._data).split(b"\x00")[0]
19
+ self._data = DatatypeFormattedTable(json.loads(b.decode("utf-8")))
20
+
21
+ @property
22
+ def data(self) -> Optional[DatatypeFormattedTable]:
23
+ if self._incomplete:
24
+ raise EntityIncompleteException(self)
25
+ return self._data
@@ -0,0 +1,34 @@
1
+ from typing import Optional, cast
2
+
3
+ from LOGS.Auxiliary.Exceptions import EntityIncompleteException
4
+ from LOGS.Entities.Datatrack import Datatrack
5
+
6
+
7
+ class DatatrackGeneric(Datatrack):
8
+ _type = "formatted_table"
9
+ _data: Optional[str] = None
10
+
11
+ def _fetchData(self):
12
+ super()._fetchData()
13
+
14
+ if self._data is not None:
15
+ s = cast(bytes, self._data)
16
+ try:
17
+ self._data = s.decode()
18
+ return
19
+ except:
20
+ pass
21
+
22
+ try:
23
+ self._data = s.decode("latin-1")
24
+ return
25
+ except:
26
+ pass
27
+
28
+ self._data = None
29
+
30
+ @property
31
+ def data(self) -> Optional[str]:
32
+ if self._incomplete:
33
+ raise EntityIncompleteException(self)
34
+ return self._data
@@ -0,0 +1,25 @@
1
+ from io import BytesIO
2
+ from typing import Optional, cast
3
+
4
+ import PIL.Image
5
+ from PIL.Image import Image
6
+
7
+ from LOGS.Auxiliary.Exceptions import EntityIncompleteException
8
+ from LOGS.Entities.Datatrack import Datatrack
9
+
10
+
11
+ class DatatrackImage(Datatrack):
12
+ _type = "image"
13
+ _data: Optional[Image] = None
14
+
15
+ def _fetchData(self):
16
+ super()._fetchData()
17
+
18
+ if self._data:
19
+ self._data = PIL.Image.open(BytesIO(cast(bytes, self._data)))
20
+
21
+ @property
22
+ def data(self) -> Optional[Image]:
23
+ if self._incomplete:
24
+ raise EntityIncompleteException(self)
25
+ return self._data
@@ -1,51 +1,15 @@
1
- from typing import Literal, Optional, cast
1
+ from typing import Optional, cast
2
2
 
3
3
  import numpy as np
4
4
 
5
- from LOGS.Auxiliary.Exceptions import (
6
- EntityIncompleteException,
7
- LOGSException,
8
- formatErrorMessage,
9
- )
5
+ from LOGS.Auxiliary.Exceptions import EntityIncompleteException
10
6
  from LOGS.Entities.Datatrack import Datatrack
11
- from LOGS.LOGSConnection import ResponseTypes
12
-
13
- NumberTypeType = Literal["int", "float", "double"]
14
- DatatrackType = Literal[
15
- "binary", "char", "formatted_table", "image", "numeric_array", "numeric_matrix"
16
- ]
17
- CodecType = Literal["char", "jpeg", "points", "generator"]
18
7
 
19
8
 
20
9
  class DatatrackNumericArray(Datatrack):
10
+ _type = "numeric_array"
21
11
  _data: Optional[np.ndarray] = None
22
12
 
23
- def _getConnectionData(self):
24
- if not self._endpoint:
25
- raise NotImplementedError(
26
- "Endpoint missing for of entity type %a." % (type(self).__name__)
27
- )
28
-
29
- if not self.id:
30
- raise LOGSException("%s id is not defined." % type(self).__name__)
31
-
32
- return self._getConnection(), self._endpoint, self.id
33
-
34
- def _fetchData(self):
35
- connection, endpoint, id = self._getConnectionData()
36
-
37
- data, responseError = connection.getEndpoint(
38
- endpoint + [id], responseType=ResponseTypes.RAW
39
- )
40
- if responseError:
41
- raise LOGSException(
42
- "Could not fetch %s: %s"
43
- % (type(self).__name__, formatErrorMessage(responseError.errors)),
44
- responseError=responseError,
45
- )
46
-
47
- self._data = np.frombuffer(cast(bytes, data), dtype=np.double)
48
-
49
13
  def __iter__(self):
50
14
  if self._incomplete:
51
15
  raise EntityIncompleteException(self)
@@ -53,6 +17,12 @@ class DatatrackNumericArray(Datatrack):
53
17
  for x in self._data:
54
18
  yield x
55
19
 
20
+ def _fetchData(self):
21
+ super()._fetchData()
22
+
23
+ if self._data:
24
+ self._data = np.frombuffer(cast(bytes, self._data), dtype=np.double)
25
+
56
26
  @property
57
27
  def data(self) -> Optional[np.ndarray]:
58
28
  if self._incomplete:
@@ -0,0 +1,86 @@
1
+ from typing import Optional, Tuple, cast
2
+
3
+ import numpy as np
4
+
5
+ from LOGS.Auxiliary.Exceptions import EntityIncompleteException
6
+ from LOGS.Entities.Datatrack import Datatrack
7
+
8
+
9
+ class DatatrackNumericMatrix(Datatrack):
10
+ _type = "numeric_matrix"
11
+ _data: Optional[np.ndarray] = None
12
+
13
+ def __iter__(self):
14
+ if self._incomplete:
15
+ raise EntityIncompleteException(self)
16
+
17
+ if self.size is None:
18
+ raise ValueError("Datatrack has no size defined.")
19
+
20
+ if self._data is not None:
21
+ for x in range(self.size[0]):
22
+ for y in range(self.size[1]):
23
+ yield x, y
24
+
25
+ def _fetchData(self):
26
+ super()._fetchData()
27
+
28
+ if self._data and self.size and len(self.size) > 1:
29
+ self._data = np.frombuffer(cast(bytes, self._data), dtype=np.double)
30
+ self._data = self._data.reshape((self.size[1], self.size[0]))
31
+ self._data = self._data.T
32
+
33
+ def getCoordinate(self, index: Tuple[int, int]):
34
+ if self._incomplete:
35
+ raise EntityIncompleteException(self)
36
+ if self.min is None or self.max is None or self.size is None:
37
+ return None
38
+
39
+ return (
40
+ self.min[0] + index[0] * (self.max[0] - self.min[0]) / self.size[0],
41
+ self.min[1] + index[1] * (self.max[1] - self.min[1]) / self.size[1],
42
+ )
43
+
44
+ def getIndex(self, coord: Tuple[float, float]):
45
+ if self._incomplete:
46
+ raise EntityIncompleteException(self)
47
+ if self.min is None or self.max is None or self.size is None:
48
+ raise ValueError("Datatrack has no min, max or size defined.")
49
+
50
+ return (
51
+ int((coord[0] - self.min[0]) * self.size[0] / (self.max[0] - self.min[0])),
52
+ int((coord[1] - self.min[1]) * self.size[1] / (self.max[1] - self.min[1])),
53
+ )
54
+
55
+ def getValueFromCoordinate(self, coord: Tuple[float, float]):
56
+ if self._incomplete:
57
+ raise EntityIncompleteException(self)
58
+ if self._data is None:
59
+ return None
60
+
61
+ return self.getValueFromIndex(self.getIndex(coord))
62
+
63
+ def getValueFromIndex(self, index: Tuple[int, int]):
64
+ if self._incomplete:
65
+ raise EntityIncompleteException(self)
66
+ if self._data is None:
67
+ return None
68
+
69
+ if self.size is None:
70
+ raise ValueError("Datatrack has no size defined.")
71
+
72
+ if (
73
+ index[0] < 0
74
+ or index[0] >= self.size[0]
75
+ or index[1] < 0
76
+ or index[1] >= self.size[1]
77
+ ):
78
+ raise ValueError("Index out of bounds.")
79
+
80
+ return self._data[index]
81
+
82
+ @property
83
+ def data(self) -> Optional[np.ndarray]:
84
+ if self._incomplete:
85
+ raise EntityIncompleteException(self)
86
+ return self._data
@@ -3,16 +3,16 @@ from datetime import datetime
3
3
  from typing import List, Optional
4
4
 
5
5
  from LOGS.Entity.EntityRequestParameter import EntityRequestParameter
6
+ from LOGS.Interfaces.IProjectBased import IProjectBasedRequest
6
7
 
7
8
 
8
9
  @dataclass
9
- class DocumentRequestParameter(EntityRequestParameter):
10
+ class DocumentRequestParameter(EntityRequestParameter, IProjectBasedRequest):
10
11
  name: Optional[str] = None
11
12
  creationDate: Optional[datetime] = None
12
13
  publicationTypes: Optional[List[int]] = None
13
14
  doi: Optional[str] = None
14
15
  authorIds: Optional[List[int]] = None
15
- projectIds: Optional[List[int]] = None
16
16
  datasetIds: Optional[List[int]] = None
17
17
  documentIds: Optional[List[int]] = None
18
18
  sampleIds: Optional[List[int]] = None
@@ -1,5 +1,5 @@
1
1
  from dataclasses import dataclass
2
- from typing import List, Optional, Union
2
+ from typing import List, Optional, Sequence, Union
3
3
  from uuid import UUID
4
4
 
5
5
  from LOGS.Entity.SerializeableContent import SerializeableClass
@@ -8,5 +8,5 @@ from LOGS.Entity.SerializeableContent import SerializeableClass
8
8
  @dataclass
9
9
  class EntitiesRequestParameter(SerializeableClass):
10
10
  _noSerialize = ["asString"]
11
- uids: Optional[List[Union[str, UUID]]] = None
11
+ uids: Optional[Sequence[Union[str, UUID]]] = None
12
12
  names: Optional[List[str]] = None
@@ -9,7 +9,7 @@ from LOGS.Interfaces.ICreationRecord import ICreationRecord
9
9
  from LOGS.Interfaces.IModificationRecord import IModificationRecord
10
10
  from LOGS.Interfaces.INamedEntity import INamedEntity
11
11
  from LOGS.Interfaces.IOwnedEntity import IOwnedEntity
12
- from LOGS.Interfaces.IPermissionedEntity import IPermissionedEntity
12
+ from LOGS.Interfaces.IPermissionedEntity import GenericPermissionEntity
13
13
  from LOGS.Interfaces.IRelatedEntity import IRelatedEntity
14
14
  from LOGS.Interfaces.IUniqueEntity import IUniqueEntity
15
15
  from LOGS.LOGSConnection import LOGSConnection
@@ -24,9 +24,9 @@ class Experiment(
24
24
  IModificationRecord,
25
25
  IOwnedEntity,
26
26
  IRelatedEntity[ExperimentRelations],
27
- IPermissionedEntity,
27
+ GenericPermissionEntity,
28
28
  ):
29
- _relationType = type(ExperimentRelations)
29
+ _relationType = ExperimentRelations
30
30
 
31
31
  _method: Optional[MethodMinimal]
32
32
  _notes: Optional[str]
@@ -0,0 +1,8 @@
1
+ from typing import Optional
2
+
3
+ from LOGS.Entity.SerializeableContent import SerializeableClass
4
+
5
+
6
+ class FileExcludePattern(SerializeableClass):
7
+ name: Optional[str] = None
8
+ regex: Optional[str] = None