PFASGroups 3.4.2__tar.gz → 3.4.3__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.
Files changed (82) hide show
  1. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups/PFASDefinitionModel.py +27 -14
  2. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups/data/PFAS_definitions_smarts.json +4 -4
  3. {pfasgroups-3.4.2 → pfasgroups-3.4.3/PFASGroups.egg-info}/PKG-INFO +3 -1
  4. {pfasgroups-3.4.2/PFASGroups.egg-info → pfasgroups-3.4.3}/PKG-INFO +3 -1
  5. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/README.md +2 -0
  6. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/pyproject.toml +1 -1
  7. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/setup.cfg +1 -1
  8. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/HalogenGroups/__init__.py +0 -0
  9. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups/ComponentsSolverModel.py +0 -0
  10. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups/HalogenGroupModel.py +0 -0
  11. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups/PFASEmbeddings.py +0 -0
  12. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups/__init__.py +0 -0
  13. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups/cli.py +0 -0
  14. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups/core.py +0 -0
  15. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups/data/Halogen_groups_smarts.json +0 -0
  16. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups/data/component_smarts.json +0 -0
  17. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups/data/component_smarts_halogens.json +0 -0
  18. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups/data/diatomic_bonds_dict.json +0 -0
  19. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups/draw_mols.py +0 -0
  20. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups/embeddings.py +0 -0
  21. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups/fragmentation.py +0 -0
  22. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups/generate_homologues.py +0 -0
  23. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups/generate_mol.py +0 -0
  24. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups/generate_paper_figures.py +0 -0
  25. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups/getter.py +0 -0
  26. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups/group_features.py +0 -0
  27. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups/homologue_series.py +0 -0
  28. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups/parser.py +0 -0
  29. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups/prioritise.py +0 -0
  30. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups.egg-info/SOURCES.txt +0 -0
  31. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups.egg-info/dependency_links.txt +0 -0
  32. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups.egg-info/entry_points.txt +0 -0
  33. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups.egg-info/requires.txt +0 -0
  34. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/PFASGroups.egg-info/top_level.txt +0 -0
  35. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/gui/__init__.py +0 -0
  36. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/gui/__main__.py +0 -0
  37. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/gui/app.py +0 -0
  38. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/gui/data/help.html +0 -0
  39. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/gui/style.py +0 -0
  40. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/gui/tabs/__init__.py +0 -0
  41. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/gui/tabs/chemspace_tab.py +0 -0
  42. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/gui/tabs/classify_tab.py +0 -0
  43. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/gui/tabs/definition_tester_tab.py +0 -0
  44. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/gui/tabs/help_tab.py +0 -0
  45. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/gui/tabs/modelling_tab.py +0 -0
  46. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/gui/tabs/prioritise_tab.py +0 -0
  47. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/gui/tabs/results_tab.py +0 -0
  48. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/gui/utils/__init__.py +0 -0
  49. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/gui/utils/chemspace.py +0 -0
  50. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/gui/utils/export_dialog.py +0 -0
  51. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/gui/utils/fingerprints.py +0 -0
  52. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/gui/utils/io_readers.py +0 -0
  53. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/gui/utils/modelling.py +0 -0
  54. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/gui/utils/mol_renderer.py +0 -0
  55. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/gui/workers.py +0 -0
  56. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_bde_resistance.py +0 -0
  57. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_component_fractions.py +0 -0
  58. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_component_ratios.py +0 -0
  59. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_comprehensive_metrics.py +0 -0
  60. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_database_integration.py +0 -0
  61. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_definition_comparison.py +0 -0
  62. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_fingerprints_vs_txppfas.py +0 -0
  63. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_fraction_analysis.py +0 -0
  64. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_generate_homologues.py +0 -0
  65. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_halogen_groups_smarts.py +0 -0
  66. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_linker_smarts.py +0 -0
  67. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_metrics.py +0 -0
  68. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_metrics_detailed.py +0 -0
  69. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_n_spacer_ring_size.py +0 -0
  70. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_parser_wildcard.py +0 -0
  71. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_pfasstructv5.py +0 -0
  72. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_prioritise.py +0 -0
  73. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_readme_and_docs_examples.py +0 -0
  74. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_results_fingerprint.py +0 -0
  75. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_results_model.py +0 -0
  76. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_results_sql.py +0 -0
  77. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_run_groups_definitions_tests.py +0 -0
  78. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_smarts_atom_count.py +0 -0
  79. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_smarts_matching.py +0 -0
  80. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_smarts_precompute.py +0 -0
  81. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_summary.py +0 -0
  82. {pfasgroups-3.4.2 → pfasgroups-3.4.3}/tests/test_telomer_validation.py +0 -0
@@ -177,36 +177,49 @@ class PFASDefinition:
177
177
 
178
178
  def _check_fluorine_ratio(self, formula: Dict[str, int], include_hydrogen: bool) -> bool:
179
179
  """Check if the fluorine ratio in a molecular formula meets the threshold.
180
-
180
+
181
+ Mass-weighted (F mass / total mass), matching the zeropmdb production
182
+ database's `fluorine_ratio` field (see `Update_CFHNOPS.sql`):
183
+ `fluorine_ratio = F_mass / (molecular_weight - H_mass)`. This is NOT an
184
+ atom-count ratio -- a molecule with heavy non-F/non-H atoms (e.g. Cl, Br)
185
+ will have a lower ratio per atom than per unit mass would suggest, and
186
+ vice versa for light atoms (C, N, O), so the two formulas can disagree
187
+ on which side of a threshold like 0.3 a given molecule falls.
188
+
181
189
  Parameters
182
190
  ----------
183
191
  formula : Dict[str, int]
184
192
  Molecular formula as {element: count} dictionary
185
193
  include_hydrogen : bool
186
- If True, includes hydrogen atoms in total atom count.
187
- If False, excludes hydrogen from total (heavy atoms only)
188
-
194
+ If True, includes hydrogen mass in the total mass.
195
+ If False, excludes hydrogen mass from total (heavy atoms only) --
196
+ this is the "heavy atoms only" mode PFASSTRUCTv5 uses.
197
+
189
198
  Returns
190
199
  -------
191
200
  bool
192
- True if (F_count / total_atoms) >= self.fluorineRatio, False otherwise
193
-
201
+ True if (F_mass / total_mass) >= self.fluorineRatio, False otherwise
202
+
194
203
  Notes
195
204
  -----
196
- - Returns False if total_atoms is 0
205
+ - Returns False if total_mass is 0
197
206
  - Formula with no fluorine (F_count=0) will fail unless fluorineRatio=0
198
207
  """
208
+ from rdkit.Chem import GetPeriodicTable
209
+ pt = GetPeriodicTable()
210
+
199
211
  f_count = formula.get('F', 0)
200
-
212
+ f_mass = f_count * pt.GetAtomicWeight('F')
213
+
201
214
  if include_hydrogen:
202
- total_atoms = sum(formula.values())
215
+ total_mass = sum(count * pt.GetAtomicWeight(sym) for sym, count in formula.items())
203
216
  else:
204
- total_atoms = sum(v for k, v in formula.items() if k != 'H')
205
-
206
- if total_atoms == 0:
217
+ total_mass = sum(count * pt.GetAtomicWeight(sym) for sym, count in formula.items() if sym != 'H')
218
+
219
+ if total_mass == 0:
207
220
  return False
208
-
209
- ratio = f_count / total_atoms
221
+
222
+ ratio = f_mass / total_mass
210
223
  return ratio >= self.fluorineRatio
211
224
 
212
225
  def test(self, test_data=None):
@@ -134,11 +134,13 @@
134
134
  ],
135
135
  "fluorineRatio": 0.3,
136
136
  "includeHydrogen": false,
137
- "description": "Custom structural patterns or F ratio ≥ 0.3 (heavy atoms only)",
137
+ "description": "Custom structural patterns or F ratio >= 0.3, mass-weighted (F mass / heavy-atom mass), matching the zeropmdb production database's fluorine_ratio field. Not an atom-count ratio: molecules with heavier non-F/non-H atoms (Cl, Br, S...) score lower per unit mass than per atom, and vice versa for lighter atoms (C, N, O).",
138
138
  "test": {
139
139
  "category": "definition",
140
140
  "examples": {
141
141
  "positives": [
142
+ "C1=COC(=C1)C=C(S(=O)(=O)C(F)(F)F)S(=O)(=O)C(F)(F)F",
143
+ "COC(=C(F)Cl)F",
142
144
  "C(=O)(C(F)(F)Cl)C(F)(F)Cl",
143
145
  "COC(C(OC(C(=O)C(F)(F)F)(F)F)F)(F)F",
144
146
  "C(C(=O)CC(C(=O)C(F)(F)F)(F)F)C(C(=O)C(F)(F)F)(F)F",
@@ -160,9 +162,7 @@
160
162
  ],
161
163
  "negatives": [
162
164
  "CCCCC(CC(C(F)(F)Br)(F)Cl)Br",
163
- "C(C(OC(Cl)(Cl)Cl)(F)F)(F)Cl",
164
- "C1=COC(=C1)C=C(S(=O)(=O)C(F)(F)F)S(=O)(=O)C(F)(F)F",
165
- "COC(=C(F)Cl)F"
165
+ "C(C(OC(Cl)(Cl)Cl)(F)F)(F)Cl"
166
166
  ]
167
167
  }
168
168
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PFASGroups
3
- Version: 3.4.2
3
+ Version: 3.4.3
4
4
  Summary: A comprehensive cheminformatics package for automated detection, classification, and analysis of halogenated substances, with a focus on per- and polyfluoroalkyl substances (PFAS). Combines SMARTS pattern matching, molecular formula constraints, and graph-based pathfinding to identify 119 groups. Supports creations of embeddings with graph metrics for Machine Learning workflows.
5
5
  Author: Luc T. Miaz
6
6
  Author-email: "Luc T. Miaz" <luc@miaz.ch>
@@ -846,6 +846,8 @@ See [USER_GUIDE.md](USER_GUIDE.md) for comprehensive examples including:
846
846
  - Integration with pandas and scikit-learn
847
847
 
848
848
  ## Summary of changes by version
849
+ - **Version 3.4.3**: Fixed ratio error, specific to PFASSTRUCTv5
850
+
849
851
  - **Version 3.4.2**: Fixed ambiguity with OPPT 2023.
850
852
 
851
853
  - **Version 3.4.1**: Added generic embedding for non-halogenated specific compounds which includes wildcard-components functional groups and halogen component size. Fixed H components and added cyclic and aryl H components.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PFASGroups
3
- Version: 3.4.2
3
+ Version: 3.4.3
4
4
  Summary: A comprehensive cheminformatics package for automated detection, classification, and analysis of halogenated substances, with a focus on per- and polyfluoroalkyl substances (PFAS). Combines SMARTS pattern matching, molecular formula constraints, and graph-based pathfinding to identify 119 groups. Supports creations of embeddings with graph metrics for Machine Learning workflows.
5
5
  Author: Luc T. Miaz
6
6
  Author-email: "Luc T. Miaz" <luc@miaz.ch>
@@ -846,6 +846,8 @@ See [USER_GUIDE.md](USER_GUIDE.md) for comprehensive examples including:
846
846
  - Integration with pandas and scikit-learn
847
847
 
848
848
  ## Summary of changes by version
849
+ - **Version 3.4.3**: Fixed ratio error, specific to PFASSTRUCTv5
850
+
849
851
  - **Version 3.4.2**: Fixed ambiguity with OPPT 2023.
850
852
 
851
853
  - **Version 3.4.1**: Added generic embedding for non-halogenated specific compounds which includes wildcard-components functional groups and halogen component size. Fixed H components and added cyclic and aryl H components.
@@ -798,6 +798,8 @@ See [USER_GUIDE.md](USER_GUIDE.md) for comprehensive examples including:
798
798
  - Integration with pandas and scikit-learn
799
799
 
800
800
  ## Summary of changes by version
801
+ - **Version 3.4.3**: Fixed ratio error, specific to PFASSTRUCTv5
802
+
801
803
  - **Version 3.4.2**: Fixed ambiguity with OPPT 2023.
802
804
 
803
805
  - **Version 3.4.1**: Added generic embedding for non-halogenated specific compounds which includes wildcard-components functional groups and halogen component size. Fixed H components and added cyclic and aryl H components.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "PFASGroups"
7
- version = "3.4.2"
7
+ version = "3.4.3"
8
8
  description = "A comprehensive cheminformatics package for automated detection, classification, and analysis of halogenated substances, with a focus on per- and polyfluoroalkyl substances (PFAS). Combines SMARTS pattern matching, molecular formula constraints, and graph-based pathfinding to identify 119 groups. Supports creations of embeddings with graph metrics for Machine Learning workflows."
9
9
  authors = [
10
10
  { name = "Luc T. Miaz", email = "luc@miaz.ch" }
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = PFASGroups
3
- version = 3.4.2
3
+ version = 3.4.3
4
4
  description = A comprehensive cheminformatics package for automated detection, classification, and analysis of halogenated substances, with a focus on per- and polyfluoroalkyl substances (PFAS). Supports multi-halogen fingerprinting (F, Cl, Br, I) with per/poly saturation filtering and stackable fingerprint vectors.
5
5
  long_description = file: README.md
6
6
  long_description_content_type = text/markdown
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes