Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
9784709
Animal][Reproduction] Refactor Reproduction.execute_cow_ed_protocol()
allisterakun Apr 7, 2026
d66e53e
Update changelog.md
allisterakun Apr 7, 2026
ad93ddf
Merge d66e53e817856415d6c7f697f91c72975228ee18 into 472a3fefa4c4fc717…
allisterakun Apr 7, 2026
ac804b0
Apply Black Formatting
github-actions[bot] Apr 7, 2026
30d36c2
Update badges on README
allisterakun Apr 7, 2026
5f47519
flake8
allisterakun Apr 7, 2026
74a3a2c
Merge 5f475190d210f44396c56c3b4edfdf50c0cab17d into 472a3fefa4c4fc717…
allisterakun Apr 7, 2026
8d77836
Apply Black Formatting
github-actions[bot] Apr 7, 2026
e2a85ee
Update badges on README
allisterakun Apr 7, 2026
6767190
[XV] Add support for complex data structure
allisterakun Apr 7, 2026
f1251a4
Merge 676719020a4d8646dc4b101963a23a6541b51494 into 53349675447bf39b6…
allisterakun Apr 7, 2026
683f125
Apply Black Formatting
github-actions[bot] Apr 7, 2026
eae6de9
Update example_cross_validation.json
allisterakun Apr 7, 2026
ec7367f
Merge eae6de912a33e789bd43a47bc5b3a7981d6a2b15 into 53349675447bf39b6…
allisterakun Apr 7, 2026
6477821
Apply Black Formatting
github-actions[bot] Apr 7, 2026
445bed0
Merge branch 'dev' into refactor_execute_cow_ed
allisterakun Apr 8, 2026
2f5a2fe
Merge 445bed00f6fdf2f83e926d883733d77499d5b0cb into 53349675447bf39b6…
allisterakun Apr 8, 2026
4b8f15f
Apply Black Formatting
github-actions[bot] Apr 8, 2026
9606fad
Merge pull request #2934 from RuminantFarmSystems/refactor_execute_co…
allisterakun Apr 8, 2026
df3d7ca
Update example_cross_validation.json
allisterakun Apr 10, 2026
53ea4f6
Merge df3d7caff9cd30b1ac83e89e6dbb940905ac7da6 into 9606fad71192c8f9c…
allisterakun Apr 10, 2026
6a3bc7e
Apply Black Formatting
github-actions[bot] Apr 10, 2026
71d3004
updated
allisterakun Apr 13, 2026
12b67f0
Merge 71d30042cdb5f00c98b9702c56e3fced66426d93 into 9606fad71192c8f9c…
allisterakun Apr 13, 2026
8ac064a
Apply Black Formatting
github-actions[bot] Apr 13, 2026
5c905db
Update badges on README
allisterakun Apr 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[![Flake8](https://img.shields.io/badge/Flake8-passed-brightgreen)](https://github.com/RuminantFarmSystems/MASM/actions/workflows/combined_format_lint_test_mypy.yml)
[![Pytest](https://img.shields.io/badge/Pytest-passed-brightgreen)](https://github.com/RuminantFarmSystems/MASM/actions/workflows/combined_format_lint_test_mypy.yml)
[![Coverage](https://img.shields.io/badge/Coverage-99%25-brightgreen)](https://github.com/RuminantFarmSystems/MASM/actions/workflows/combined_format_lint_test_mypy.yml)
[![Mypy](https://img.shields.io/badge/Mypy-1191%20errors-red)](https://github.com/RuminantFarmSystems/MASM/actions/workflows/combined_format_lint_test_mypy.yml)
[![Flake8](https://img.shields.io/badge/Flake8-failed-red)](https://github.com/RuminantFarmSystems/MASM/actions/workflows/combined_format_lint_test_mypy.yml)
[![Pytest](https://img.shields.io/badge/Pytest-failed-red)](https://github.com/RuminantFarmSystems/MASM/actions/workflows/combined_format_lint_test_mypy.yml)
[![Coverage](https://img.shields.io/badge/Coverage-%25-red)](https://github.com/RuminantFarmSystems/MASM/actions/workflows/combined_format_lint_test_mypy.yml)
[![Mypy](https://img.shields.io/badge/Mypy-1194%20errors-red)](https://github.com/RuminantFarmSystems/MASM/actions/workflows/combined_format_lint_test_mypy.yml)


# RuFaS: Ruminant Farm Systems
Expand Down
119 changes: 69 additions & 50 deletions RUFAS/biophysical/animal/reproduction/reproduction.py
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like changes from other PRs

Original file line number Diff line number Diff line change
Expand Up @@ -1313,74 +1313,93 @@ def _calculate_conception_rate_on_ai_day(self) -> None:

self.conception_rate = max(0.0, self.conception_rate)

def execute_cow_ed_protocol( # noqa
def execute_cow_ed_protocol(
self, reproduction_data_stream: ReproductionDataStream, simulation_day: int
) -> ReproductionDataStream:
"""Execute the estrus detection (ED) protocol for cows."""
self._update_ed_days(reproduction_data_stream)
if 1 <= reproduction_data_stream.days_in_milk <= AnimalConfig.voluntary_waiting_period:
reproduction_data_stream = self._repeat_estrus_simulation_before_vwp(
reproduction_data_stream, simulation_day
)
elif reproduction_data_stream.days_in_milk > AnimalConfig.voluntary_waiting_period:
reproduction_data_stream = self._handle_ed_after_vwp(reproduction_data_stream, simulation_day)
return reproduction_data_stream

def _update_ed_days(self, reproduction_data_stream: ReproductionDataStream) -> None:
"""Update ED days statistic based on pregnancy status."""
if not reproduction_data_stream.is_pregnant:
self.reproduction_statistics.ED_days += 1
else:
self.reproduction_statistics.ED_days = 0
if 1 <= reproduction_data_stream.days_in_milk <= AnimalConfig.voluntary_waiting_period:
reproduction_data_stream = self._repeat_estrus_simulation_before_vwp(
reproduction_data_stream, simulation_day

def _handle_ed_after_vwp(
self, reproduction_data_stream: ReproductionDataStream, simulation_day: int
) -> ReproductionDataStream:
"""Handle ED protocol logic after the voluntary waiting period."""
if (
self.repro_state_manager.is_in(ReproStateEnum.ENTER_HERD_FROM_INIT)
and reproduction_data_stream.days_born > self.estrus_day
):
reproduction_data_stream = self._simulate_estrus(
reproduction_data_stream,
reproduction_data_stream.days_born,
simulation_day,
animal_constants.ESTRUS_DAY_SCHEDULED_NOTE,
AnimalConfig.average_estrus_cycle_cow,
AnimalConfig.std_estrus_cycle_cow,
)

elif reproduction_data_stream.days_in_milk > AnimalConfig.voluntary_waiting_period:
if (
self.repro_state_manager.is_in(ReproStateEnum.ENTER_HERD_FROM_INIT)
and reproduction_data_stream.days_born > self.estrus_day
):
reproduction_data_stream = self._simulate_estrus(
reproduction_data_stream,
reproduction_data_stream.days_born,
simulation_day,
animal_constants.ESTRUS_DAY_SCHEDULED_NOTE,
AnimalConfig.average_estrus_cycle_cow,
AnimalConfig.std_estrus_cycle_cow,
)
if self.repro_state_manager.is_in_any({ReproStateEnum.FRESH, ReproStateEnum.ENTER_HERD_FROM_INIT}):
self.repro_state_manager.enter(ReproStateEnum.WAITING_FULL_ED_CYCLE)
reproduction_data_stream.events.add_event(
reproduction_data_stream.days_born,
simulation_day,
f"Current repro state(s): {self.repro_state_manager}",
)

if self.repro_state_manager.is_in_any({ReproStateEnum.FRESH, ReproStateEnum.ENTER_HERD_FROM_INIT}):
self.repro_state_manager.enter(ReproStateEnum.WAITING_FULL_ED_CYCLE)
if reproduction_data_stream.days_born == self.estrus_day:
reproduction_data_stream = self._handle_estrus_day_states(reproduction_data_stream, simulation_day)

return reproduction_data_stream

def _handle_estrus_day_states(
self, reproduction_data_stream: ReproductionDataStream, simulation_day: int
) -> ReproductionDataStream:
"""Handle estrus detection state transitions on the scheduled estrus day."""
if self.repro_state_manager.is_in(ReproStateEnum.WAITING_SHORT_ED_CYCLE):
self.repro_state_manager.exit(ReproStateEnum.WAITING_SHORT_ED_CYCLE)
reproduction_data_stream = self._handle_estrus_detection(
reproduction_data_stream,
simulation_day,
on_estrus_detected=self._setup_ai_day_after_estrus_detected,
on_estrus_not_detected=self._enter_ovsynch_repro_state,
)
if self.repro_state_manager.is_in(ReproStateEnum.IN_OVSYNCH):
reproduction_data_stream.events.add_event(
reproduction_data_stream.days_born,
simulation_day,
f"Current repro state(s): {self.repro_state_manager}",
)

if reproduction_data_stream.days_born == self.estrus_day:
if self.repro_state_manager.is_in(ReproStateEnum.WAITING_SHORT_ED_CYCLE):
self.repro_state_manager.exit(ReproStateEnum.WAITING_SHORT_ED_CYCLE)
reproduction_data_stream = self._handle_estrus_detection(
reproduction_data_stream,
simulation_day,
on_estrus_detected=self._setup_ai_day_after_estrus_detected,
on_estrus_not_detected=self._enter_ovsynch_repro_state,
)
if self.repro_state_manager.is_in(ReproStateEnum.IN_OVSYNCH):
reproduction_data_stream.events.add_event(
reproduction_data_stream.days_born,
simulation_day,
f"Current repro state(s): {self.repro_state_manager}",
)
elif self.repro_state_manager.is_in(ReproStateEnum.WAITING_FULL_ED_CYCLE):
self.repro_state_manager.exit(ReproStateEnum.WAITING_FULL_ED_CYCLE)
reproduction_data_stream = self._handle_estrus_detection(
reproduction_data_stream,
simulation_day,
on_estrus_detected=self._setup_ai_day_after_estrus_detected,
on_estrus_not_detected=self._simulate_full_estrus_cycle,
)

elif self.repro_state_manager.is_in(ReproStateEnum.WAITING_FULL_ED_CYCLE):
self.repro_state_manager.exit(ReproStateEnum.WAITING_FULL_ED_CYCLE)
reproduction_data_stream = self._handle_estrus_detection(
reproduction_data_stream,
simulation_day,
on_estrus_detected=self._setup_ai_day_after_estrus_detected,
on_estrus_not_detected=self._simulate_full_estrus_cycle,
)
elif self.repro_state_manager.is_in(ReproStateEnum.WAITING_FULL_ED_CYCLE_BEFORE_OVSYNCH):
self.repro_state_manager.exit(ReproStateEnum.WAITING_FULL_ED_CYCLE_BEFORE_OVSYNCH)
reproduction_data_stream = self._handle_estrus_detection(
reproduction_data_stream,
simulation_day,
on_estrus_detected=self._setup_ai_day_after_estrus_detected,
on_estrus_not_detected=self._simulate_full_estrus_cycle_before_ovsynch,
)

elif self.repro_state_manager.is_in(ReproStateEnum.WAITING_FULL_ED_CYCLE_BEFORE_OVSYNCH):
self.repro_state_manager.exit(ReproStateEnum.WAITING_FULL_ED_CYCLE_BEFORE_OVSYNCH)
reproduction_data_stream = self._handle_estrus_detection(
reproduction_data_stream,
simulation_day,
on_estrus_detected=self._setup_ai_day_after_estrus_detected,
on_estrus_not_detected=self._simulate_full_estrus_cycle_before_ovsynch,
)
return reproduction_data_stream

def _enter_ovsynch_repro_state(
Expand Down
Loading