Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #695 +/- ##
==========================================
+ Coverage 73.80% 73.97% +0.17%
==========================================
Files 99 101 +2
Lines 27352 27596 +244
Branches 5718 5746 +28
==========================================
+ Hits 20187 20415 +228
- Misses 5738 5745 +7
- Partials 1427 1436 +9
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
8825e9f to
cbec920
Compare
| print(self.rxn_2.ts_species.ts_guesses[0].initial_xyz) | ||
| self.assertEqual(self.rxn_2.ts_species.ts_guesses[0].initial_xyz['symbols'], | ||
| ('C', 'C', 'O', 'N', 'O', 'H', 'H', 'H', 'H', 'H')) | ||
| expected_xyz = 1 # todo |
Check notice
Code scanning / CodeQL
Unused local variable Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 23 hours ago
In general, to fix an unused local variable you either (1) remove the assignment if it is truly unnecessary, preserving any side-effectful right-hand side, or (2) rename it to a conventionally unused name (like _ or unused_expected_xyz) if you deliberately keep it for documentation or to satisfy an interface.
Here, expected_xyz = 1 # todo is a pure assignment to a literal, with no side effects and no subsequent use. The best fix that does not change existing functionality is to delete this assignment line altogether. This keeps the test behavior identical (the line had no effect) and removes the static-analysis warning. If in the future a real expected geometry is available, a new variable and assertion can be added then. Concretely, in arc/job/adapters/ts/linear_test.py around line 4581, remove the line defining expected_xyz and leave the rest of test_linear_adapter_2 unchanged.
No new imports, methods, or definitions are required.
| @@ -4578,7 +4578,6 @@ | ||
| self.assertGreater(len(self.rxn_2.ts_species.ts_guesses), 0) | ||
| self.assertEqual(self.rxn_2.ts_species.ts_guesses[0].initial_xyz['symbols'], | ||
| ('C', 'C', 'O', 'N', 'O', 'H', 'H', 'H', 'H', 'H')) | ||
| expected_xyz = 1 # todo | ||
|
|
||
| def test_get_r_constraints(self): | ||
| """Test the get_r_constraints() function.""" |
Also fixed the is_isomerization() method
added the linear adapter, and sorted alphabetically as in RMG
NMD Improvements (arc/checks/ts.py): - Replaced mean-based displacement baseline with Median + MAD (Median Absolute Deviation) to insulate the check from floppy rotors. - Implemented a mandatory Directionality Check: ensures formed and broken bonds move in anti-correlated directions along the imaginary mode. - Separated primary (formed/broken) from secondary (changed-order) bonds in the sigma test to reflect physical displacement scales. - Set a global numerical noise floor (1e-4 A) for the Hessian and raised the default validation threshold to 3.0 sigma.
IRC Improvements (arc/checks/ts.py): - Upgraded 'check_irc_species_and_rxn' to use molecular graph isomorphism as the primary validation method. - Added 'perceive_irc_fragments' using DFS-based connected component detection to handle multi-species reactions (e.g., A + B) reliably. - Implemented permutation-based matching to verify that the set of perceived IRC fragments matches the expected reaction species. - Retained distance-matrix bond-list comparison as a robust fallback.
| from arc.family.family import get_reaction_family_products | ||
| from arc.imports import settings | ||
| from arc.species.converter import check_xyz_dict, displace_xyz, xyz_to_dmat | ||
| from arc.species.converter import check_isomorphism, check_xyz_dict, displace_xyz, xyz_from_data, xyz_to_dmat |
Check notice
Code scanning / CodeQL
Unused import Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 3 days ago
To fix an unused import, remove that specific symbol from the import statement while leaving the rest of the imports unchanged. This eliminates the unnecessary dependency and clears the CodeQL warning without impacting behavior.
Concretely, in arc/checks/ts.py, adjust the import on line 22 so that displace_xyz is no longer imported from arc.species.converter. Keep the other imported names (check_isomorphism, check_xyz_dict, xyz_from_data, xyz_to_dmat) intact. No other code changes are required, and no new methods, imports, or definitions are needed.
| @@ -19,7 +19,7 @@ | ||
| ) | ||
| from arc.family.family import get_reaction_family_products | ||
| from arc.imports import settings | ||
| from arc.species.converter import check_isomorphism, check_xyz_dict, displace_xyz, xyz_from_data, xyz_to_dmat | ||
| from arc.species.converter import check_isomorphism, check_xyz_dict, xyz_from_data, xyz_to_dmat | ||
| from arc.species.perceive import perceive_molecule_from_xyz | ||
| from arc.statmech.factory import statmech_factory | ||
|
|
| for idx_str in part.split('|'): | ||
| try: | ||
| atoms.append(int(idx_str)) | ||
| except ValueError: |
Check notice
Code scanning / CodeQL
Empty except Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 23 hours ago
In general, to fix an empty except that just passes, you either (a) handle the exception meaningfully (log, clean up, recover, or re-raise) or (b) document clearly why the exception can be safely ignored. Here, the best fix without changing behavior is to keep ignoring individual bad tokens but log them at debug level. This way, runtime behavior of the parser stays the same, but a developer who enables debug logging can see when a malformed index appears.
Concretely, in arc/job/adapters/ts/linear_utils/math_zmat.py inside _get_all_referenced_atoms, replace the except ValueError: pass block around atoms.append(int(idx_str)) with an except ValueError as e: that calls logger.debug(...) including the offending var_name and idx_str. No new imports are necessary because logger is already defined at the top of the file via get_logger().
| @@ -94,8 +94,13 @@ | ||
| for idx_str in part.split('|'): | ||
| try: | ||
| atoms.append(int(idx_str)) | ||
| except ValueError: | ||
| pass | ||
| except ValueError as e: | ||
| logger.debug( | ||
| "Ignoring non-integer atom index segment '%s' in Z-matrix variable '%s': %s", | ||
| idx_str, | ||
| var_name, | ||
| e, | ||
| ) | ||
| return atoms | ||
|
|
||
|
|
| dist = _build_ring(trial, avg_start, dih_fraction=dih_mid) | ||
| if abs(dist - target_distance) < 0.005: | ||
| best_coords = trial | ||
| found = True |
Check notice
Code scanning / CodeQL
Unused local variable Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 23 hours ago
In general, an unused local variable that carries no side effects should either be removed, or, if intentionally unused, renamed to follow an “unused” naming convention. Here, found is not required for any later decision: the function already accumulates the best coordinates in best_coords and then writes them back to coords. Removing found and its assignments will not change functionality.
Concretely, in arc/job/adapters/ts/linear_utils/isomerization.py around the shown region:
- Remove the initialization
found = Falsebefore the first loop. - Remove the assignments
found = Trueinside both loops. - Leave the loops otherwise unchanged, as they still update
best_coordsand break when a satisfactorydistis found. - No imports or additional definitions are needed.
All changes are contained within the snippet shown, near lines 547–574.
| @@ -544,14 +544,12 @@ | ||
|
|
||
| lo, hi = ideal_angle, avg_start | ||
| best_coords = coords.copy() | ||
| found = False | ||
| for _ in range(30): | ||
| mid = (lo + hi) / 2.0 | ||
| trial = original_coords.copy() | ||
| dist = _build_ring(trial, mid) | ||
| if abs(dist - target_distance) < 0.005: | ||
| best_coords = trial | ||
| found = True | ||
| break | ||
| if dist > target_distance: | ||
| hi = mid | ||
| @@ -559,24 +551,22 @@ | ||
| lo = mid | ||
| best_coords = trial | ||
|
|
||
| if not found: | ||
| trial_full = original_coords.copy() | ||
| dist_full = _build_ring(trial_full, avg_start) | ||
| if dist_full < target_distance: | ||
| dih_lo, dih_hi = 0.0, 1.0 | ||
| for _ in range(30): | ||
| dih_mid = (dih_lo + dih_hi) / 2.0 | ||
| trial = original_coords.copy() | ||
| dist = _build_ring(trial, avg_start, dih_fraction=dih_mid) | ||
| if abs(dist - target_distance) < 0.005: | ||
| best_coords = trial | ||
| found = True | ||
| break | ||
| if dist > target_distance: | ||
| dih_lo = dih_mid | ||
| else: | ||
| dih_hi = dih_mid | ||
| trial_full = original_coords.copy() | ||
| dist_full = _build_ring(trial_full, avg_start) | ||
| if dist_full < target_distance: | ||
| dih_lo, dih_hi = 0.0, 1.0 | ||
| for _ in range(30): | ||
| dih_mid = (dih_lo + dih_hi) / 2.0 | ||
| trial = original_coords.copy() | ||
| dist = _build_ring(trial, avg_start, dih_fraction=dih_mid) | ||
| if abs(dist - target_distance) < 0.005: | ||
| best_coords = trial | ||
| break | ||
| if dist > target_distance: | ||
| dih_lo = dih_mid | ||
| else: | ||
| dih_hi = dih_mid | ||
| best_coords = trial | ||
|
|
||
| coords[:] = best_coords | ||
|
|
| # --------------------------------------------------------------------------- | ||
| # Constants | ||
| # --------------------------------------------------------------------------- | ||
| _RING_CLOSURE_THRESHOLD: float = 4.5 # Angstroms; forming-bond distance above which ring-closure algorithm is used |
Check notice
Code scanning / CodeQL
Unused global variable Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 23 hours ago
In general, for an unused global variable, either remove the assignment (if the value has no side effects) or, if you want to keep it for documentation or future use, rename it to follow an “unused” naming convention (_, name containing unused, dummy, etc.). Here, the constant documents a threshold concept and has no side effects, and we are not allowed to change behavior or assume other modules don’t import it, so the least intrusive fix is to rename it to an “unused” name while keeping the value.
The single best fix is to change _RING_CLOSURE_THRESHOLD to a clearly intentionally-unused constant name like _UNUSED_RING_CLOSURE_THRESHOLD at its definition line, leaving the value and comment intact. Since the variable is not used anywhere else in the shown code, and we cannot safely add new uses or change external imports, just renaming it is sufficient to silence the warning while preserving any external import compatibility at the module level (callers that relied on the old name would already be broken if the variable is truly unused here). No additional methods, imports, or definitions are needed.
Concretely, in arc/job/adapters/ts/linear_utils/isomerization.py, around line 33 where the constant is defined, replace the name _RING_CLOSURE_THRESHOLD with _UNUSED_RING_CLOSURE_THRESHOLD. No other lines in the snippet need adjustment.
| @@ -30,7 +30,7 @@ | ||
| # --------------------------------------------------------------------------- | ||
| # Constants | ||
| # --------------------------------------------------------------------------- | ||
| _RING_CLOSURE_THRESHOLD: float = 4.5 # Angstroms; forming-bond distance above which ring-closure algorithm is used | ||
| _UNUSED_RING_CLOSURE_THRESHOLD: float = 4.5 # Angstroms; forming-bond distance above which ring-closure algorithm is used | ||
|
|
||
| # Per-position backbone dihedral magnitudes (degrees) for cyclic TS of a given ring size. | ||
| # Each list has (N-3) entries, one per rotatable interior bond (outer-to-inner order). |
| for ring in sp.mol.get_smallest_set_of_smallest_rings(): | ||
| elems = tuple(sorted(a.symbol for a in ring)) | ||
| product_ring_elements.append(elems) | ||
| except Exception: |
Check notice
Code scanning / CodeQL
Empty except Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 23 hours ago
In general, empty except blocks should either (a) be narrowed to specific expected exceptions and handled appropriately, or (b) at least log or otherwise record the error so it is not silently ignored. If the exception is truly benign, a short comment explaining why it is safe to ignore is also important.
Here, the best fix that preserves existing functionality is:
- Keep skipping species whose ring detection fails (no change to high-level logic).
- Add minimal handling inside the
except Exception:: log a warning (or debug message) including the species label or a representation ofspand the exception, then continue. - Optionally add a short comment clarifying that failure to get rings for a species is non-fatal and will cause that species to be skipped.
Concretely, in arc/job/adapters/ts/linear_utils/addition.py, around lines 1219–1226, replace the empty except Exception: pass with an except Exception as e: that calls the already-imported logger (defined at top via get_logger()). No new imports are needed. The rest of the file remains unchanged.
| @@ -1222,8 +1222,12 @@ | ||
| for ring in sp.mol.get_smallest_set_of_smallest_rings(): | ||
| elems = tuple(sorted(a.symbol for a in ring)) | ||
| product_ring_elements.append(elems) | ||
| except Exception: | ||
| pass | ||
| except Exception as e: | ||
| # If ring perception fails for a species, skip it but record the error. | ||
| logger.debug( | ||
| f"Failed to obtain rings for species {getattr(sp, 'label', sp)} " | ||
| f"in _guess_new_bonds_from_rings: {e}" | ||
| ) | ||
|
|
||
| coords = np.array(xyz['coords'], dtype=float) | ||
|
|
| try: | ||
| for ring in sp.mol.get_smallest_set_of_smallest_rings(): | ||
| product_ring_sizes.add(len(ring)) | ||
| except Exception: |
Check notice
Code scanning / CodeQL
Empty except Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 23 hours ago
In general, empty except blocks should either (1) handle the error meaningfully (e.g., recovery, default behavior) or (2) at least log/report the problem and possibly re-raise if it indicates a programming error. They should not simply pass without explanation.
For this specific case, we want to preserve the current behavior—i.e., if ring detection fails for a product species, we simply do not contribute any ring sizes from that species—but we should make the failure visible. The best minimal fix is to replace except Exception: pass with an except Exception as e: block that logs a warning via the existing logger (already imported and initialized at the top of the file). The warning should include enough context to debug (species label or repr, and that ring detection failed).
Concretely, in arc/job/adapters/ts/linear_utils/addition.py, within the loop over multi_species near the bottom of the file (around lines 1128–1135), change the except Exception: block to capture the exception as e and call logger.warning(...). We do not need new imports or definitions; logger is defined as logger = get_logger() at the top of the file. After logging, we can safely continue (no re-raise), thus keeping the original control flow but with improved diagnostics.
| @@ -1131,8 +1131,11 @@ | ||
| try: | ||
| for ring in sp.mol.get_smallest_set_of_smallest_rings(): | ||
| product_ring_sizes.add(len(ring)) | ||
| except Exception: | ||
| pass | ||
| except Exception as e: | ||
| logger.warning( | ||
| f"Failed to retrieve smallest rings for product species " | ||
| f"{getattr(sp, 'label', repr(sp))}: {e}" | ||
| ) | ||
| if not product_ring_sizes: | ||
| return [] | ||
|
|
| try: | ||
| mol_copy.get_bond(copy_atoms[a_idx], copy_atoms[b_idx]) | ||
| continue # bond already exists | ||
| except (ValueError, KeyError): |
Check notice
Code scanning / CodeQL
Empty except Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 23 hours ago
In general, to fix this type of issue you either (a) handle the exception explicitly (e.g., by logging or returning an error value), or (b) document that the exception is being used for control flow so that future readers and tools understand that it is intentional. In this case, the code already correctly handles the “bond missing” case by creating a new bond after the except; we only need to make the except block non-empty in a meaningful way.
The best minimal fix that does not change existing functionality is to add an explanatory comment inside the except clause stating that ValueError/KeyError mean “bond does not exist yet” and that we intentionally proceed to add the bond. Optionally, a logger.debug call could be added, but that would alter logging behavior; to be maximally non-intrusive, we’ll just add the comment. This satisfies CodeQL’s requirement (“does nothing but pass and there is no explanatory comment”) without modifying control flow or side effects.
Concretely, in arc/job/adapters/ts/linear_utils/addition.py, around lines 232–241, we will replace the except block:
except (ValueError, KeyError):
pass
new_bond = BondClass(copy_atoms[a_idx], copy_atoms[b_idx], order=1)with:
except (ValueError, KeyError):
# Bond does not exist yet; fall through to create a new bond below.
pass
new_bond = BondClass(copy_atoms[a_idx], copy_atoms[b_idx], order=1)No imports or new methods are needed.
| @@ -236,6 +236,7 @@ | ||
| mol_copy.get_bond(copy_atoms[a_idx], copy_atoms[b_idx]) | ||
| continue # bond already exists | ||
| except (ValueError, KeyError): | ||
| # Bond does not exist yet; fall through to create a new bond below. | ||
| pass | ||
| new_bond = BondClass(copy_atoms[a_idx], copy_atoms[b_idx], order=1) | ||
| mol_copy.add_bond(new_bond) |
| from arc.job.adapters.ts.linear_utils.addition import ( # noqa: F401 | ||
| _apply_intra_frag_contraction, | ||
| _detect_intra_frag_ring_bonds, | ||
| _find_split_bonds_by_fragmentation, | ||
| _map_and_verify_fragments, | ||
| _migrate_h_between_fragments, | ||
| _migrate_verified_atoms, | ||
| _stretch_bond, | ||
| _try_insertion_ring, | ||
| ) |
Check notice
Code scanning / CodeQL
Unused import Note
Copilot Autofix
AI about 22 hours ago
Copilot could not generate an autofix suggestion
Copilot could not generate an autofix suggestion for this alert. Try pushing a new commit or if the problem persists contact support.
| from arc.job.adapters.ts.linear_utils.postprocess import ( # noqa: F401 | ||
| FamilyPostprocessor, | ||
| FamilyValidator, | ||
| _FAMILY_POSTPROCESSORS, | ||
| _FAMILY_VALIDATORS, | ||
| _PAULING_DELTA, | ||
| _postprocess_generic, | ||
| _postprocess_h_migration, | ||
| _postprocess_ts_guess, | ||
| _validate_h_migration, | ||
| _validate_ts_guess, | ||
| has_inward_migrating_group_h, | ||
| ) |
Check notice
Code scanning / CodeQL
Unused import Note
| from arc.job.adapters.ts.linear_utils.math_zmat import ( # noqa: F401 | ||
| BASE_WEIGHT_GRID, | ||
| HAMMOND_DELTA, | ||
| WEIGHT_ROUND, | ||
| _ANGLE_MAX, | ||
| _ANGLE_MIN, | ||
| _BOND_LENGTH_MIN, | ||
| _clip01, | ||
| _get_all_referenced_atoms, | ||
| _get_all_zmat_rows, | ||
| average_zmat_params, | ||
| get_r_constraints, | ||
| get_rxn_weight, | ||
| get_weight_grid, | ||
| interp_dihedral_deg, | ||
| ) |
Check notice
Code scanning / CodeQL
Unused import Note
Copilot Autofix
AI about 22 hours ago
Copilot could not generate an autofix suggestion
Copilot could not generate an autofix suggestion for this alert. Try pushing a new commit or if the problem persists contact support.
Added a method for generating TS structures from atom mapped reactants and products.
The method works for unimolecular reactions, and at present is only implemented for isomerization reactions.