sapiopycommons 2025.2.25a449__tar.gz → 2025.2.25a450__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 (83) hide show
  1. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/PKG-INFO +1 -1
  2. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/pyproject.toml +1 -1
  3. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/ai/tool_of_tools.py +84 -17
  4. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/.gitignore +0 -0
  5. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/LICENSE +0 -0
  6. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/README.md +0 -0
  7. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/__init__.py +0 -0
  8. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/ai/__init__.py +0 -0
  9. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/callbacks/__init__.py +0 -0
  10. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/callbacks/callback_util.py +0 -0
  11. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/callbacks/field_builder.py +0 -0
  12. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/chem/IndigoMolecules.py +0 -0
  13. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/chem/Molecules.py +0 -0
  14. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/chem/__init__.py +0 -0
  15. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/customreport/__init__.py +0 -0
  16. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/customreport/auto_pagers.py +0 -0
  17. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/customreport/column_builder.py +0 -0
  18. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/customreport/custom_report_builder.py +0 -0
  19. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/customreport/term_builder.py +0 -0
  20. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/datatype/__init__.py +0 -0
  21. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/datatype/attachment_util.py +0 -0
  22. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/datatype/data_fields.py +0 -0
  23. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/datatype/pseudo_data_types.py +0 -0
  24. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/eln/__init__.py +0 -0
  25. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/eln/experiment_handler.py +0 -0
  26. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/eln/experiment_report_util.py +0 -0
  27. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/eln/plate_designer.py +0 -0
  28. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/files/__init__.py +0 -0
  29. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/files/complex_data_loader.py +0 -0
  30. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/files/file_bridge.py +0 -0
  31. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/files/file_bridge_handler.py +0 -0
  32. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/files/file_data_handler.py +0 -0
  33. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/files/file_util.py +0 -0
  34. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/files/file_validator.py +0 -0
  35. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/files/file_writer.py +0 -0
  36. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/flowcyto/flow_cyto.py +0 -0
  37. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/flowcyto/flowcyto_data.py +0 -0
  38. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/general/__init__.py +0 -0
  39. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/general/accession_service.py +0 -0
  40. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/general/aliases.py +0 -0
  41. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/general/audit_log.py +0 -0
  42. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/general/custom_report_util.py +0 -0
  43. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/general/directive_util.py +0 -0
  44. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/general/exceptions.py +0 -0
  45. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/general/popup_util.py +0 -0
  46. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/general/sapio_links.py +0 -0
  47. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/general/storage_util.py +0 -0
  48. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/general/time_util.py +0 -0
  49. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/multimodal/multimodal.py +0 -0
  50. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/multimodal/multimodal_data.py +0 -0
  51. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/processtracking/__init__.py +0 -0
  52. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/processtracking/custom_workflow_handler.py +0 -0
  53. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/processtracking/endpoints.py +0 -0
  54. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/recordmodel/__init__.py +0 -0
  55. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/recordmodel/record_handler.py +0 -0
  56. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/rules/__init__.py +0 -0
  57. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/rules/eln_rule_handler.py +0 -0
  58. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/rules/on_save_rule_handler.py +0 -0
  59. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/samples/aliquot.py +0 -0
  60. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/sftpconnect/__init__.py +0 -0
  61. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/sftpconnect/sftp_builder.py +0 -0
  62. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/webhook/__init__.py +0 -0
  63. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/webhook/webhook_context.py +0 -0
  64. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/webhook/webhook_handlers.py +0 -0
  65. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/src/sapiopycommons/webhook/webservice_handlers.py +0 -0
  66. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/tests/AF-A0A009IHW8-F1-model_v4.cif +0 -0
  67. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/tests/_do_not_add_init_py_here +0 -0
  68. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/tests/accession_test.py +0 -0
  69. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/tests/aliquot_test.py +0 -0
  70. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/tests/bio_reg_test.py +0 -0
  71. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/tests/chem_test.py +0 -0
  72. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/tests/chem_test_curation_queue.py +0 -0
  73. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/tests/curation_queue_test.sdf +0 -0
  74. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/tests/data_type_models.py +0 -0
  75. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/tests/flowcyto/101_DEN084Y5_15_E01_008_clean.fcs +0 -0
  76. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/tests/flowcyto/101_DEN084Y5_15_E03_009_clean.fcs +0 -0
  77. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/tests/flowcyto/101_DEN084Y5_15_E05_010_clean.fcs +0 -0
  78. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/tests/flowcyto/8_color_ICS.wsp +0 -0
  79. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/tests/flowcyto/COVID19_W_001_O.fcs +0 -0
  80. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/tests/flowcyto_test.py +0 -0
  81. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/tests/kappa.chains.fasta +0 -0
  82. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/tests/mafft_test.py +0 -0
  83. {sapiopycommons-2025.2.25a449 → sapiopycommons-2025.2.25a450}/tests/test.gb +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: sapiopycommons
3
- Version: 2025.2.25a449
3
+ Version: 2025.2.25a450
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.25a449'
7
+ version='2025.02.25a450'
8
8
  authors = [
9
9
  { name="Jonathan Steck", email="jsteck@sapiosciences.com" },
10
10
  { name="Yechen Qiao", email="yqiao@sapiosciences.com" },
@@ -7,14 +7,15 @@ from typing import Final, Mapping, Any
7
7
  import requests
8
8
  from pandas import DataFrame
9
9
  from requests import Response
10
+ from sapiopylib.rest.DataMgmtService import DataMgmtServer
10
11
  from sapiopylib.rest.DataRecordManagerService import DataRecordManager
11
12
  from sapiopylib.rest.DataTypeService import DataTypeManager
12
13
  from sapiopylib.rest.ELNService import ElnManager
13
14
  from sapiopylib.rest.User import SapioUser
14
15
  from sapiopylib.rest.pojo.DataRecord import DataRecord
15
16
  from sapiopylib.rest.pojo.Sort import SortDirection
16
- from sapiopylib.rest.pojo.chartdata.DashboardDefinition import GaugeChartDefinition
17
- from sapiopylib.rest.pojo.chartdata.DashboardEnums import ChartGroupingType, ChartOperationType
17
+ from sapiopylib.rest.pojo.chartdata.DashboardDefinition import GaugeChartDefinition, DashboardDefinition
18
+ from sapiopylib.rest.pojo.chartdata.DashboardEnums import ChartGroupingType, ChartOperationType, DashboardScope
18
19
  from sapiopylib.rest.pojo.chartdata.DashboardSeries import GaugeChartSeries
19
20
  from sapiopylib.rest.pojo.datatype.DataType import DataTypeDefinition
20
21
  from sapiopylib.rest.pojo.datatype.DataTypeLayout import DataTypeLayout, TableLayout
@@ -24,7 +25,7 @@ from sapiopylib.rest.pojo.eln.ElnEntryPosition import ElnEntryPosition
24
25
  from sapiopylib.rest.pojo.eln.ElnExperiment import ElnExperiment
25
26
  from sapiopylib.rest.pojo.eln.ExperimentEntry import ExperimentEntry
26
27
  from sapiopylib.rest.pojo.eln.ExperimentEntryCriteria import ElnEntryCriteria, ElnFormEntryUpdateCriteria, \
27
- ElnDashboardEntryUpdateCriteria, ElnTextEntryUpdateCriteria
28
+ ElnDashboardEntryUpdateCriteria
28
29
  from sapiopylib.rest.pojo.eln.SapioELNEnums import ElnEntryType, ElnBaseDataType
29
30
  from sapiopylib.rest.pojo.eln.eln_headings import ElnExperimentTabAddCriteria, ElnExperimentTab
30
31
  from sapiopylib.rest.pojo.eln.field_set import ElnFieldSetInfo
@@ -725,26 +726,21 @@ class ToolOfToolsHelper:
725
726
  # tool started and format the description so that the text isn't too small to read.
726
727
  # TODO: Get the UTC offset in seconds from the header once that's being sent.
727
728
  now: str = TimeUtil.now_in_format("%Y-%m-%d %H:%M:%S UTC", "UTC")
728
- text_entry = ElnEntryStep(self.helper.protocol, self.helper.create_text_entry(self.tab, now, self.description))
729
+ description: str = f"<p>{HtmlFormatter.timestamp(now)}<br>{HtmlFormatter.body(self.description)}</p>"
730
+ text_entry: ElnEntryStep = _ELNStepFactory.create_text_entry(self.helper.protocol, description,
731
+ column_order=0, column_span=2)
729
732
  self.description_entry = text_entry
730
733
  self.description_record = text_entry.get_records()[0]
731
734
 
732
- # Shrink the text entry by one column.
733
- text_update_crit = ElnTextEntryUpdateCriteria()
734
- text_update_crit.column_order = 0
735
- text_update_crit.column_span = 2
736
- self.eln_man.update_experiment_entry(self.exp_id, self.description_entry.get_id(), text_update_crit)
737
-
738
735
  # Create a gauge entry to display the progress.
739
- gauge_entry: ElnEntryStep = self._create_gauge_chart(self.helper.protocol, progress_entry,
740
- f"{self.name} Progress", "Progress", "StatusMsg")
736
+ gauge_entry: ElnEntryStep = _ELNStepFactory._create_gauge_chart(self.helper.protocol, progress_entry,
737
+ f"{self.name} Progress", "Progress", "StatusMsg",
738
+ column_order=2, column_span=2)
741
739
  self.progress_gauge_entry = gauge_entry
742
740
 
743
741
  # Make sure the gauge entry isn't too big and stick it to the right of the text entry.
744
742
  dash_update_crit = ElnDashboardEntryUpdateCriteria()
745
743
  dash_update_crit.entry_height = 250
746
- dash_update_crit.column_order = 2
747
- dash_update_crit.column_span = 2
748
744
  self.eln_man.update_experiment_entry(self.exp_id, self.progress_gauge_entry.get_id(), dash_update_crit)
749
745
 
750
746
  # Create a results entry if this tool produces result records.
@@ -839,10 +835,37 @@ class ToolOfToolsHelper:
839
835
 
840
836
  return self.helper.create_attachment_entry_from_file(self.tab, entry_name, file_path)
841
837
 
838
+
839
+ class _ELNStepFactory:
840
+ """
841
+ Factory that provides simple functions to create a new ELN step under an ELN protocol.
842
+ """
843
+ @staticmethod
844
+ def create_text_entry(protocol: ElnExperimentProtocol, text_data: str,
845
+ position: ElnEntryPosition | None = None, **kwargs) -> ElnEntryStep:
846
+ """
847
+ Create a text entry at the end of the protocol, with a initial text specified in the text entry.
848
+ :param protocol: The protocol to create a new step for.
849
+ :param text_data: Must be non-blank. This is what will be displayed. Some HTML format tags can be inserted.
850
+ :param position: The position of the new step. If not specified, the new step will be added at the end.
851
+ :return: The new text entry step.
852
+ """
853
+ eln_manager, new_entry = _ELNStepFactory._get_entry_creation_criteria(ElnBaseDataType.TEXT_ENTRY_DETAIL.data_type_name,
854
+ protocol, 'Text Entry', ElnEntryType.Text,
855
+ position, **kwargs)
856
+ record = eln_manager.get_data_records_for_entry(protocol.eln_experiment.notebook_experiment_id,
857
+ new_entry.entry_id).result_list[0]
858
+ record.set_field_value(ElnBaseDataType.get_text_entry_data_field_name(), text_data)
859
+ DataMgmtServer.get_data_record_manager(protocol.user).commit_data_records([record])
860
+ ret = ElnEntryStep(protocol, new_entry)
861
+ protocol.invalidate()
862
+ return ret
863
+
842
864
  # TODO: Remove this once pylib's gauge chart definition is up to date.
843
865
  @staticmethod
844
866
  def _create_gauge_chart(protocol: ElnExperimentProtocol, data_source_step: ElnEntryStep, step_name: str,
845
- field_name: str, status_field: str, group_by_field_name: str = "DataRecordName") \
867
+ field_name: str, status_field: str, group_by_field_name: str = "DataRecordName",
868
+ **kwargs) \
846
869
  -> ElnEntryStep:
847
870
  """
848
871
  Create a gauge chart step in the experiment protocol.
@@ -861,11 +884,55 @@ class ToolOfToolsHelper:
861
884
  chart.grouping_type = ChartGroupingType.GROUP_BY_FIELD
862
885
  chart.grouping_type_data_type_name = data_type_name
863
886
  chart.grouping_type_data_field_name = group_by_field_name
864
- dashboard, step = ELNStepFactory._create_dashboard_step_from_chart(chart, data_source_step, protocol, step_name,
865
- None)
887
+ dashboard, step = _ELNStepFactory._create_dashboard_step_from_chart(chart, data_source_step, protocol, step_name,
888
+ None, **kwargs)
866
889
  protocol.invalidate()
867
890
  return step
868
891
 
892
+ @staticmethod
893
+ def _create_dashboard_step_from_chart(chart: GaugeChartDefinition, data_source_step: ElnEntryStep,
894
+ protocol: ElnExperimentProtocol, step_name: str,
895
+ position: ElnEntryPosition | None = None, **kwargs) -> \
896
+ tuple[DashboardDefinition, ElnEntryStep]:
897
+ dashboard: DashboardDefinition = DashboardDefinition()
898
+ dashboard.chart_definition_list = [chart]
899
+ dashboard.dashboard_scope = DashboardScope.PRIVATE_ELN
900
+ dashboard = DataMgmtServer.get_dashboard_manager(protocol.user).store_dashboard_definition(dashboard)
901
+ eln_manager, new_entry = _ELNStepFactory._get_entry_creation_criteria("", protocol, step_name,
902
+ ElnEntryType.Dashboard, position,
903
+ **kwargs)
904
+ # noinspection PyTypeChecker
905
+ update_criteria = ElnDashboardEntryUpdateCriteria()
906
+ update_criteria.dashboard_guid = dashboard.dashboard_guid
907
+ update_criteria.data_source_entry_id = data_source_step.get_id()
908
+ update_criteria.entry_height = 500
909
+ eln_manager.update_experiment_entry(protocol.eln_experiment.notebook_experiment_id, new_entry.entry_id,
910
+ update_criteria)
911
+ step = ElnEntryStep(protocol, new_entry)
912
+ return dashboard, step
913
+
914
+ @staticmethod
915
+ def _get_entry_creation_criteria(data_type_name: str | None, protocol: ElnExperimentProtocol,
916
+ step_name: str, entry_type: ElnEntryType, position: ElnEntryPosition | None = None,
917
+ **kwargs):
918
+ tab_id: int | None = None
919
+ order: int | None = None
920
+ if position:
921
+ tab_id = position.tab_id
922
+ order = position.order
923
+ # noinspection PyTypeChecker
924
+ last_step: ElnEntryStep = protocol.get_sorted_step_list()[-1]
925
+ if tab_id is None:
926
+ tab_id = last_step.eln_entry.notebook_experiment_tab_id
927
+ if order is None:
928
+ order = last_step.eln_entry.order + 1
929
+ eln_manager = DataMgmtServer.get_eln_manager(protocol.user)
930
+ entry_criteria = ElnEntryCriteria(entry_type, step_name, data_type_name=data_type_name,
931
+ order=order, notebook_experiment_tab_id=tab_id, **kwargs)
932
+ new_entry: ExperimentEntry = eln_manager.add_experiment_entry(protocol.eln_experiment.notebook_experiment_id,
933
+ entry_criteria)
934
+ return eln_manager, new_entry
935
+
869
936
 
870
937
  # TODO: Using this to set the new status field setting.
871
938
  class _GaugeChartDefinition(GaugeChartDefinition):