sapiopycommons 2025.7.8a581__py3-none-any.whl → 2025.7.9a582__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 sapiopycommons might be problematic. Click here for more details.
- sapiopycommons/ai/__init__.py +0 -0
- sapiopycommons/ai/api/fielddefinitions/proto/fields_pb2.py +43 -0
- sapiopycommons/ai/api/fielddefinitions/proto/fields_pb2.pyi +31 -0
- sapiopycommons/ai/api/fielddefinitions/proto/fields_pb2_grpc.py +24 -0
- sapiopycommons/ai/api/fielddefinitions/proto/velox_field_def_pb2.py +123 -0
- sapiopycommons/ai/api/fielddefinitions/proto/velox_field_def_pb2.pyi +598 -0
- sapiopycommons/ai/api/fielddefinitions/proto/velox_field_def_pb2_grpc.py +24 -0
- sapiopycommons/ai/api/plan/proto/step_output_pb2.py +45 -0
- sapiopycommons/ai/api/plan/proto/step_output_pb2.pyi +42 -0
- sapiopycommons/ai/api/plan/proto/step_output_pb2_grpc.py +24 -0
- sapiopycommons/ai/api/plan/proto/step_pb2.py +43 -0
- sapiopycommons/ai/api/plan/proto/step_pb2.pyi +43 -0
- sapiopycommons/ai/api/plan/proto/step_pb2_grpc.py +24 -0
- sapiopycommons/ai/api/plan/script/proto/script_pb2.py +55 -0
- sapiopycommons/ai/api/plan/script/proto/script_pb2.pyi +115 -0
- sapiopycommons/ai/api/plan/script/proto/script_pb2_grpc.py +153 -0
- sapiopycommons/ai/api/plan/tool/proto/entry_pb2.py +57 -0
- sapiopycommons/ai/api/plan/tool/proto/entry_pb2.pyi +96 -0
- sapiopycommons/ai/api/plan/tool/proto/entry_pb2_grpc.py +24 -0
- sapiopycommons/ai/api/plan/tool/proto/tool_pb2.py +67 -0
- sapiopycommons/ai/api/plan/tool/proto/tool_pb2.pyi +220 -0
- sapiopycommons/ai/api/plan/tool/proto/tool_pb2_grpc.py +154 -0
- sapiopycommons/ai/api/session/proto/sapio_conn_info_pb2.py +39 -0
- sapiopycommons/ai/api/session/proto/sapio_conn_info_pb2.pyi +32 -0
- sapiopycommons/ai/api/session/proto/sapio_conn_info_pb2_grpc.py +24 -0
- sapiopycommons/ai/protobuf_utils.py +508 -0
- sapiopycommons/ai/test_client.py +251 -0
- sapiopycommons/ai/tool_service_base.py +798 -0
- sapiopycommons/callbacks/callback_util.py +332 -665
- sapiopycommons/callbacks/field_builder.py +0 -2
- sapiopycommons/chem/IndigoMolecules.py +1 -31
- sapiopycommons/chem/Molecules.py +3 -3
- sapiopycommons/customreport/auto_pagers.py +1 -26
- sapiopycommons/customreport/term_builder.py +1 -1
- sapiopycommons/datatype/pseudo_data_types.py +326 -349
- sapiopycommons/eln/experiment_handler.py +767 -408
- sapiopycommons/eln/experiment_report_util.py +6 -11
- sapiopycommons/eln/plate_designer.py +2 -7
- sapiopycommons/files/file_util.py +5 -7
- sapiopycommons/general/accession_service.py +2 -2
- sapiopycommons/general/aliases.py +1 -3
- sapiopycommons/general/audit_log.py +0 -7
- sapiopycommons/general/custom_report_util.py +0 -12
- sapiopycommons/processtracking/custom_workflow_handler.py +1 -11
- sapiopycommons/processtracking/endpoints.py +0 -27
- sapiopycommons/recordmodel/record_handler.py +317 -657
- sapiopycommons/rules/eln_rule_handler.py +1 -8
- sapiopycommons/rules/on_save_rule_handler.py +1 -8
- sapiopycommons/webhook/webhook_handlers.py +0 -3
- sapiopycommons/webhook/webservice_handlers.py +2 -2
- {sapiopycommons-2025.7.8a581.dist-info → sapiopycommons-2025.7.9a582.dist-info}/METADATA +2 -2
- sapiopycommons-2025.7.9a582.dist-info/RECORD +92 -0
- sapiopycommons/chem/ps_commons.py +0 -455
- sapiopycommons/eln/experiment_cache.py +0 -188
- sapiopycommons/eln/experiment_step_factory.py +0 -476
- sapiopycommons/eln/step_creation.py +0 -236
- sapiopycommons/general/data_structure_util.py +0 -115
- sapiopycommons-2025.7.8a581.dist-info/RECORD +0 -69
- {sapiopycommons-2025.7.8a581.dist-info → sapiopycommons-2025.7.9a582.dist-info}/WHEEL +0 -0
- {sapiopycommons-2025.7.8a581.dist-info → sapiopycommons-2025.7.9a582.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from weakref import WeakValueDictionary
|
|
4
|
-
|
|
5
|
-
from sapiopylib.rest.ELNService import ElnManager
|
|
6
|
-
from sapiopylib.rest.User import SapioUser
|
|
7
|
-
from sapiopylib.rest.pojo.datatype.FieldDefinition import AbstractVeloxFieldDefinition
|
|
8
|
-
from sapiopylib.rest.pojo.eln.ElnExperiment import ElnTemplate, TemplateExperimentQuery
|
|
9
|
-
from sapiopylib.rest.pojo.eln.SapioELNEnums import ElnBaseDataType
|
|
10
|
-
from sapiopylib.rest.pojo.eln.field_set import ElnFieldSetInfo
|
|
11
|
-
from sapiopylib.rest.pojo.eln.protocol_template import ProtocolTemplateInfo, ProtocolTemplateQuery
|
|
12
|
-
|
|
13
|
-
from sapiopycommons.general.aliases import UserIdentifier, AliasUtil
|
|
14
|
-
from sapiopycommons.general.exceptions import SapioException
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
# FR-47530: Created a class that caches experiment template and predefined field information.
|
|
18
|
-
class ExperimentCacheManager:
|
|
19
|
-
"""
|
|
20
|
-
A class to manage the caching of experiment-related information.
|
|
21
|
-
"""
|
|
22
|
-
user: SapioUser
|
|
23
|
-
eln_man: ElnManager
|
|
24
|
-
|
|
25
|
-
_templates: list[ElnTemplate]
|
|
26
|
-
"""A list of experiment templates. Only cached when first accessed."""
|
|
27
|
-
_protocols: list[ProtocolTemplateInfo]
|
|
28
|
-
"""A list of protocol templates. Only cached when first accessed."""
|
|
29
|
-
_field_sets: dict[str, ElnFieldSetInfo]
|
|
30
|
-
"""A dictionary of field set name to field set. Only cached when first accessed."""
|
|
31
|
-
_field_set_fields: dict[int, list[AbstractVeloxFieldDefinition]]
|
|
32
|
-
"""A dictionary of field set ID to field definitions. Only cached when first accessed."""
|
|
33
|
-
_predefined_fields: dict[str, dict[str, AbstractVeloxFieldDefinition]]
|
|
34
|
-
"""A dictionary of ELN data type name to predefined field definitions. Only cached when first accessed."""
|
|
35
|
-
|
|
36
|
-
__instances: WeakValueDictionary[SapioUser, ExperimentCacheManager] = WeakValueDictionary()
|
|
37
|
-
__initialized: bool
|
|
38
|
-
|
|
39
|
-
def __new__(cls, context: UserIdentifier):
|
|
40
|
-
"""
|
|
41
|
-
:param context: The current webhook context or a user object to send requests from.
|
|
42
|
-
"""
|
|
43
|
-
user = AliasUtil.to_sapio_user(context)
|
|
44
|
-
obj = cls.__instances.get(user)
|
|
45
|
-
if not obj:
|
|
46
|
-
obj = object.__new__(cls)
|
|
47
|
-
obj.__initialized = False
|
|
48
|
-
cls.__instances[user] = obj
|
|
49
|
-
return obj
|
|
50
|
-
|
|
51
|
-
def __init__(self, context: UserIdentifier):
|
|
52
|
-
"""
|
|
53
|
-
:param context: The current webhook context or a user object to send requests from.
|
|
54
|
-
"""
|
|
55
|
-
if self.__initialized:
|
|
56
|
-
return
|
|
57
|
-
self.__initialized = True
|
|
58
|
-
|
|
59
|
-
self.user = AliasUtil.to_sapio_user(context)
|
|
60
|
-
self.eln_man = ElnManager(self.user)
|
|
61
|
-
|
|
62
|
-
self._field_set_fields = {}
|
|
63
|
-
self._predefined_fields = {}
|
|
64
|
-
|
|
65
|
-
def get_experiment_template(self, name: str, active: bool = True, version: int | None = None,
|
|
66
|
-
first_match: bool = False, public: bool | None = True) -> ElnTemplate:
|
|
67
|
-
"""
|
|
68
|
-
Get the experiment template with the given information.
|
|
69
|
-
|
|
70
|
-
:param name: The name of the template.
|
|
71
|
-
:param active: Whether the template is marked as active.
|
|
72
|
-
:param version: The version of the template to get. If None, the latest version will be returned.
|
|
73
|
-
:param first_match: If true, returns the first match found. If false, raises an exception.
|
|
74
|
-
:param public: Whether the template is public. If true, only pubic templates will be queried. If false, only
|
|
75
|
-
private templates will be queried. If None, both public and private templates will be queried. Non-public
|
|
76
|
-
templates do not have a version number, so this will always fail if public is false and a version number is
|
|
77
|
-
provided.
|
|
78
|
-
:return: The experiment template with the given information.
|
|
79
|
-
"""
|
|
80
|
-
if not hasattr(self, "_templates"):
|
|
81
|
-
query = TemplateExperimentQuery()
|
|
82
|
-
query.active_templates_only = False
|
|
83
|
-
query.latest_version_only = False
|
|
84
|
-
self._templates = self.eln_man.get_template_experiment_list(query)
|
|
85
|
-
return self._find_template(self._templates, name, active, version, first_match, public)
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
def get_protocol_template(self, name: str, active: bool = True, version: int | None = None,
|
|
89
|
-
first_match: bool = False, public: bool | None = True) -> ProtocolTemplateInfo:
|
|
90
|
-
"""
|
|
91
|
-
Get the protocol template with the given information. Will throw an exception if multiple templates match
|
|
92
|
-
the given information.
|
|
93
|
-
|
|
94
|
-
:param name: The name of the template.
|
|
95
|
-
:param active: Whether the template is marked as active.
|
|
96
|
-
:param version: The version of the template to get. If None, the latest version will be returned.
|
|
97
|
-
:param first_match: If true, returns the first match found. If false, raises an exception.
|
|
98
|
-
:param public: Whether the template is public. If true, only pubic templates will be queried. If false, only
|
|
99
|
-
private templates will be queried. If None, both public and private templates will be queried. Non-public
|
|
100
|
-
templates do not have a version number, so this will always fail if public is false and a version number is
|
|
101
|
-
provided.
|
|
102
|
-
:return: The protocol template with the given information.
|
|
103
|
-
"""
|
|
104
|
-
if not hasattr(self, "_protocols"):
|
|
105
|
-
query = ProtocolTemplateQuery()
|
|
106
|
-
query.active_templates_only = False
|
|
107
|
-
query.latest_version_only = False
|
|
108
|
-
self._protocols = self.eln_man.get_protocol_template_info_list(query)
|
|
109
|
-
return self._find_template(self._protocols, name, active, version, first_match, public)
|
|
110
|
-
|
|
111
|
-
@staticmethod
|
|
112
|
-
def _find_template(templates: list[ElnTemplate] | list[ProtocolTemplateInfo], name: str, active: bool,
|
|
113
|
-
version: int, first_match: bool, public: bool | None) -> ElnTemplate | ProtocolTemplateInfo:
|
|
114
|
-
"""
|
|
115
|
-
Find the experiment or protocol template with the given information.
|
|
116
|
-
"""
|
|
117
|
-
matches = []
|
|
118
|
-
for template in templates:
|
|
119
|
-
if template.template_name != name:
|
|
120
|
-
continue
|
|
121
|
-
if template.active != active:
|
|
122
|
-
continue
|
|
123
|
-
if version is not None and template.template_version != version:
|
|
124
|
-
continue
|
|
125
|
-
if public is True and template.template_version is None:
|
|
126
|
-
continue
|
|
127
|
-
if public is False and template.template_version is not None:
|
|
128
|
-
continue
|
|
129
|
-
matches.append(template)
|
|
130
|
-
if not matches:
|
|
131
|
-
raise SapioException(f"No template with the name \"{name}\"" +
|
|
132
|
-
("" if version is None else f" and the version {version}") +
|
|
133
|
-
f" found.")
|
|
134
|
-
# Only filter for the max version number if any of the matches actually have a version number.
|
|
135
|
-
versioned_matches = [x for x in matches if x.template_version is not None]
|
|
136
|
-
if version is None and versioned_matches:
|
|
137
|
-
return max(versioned_matches, key=lambda x: x.template_version)
|
|
138
|
-
if len(matches) > 1 and not first_match:
|
|
139
|
-
raise SapioException(f"Multiple templates with the name \"{name}\" found. Consider setting first_match to "
|
|
140
|
-
f"true, or restrict your search criteria further.")
|
|
141
|
-
return matches[0]
|
|
142
|
-
|
|
143
|
-
def get_predefined_field(self, field_name: str, data_type: ElnBaseDataType) -> AbstractVeloxFieldDefinition:
|
|
144
|
-
"""
|
|
145
|
-
Get the predefined field of the given name for the given ELN data type.
|
|
146
|
-
|
|
147
|
-
:param field_name: The name of the field.
|
|
148
|
-
:param data_type: The ELN data type of the field.
|
|
149
|
-
:return: The predefined field of the given name for the given ELN data type.
|
|
150
|
-
"""
|
|
151
|
-
return self.get_predefined_fields(data_type)[field_name]
|
|
152
|
-
|
|
153
|
-
def get_predefined_fields(self, data_type: ElnBaseDataType) -> dict[str, AbstractVeloxFieldDefinition]:
|
|
154
|
-
"""
|
|
155
|
-
Get the predefined fields for the given ELN data type.
|
|
156
|
-
|
|
157
|
-
:param data_type: The ELN data type to get the predefined fields for.
|
|
158
|
-
:return: A dictionary of field name to field definition for the given ELN data type.
|
|
159
|
-
"""
|
|
160
|
-
if data_type.data_type_name not in self._predefined_fields:
|
|
161
|
-
fields: list[AbstractVeloxFieldDefinition] = self.eln_man.get_predefined_fields(data_type)
|
|
162
|
-
self._predefined_fields[data_type.data_type_name] = {x.data_field_name: x for x in fields}
|
|
163
|
-
return self._predefined_fields[data_type.data_type_name]
|
|
164
|
-
|
|
165
|
-
def get_field_set(self, name: str) -> ElnFieldSetInfo:
|
|
166
|
-
"""
|
|
167
|
-
Get the field set with the given name.
|
|
168
|
-
|
|
169
|
-
:param name: The name of the field set.
|
|
170
|
-
:return: The field set with the given name.
|
|
171
|
-
"""
|
|
172
|
-
if not hasattr(self, "_field_sets"):
|
|
173
|
-
self._field_sets = {x.field_set_name: x for x in self.eln_man.get_field_set_info_list()}
|
|
174
|
-
return self._field_sets[name]
|
|
175
|
-
|
|
176
|
-
def get_field_set_fields(self, field_set: ElnFieldSetInfo | int) -> list[AbstractVeloxFieldDefinition]:
|
|
177
|
-
"""
|
|
178
|
-
Get the fields of the given field set.
|
|
179
|
-
|
|
180
|
-
:param field_set: The field set to get the fields from. Can be either an ElnFieldSetInfo object or an integer
|
|
181
|
-
for the set ID.
|
|
182
|
-
:return: The fields of the given field set.
|
|
183
|
-
"""
|
|
184
|
-
field_set: int = field_set if isinstance(field_set, int) else field_set.field_set_id
|
|
185
|
-
if field_set in self._field_set_fields:
|
|
186
|
-
return self._field_set_fields[field_set]
|
|
187
|
-
self._field_set_fields[field_set] = self.eln_man.get_predefined_fields_from_field_set_id(field_set)
|
|
188
|
-
return self._field_set_fields[field_set]
|
|
@@ -1,476 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from collections.abc import Iterable
|
|
4
|
-
from typing import cast
|
|
5
|
-
|
|
6
|
-
from sapiopycommons.datatype.data_fields import SystemFields
|
|
7
|
-
from sapiopycommons.eln.step_creation import StepCreation, AttachmentStepCreation, GlobalDtFormStepCreation, \
|
|
8
|
-
ELnDtFormStepCreation, PluginStepCreation, TextStepCreation, TempDataStepCreation, ELnDtTableStepCreation, \
|
|
9
|
-
GlobalDtTableStepCreation, DashboardStepCreation
|
|
10
|
-
from sapiopycommons.eln.experiment_cache import ExperimentCacheManager
|
|
11
|
-
from sapiopycommons.eln.experiment_handler import ExperimentHandler, Step
|
|
12
|
-
from sapiopycommons.eln.experiment_tags import PLATE_DESIGNER_PLUGIN
|
|
13
|
-
from sapiopycommons.general.aliases import AliasUtil, SapioRecord, DataTypeIdentifier, FieldMap, \
|
|
14
|
-
ExperimentEntryIdentifier
|
|
15
|
-
from sapiopycommons.general.exceptions import SapioException
|
|
16
|
-
from sapiopylib.rest.DataRecordManagerService import DataRecordManager
|
|
17
|
-
from sapiopylib.rest.ELNService import ElnManager
|
|
18
|
-
from sapiopylib.rest.User import SapioUser
|
|
19
|
-
from sapiopylib.rest.pojo.DataRecord import DataRecord
|
|
20
|
-
from sapiopylib.rest.pojo.TableColumn import TableColumn
|
|
21
|
-
from sapiopylib.rest.pojo.eln.ElnEntryPosition import ElnEntryPosition
|
|
22
|
-
from sapiopylib.rest.pojo.eln.ExperimentEntry import EntryAttachment, EntryRecordAttachment
|
|
23
|
-
from sapiopylib.rest.pojo.eln.ExperimentEntryCriteria import ExperimentEntryCriteriaUtil, AbstractElnEntryCriteria, \
|
|
24
|
-
ElnAttachmentEntryCriteria, \
|
|
25
|
-
ElnFormEntryCriteria, ElnPluginEntryCriteria, ElnTextEntryCriteria, ElnTempDataEntryCriteria, ElnTableEntryCriteria, \
|
|
26
|
-
ElnDashboardEntryCriteria
|
|
27
|
-
from sapiopylib.rest.pojo.eln.SapioELNEnums import ElnBaseDataType
|
|
28
|
-
from sapiopylib.rest.pojo.eln.eln_headings import ElnExperimentTab
|
|
29
|
-
from sapiopylib.rest.pojo.eln.field_set import ElnFieldSetInfo
|
|
30
|
-
from sapiopylib.rest.utils.Protocols import ElnEntryStep
|
|
31
|
-
from sapiopylib.rest.utils.plates.MultiLayerPlating import MultiLayerPlateConfig, MultiLayerPlateLayer, \
|
|
32
|
-
MultiLayerDataTypeConfig, MultiLayerReplicateConfig, MultiLayerDilutionConfig
|
|
33
|
-
from sapiopylib.rest.utils.plates.MultiLayerPlatingUtils import MultiLayerPlatingManager
|
|
34
|
-
from sapiopylib.rest.utils.plates.PlatingUtils import PlatingOrder
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
# CR-47564: Moved the entry creation functions to their own class.
|
|
38
|
-
class ExperimentStepFactory:
|
|
39
|
-
user: SapioUser
|
|
40
|
-
_exp_handler: ExperimentHandler
|
|
41
|
-
|
|
42
|
-
_exp_id: int
|
|
43
|
-
|
|
44
|
-
_eln_man: ElnManager
|
|
45
|
-
_exp_cache: ExperimentCacheManager
|
|
46
|
-
|
|
47
|
-
def __init__(self, exp_handler: ExperimentHandler):
|
|
48
|
-
self.user = exp_handler.user
|
|
49
|
-
self._exp_handler = exp_handler
|
|
50
|
-
self._exp_id = exp_handler.protocol.get_id()
|
|
51
|
-
self._eln_man = ElnManager(self.user)
|
|
52
|
-
self._exp_cache = ExperimentCacheManager(self.user)
|
|
53
|
-
|
|
54
|
-
# FR-47468: Add functions for creating new entries in the experiment.
|
|
55
|
-
def create_attachment_step(self, entry_name: str, data_type: DataTypeIdentifier,
|
|
56
|
-
attachments: Iterable[EntryAttachment] | Iterable[SapioRecord] | None = None,
|
|
57
|
-
criteria: AttachmentStepCreation = AttachmentStepCreation(),
|
|
58
|
-
position: ElnEntryPosition | None = None) -> ElnEntryStep:
|
|
59
|
-
"""
|
|
60
|
-
Create a new attachment entry in the experiment.
|
|
61
|
-
|
|
62
|
-
:param entry_name: The name of the entry.
|
|
63
|
-
:param data_type: The data type of the entry.
|
|
64
|
-
:param attachments: The list of attachments to initially populate the entry with.
|
|
65
|
-
:param criteria: Additional criteria for creating the entry.
|
|
66
|
-
:param position: Information about where to place the entry in the experiment.
|
|
67
|
-
:return: The newly created attachment entry.
|
|
68
|
-
"""
|
|
69
|
-
entry_criteria = cast(ElnAttachmentEntryCriteria,
|
|
70
|
-
self._create_step_criteria(entry_name, data_type, criteria, position))
|
|
71
|
-
|
|
72
|
-
if attachments:
|
|
73
|
-
entry_attachments: list[EntryAttachment] = []
|
|
74
|
-
for entry in attachments:
|
|
75
|
-
if isinstance(entry, EntryAttachment):
|
|
76
|
-
entry_attachments.append(entry)
|
|
77
|
-
elif isinstance(entry, SapioRecord):
|
|
78
|
-
entry: SapioRecord
|
|
79
|
-
file_name: str = entry.get_field_value("FilePath")
|
|
80
|
-
if not file_name:
|
|
81
|
-
file_name = entry.get_field_value(SystemFields.DATA_RECORD_NAME__FIELD.field_name)
|
|
82
|
-
rec_id: int = AliasUtil.to_record_id(entry)
|
|
83
|
-
entry_attachments.append(EntryRecordAttachment(file_name, rec_id))
|
|
84
|
-
else:
|
|
85
|
-
raise SapioException("Attachments must be of type EntryAttachment or SapioRecord.")
|
|
86
|
-
entry_criteria.entry_attachment_list = entry_attachments
|
|
87
|
-
|
|
88
|
-
step = self._exp_handler.add_entry_to_caches(self._eln_man.add_experiment_entry(self._exp_id, entry_criteria))
|
|
89
|
-
return step
|
|
90
|
-
|
|
91
|
-
def create_dashboard_step(self, entry_name, data_type: DataTypeIdentifier,
|
|
92
|
-
criteria: DashboardStepCreation = DashboardStepCreation(),
|
|
93
|
-
position: ElnEntryPosition | None = None) -> ElnEntryStep:
|
|
94
|
-
entry_criteria = cast(ElnDashboardEntryCriteria,
|
|
95
|
-
self._create_step_criteria(entry_name, data_type, criteria, position))
|
|
96
|
-
|
|
97
|
-
if criteria:
|
|
98
|
-
if entry_criteria.source_entry_id:
|
|
99
|
-
entry_criteria.source_entry_id = self.__to_entry_ids([criteria.source_entry])[0]
|
|
100
|
-
if criteria.dashboard_guids:
|
|
101
|
-
entry_criteria.dashboard_guid_list = list(criteria.dashboard_guids)
|
|
102
|
-
|
|
103
|
-
step = self._exp_handler.add_entry_to_caches(self._eln_man.add_experiment_entry(self._exp_id, entry_criteria))
|
|
104
|
-
return step
|
|
105
|
-
|
|
106
|
-
def create_form_step(self, entry_name: str,
|
|
107
|
-
data_type: DataTypeIdentifier,
|
|
108
|
-
record: SapioRecord | None = None,
|
|
109
|
-
criteria: GlobalDtFormStepCreation = GlobalDtFormStepCreation(),
|
|
110
|
-
position: ElnEntryPosition | None = None) -> ElnEntryStep:
|
|
111
|
-
"""
|
|
112
|
-
Create a new form entry in the experiment.
|
|
113
|
-
|
|
114
|
-
:param entry_name: The name of the entry.
|
|
115
|
-
:param data_type: The data type of the entry.
|
|
116
|
-
:param record: The record to initially populate the entry with.
|
|
117
|
-
:param criteria: Additional criteria for creating the entry.
|
|
118
|
-
:param position: Information about where to place the entry in the experiment.
|
|
119
|
-
:return: The newly created form entry.
|
|
120
|
-
"""
|
|
121
|
-
if record:
|
|
122
|
-
rdt: str = AliasUtil.to_data_type_name(record)
|
|
123
|
-
sdt: str = AliasUtil.to_data_type_name(data_type)
|
|
124
|
-
if rdt != sdt:
|
|
125
|
-
raise SapioException(f"Cannot set {rdt} records for entry {entry_name} of type "
|
|
126
|
-
f"{sdt}.")
|
|
127
|
-
|
|
128
|
-
entry_criteria = cast(ElnFormEntryCriteria,
|
|
129
|
-
self._create_step_criteria(entry_name, data_type, criteria, position))
|
|
130
|
-
if record:
|
|
131
|
-
entry_criteria.record_id = AliasUtil.to_record_id(record)
|
|
132
|
-
if criteria:
|
|
133
|
-
entry_criteria.data_type_layout_name = criteria.layout_name
|
|
134
|
-
if entry_criteria.form_name_list:
|
|
135
|
-
entry_criteria.form_name_list = list(criteria.form_names)
|
|
136
|
-
if criteria.extension_types:
|
|
137
|
-
entry_criteria.extension_type_list = AliasUtil.to_data_type_names(criteria.extension_types)
|
|
138
|
-
if criteria.field_names:
|
|
139
|
-
entry_criteria.data_field_name_list = AliasUtil.to_data_field_names(criteria.field_names)
|
|
140
|
-
|
|
141
|
-
step = self._exp_handler.add_entry_to_caches(self._eln_man.add_experiment_entry(self._exp_id, entry_criteria))
|
|
142
|
-
return step
|
|
143
|
-
|
|
144
|
-
def create_experiment_detail_form_step(self, entry_name: str,
|
|
145
|
-
field_map: FieldMap | None = None,
|
|
146
|
-
criteria: ELnDtFormStepCreation = ELnDtFormStepCreation(),
|
|
147
|
-
position: ElnEntryPosition | None = None) -> ElnEntryStep:
|
|
148
|
-
"""
|
|
149
|
-
Create a new ELN experiment details form entry in the experiment.
|
|
150
|
-
|
|
151
|
-
:param entry_name: The name of the entry.
|
|
152
|
-
:param field_map: A field map that will be used to populate the entry. The data field names in
|
|
153
|
-
the map must match the field names of the provided field definitions.
|
|
154
|
-
:param criteria: Additional criteria for creating the entry.
|
|
155
|
-
:param position: Information about where to place the entry in the experiment.
|
|
156
|
-
:return: The newly created form entry.
|
|
157
|
-
"""
|
|
158
|
-
dt = ElnBaseDataType.EXPERIMENT_DETAIL
|
|
159
|
-
return self._create_eln_dt_form_step(entry_name, dt, field_map, criteria, position)
|
|
160
|
-
|
|
161
|
-
def create_sample_detail_form_step(self, entry_name: str,
|
|
162
|
-
field_map: FieldMap | None = None,
|
|
163
|
-
criteria: ELnDtFormStepCreation = ELnDtFormStepCreation(),
|
|
164
|
-
position: ElnEntryPosition | None = None) -> ElnEntryStep:
|
|
165
|
-
"""
|
|
166
|
-
Create a new ELN sample details form entry in the experiment.
|
|
167
|
-
|
|
168
|
-
:param entry_name: The name of the entry.
|
|
169
|
-
:param field_map: A field map that will be used to populate the entry. The data field names in
|
|
170
|
-
the map must match the field names of the provided field definitions.
|
|
171
|
-
:param criteria: Additional criteria for creating the entry.
|
|
172
|
-
:param position: Information about where to place the entry in the experiment.
|
|
173
|
-
:return: The newly created form entry.
|
|
174
|
-
"""
|
|
175
|
-
dt = ElnBaseDataType.SAMPLE_DETAIL
|
|
176
|
-
return self._create_eln_dt_form_step(entry_name, dt, field_map, criteria, position)
|
|
177
|
-
|
|
178
|
-
def _create_eln_dt_form_step(self, entry_name: str,
|
|
179
|
-
dt: ElnBaseDataType,
|
|
180
|
-
field_map: FieldMap | None = None,
|
|
181
|
-
criteria: ELnDtFormStepCreation = ELnDtFormStepCreation(),
|
|
182
|
-
position: ElnEntryPosition | None = None) -> ElnEntryStep:
|
|
183
|
-
entry_criteria = cast(ElnFormEntryCriteria,
|
|
184
|
-
self._create_step_criteria(entry_name, dt.data_type_name, criteria, position))
|
|
185
|
-
|
|
186
|
-
if field_map:
|
|
187
|
-
entry_criteria.field_map = field_map
|
|
188
|
-
if criteria:
|
|
189
|
-
entry_criteria.is_field_addable = criteria.is_field_addable
|
|
190
|
-
entry_criteria.is_existing_field_removable = criteria.is_existing_field_removable
|
|
191
|
-
if criteria.field_sets:
|
|
192
|
-
field_sets: set[int] = set()
|
|
193
|
-
for field_set in criteria.field_sets:
|
|
194
|
-
if isinstance(field_set, int):
|
|
195
|
-
field_sets.add(field_set)
|
|
196
|
-
elif isinstance(field_set, ElnFieldSetInfo):
|
|
197
|
-
field_sets.add(field_set.field_set_id)
|
|
198
|
-
elif isinstance(field_set, str):
|
|
199
|
-
field_sets.add(self._exp_cache.get_field_set(field_set).field_set_id)
|
|
200
|
-
entry_criteria.field_set_id_list = list(field_sets)
|
|
201
|
-
if criteria.field_definitions:
|
|
202
|
-
entry_criteria.field_definition_list = list(criteria.field_definitions)
|
|
203
|
-
if criteria.predefined_field_names:
|
|
204
|
-
if entry_criteria.field_definition_list is None:
|
|
205
|
-
entry_criteria.field_definition_list = []
|
|
206
|
-
for field_name in criteria.predefined_field_names:
|
|
207
|
-
entry_criteria.field_definition_list.append(self._exp_cache.get_predefined_field(field_name, dt))
|
|
208
|
-
|
|
209
|
-
step = self._exp_handler.add_entry_to_caches(self._eln_man.add_experiment_entry(self._exp_id, entry_criteria))
|
|
210
|
-
return step
|
|
211
|
-
|
|
212
|
-
def create_plugin_step(self, entry_name: str,
|
|
213
|
-
data_type: DataTypeIdentifier,
|
|
214
|
-
criteria: PluginStepCreation | None,
|
|
215
|
-
position: ElnEntryPosition | None = None) -> ElnEntryStep:
|
|
216
|
-
"""
|
|
217
|
-
Create a new plugin entry in the experiment.
|
|
218
|
-
|
|
219
|
-
:param entry_name: The name of the entry.
|
|
220
|
-
:param data_type: The data type of the entry.
|
|
221
|
-
:param criteria: Additional criteria for creating the entry, such as plugin name and whether it provides
|
|
222
|
-
:param position: Information about where to place the entry in the experiment.
|
|
223
|
-
:return: The newly created plugin entry.
|
|
224
|
-
"""
|
|
225
|
-
entry_criteria = cast(ElnPluginEntryCriteria,
|
|
226
|
-
self._create_step_criteria(entry_name, data_type, criteria, position))
|
|
227
|
-
|
|
228
|
-
if criteria:
|
|
229
|
-
entry_criteria.csp_plugin_name = criteria.plugin_name
|
|
230
|
-
entry_criteria.using_template_data = criteria.using_template_data
|
|
231
|
-
entry_criteria.provides_template_data = criteria.provides_template_data
|
|
232
|
-
|
|
233
|
-
step = self._exp_handler.add_entry_to_caches(self._eln_man.add_experiment_entry(self._exp_id, entry_criteria))
|
|
234
|
-
return step
|
|
235
|
-
|
|
236
|
-
def create_table_step(self, entry_name: str, data_type: DataTypeIdentifier,
|
|
237
|
-
records: list[SapioRecord] | None = None,
|
|
238
|
-
criteria: GlobalDtTableStepCreation = GlobalDtTableStepCreation(),
|
|
239
|
-
position: ElnEntryPosition | None = None) -> ElnEntryStep:
|
|
240
|
-
"""
|
|
241
|
-
Create a new table entry in the experiment.
|
|
242
|
-
|
|
243
|
-
:param entry_name: The name of the entry.
|
|
244
|
-
:param data_type: The data type of the entry.
|
|
245
|
-
:param criteria: Additional criteria for creating the entry.
|
|
246
|
-
:param position: Information about where to place the entry in the experiment.
|
|
247
|
-
:param records: The list of records to initially populate the entry with.
|
|
248
|
-
:return: The newly created table entry.
|
|
249
|
-
"""
|
|
250
|
-
entry_criteria = cast(ElnTableEntryCriteria,
|
|
251
|
-
self._create_step_criteria(entry_name, data_type, criteria, position))
|
|
252
|
-
if criteria:
|
|
253
|
-
entry_criteria.data_type_layout_name = criteria.layout_name
|
|
254
|
-
entry_criteria.show_key_fields = criteria.show_key_fields
|
|
255
|
-
if criteria.extension_types:
|
|
256
|
-
entry_criteria.extension_type_list = list(criteria.extension_types)
|
|
257
|
-
if criteria.table_columns:
|
|
258
|
-
entry_criteria.table_column_list = list(criteria.table_columns)
|
|
259
|
-
if criteria.field_names:
|
|
260
|
-
if entry_criteria.table_column_list is None:
|
|
261
|
-
entry_criteria.table_column_list = []
|
|
262
|
-
for field in AliasUtil.to_data_field_names(criteria.field_names):
|
|
263
|
-
entry_criteria.table_column_list.append(TableColumn(data_type, field))
|
|
264
|
-
|
|
265
|
-
step = self._exp_handler.add_entry_to_caches(self._eln_man.add_experiment_entry(self._exp_id, entry_criteria))
|
|
266
|
-
if records:
|
|
267
|
-
self._exp_handler.set_step_records(step, records)
|
|
268
|
-
return step
|
|
269
|
-
|
|
270
|
-
def create_experiment_detail_table_step(self, entry_name: str,
|
|
271
|
-
field_maps: list[FieldMap] | None = None,
|
|
272
|
-
criteria: ELnDtTableStepCreation = ELnDtTableStepCreation(),
|
|
273
|
-
position: ElnEntryPosition | None = None) -> ElnEntryStep:
|
|
274
|
-
"""
|
|
275
|
-
Create a new ELN experiment details table entry in the experiment.
|
|
276
|
-
|
|
277
|
-
:param entry_name: The name of the entry.
|
|
278
|
-
:param field_maps: A field maps list that will be used to populate the entry. The data field names in
|
|
279
|
-
the maps must match the field names of the provided field definitions.
|
|
280
|
-
:param criteria: Additional criteria for creating the entry.
|
|
281
|
-
:param position: Information about where to place the entry in the experiment.
|
|
282
|
-
:return: The newly created table entry.
|
|
283
|
-
"""
|
|
284
|
-
dt = ElnBaseDataType.EXPERIMENT_DETAIL
|
|
285
|
-
return self._create_eln_dt_table_step(entry_name, dt, field_maps, criteria, position)
|
|
286
|
-
|
|
287
|
-
def create_sample_detail_table_step(self, entry_name: str,
|
|
288
|
-
field_maps: list[FieldMap] | None = None,
|
|
289
|
-
criteria: ELnDtTableStepCreation = ELnDtTableStepCreation(),
|
|
290
|
-
position: ElnEntryPosition | None = None) -> ElnEntryStep:
|
|
291
|
-
"""
|
|
292
|
-
Create a new ELN sample details table entry in the experiment.
|
|
293
|
-
|
|
294
|
-
:param entry_name: The name of the entry.
|
|
295
|
-
:param field_maps: A field maps list that will be used to populate the entry. The data field names in
|
|
296
|
-
the maps must match the field names of the provided field definitions.
|
|
297
|
-
:param criteria: Additional criteria for creating the entry.
|
|
298
|
-
:param position: Information about where to place the entry in the experiment.
|
|
299
|
-
:return: The newly created table entry.
|
|
300
|
-
"""
|
|
301
|
-
dt = ElnBaseDataType.SAMPLE_DETAIL
|
|
302
|
-
return self._create_eln_dt_table_step(entry_name, dt, field_maps, criteria, position)
|
|
303
|
-
|
|
304
|
-
def _create_eln_dt_table_step(self, entry_name: str,
|
|
305
|
-
dt: ElnBaseDataType,
|
|
306
|
-
field_maps: list[FieldMap] | None = None,
|
|
307
|
-
criteria: ELnDtTableStepCreation = ELnDtTableStepCreation(),
|
|
308
|
-
position: ElnEntryPosition | None = None) -> ElnEntryStep:
|
|
309
|
-
entry_criteria = cast(ElnTableEntryCriteria,
|
|
310
|
-
self._create_step_criteria(entry_name, dt.data_type_name, criteria, position))
|
|
311
|
-
|
|
312
|
-
if field_maps:
|
|
313
|
-
entry_criteria.field_map_list = field_maps
|
|
314
|
-
if criteria:
|
|
315
|
-
entry_criteria.is_field_addable = criteria.is_field_addable
|
|
316
|
-
entry_criteria.is_existing_field_removable = criteria.is_existing_field_removable
|
|
317
|
-
if criteria.field_sets:
|
|
318
|
-
field_sets: set[int] = set()
|
|
319
|
-
for field_set in criteria.field_sets:
|
|
320
|
-
if isinstance(field_set, int):
|
|
321
|
-
field_sets.add(field_set)
|
|
322
|
-
elif isinstance(field_set, ElnFieldSetInfo):
|
|
323
|
-
field_sets.add(field_set.field_set_id)
|
|
324
|
-
elif isinstance(field_set, str):
|
|
325
|
-
field_sets.add(self._exp_cache.get_field_set(field_set).field_set_id)
|
|
326
|
-
entry_criteria.field_set_id_list = list(field_sets)
|
|
327
|
-
if criteria.field_definitions:
|
|
328
|
-
entry_criteria.field_definition_list = list(criteria.field_definitions)
|
|
329
|
-
if criteria.predefined_field_names:
|
|
330
|
-
if entry_criteria.field_definition_list is None:
|
|
331
|
-
entry_criteria.field_definition_list = []
|
|
332
|
-
for field_name in criteria.predefined_field_names:
|
|
333
|
-
entry_criteria.field_definition_list.append(self._exp_cache.get_predefined_field(field_name, dt))
|
|
334
|
-
if criteria.table_columns:
|
|
335
|
-
entry_criteria.table_column_list = list(criteria.table_columns)
|
|
336
|
-
|
|
337
|
-
step = self._exp_handler.add_entry_to_caches(self._eln_man.add_experiment_entry(self._exp_id, entry_criteria))
|
|
338
|
-
return step
|
|
339
|
-
|
|
340
|
-
def create_temp_data_step(self, entry_name: str,
|
|
341
|
-
data_type: DataTypeIdentifier,
|
|
342
|
-
criteria: TempDataStepCreation = TempDataStepCreation(),
|
|
343
|
-
position: ElnEntryPosition | None = None) -> ElnEntryStep:
|
|
344
|
-
"""
|
|
345
|
-
Create a new temp data entry in the experiment.
|
|
346
|
-
|
|
347
|
-
:param entry_name: The name of the entry.
|
|
348
|
-
:param data_type: The data type of the entry.
|
|
349
|
-
:param criteria: Additional criteria for creating the entry.
|
|
350
|
-
:param position: Information about where to place the entry in the experiment.
|
|
351
|
-
:return: The newly created temp data entry.
|
|
352
|
-
"""
|
|
353
|
-
entry_criteria = cast(ElnTempDataEntryCriteria,
|
|
354
|
-
self._create_step_criteria(entry_name, data_type, criteria, position))
|
|
355
|
-
|
|
356
|
-
if criteria:
|
|
357
|
-
entry_criteria.temp_data_plugin_path = criteria.plugin_path
|
|
358
|
-
|
|
359
|
-
step = self._exp_handler.add_entry_to_caches(self._eln_man.add_experiment_entry(self._exp_id, entry_criteria))
|
|
360
|
-
return step
|
|
361
|
-
|
|
362
|
-
def create_text_step(self, entry_name: str,
|
|
363
|
-
text: str | None = None,
|
|
364
|
-
criteria: TextStepCreation = TextStepCreation(),
|
|
365
|
-
position: ElnEntryPosition | None = None) -> ElnEntryStep:
|
|
366
|
-
"""
|
|
367
|
-
Create a new text entry in the experiment.
|
|
368
|
-
|
|
369
|
-
:param entry_name: The name of the entry.
|
|
370
|
-
:param text: The text to populate the entry with.
|
|
371
|
-
:param criteria: Additional criteria for creating the entry.
|
|
372
|
-
:param position: Information about where to place the entry in the experiment.
|
|
373
|
-
:return: The newly created text entry.
|
|
374
|
-
"""
|
|
375
|
-
dt = ElnBaseDataType.TEXT_ENTRY_DETAIL.data_type_name
|
|
376
|
-
entry_criteria = cast(ElnTextEntryCriteria,
|
|
377
|
-
self._create_step_criteria(entry_name, dt, criteria, position))
|
|
378
|
-
|
|
379
|
-
step = self._exp_handler.add_entry_to_caches(self._eln_man.add_experiment_entry(self._exp_id, entry_criteria))
|
|
380
|
-
|
|
381
|
-
if text:
|
|
382
|
-
text_record: DataRecord = step.get_records()[0]
|
|
383
|
-
text_record.set_field_value(ElnBaseDataType.get_text_entry_data_field_name(), text)
|
|
384
|
-
DataRecordManager(self.user).commit_data_records([text_record])
|
|
385
|
-
|
|
386
|
-
return step
|
|
387
|
-
|
|
388
|
-
def create_plate_designer_step(self, entry_name: str,
|
|
389
|
-
source_entry: Step | None = None,
|
|
390
|
-
criteria: PluginStepCreation = PluginStepCreation(),
|
|
391
|
-
position: ElnEntryPosition | None = None) -> ElnEntryStep:
|
|
392
|
-
"""
|
|
393
|
-
Create a new 3D plate designer entry in the experiment.
|
|
394
|
-
|
|
395
|
-
:param entry_name: The name of the entry.
|
|
396
|
-
:param source_entry: The entry that the plate designer will source its samples from.
|
|
397
|
-
:param criteria: Additional criteria for creating the entry.
|
|
398
|
-
:param position: Information about where to place the entry in the experiment.
|
|
399
|
-
:return: The newly created plate designer entry.
|
|
400
|
-
"""
|
|
401
|
-
criteria.plugin_name = PLATE_DESIGNER_PLUGIN
|
|
402
|
-
if criteria.entry_height is None:
|
|
403
|
-
criteria.entry_height = 600
|
|
404
|
-
if source_entry is not None:
|
|
405
|
-
criteria.related_entry_set = [source_entry]
|
|
406
|
-
default_layer = MultiLayerPlateLayer(
|
|
407
|
-
MultiLayerDataTypeConfig("Sample"),
|
|
408
|
-
PlatingOrder.FillBy.BY_COLUMN,
|
|
409
|
-
MultiLayerReplicateConfig(),
|
|
410
|
-
MultiLayerDilutionConfig()
|
|
411
|
-
)
|
|
412
|
-
initial_step_options: dict[str, str] = {
|
|
413
|
-
"MultiLayerPlating_Plate_RecordIdList": "",
|
|
414
|
-
"MultiLayerPlating_Entry_Prefs": MultiLayerPlatingManager.get_entry_prefs_json([default_layer]),
|
|
415
|
-
"MultiLayerPlating_Entry_PrePlating_Prefs": MultiLayerPlatingManager.get_plate_configs_json(MultiLayerPlateConfig())
|
|
416
|
-
}
|
|
417
|
-
if criteria.entry_options is None:
|
|
418
|
-
criteria.entry_options = initial_step_options
|
|
419
|
-
else:
|
|
420
|
-
criteria.entry_options.update(initial_step_options)
|
|
421
|
-
return self.create_plugin_step(entry_name, "Sample", criteria, position)
|
|
422
|
-
|
|
423
|
-
def _create_step_criteria(self, name: str, dt: DataTypeIdentifier,
|
|
424
|
-
criteria: StepCreation, position: ElnEntryPosition | None) \
|
|
425
|
-
-> AbstractElnEntryCriteria:
|
|
426
|
-
"""
|
|
427
|
-
Create the criteria for a new entry in the experiment of the given type.
|
|
428
|
-
"""
|
|
429
|
-
if position is not None:
|
|
430
|
-
order: int = position.order
|
|
431
|
-
tab_id: int = position.tab_id
|
|
432
|
-
column_order: int = position.column_order
|
|
433
|
-
column_span: int = position.column_span
|
|
434
|
-
else:
|
|
435
|
-
last_tab: ElnExperimentTab = self._exp_handler.get_last_tab()
|
|
436
|
-
order: int = self._exp_handler.get_next_entry_order_in_tab(last_tab)
|
|
437
|
-
tab_id: int = last_tab.tab_id
|
|
438
|
-
column_order: int = 0
|
|
439
|
-
column_span: int = last_tab.max_number_of_columns
|
|
440
|
-
|
|
441
|
-
dt: str = AliasUtil.to_data_type_name(dt)
|
|
442
|
-
et = criteria.entry_type
|
|
443
|
-
entry_criteria = ExperimentEntryCriteriaUtil.get_entry_creation_criteria(et, name, dt, order)
|
|
444
|
-
entry_criteria.notebook_experiment_tab_id = tab_id
|
|
445
|
-
entry_criteria.column_order = column_order
|
|
446
|
-
entry_criteria.column_span = column_span
|
|
447
|
-
if criteria:
|
|
448
|
-
entry_criteria.is_shown_in_template = criteria.is_shown_in_template
|
|
449
|
-
entry_criteria.is_removable = criteria.is_removable
|
|
450
|
-
entry_criteria.is_renamable = criteria.is_renamable
|
|
451
|
-
entry_criteria.is_static_view = criteria.is_static_view
|
|
452
|
-
if criteria.related_entry_set:
|
|
453
|
-
entry_criteria.related_entry_set = self.__to_entry_ids(criteria.related_entry_set)
|
|
454
|
-
if criteria.dependency_set:
|
|
455
|
-
entry_criteria.dependency_set = self.__to_entry_ids(criteria.dependency_set)
|
|
456
|
-
entry_criteria.requires_grabber_plugin = criteria.requires_grabber_plugin
|
|
457
|
-
entry_criteria.entry_singleton_id = criteria.entry_singleton_id
|
|
458
|
-
entry_criteria.is_hidden = criteria.is_hidden
|
|
459
|
-
entry_criteria.entry_height = criteria.entry_height
|
|
460
|
-
entry_criteria.description = criteria.description
|
|
461
|
-
entry_criteria.is_initialization_required = criteria.is_initialization_required
|
|
462
|
-
entry_criteria.collapse_entry = criteria.collapse_entry
|
|
463
|
-
entry_criteria.entry_status = criteria.entry_status
|
|
464
|
-
entry_criteria.template_item_fulfilled_timestamp = criteria.template_item_fulfilled_timestamp
|
|
465
|
-
entry_criteria.entry_options = criteria.entry_options
|
|
466
|
-
|
|
467
|
-
return entry_criteria
|
|
468
|
-
|
|
469
|
-
def __to_entry_ids(self, entries: Iterable[ExperimentEntryIdentifier | str]) -> list[int] | None:
|
|
470
|
-
entry_ids: set[int] = set()
|
|
471
|
-
for entry in entries:
|
|
472
|
-
if isinstance(entry, str):
|
|
473
|
-
entry_ids.add(self._exp_handler.get_step(entry).get_id())
|
|
474
|
-
else:
|
|
475
|
-
entry_ids.add(AliasUtil.to_entry_id(entry))
|
|
476
|
-
return list(entry_ids)
|