sapiopycommons 2025.7.2a579__tar.gz → 2025.7.8a581__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 (88) hide show
  1. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/PKG-INFO +1 -1
  2. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/pyproject.toml +1 -1
  3. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/chem/ps_commons.py +76 -2
  4. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/.gitignore +0 -0
  5. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/LICENSE +0 -0
  6. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/README.md +0 -0
  7. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/__init__.py +0 -0
  8. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/callbacks/__init__.py +0 -0
  9. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/callbacks/callback_util.py +0 -0
  10. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/callbacks/field_builder.py +0 -0
  11. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/chem/IndigoMolecules.py +0 -0
  12. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/chem/Molecules.py +0 -0
  13. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/chem/__init__.py +0 -0
  14. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/customreport/__init__.py +0 -0
  15. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/customreport/auto_pagers.py +0 -0
  16. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/customreport/column_builder.py +0 -0
  17. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/customreport/custom_report_builder.py +0 -0
  18. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/customreport/term_builder.py +0 -0
  19. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/datatype/__init__.py +0 -0
  20. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/datatype/attachment_util.py +0 -0
  21. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/datatype/data_fields.py +0 -0
  22. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/datatype/pseudo_data_types.py +0 -0
  23. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/eln/__init__.py +0 -0
  24. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/eln/experiment_cache.py +0 -0
  25. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/eln/experiment_handler.py +0 -0
  26. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/eln/experiment_report_util.py +0 -0
  27. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/eln/experiment_step_factory.py +0 -0
  28. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/eln/experiment_tags.py +0 -0
  29. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/eln/plate_designer.py +0 -0
  30. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/eln/step_creation.py +0 -0
  31. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/files/__init__.py +0 -0
  32. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/files/complex_data_loader.py +0 -0
  33. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/files/file_bridge.py +0 -0
  34. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/files/file_bridge_handler.py +0 -0
  35. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/files/file_data_handler.py +0 -0
  36. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/files/file_util.py +0 -0
  37. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/files/file_validator.py +0 -0
  38. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/files/file_writer.py +0 -0
  39. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/flowcyto/flow_cyto.py +0 -0
  40. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/flowcyto/flowcyto_data.py +0 -0
  41. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/general/__init__.py +0 -0
  42. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/general/accession_service.py +0 -0
  43. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/general/aliases.py +0 -0
  44. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/general/audit_log.py +0 -0
  45. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/general/custom_report_util.py +0 -0
  46. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/general/data_structure_util.py +0 -0
  47. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/general/directive_util.py +0 -0
  48. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/general/exceptions.py +0 -0
  49. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/general/html_formatter.py +0 -0
  50. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/general/popup_util.py +0 -0
  51. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/general/sapio_links.py +0 -0
  52. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/general/storage_util.py +0 -0
  53. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/general/time_util.py +0 -0
  54. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/multimodal/multimodal.py +0 -0
  55. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/multimodal/multimodal_data.py +0 -0
  56. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/processtracking/__init__.py +0 -0
  57. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/processtracking/custom_workflow_handler.py +0 -0
  58. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/processtracking/endpoints.py +0 -0
  59. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/recordmodel/__init__.py +0 -0
  60. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/recordmodel/record_handler.py +0 -0
  61. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/rules/__init__.py +0 -0
  62. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/rules/eln_rule_handler.py +0 -0
  63. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/rules/on_save_rule_handler.py +0 -0
  64. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/samples/aliquot.py +0 -0
  65. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/sftpconnect/__init__.py +0 -0
  66. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/sftpconnect/sftp_builder.py +0 -0
  67. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/webhook/__init__.py +0 -0
  68. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/webhook/webhook_context.py +0 -0
  69. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/webhook/webhook_handlers.py +0 -0
  70. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/src/sapiopycommons/webhook/webservice_handlers.py +0 -0
  71. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/tests/AF-A0A009IHW8-F1-model_v4.cif +0 -0
  72. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/tests/_do_not_add_init_py_here +0 -0
  73. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/tests/accession_test.py +0 -0
  74. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/tests/aliquot_test.py +0 -0
  75. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/tests/bio_reg_test.py +0 -0
  76. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/tests/chem_test.py +0 -0
  77. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/tests/chem_test_curation_queue.py +0 -0
  78. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/tests/curation_queue_test.sdf +0 -0
  79. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/tests/data_type_models.py +0 -0
  80. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/tests/flowcyto/101_DEN084Y5_15_E01_008_clean.fcs +0 -0
  81. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/tests/flowcyto/101_DEN084Y5_15_E03_009_clean.fcs +0 -0
  82. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/tests/flowcyto/101_DEN084Y5_15_E05_010_clean.fcs +0 -0
  83. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/tests/flowcyto/8_color_ICS.wsp +0 -0
  84. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/tests/flowcyto/COVID19_W_001_O.fcs +0 -0
  85. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/tests/flowcyto_test.py +0 -0
  86. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/tests/kappa.chains.fasta +0 -0
  87. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/tests/mafft_test.py +0 -0
  88. {sapiopycommons-2025.7.2a579 → sapiopycommons-2025.7.8a581}/tests/test.gb +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: sapiopycommons
3
- Version: 2025.7.2a579
3
+ Version: 2025.7.8a581
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.07.02a579'
7
+ version='2025.07.08a581'
8
8
  authors = [
9
9
  { name="Jonathan Steck", email="jsteck@sapiosciences.com" },
10
10
  { name="Yechen Qiao", email="yqiao@sapiosciences.com" },
@@ -46,7 +46,7 @@ class SerializableMoleculeMatch:
46
46
  _matching_molecule_file: str
47
47
  _query_molecule: IndigoObject
48
48
  _matching_molecule: IndigoObject
49
- _record_id: int # Only when received from Sapio.
49
+ _record_id: int # Only when received from Sapio.
50
50
 
51
51
  @property
52
52
  def record_id(self) -> int:
@@ -59,6 +59,22 @@ class SerializableMoleculeMatch:
59
59
  def __str__(self):
60
60
  return json.dumps(self.to_json())
61
61
 
62
+ def __hash__(self):
63
+ return hash(self._query_molecule.smarts())
64
+
65
+ def __eq__(self, other):
66
+ if not isinstance(other, SerializableMoleculeMatch):
67
+ return False
68
+ if self._query_atom_to_atom == other._query_atom_to_atom and \
69
+ self._query_bond_to_bond == other._query_bond_to_bond and \
70
+ self._query_molecule_file == other._query_molecule_file and \
71
+ self._matching_molecule_file == other._matching_molecule_file and \
72
+ self._record_id == other._record_id:
73
+ return True
74
+ if self._query_molecule.smarts() != other._query_molecule.smarts():
75
+ return False
76
+ return are_symmetrical_subs(self, other)
77
+
62
78
  def mapAtom(self, atom: IndigoObject) -> IndigoObject | None:
63
79
  if not self._query_atom_to_atom or atom.index() not in self._query_atom_to_atom:
64
80
  return None
@@ -378,4 +394,62 @@ def get_used_reactants_for_match(
378
394
  ret.append(found)
379
395
  else:
380
396
  return []
381
- return ret
397
+ return ret
398
+
399
+
400
+ def are_symmetrical_subs(match1: SerializableMoleculeMatch, match2: SerializableMoleculeMatch) -> bool:
401
+ """
402
+ Check if two SerializableMoleculeMatch objects are symmetrical.
403
+ That is, if we only get the atoms and bonds in the mapping, the two molecules are identical.
404
+ :param match1: The first SerializableMoleculeMatch object.
405
+ :param match2: The second SerializableMoleculeMatch object.
406
+ :return: True if the matches are symmetrical, False otherwise.
407
+ """
408
+ match1_test = match1.get_matched_molecule_copy()
409
+ match1_atom_indexes = set(match1._query_atom_to_atom.values())
410
+ match1_bond_indexes = set(match1._query_bond_to_bond.values())
411
+ atom_delete_list: list[int] = []
412
+ atom_mirror_list: list[int] = []
413
+ bond_delete_list: list[int] = []
414
+ bond_mirror_list: list[int] = []
415
+ for atom in match1_test.iterateAtoms():
416
+ if atom.index() not in match1_atom_indexes:
417
+ atom_delete_list.append(atom.index())
418
+ else:
419
+ atom_mirror_list.append(atom.index())
420
+ for bond in match1_test.iterateBonds():
421
+ if bond.index() not in match1_bond_indexes:
422
+ bond_delete_list.append(bond.index())
423
+ else:
424
+ bond_mirror_list.append(bond.index())
425
+ match1_test.removeBonds(bond_delete_list)
426
+ match1_test.removeAtoms(atom_delete_list)
427
+ match1_mirror_test = match1.get_matched_molecule_copy()
428
+ match1_mirror_test.removeBonds(bond_mirror_list)
429
+ match1_mirror_test.removeAtoms(atom_mirror_list)
430
+
431
+ match2_test = match2.get_matched_molecule_copy()
432
+ match2_atom_indexes = set(match2._query_atom_to_atom.values())
433
+ match2_bond_indexes = set(match2._query_bond_to_bond.values())
434
+ atom_delete_list = []
435
+ bond_delete_list = []
436
+ atom_mirror_list = []
437
+ bond_mirror_list = []
438
+ for atom in match2_test.iterateAtoms():
439
+ if atom.index() not in match2_atom_indexes:
440
+ atom_delete_list.append(atom.index())
441
+ else:
442
+ atom_mirror_list.append(atom.index())
443
+ for bond in match2_test.iterateBonds():
444
+ if bond.index() not in match2_bond_indexes:
445
+ bond_delete_list.append(bond.index())
446
+ else:
447
+ bond_mirror_list.append(bond.index())
448
+ match2_test.removeBonds(bond_delete_list)
449
+ match2_test.removeAtoms(atom_delete_list)
450
+ match2_mirror_test = match2.get_matched_molecule_copy()
451
+ match2_mirror_test.removeBonds(bond_mirror_list)
452
+ match2_mirror_test.removeAtoms(atom_mirror_list)
453
+
454
+ return match1_test.canonicalSmiles() == match2_test.canonicalSmiles() and \
455
+ match1_mirror_test.canonicalSmiles() == match2_mirror_test.canonicalSmiles()