pymast 0.0.6__tar.gz → 1.0.1__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 (46) hide show
  1. pymast-1.0.1/PKG-INFO +636 -0
  2. pymast-1.0.1/README.md +590 -0
  3. pymast-1.0.1/pymast/__init__.py +50 -0
  4. {pymast-0.0.6 → pymast-1.0.1}/pymast/fish_history.py +59 -6
  5. pymast-1.0.1/pymast/formatter.py +1350 -0
  6. pymast-1.0.1/pymast/logger.py +58 -0
  7. {pymast-0.0.6 → pymast-1.0.1}/pymast/naive_bayes.py +116 -9
  8. pymast-1.0.1/pymast/overlap_removal.py +2385 -0
  9. {pymast-0.0.6 → pymast-1.0.1}/pymast/parsers.py +1091 -208
  10. pymast-1.0.1/pymast/predictors.py +356 -0
  11. pymast-1.0.1/pymast/radio_project.py +2036 -0
  12. pymast-1.0.1/pymast/validation.py +224 -0
  13. pymast-1.0.1/pymast.egg-info/PKG-INFO +636 -0
  14. pymast-1.0.1/pymast.egg-info/SOURCES.txt +31 -0
  15. pymast-1.0.1/pymast.egg-info/requires.txt +22 -0
  16. pymast-1.0.1/pyproject.toml +76 -0
  17. pymast-1.0.1/setup.py +6 -0
  18. pymast-1.0.1/tests/test_basic.py +138 -0
  19. pymast-1.0.1/tests/test_csv_pit.py +49 -0
  20. pymast-1.0.1/tests/test_formatter_tte.py +121 -0
  21. pymast-1.0.1/tests/test_initial_state_release.py +85 -0
  22. pymast-1.0.1/tests/test_overlap_hdf5_integration.py +74 -0
  23. pymast-1.0.1/tests/test_overlap_loading.py +54 -0
  24. pymast-1.0.1/tests/test_overlap_small.py +56 -0
  25. pymast-1.0.1/tests/test_overlap_unit.py +200 -0
  26. pymast-1.0.1/tests/test_parsers_basic.py +86 -0
  27. pymast-1.0.1/tests/test_pit_multiple_parser.py +55 -0
  28. pymast-1.0.1/tests/test_pit_parser.py +54 -0
  29. pymast-1.0.1/tests/test_unified_pit.py +84 -0
  30. pymast-0.0.6/PKG-INFO +0 -18
  31. pymast-0.0.6/README.md +0 -233
  32. pymast-0.0.6/pymast/__init__.py +0 -21
  33. pymast-0.0.6/pymast/formatter.py +0 -1012
  34. pymast-0.0.6/pymast/overlap_removal.py +0 -548
  35. pymast-0.0.6/pymast/predictors.py +0 -170
  36. pymast-0.0.6/pymast/radio_project.py +0 -1166
  37. pymast-0.0.6/pymast/table_merge.py +0 -154
  38. pymast-0.0.6/pymast.egg-info/PKG-INFO +0 -18
  39. pymast-0.0.6/pymast.egg-info/SOURCES.txt +0 -18
  40. pymast-0.0.6/pymast.egg-info/not-zip-safe +0 -1
  41. pymast-0.0.6/pymast.egg-info/requires.txt +0 -8
  42. pymast-0.0.6/setup.py +0 -23
  43. {pymast-0.0.6 → pymast-1.0.1}/LICENSE.txt +0 -0
  44. {pymast-0.0.6 → pymast-1.0.1}/pymast.egg-info/dependency_links.txt +0 -0
  45. {pymast-0.0.6 → pymast-1.0.1}/pymast.egg-info/top_level.txt +0 -0
  46. {pymast-0.0.6 → pymast-1.0.1}/setup.cfg +0 -0
pymast-1.0.1/PKG-INFO ADDED
@@ -0,0 +1,636 @@
1
+ Metadata-Version: 2.4
2
+ Name: pymast
3
+ Version: 1.0.1
4
+ Summary: Movement Analysis Software for Telemetry (MAST) - False positive removal and movement analysis for radio telemetry data
5
+ Author: Theodore Castro-Santos
6
+ Author-email: "Kevin P. Nebiolo" <kevin.nebiolo@kleinschmidtgroup.com>
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://github.com/knebiolo/mast
9
+ Project-URL: Documentation, https://github.com/knebiolo/mast/blob/main/README.md
10
+ Project-URL: Repository, https://github.com/knebiolo/mast
11
+ Project-URL: Bug Tracker, https://github.com/knebiolo/mast/issues
12
+ Keywords: telemetry,radio-tracking,fish,wildlife,movement-ecology,false-positive
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
21
+ Requires-Python: >=3.8
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE.txt
24
+ Requires-Dist: numpy>=1.20.0
25
+ Requires-Dist: pandas>=1.3.0
26
+ Requires-Dist: matplotlib>=3.4.0
27
+ Requires-Dist: statsmodels>=0.12.0
28
+ Requires-Dist: networkx>=2.5
29
+ Requires-Dist: scipy>=1.7.1
30
+ Requires-Dist: scikit-learn>=0.24.0
31
+ Requires-Dist: h5py>=3.0.0
32
+ Requires-Dist: dask>=2021.3.0
33
+ Requires-Dist: dask-ml>=1.9.0
34
+ Requires-Dist: distributed>=2021.3.0
35
+ Requires-Dist: numba>=0.53.0
36
+ Requires-Dist: tables>=3.8.0
37
+ Requires-Dist: intervaltree>=3.1.0
38
+ Provides-Extra: dev
39
+ Requires-Dist: pytest>=6.0; extra == "dev"
40
+ Requires-Dist: pytest-cov; extra == "dev"
41
+ Requires-Dist: black; extra == "dev"
42
+ Requires-Dist: flake8; extra == "dev"
43
+ Requires-Dist: sphinx; extra == "dev"
44
+ Requires-Dist: sphinx-rtd-theme; extra == "dev"
45
+ Dynamic: license-file
46
+
47
+ # PyMAST - Movement Analysis Software for Telemetry
48
+
49
+ <p align="center">
50
+ <img src="pymast_logo.png" alt="PyMAST Logo" width="400"/>
51
+ </p>
52
+
53
+ <p align="center">
54
+ <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"/></a>
55
+ <a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.8+-blue.svg" alt="Python 3.8+"/></a>
56
+ </p>
57
+
58
+ **PyMAST** (Movement Analysis Software for Telemetry) is a Python toolkit for processing, analyzing, and modeling radio telemetry data. From data import to statistical model export, PyMAST provides a complete solution for aquatic telemetry studies.
59
+
60
+ ## Key Features
61
+
62
+ - **Multi-Manufacturer Support** - Import from Lotek (SRX600/800/1200), Orion, ARES, and VR2 receivers
63
+ - **Automated Classification** - Naive Bayes classifier removes false positives
64
+ - **Bout Detection** - DBSCAN clustering identifies continuous presence periods
65
+ - **Overlap Resolution** - Signal quality comparison resolves spatial ambiguity
66
+ - **Movement Filtering** - Adjacency filter removes impossible transitions
67
+ - **Statistical Export** - CJS, LRDR, and Time-to-Event formats for Program MARK/R
68
+ - **HDF5 Database** - Fast queries and efficient storage for large datasets
69
+ - **Comprehensive Documentation** - All modules accessible via Python `help()` system
70
+ - **Visualization Suite** - Network graphs, bout distributions, overlap analysis, 3D fish tracks
71
+
72
+ ---
73
+
74
+ ## Quick Start
75
+
76
+ **New users: Start with [GETTING_STARTED.md](GETTING_STARTED.md) for a complete walkthrough.**
77
+
78
+ ### Installation
79
+
80
+ ```bash
81
+ pip install pymast
82
+ ```
83
+
84
+ Or from source:
85
+
86
+ ```bash
87
+ cd mast
88
+ pip install -e .
89
+ ```
90
+
91
+ ### 30-Second Example
92
+
93
+ ```python
94
+ from pymast.radio_project import radio_project
95
+ import pandas as pd
96
+
97
+ # Initialize project
98
+ proj = radio_project(
99
+ project_dir='C:/my_study',
100
+ db_name='study.h5',
101
+ tag_list=pd.read_csv('tags.csv'),
102
+ rec_list=pd.read_csv('receivers.csv')
103
+ )
104
+
105
+ # Import receiver data
106
+ proj.import_data(
107
+ file_name='receiver_001.csv',
108
+ receiver_make='srx1200',
109
+ rec_id='REC001',
110
+ scan_time=2.5,
111
+ channels=1
112
+ )
113
+
114
+ # Process and analyze
115
+ proj.make_recaptures_table()
116
+ ```
117
+
118
+ See [GETTING_STARTED.md](GETTING_STARTED.md) for complete workflows.
119
+
120
+ ---
121
+
122
+ ## Documentation
123
+
124
+ | Document | Description |
125
+ |----------|-------------|
126
+ | **[GETTING_STARTED.md](GETTING_STARTED.md)** | **Start here!** Complete setup guide |
127
+ | [ARCHITECTURE.md](ARCHITECTURE.md) | System design, database structure, workflow |
128
+ | [docs/TUTORIAL.md](docs/TUTORIAL.md) | Step-by-step analysis examples |
129
+ | [docs/API_REFERENCE.md](docs/API_REFERENCE.md) | Detailed function documentation |
130
+ | [CHANGELOG.md](CHANGELOG.md) | Version history and updates |
131
+
132
+ ### In-Code Documentation
133
+
134
+ All modules support Python's `help()` system:
135
+
136
+ ```python
137
+ import pymast
138
+ help(pymast.parsers) # Module overview
139
+ help(pymast.overlap_removal.bout) # Class documentation
140
+ help(pymast.naive_bayes.calculate_likelihood) # Function details
141
+ ```
142
+
143
+ ---
144
+
145
+ ## System Architecture
146
+
147
+ ```
148
+ Raw receiver files
149
+ -> Parsers (HDF5 import)
150
+ -> Classification (false positive removal)
151
+ -> Recaptures (link detections to locations)
152
+ -> Bout detection (presence periods)
153
+ -> Overlap resolution (multi-receiver conflicts)
154
+ -> Adjacency filter (movement constraints)
155
+ -> Formatter (CJS/LRDR/TTE)
156
+ -> Program MARK / R analysis
157
+ ```
158
+
159
+ See [ARCHITECTURE.md](ARCHITECTURE.md) for details.
160
+
161
+ ---
162
+
163
+ ## System Requirements
164
+
165
+ - **Python**: 3.8 or higher
166
+ - **RAM**: 8+ GB recommended for large datasets
167
+ - **Storage**: HDF5 database typically 20-50% of raw data size
168
+ - **Disk Space**: 10+ GB for large projects with beacon tags
169
+ - **Operating System**: Windows, macOS, or Linux
170
+
171
+ ### Required Input Files
172
+
173
+ MAST requires three CSV files to initialize a project:
174
+
175
+ #### 1. Master Tag File (`tblMasterTag.csv`)
176
+
177
+ | Field | Type | Required | Description |
178
+ |------------|----------|----------|------------------------------------------------|
179
+ | freq_code | string | Yes | Unique frequency-code combination |
180
+ | pulse_rate | float | Yes | Seconds between tag pulses |
181
+ | tag_type | string | Yes | 'study', 'BEACON', or 'TEST' |
182
+ | rel_date | datetime | Yes | Release date and time (YYYY-MM-DD HH:MM:SS) |
183
+ | rel_loc | string | Yes | Release location |
184
+ | cap_loc | string | Yes | Capture location |
185
+ | mort_rate | float | No | Mortality pulse rate (if equipped) |
186
+ | length | int | No | Fish length (mm) |
187
+ | weight | float | No | Fish weight (g) |
188
+ | species | string | No | Species name |
189
+ | sex | string | No | 'M' or 'F' |
190
+
191
+ **Example:**
192
+ ```csv
193
+ freq_code,pulse_rate,tag_type,rel_date,rel_loc,cap_loc,length,species
194
+ 164.123 45,3.0,study,2024-05-15 08:30:00,Release Site 1,Capture Site A,450,Atlantic Salmon
195
+ 164.234 12,5.0,BEACON,2024-05-01 00:00:00,Beacon Location,Beacon Location,NA,NA
196
+ ```
197
+
198
+ #### 2. Master Receiver File (`tblMasterReceiver.csv`)
199
+
200
+ | Field | Type | Required | Description |
201
+ |----------|--------|----------|-----------------------------------------------|
202
+ | rec_id | string | Yes | Unique receiver identifier |
203
+ | rec_type | string | Yes | 'srx600', 'srx800', 'srx1200', 'orion', 'ares', 'VR2' |
204
+ | node | string | Yes | Network node identifier |
205
+ | name | string | No | Common name for receiver location |
206
+
207
+ **Example:**
208
+ ```csv
209
+ rec_id,rec_type,node,name
210
+ R01,srx800,N01,Downstream Array
211
+ R02,srx800,N02,Fishway Entrance
212
+ R03,orion,N03,Upstream Release
213
+ ```
214
+
215
+ #### 3. Nodes File (`tblNodes.csv`)
216
+
217
+ | Field | Type | Required | Description |
218
+ |-------|--------|----------|--------------------------------------|
219
+ | node | string | Yes | Unique node identifier (matches receivers) |
220
+ | reach | string | No | Common name for river reach |
221
+ | X | int | Yes | Arbitrary X coordinate for visualization |
222
+ | Y | int | Yes | Arbitrary Y coordinate for visualization |
223
+
224
+ **Note:** Use arbitrary coordinates for visualization, not actual lat/lon. This creates clearer network diagrams for sinuous river systems.
225
+
226
+ **Example:**
227
+ ```csv
228
+ node,reach,X,Y
229
+ N01,Lower River,100,100
230
+ N02,Fishway,200,150
231
+ N03,Upper River,300,200
232
+ ```
233
+
234
+ ### Project Directory Structure
235
+
236
+ When you create a project, MAST automatically creates this structure:
237
+
238
+ ```
239
+ your_project/
240
+ Data/
241
+ tblMasterTag.csv
242
+ tblMasterReceiver.csv
243
+ tblNodes.csv
244
+ Training_Files/
245
+ [raw receiver files]
246
+ Output/
247
+ Figures/
248
+ recaptures.csv
249
+ your_database.h5
250
+ ```
251
+
252
+ ---
253
+
254
+ ## Workflow Steps
255
+
256
+ ### 1. Project Initialization
257
+
258
+ ```python
259
+ from pymast.radio_project import radio_project
260
+ import pandas as pd
261
+ import os
262
+
263
+ project_dir = r"C:\MyProject"
264
+ db_name = 'my_study'
265
+
266
+ # Load input files
267
+ tags = pd.read_csv(os.path.join(project_dir, 'tblMasterTag.csv'))
268
+ receivers = pd.read_csv(os.path.join(project_dir, 'tblMasterReceiver.csv'))
269
+ nodes = pd.read_csv(os.path.join(project_dir, 'tblNodes.csv'))
270
+
271
+ # Create project (detection_count and duration are classifier parameters)
272
+ project = radio_project(
273
+ project_dir=project_dir,
274
+ db_name=db_name,
275
+ detection_count=5, # Number of detections in detection history window
276
+ duration=1, # Duration (minutes) for noise ratio calculation
277
+ tag_data=tags,
278
+ receiver_data=receivers,
279
+ nodes_data=nodes
280
+ )
281
+ ```
282
+
283
+ ### 2. Import Raw Data
284
+
285
+ ```python
286
+ # Import data from one receiver
287
+ project.telem_data_import(
288
+ rec_id='R01', # Receiver ID from tblMasterReceiver
289
+ rec_type='srx800', # Receiver type
290
+ file_dir=os.path.join(project_dir, 'Data', 'Training_Files'),
291
+ db_dir=os.path.join(project_dir, f'{db_name}.h5'),
292
+ scan_time=1, # Channel scan time (seconds) for Orion/Ares
293
+ channels=1, # Number of channels for Orion/Ares
294
+ ant_to_rec_dict={'A0': 'R01'} # Antenna to receiver mapping
295
+ )
296
+
297
+ # Undo import if needed
298
+ # project.undo_import('R01')
299
+ ```
300
+
301
+ ### 3. Train Classifier
302
+
303
+ Training creates a dataset of known true and false positive detections using beacon tags and miscoded detections.
304
+
305
+ ```python
306
+ rec_id = 'R01'
307
+ rec_type = 'srx800'
308
+
309
+ # Get all fish detected at this receiver
310
+ fishes = project.get_fish(rec_id=rec_id)
311
+
312
+ # Train on each fish
313
+ for fish in fishes:
314
+ project.train(fish, rec_id)
315
+
316
+ # Generate training summary with visualization
317
+ project.training_summary(rec_type, site=[rec_id])
318
+
319
+ # Undo training if needed
320
+ # project.undo_training(rec_id)
321
+ ```
322
+
323
+ ### 4. Classify Detections
324
+
325
+ Apply the Naive Bayes classifier to identify false positives.
326
+
327
+ ```python
328
+ project.reclassify(
329
+ project=project,
330
+ rec_id='R01',
331
+ rec_type='srx800',
332
+ threshold_ratio=1.0, # 1.0 = MAP hypothesis, >1.0 = more strict, <1.0 = less strict
333
+ likelihood_model=['hit_ratio', 'cons_length', 'noise_ratio', 'power', 'lag_diff']
334
+ )
335
+
336
+ # Undo classification if needed
337
+ # project.undo_classification('R01')
338
+ ```
339
+
340
+ **Available Likelihood Predictors:**
341
+ - `hit_ratio`: Proportion of expected pulses detected
342
+ - `cons_length`: Maximum consecutive detections
343
+ - `noise_ratio`: Ratio of miscoded to correct detections
344
+ - `power`: Signal strength
345
+ - `lag_diff`: Second-order difference in detection intervals
346
+
347
+ ### 5. Bout Detection (Optional)
348
+
349
+ Identify discrete presence events at receivers.
350
+
351
+ ```python
352
+ import pymast
353
+
354
+ node = 'N01'
355
+ bout = pymast.bout(project, node, lag_window=2, time_limit=21600)
356
+
357
+ # Fit processes to find optimal threshold
358
+ threshold = bout.fit_processes()
359
+
360
+ # Calculate presences using fitted threshold
361
+ bout.presence(threshold)
362
+
363
+ # Or use a manual threshold (seconds)
364
+ # bout.presence(120)
365
+
366
+ # Undo if needed
367
+ # project.undo_bouts(node)
368
+ ```
369
+
370
+ ### 6. Overlap Removal (Optional)
371
+
372
+ Remove detections from parent receivers when fish is present at nested child receivers.
373
+
374
+ ```python
375
+ import pymast
376
+
377
+ # Define parent:child relationships (large:small detection zones)
378
+ edges = [
379
+ ('R01', 'R02'), # R01 overlaps R02
380
+ ('R01', 'R03'), # R01 overlaps R03
381
+ ('R02', 'R04'), # R02 overlaps R04
382
+ ]
383
+
384
+ nodes = ['R01', 'R02', 'R03', 'R04']
385
+
386
+ # Create overlap object and apply nested doll algorithm
387
+ doll = pymast.overlap_reduction(nodes, edges, project)
388
+ doll.nested_doll()
389
+
390
+ # Alternative: unsupervised removal (uses clustering)
391
+ # doll.unsupervised_removal()
392
+
393
+ # Undo if needed
394
+ # project.undo_overlap()
395
+ ```
396
+
397
+ ### 7. Create Recaptures Table
398
+
399
+ Compile all classified, de-overlapped detections into a final recaptures table.
400
+
401
+ ```python
402
+ # Create and export recaptures table
403
+ project.make_recaptures_table(export=True)
404
+
405
+ # Output will be saved to: Output/recaptures.csv
406
+
407
+ # Undo if needed
408
+ # project.undo_recaptures()
409
+ ```
410
+
411
+ ---
412
+
413
+ ## Statistical Data Formatting
414
+
415
+ ### Cormack-Jolly-Seber (CJS) Format
416
+
417
+ ```python
418
+ from pymast.formatter import cjs_data_prep
419
+
420
+ # Define receiver to recapture occasion mapping
421
+ receiver_to_recap = {
422
+ 'R01': 'R00', # Release
423
+ 'R02': 'R01', # First recapture
424
+ 'R03': 'R02', # Second recapture
425
+ 'R04': 'R03', # Third recapture
426
+ }
427
+
428
+ # Create CJS formatted data
429
+ cjs = cjs_data_prep(
430
+ receiver_to_recap=receiver_to_recap,
431
+ project=project,
432
+ rel_loc='Release Site 1', # Optional filter
433
+ initial_recap_release=False # True if starting from first recapture
434
+ )
435
+
436
+ # Export to .inp file for Program MARK
437
+ cjs.input_file('my_model', project.output_dir)
438
+ ```
439
+
440
+ ### Competing Risks / Time-to-Event Format
441
+
442
+ ```python
443
+ from pymast.formatter import time_to_event
444
+
445
+ # Define node to state mapping
446
+ node_to_state = {
447
+ 'N01': 1, # Downstream
448
+ 'N02': 2, # Fishway
449
+ 'N03': 3, # Upstream
450
+ }
451
+
452
+ # Create time-to-event data
453
+ tte = time_to_event(
454
+ node_to_state=node_to_state,
455
+ project=project,
456
+ bucket_length_min=15 # Time bin size in minutes
457
+ )
458
+
459
+ # Export for survival analysis in R
460
+ tte.to_csv(os.path.join(project.output_dir, 'time_to_event.csv'))
461
+ ```
462
+
463
+ ---
464
+
465
+ ## Visualization
466
+
467
+ ### Fish Movement History
468
+
469
+ ```python
470
+ from pymast.fish_history import fish_history
471
+
472
+ # Create fish history object
473
+ fh = fish_history(
474
+ projectDB=project.db,
475
+ filtered=True, # Use classified data
476
+ overlapping=False # Exclude overlapping detections
477
+ )
478
+
479
+ # Plot a specific fish in 3D space-time
480
+ fh.fish_plot('164.123 45')
481
+ ```
482
+
483
+ ---
484
+
485
+ ## Supported Receiver Types
486
+
487
+ | Manufacturer | Model | Code | Notes |
488
+ |--------------|-----------------|------------|---------------------------------|
489
+ | Lotek | SRX600 | `srx600` | Standard format |
490
+ | Lotek | SRX800 | `srx800` | Standard format |
491
+ | Lotek | SRX1200 | `srx1200` | Standard format |
492
+ | SigmaEight | Orion | `orion` | Supports multi-channel/antenna |
493
+ | SigmaEight | Ares | `ares` | Multiple firmware versions |
494
+ | Vemco | VR2 | `VR2` | Standard format |
495
+
496
+ ---
497
+
498
+ ## Scientific Background
499
+
500
+ PyMAST implements validated algorithms for radio telemetry data processing, peer-reviewed and published in *Animal Biotelemetry*:
501
+
502
+ > **Nebiolo, K.P., & Castro-Santos, T.** (2024). MAST: Movement Analysis Software for Telemetry data. Part I: the semi-automated removal of false positives from radio telemetry data. *Animal Biotelemetry*, 12(1), 11. https://doi.org/10.1186/s40317-024-00358-1
503
+
504
+ ### False Positive Detection Algorithm
505
+
506
+ MAST uses a **Naive Bayes classifier** with the conditional independence assumption:
507
+
508
+ ```
509
+ P(True|X) = P(True) * P(Xi|True)
510
+ P(False|X) = P(False) * P(Xi|False)
511
+ ```
512
+
513
+ Where X represents the vector of predictor variables. The classifier computes the posterior probability for each detection and classifies using the Maximum A Posteriori (MAP) hypothesis.
514
+
515
+ **Key Innovation:** Laplace smoothing (add-one smoothing) prevents zero probabilities for unseen feature combinations, making the classifier robust to novel detection patterns.
516
+
517
+ ### Bout Detection Algorithm
518
+
519
+ Fits a **three-process broken-stick model** (piecewise exponential decay) to inter-detection intervals:
520
+
521
+ 1. **Process 1**: Continuous presence (seconds to minutes)
522
+ 2. **Process 2**: Edge milling behavior (minutes to hours)
523
+ 3. **Process 3**: True departure and return (hours to days)
524
+
525
+ The knot locations determine threshold values for classifying detection gaps.
526
+
527
+ ### Nested Doll Overlap Removal
528
+
529
+ Uses a **directed acyclic graph** (DAG) representing parent:child relationships between receivers. If a fish is present at a child receiver (small detection zone) while also detected at a parent receiver (large detection zone), the algorithm removes the overlapping parent detections.
530
+
531
+ **Analogy:** Like nested Russian dolls - if you can place an object in the innermost doll, you know it is not in the outer dolls.
532
+
533
+ ---
534
+
535
+ ## Examples
536
+
537
+ See the following for complete examples:
538
+
539
+ - **`MAST_Project.ipynb`** - Interactive Jupyter notebook with full workflow
540
+ - **`scripts/mast_complete_project.py`** - Python script implementation
541
+ - **Sample data** - Check `data/` folder for example file formats
542
+
543
+ ---
544
+
545
+ ## Contributing
546
+
547
+ We welcome contributions. Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
548
+
549
+ **Quick Development Setup:**
550
+
551
+ ```bash
552
+ git clone https://github.com/knebiolo/mast.git
553
+ cd mast
554
+ python -m venv venv
555
+ venv\Scripts\activate # Windows
556
+ # source venv/bin/activate # macOS/Linux
557
+ pip install -e .
558
+ ```
559
+
560
+ ---
561
+
562
+ ## Citation
563
+
564
+ If you use PyMAST in your research, please cite:
565
+
566
+ ```bibtex
567
+ @article{nebiolo2024mast,
568
+ author = {Nebiolo, Kevin P. and Castro-Santos, Theodore},
569
+ title = {MAST: Movement Analysis Software for Telemetry data. Part I: the semi-automated removal of false positives from radio telemetry data},
570
+ journal = {Animal Biotelemetry},
571
+ year = {2024},
572
+ volume = {12},
573
+ number = {1},
574
+ pages = {11},
575
+ doi = {10.1186/s40317-024-00358-1},
576
+ url = {https://doi.org/10.1186/s40317-024-00358-1}
577
+ }
578
+ ```
579
+
580
+ **Software Citation:**
581
+
582
+ ```bibtex
583
+ @software{nebiolo2025pymast,
584
+ author = {Nebiolo, Kevin P. and Castro-Santos, Theodore},
585
+ title = {PyMAST: Movement Analysis Software for Telemetry},
586
+ year = {2025},
587
+ publisher = {GitHub},
588
+ url = {https://github.com/knebiolo/mast}
589
+ }
590
+ ```
591
+
592
+ **Additional Key Publications:**
593
+
594
+ - Beeman, J.W., & Perry, R.W. (2012). *Bias from False-Positive Detections and Strategies for their Removal in Studies Using Telemetry.* American Fisheries Society.
595
+ - Sibly, R.M., Nott, H.M., & Fletcher, D.J. (1990). *Splitting Behavior into Bouts.* Animal Behavior.
596
+
597
+ ---
598
+
599
+ ## License
600
+
601
+ This project is licensed under the MIT License - see [LICENSE.txt](LICENSE.txt) for details.
602
+
603
+ ---
604
+
605
+ ## Authors and Acknowledgments
606
+
607
+ **Development Team:**
608
+ - **Kevin P. Nebiolo** - Lead Developer (Kleinschmidt Associates)
609
+ - **Theodore Castro-Santos** - Co-Developer (USGS)
610
+
611
+ **Institutional Support:**
612
+ - Kleinschmidt Associates
613
+ - U.S. Geological Survey (USGS)
614
+
615
+ **Community:**
616
+ - Thanks to the aquatic telemetry community for feedback and testing
617
+
618
+ ---
619
+
620
+ ## Support
621
+
622
+ - **Issues**: [GitHub Issues](https://github.com/knebiolo/mast/issues)
623
+ - **Email**: kevin.nebiolo@kleinschmidtgroup.com
624
+ - **Documentation**: See [CHANGELOG.md](CHANGELOG.md) for version history
625
+
626
+ ---
627
+
628
+ ## Additional Resources
629
+
630
+ - [HDF5 Documentation](https://www.hdfgroup.org/)
631
+ - [Program MARK](http://www.phidot.org/software/mark/)
632
+ - [R survival package](https://cran.r-project.org/web/packages/survival/)
633
+
634
+ ---
635
+
636
+ Happy fish tracking!