sapiopycommons 2025.2.5a413__tar.gz → 2025.2.5a415__tar.gz

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.

Files changed (81) hide show
  1. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/PKG-INFO +1 -1
  2. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/pyproject.toml +1 -1
  3. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/elain/tool_of_tools.py +78 -7
  4. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/.gitignore +0 -0
  5. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/LICENSE +0 -0
  6. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/README.md +0 -0
  7. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/__init__.py +0 -0
  8. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/callbacks/__init__.py +0 -0
  9. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/callbacks/callback_util.py +0 -0
  10. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/callbacks/field_builder.py +0 -0
  11. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/chem/IndigoMolecules.py +0 -0
  12. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/chem/Molecules.py +0 -0
  13. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/chem/__init__.py +0 -0
  14. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/customreport/__init__.py +0 -0
  15. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/customreport/auto_pagers.py +0 -0
  16. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/customreport/column_builder.py +0 -0
  17. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/customreport/custom_report_builder.py +0 -0
  18. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/customreport/term_builder.py +0 -0
  19. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/datatype/__init__.py +0 -0
  20. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/datatype/attachment_util.py +0 -0
  21. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/datatype/data_fields.py +0 -0
  22. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/datatype/pseudo_data_types.py +0 -0
  23. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/elain/__init__.py +0 -0
  24. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/eln/__init__.py +0 -0
  25. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/eln/experiment_handler.py +0 -0
  26. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/eln/experiment_report_util.py +0 -0
  27. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/eln/plate_designer.py +0 -0
  28. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/files/__init__.py +0 -0
  29. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/files/complex_data_loader.py +0 -0
  30. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/files/file_bridge.py +0 -0
  31. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/files/file_bridge_handler.py +0 -0
  32. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/files/file_data_handler.py +0 -0
  33. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/files/file_util.py +0 -0
  34. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/files/file_validator.py +0 -0
  35. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/files/file_writer.py +0 -0
  36. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/flowcyto/flow_cyto.py +0 -0
  37. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/flowcyto/flowcyto_data.py +0 -0
  38. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/general/__init__.py +0 -0
  39. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/general/accession_service.py +0 -0
  40. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/general/aliases.py +0 -0
  41. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/general/audit_log.py +0 -0
  42. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/general/custom_report_util.py +0 -0
  43. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/general/directive_util.py +0 -0
  44. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/general/exceptions.py +0 -0
  45. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/general/popup_util.py +0 -0
  46. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/general/sapio_links.py +0 -0
  47. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/general/storage_util.py +0 -0
  48. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/general/time_util.py +0 -0
  49. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/multimodal/multimodal.py +0 -0
  50. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/multimodal/multimodal_data.py +0 -0
  51. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/processtracking/__init__.py +0 -0
  52. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/processtracking/custom_workflow_handler.py +0 -0
  53. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/processtracking/endpoints.py +0 -0
  54. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/recordmodel/__init__.py +0 -0
  55. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/recordmodel/record_handler.py +0 -0
  56. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/rules/__init__.py +0 -0
  57. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/rules/eln_rule_handler.py +0 -0
  58. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/rules/on_save_rule_handler.py +0 -0
  59. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/sftpconnect/__init__.py +0 -0
  60. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/sftpconnect/sftp_builder.py +0 -0
  61. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/webhook/__init__.py +0 -0
  62. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/webhook/webhook_context.py +0 -0
  63. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/webhook/webhook_handlers.py +0 -0
  64. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/src/sapiopycommons/webhook/webservice_handlers.py +0 -0
  65. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/tests/AF-A0A009IHW8-F1-model_v4.cif +0 -0
  66. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/tests/_do_not_add_init_py_here +0 -0
  67. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/tests/accession_test.py +0 -0
  68. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/tests/bio_reg_test.py +0 -0
  69. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/tests/chem_test.py +0 -0
  70. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/tests/chem_test_curation_queue.py +0 -0
  71. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/tests/curation_queue_test.sdf +0 -0
  72. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/tests/data_type_models.py +0 -0
  73. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/tests/flowcyto/101_DEN084Y5_15_E01_008_clean.fcs +0 -0
  74. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/tests/flowcyto/101_DEN084Y5_15_E03_009_clean.fcs +0 -0
  75. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/tests/flowcyto/101_DEN084Y5_15_E05_010_clean.fcs +0 -0
  76. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/tests/flowcyto/8_color_ICS.wsp +0 -0
  77. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/tests/flowcyto/COVID19_W_001_O.fcs +0 -0
  78. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/tests/flowcyto_test.py +0 -0
  79. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/tests/kappa.chains.fasta +0 -0
  80. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/tests/mafft_test.py +0 -0
  81. {sapiopycommons-2025.2.5a413 → sapiopycommons-2025.2.5a415}/tests/test.gb +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: sapiopycommons
3
- Version: 2025.2.5a413
3
+ Version: 2025.2.5a415
4
4
  Summary: Official Sapio Python API Utilities Package
5
5
  Project-URL: Homepage, https://github.com/sapiosciences
6
6
  Author-email: Jonathan Steck <jsteck@sapiosciences.com>, Yechen Qiao <yqiao@sapiosciences.com>
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sapiopycommons"
7
- version='2025.02.05a413'
7
+ version='2025.02.05a415'
8
8
  authors = [
9
9
  { name="Jonathan Steck", email="jsteck@sapiosciences.com" },
10
10
  { name="Yechen Qiao", email="yqiao@sapiosciences.com" },
@@ -10,7 +10,8 @@ from sapiopylib.rest.pojo.chartdata.DashboardEnums import ChartGroupingType, Cha
10
10
  from sapiopylib.rest.pojo.chartdata.DashboardSeries import GaugeChartSeries
11
11
  from sapiopylib.rest.pojo.eln.ElnExperiment import ElnExperiment
12
12
  from sapiopylib.rest.pojo.eln.ExperimentEntry import ExperimentEntry
13
- from sapiopylib.rest.pojo.eln.ExperimentEntryCriteria import ElnEntryCriteria, ElnFormEntryUpdateCriteria
13
+ from sapiopylib.rest.pojo.eln.ExperimentEntryCriteria import ElnEntryCriteria, ElnFormEntryUpdateCriteria, \
14
+ ElnDashboardEntryUpdateCriteria, ElnTextEntryUpdateCriteria, AbstractElnEntryUpdateCriteria
14
15
  from sapiopylib.rest.pojo.eln.SapioELNEnums import ElnEntryType, ElnBaseDataType
15
16
  from sapiopylib.rest.pojo.eln.eln_headings import ElnExperimentTabAddCriteria, ElnExperimentTab
16
17
  from sapiopylib.rest.pojo.eln.field_set import ElnFieldSetInfo
@@ -18,6 +19,7 @@ from sapiopylib.rest.utils.ProtocolUtils import ELNStepFactory
18
19
  from sapiopylib.rest.utils.Protocols import ElnEntryStep, ElnExperimentProtocol
19
20
 
20
21
  from sapiopycommons.general.exceptions import SapioException
22
+ from sapiopycommons.general.time_util import TimeUtil
21
23
 
22
24
  CREDENTIALS_HEADER: Final[str] = "SAPIO_APP_API_KEY"
23
25
  API_URL_HEADER: Final[str] = "SAPIO_APP_API_URL"
@@ -103,6 +105,8 @@ class ToolOfToolsHelper:
103
105
  """The tab that contains the tool's entries."""
104
106
  description_entry: ElnEntryStep | None
105
107
  """The text entry that displays the description of the tool."""
108
+ description_record: DataRecord | None
109
+ """The record that stores the description of the tool."""
106
110
  progress_entry: ElnEntryStep | None
107
111
  """A hidden entry for tracking the progress of the tool."""
108
112
  progress_record: DataRecord | None
@@ -166,6 +170,7 @@ class ToolOfToolsHelper:
166
170
  elif (entry.eln_entry.entry_type == ElnEntryType.Text
167
171
  and not hasattr(self, "description_entry")):
168
172
  self.description_entry = entry
173
+ self.description_record = entry.get_records()[0]
169
174
  elif (entry.eln_entry.entry_type == ElnEntryType.Table
170
175
  and dt == self.results_data_type
171
176
  and not hasattr(self, "results_entry")):
@@ -178,6 +183,7 @@ class ToolOfToolsHelper:
178
183
  self.progress_gauge_entry = None
179
184
  if not hasattr(self, "description_entry"):
180
185
  self.description_entry = None
186
+ self.description_record = None
181
187
  if not hasattr(self, "results_entry"):
182
188
  self.results_entry = None
183
189
 
@@ -205,18 +211,39 @@ class ToolOfToolsHelper:
205
211
  self.progress_record = progress_entry.get_records()[0]
206
212
 
207
213
  # Hide the progress entry.
208
- update_crit = ElnFormEntryUpdateCriteria()
209
- update_crit.is_hidden = True
210
- self.eln_man.update_experiment_entry(self.exp_id, progress_entry.get_id(), update_crit)
214
+ form_update_crit = ElnFormEntryUpdateCriteria()
215
+ form_update_crit.is_hidden = True
216
+
217
+ # Create the text entry that displays the description of the tool. Include the timestamp of when the
218
+ # tool started and format the description so that the text isn't too small to read.
219
+ # TODO: Get the UTC offset in seconds from the header once that's being sent.
220
+ now: str = TimeUtil.now_in_format("%Y-%m-%d %H:%M:%S UTC", "UTC")
221
+ description: str = f"""<p><span style="color: rgb(35, 111, 161); font-size: 12pt; font-weight:500;">{now}</span>
222
+ <br><span style="font-size: 15pt;">{self.description}</span></p>"""
223
+ text_entry: ElnEntryStep = ELNStepFactory.create_text_entry(self._protocol, description)
224
+ self.description_entry = text_entry
225
+ self.description_record = text_entry.get_records()[0]
226
+
227
+ # Shrink the text entry by one column.
228
+ text_update_crit = _ElnTextEntryUpdateCriteria()
229
+ text_update_crit.column_span = 2
211
230
 
212
231
  # Create a gauge entry to display the progress.
213
232
  gauge_entry: ElnEntryStep = self._create_gauge_chart(self._protocol, progress_entry,
214
233
  f"{self.name} Progress", "Progress", "StatusMsg")
215
234
  self.progress_gauge_entry = gauge_entry
216
235
 
217
- # Create the text entry that displays the description of the tool.
218
- text_entry: ElnEntryStep = ELNStepFactory.create_text_entry(self._protocol, self.description)
219
- self.description_entry = text_entry
236
+ # Make sure the gauge entry isn't too big and stick it to the right of the text entry.
237
+ dash_update_crit = ElnDashboardEntryUpdateCriteria()
238
+ dash_update_crit.entry_height = 250
239
+ dash_update_crit.column_span = 2
240
+ dash_update_crit.column_order = 2
241
+
242
+ self.eln_man.update_experiment_entries(self.exp_id, {
243
+ self.progress_entry.get_id(): form_update_crit,
244
+ self.progress_gauge_entry.get_id(): dash_update_crit,
245
+ self.description_entry.get_id(): text_update_crit
246
+ })
220
247
 
221
248
  # Create a results entry if this tool produces result records.
222
249
  if self.results_data_type:
@@ -228,6 +255,20 @@ class ToolOfToolsHelper:
228
255
 
229
256
  return tab
230
257
 
258
+ def add_to_description(self, description: str) -> None:
259
+ """
260
+ Add to the description entry of the tool.
261
+
262
+ :param description: The text to add to the description.
263
+ """
264
+ if not self._initialized:
265
+ raise SapioException("The tab for this tool has not been initialized.")
266
+ field: str = ElnBaseDataType.get_text_entry_data_field_name()
267
+ update: str = self.description_record.get_field_value(field)
268
+ update += f"""<p style="padding-top: 10px;"><span style="font-size: 15pt;">{description}</span></p>"""
269
+ self.description_record.set_field_value(field, update)
270
+ self.dr_man.commit_data_records([self.description_record])
271
+
231
272
  def update_progress(self, progress: float, status_msg: str | None = None) -> None:
232
273
  """
233
274
  Updates the progress of the tool.
@@ -241,6 +282,21 @@ class ToolOfToolsHelper:
241
282
  self.progress_record.set_field_value("StatusMsg", status_msg)
242
283
  self.dr_man.commit_data_records([self.progress_record])
243
284
 
285
+ def add_results_bar_chart(self, x_axis: str, y_axis: str) -> ExperimentEntry:
286
+ """
287
+ Create a bar chart entry for the results of the tool.
288
+
289
+ :param x_axis: The data field to use for the x-axis of the chart.
290
+ :param y_axis: The data field to use for the y-axis of the chart.
291
+ :return: The newly created chart entry.
292
+ """
293
+ if not self._initialized:
294
+ raise SapioException("The tab for this tool has not been initialized.")
295
+ if not self.results_entry:
296
+ raise SapioException("This tool does not produce result records.")
297
+ return ELNStepFactory.create_bar_chart_step(self._protocol, self.results_entry, f"{self.name} Results Chart",
298
+ x_axis, y_axis)[0].eln_entry
299
+
244
300
  def add_attachment_entry(self, file_name: str, file_data: str | bytes, entry_name: str,
245
301
  tab: ElnExperimentTab | None = None) -> ExperimentEntry:
246
302
  """
@@ -339,3 +395,18 @@ class _GaugeChartDefinition(GaugeChartDefinition):
339
395
  "dataFieldName": self.status_field
340
396
  }
341
397
  return result
398
+
399
+
400
+ # TODO: Remove once the ElnTextEntryUpdateCriteria is fixed.
401
+ class _ElnTextEntryUpdateCriteria(AbstractElnEntryUpdateCriteria):
402
+ """
403
+ Text Entry Update Data Payload
404
+ Create this payload object and set the attributes you want to update before sending the request.
405
+ """
406
+
407
+ def __init__(self):
408
+ super().__init__(ElnEntryType.Text)
409
+
410
+ def to_json(self) -> dict[str, Any]:
411
+ ret = super().to_json()
412
+ return ret