Skip to content

Fix subtle logic bugs and remove duplicate definitions#2

Open
chrishwiggins wants to merge 1 commit intoFrancoisSimon:mainfrom
chrishwiggins:fix/logic-and-semantic-issues
Open

Fix subtle logic bugs and remove duplicate definitions#2
chrishwiggins wants to merge 1 commit intoFrancoisSimon:mainfrom
chrishwiggins:fix/logic-and-semantic-issues

Conversation

@chrishwiggins
Copy link
Collaborator

Summary

Hi Francois - this is a companion to PR #1 (which covered the runtime crashes). This one addresses a few subtler issues that wouldn't necessarily crash but could produce unexpected behavior or make debugging harder down the road.

I've tried to keep each change as small and self-contained as possible. Happy to discuss any of these if you see them differently.

Changes

1. Off-by-one in anomalous_diff_2D angle indexing (line 211)

The loop for i in range(len(positions)-1) used angle = angles[i-1]. When i=0, Python's negative indexing means angles[-1] reads the last element of the array rather than the first. Since angles[0] is the randomly drawn initial heading and the angles array has exactly len(positions)-1 entries (one per displacement step), the intended indexing appears to be angles[i].

This would affect the direction of the very first displacement step in simulated 2D tracks. For tracks with many sub-steps it might be hard to notice, but it could matter for short tracks or when the initial direction is important.

2. padding() dtype from loop variable (line 336)

mask = np.zeros(..., dtype = track.dtype) used the variable track which at that point refers to the last element iterated over in the preceding for track in track_list loop. This works fine in practice (all tracks have the same dtype), but it's fragile - if track_list were empty, it would reference a variable from an outer scope or raise a NameError. Changed to track_list[0].dtype to make the intent clear.

3. raise Warning(...) changed to warnings.warn(...) (line 346)

raise Warning(...) is syntactically valid Python, but Warning isn't typically used as an exception to raise. The intent here is clearly to warn the user about short tracks that get skipped, not to halt execution. Changed to warnings.warn(...) so that processing continues and users still see the message. Added import warnings at the top.

4. read_table() mutating the caller's colnames list (line 396)

When tracks have composite IDs (the colnames[3] is a list), the function does colnames[3] = 'unique_ID' which modifies the list object that was passed in. If someone calls read_table multiple times with the same colnames list, the second call would see 'unique_ID' instead of the original column names. Added colnames = list(colnames) at the top of the function to work on a copy.

5. Bare except: clause in read_table() (line 440)

The bare except: catches everything (including KeyboardInterrupt, SystemExit, typos causing NameError, etc.) and only prints the filename with no indication of what went wrong. Narrowed it to except Exception as e: and included the error message in the print so that when files do cause problems, there's some context for debugging.

6. Duplicate transpose_layer class definition removed

The class was defined identically at two locations in the file. The first definition (around line 1348) is the one used by build_model and build_abrupt_directed_motion_changes_model. Removed the second copy.

7. Duplicate MLE_loss function definition removed

MLE_loss was defined twice in the module with identical implementations. The first definition (around line 2009) is the one that's exported and used. Removed the second copy so there's a single source of truth.

Test plan

  • Verify python -m py_compile exatrack.py passes (confirmed locally)
  • Run simulation with anomalous_diff_2D and verify first displacement step direction is consistent with initial angle
  • Call read_table twice with the same colnames list and verify it isn't modified
  • Verify padding() with short tracks issues a warning instead of crashing

Generated with Claude Code

- Fix off-by-one in anomalous_diff_2D: angles[i-1] wraps to last
  element when i=0, should be angles[i]
- Fix padding() referencing loop variable for dtype instead of
  track_list[0]
- Change raise Warning(...) to warnings.warn(...) in padding()
- Copy colnames list in read_table() to avoid mutating caller's list
- Narrow bare except to except Exception and include error message
- Remove duplicate transpose_layer class definition
- Remove duplicate MLE_loss function definition

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant