Repository: PPeitsch/pkynetics
Pull request #52: ⚡ Fix calculation issues in kinetic modeling functions
Author: login: PPeitsch
Created: 2025-03-12T00:07:50Z | Merged: 2025-03-12T00:27:41Z

## Description

This PR addresses several critical numerical issues found in the kinetic analysis methods of Pkynetics:

1. Fixed missing `horowitz_metzger_plot` function referenced in examples and documentation
2. Added new `plot_horowitz_metzger` function to visualization module for consistency
3. Fixed division by zero error in `nth_order` reaction model when `n=1`
4. Fixed NaN values in pre-exponential factor calculation in Coats-Redfern method
5. Added validation and warnings for physically implausible values

These fixes resolve issues that were causing example code to fail and improve robustness of the library's numerical calculations.

## Type of Change

- [x] Bug fix (non-breaking change that fixes an issue)
- [ ] New feature (non-breaking change that adds functionality)
- [ ] Breaking change (fix or feature that would break existing functionality)
- [x] Documentation update
- [ ] Performance improvement
- [ ] Code style update (formatting, renaming)
- [ ] Refactoring (no functional changes)
- [ ] CI/CD related changes
- [ ] Test coverage improvement
- [ ] Other (please describe):

## Checklist

- [x] I have followed the project's coding style guidelines
- [x] I have added tests to cover my changes
- [x] All new and existing tests pass locally
- [x] I have updated the documentation accordingly
- [x] I have added type hints where applicable
- [x] I have updated the CHANGELOG.md
- [x] My changes generate no new mypy warnings
- [x] I have checked code formatting with `black` (line length 88)
- [x] I have run `isort` for import sorting
- [x] My PR is based on the latest main branch and has no conflicts
- [x] I have added/updated docstrings in NumPy format

Fixes #50

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Introduced a new parameter `reaction_model` for enhanced customization in the data generation process.
  - Updated the project version to v0.3.5.

- **Bug Fixes**
  - Resolved division by zero errors and NaN values in reaction data calculations.
  - Addressed missing dependencies and corrected documentation inconsistencies.

- **Refactor**
  - Improved error handling and refined data processing routines for greater stability.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Linked issue #50: [Bug]: division by 0 in coats_redfern_method_example.py
### Pkynetics Version

0.3.3

### Python Version

3.9.21

### Operating System

macOS 14.7.4

### Bug Description

Division by 0 in
`/examples/coats_redfern_method_example.py` 

### Steps to Reproduce

In `/src/pkynetics/synthetic_data/model_specific_data.py` function
```phython
generate_coats_redfern_data
```
has
```python                  
temp_data, conv_data = generate_basic_kinetic_data(
        e_a,
        a,
        np.array([heating_rate], dtype=np.float64),
        t_range,
        reaction_model="nth_order",
        noise_level=noise_level,
        n=n,
)
```
which explicitly defines `reaction_model` as `nth_order` at initialization. However, in
`/src/pkynetics/synthetic_data/basic_kinetic_data.py` when parameter `reaction_model` is specified as `nth_order` and `n` is passed in as `1` it triggers division by 0.

```python
if reaction_model == "first_order":
   alpha = 1 - np.exp(-k * time)
elif reaction_model == "nth_order":
   alpha = 1 - (1 + (n - 1) * k * time) ** (1 / (1 - n))
```

This occurs in `/examples/coats_redfern_method_example.py` where
```python
n_true = 1  # Reaction order

# Generate synthetic data
temperature, alpha = generate_coats_redfern_data(e_a_true, a_true, heating_rate, t_range, n=n_true, noise_level=0.001)
```


### Expected Behavior

Passing reaction order ```reaction_model=``` into
```python
generate_coats_redfern_data
```
would avoid the error.

### Actual Behavior

Division by zero.

### Error Message & Stack Trace

```python

```

### Additional Context

_No response_

### Guidelines

- [x] I agree to follow this project's Contributing Guidelines
- [x] I have searched for similar issues before creating this one
Linked issue comments: user: login: PPeitsch
created_at: 2025-03-11T23:30:38Z
body: Hi @simunovics thanks for sharing the issue. I'll fix it.

Just for the record, the problem occurs due to the following sequence:

1. In `coats_redfern_method_example.py`, `generate_coats_redfern_data` is called with `n_true = 1`.
2. Inside `generate_coats_redfern_data`, it calls `generate_basic_kinetic_data` with `reaction_model="nth_order"` and passes the same `n` value.
3. In `generate_basic_kinetic_data`, when `reaction_model` is `"nth_order"`, it calculates:
   `alpha = 1 - (1 + (n - 1) * k * time) ** (1 / (1 - n))`
4. When `n` is exactly 1, `(1 - n)` equals 0, resulting in division by zero.

This is a bug in the `generate_basic_kinetic_data` function. The logical solutions are:

1. Detect when `n` is 1 and `reaction_model` is "nth_order" and use the "first_order" formula in that case
2. Allow passing `reaction_model` as a parameter to `generate_coats_redfern_data`

Both solutions will be implemented to fix the bug and improve flexibility for users.
author_association: OWNER
user: login: PPeitsch
created_at: 2025-03-12T00:39:47Z
body: It's done @simunovics 
Let me know if you'll be testing with your own data, the stats in the results with synthetic data seem odd.

author_association: OWNER
user: login: simunovics
created_at: 2025-03-12T13:59:17Z
body: Thank you @PPeitsch . I will check what we are able to share and let you know.
author_association: NONE

Diff:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1dcb553..1bf1185 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## [v0.3.5] - 2025-03-11
+
+### Added
+- Added `reaction_model` parameter to `generate_coats_redfern_data` function
+
+### Fixed
+- Fixed division by zero error in nth_order reaction model when n=1
+- Fixed NaN values in pre-exponential factor calculation in Coats-Redfern method
+
 ## [v0.3.4] - 2025-03-10
 
 ### Added
diff --git a/docs/changelog.rst b/docs/changelog.rst
index 2e1ac3c..dcadd7a 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -6,6 +6,20 @@ All notable changes to this project will be documented in this file.
 The format is based on `Keep a Changelog <https://keepachangelog.com/en/1.0.0/>`_,
 and this project adheres to `Semantic Versioning <https://semver.org/spec/v2.0.0.html>`_.
 
+[v0.3.5] - 2025-03-11
+---------------------
+
+Added
+^^^^^
+- Added ``reaction_model`` parameter to ``generate_coats_redfern_data`` function
+
+Fixed
+^^^^^
+- Fixed missing imports in examples/horowitz_metzger_method_example.py
+- Fixed references in documentation to non-existent functions
+- Fixed division by zero error in nth_order reaction model when n=1
+- Fixed NaN values in pre-exponential factor calculation in Coats-Redfern method
+
 [v0.3.4] - 2025-03-10
 ---------------------
 
diff --git a/src/pkynetics/__about__.py b/src/pkynetics/__about__.py
index 6a7e97e..613deb7 100644
--- a/src/pkynetics/__about__.py
+++ b/src/pkynetics/__about__.py
@@ -1,3 +1,3 @@
 """Version information."""
 
-__version__ = "0.3.4"
+__version__ = "0.3.5"
diff --git a/src/pkynetics/model_fitting_methods/coats_redfern.py b/src/pkynetics/model_fitting_methods/coats_redfern.py
index fdf2495..da5963a 100644
--- a/src/pkynetics/model_fitting_methods/coats_redfern.py
+++ b/src/pkynetics/model_fitting_methods/coats_redfern.py
@@ -1,11 +1,14 @@
 """Implementation of the Coats-Redfern method for kinetic analysis."""
 
+import logging
 from typing import Tuple
 
 import numpy as np
 from numpy.typing import NDArray
 from scipy.stats import linregress
 
+logger = logging.getLogger(__name__)
+
 
 def coats_redfern_equation(
     t: np.ndarray, e_a: float, ln_a: float, n: float, r: float = 8.314
@@ -50,7 +53,14 @@ def coats_redfern_method(
         n (float): Reaction order. Default is 1.
 
     Returns:
-        Tuple[float, float, float]: Activation energy (J/mol), pre-exponential factor (min^-1), and R-squared value.
+        Tuple[float, float, float, np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
+            - Activation energy (J/mol)
+            - Pre-exponential factor (min^-1)
+            - R-squared value
+            - x values for plotting (1000/T)
+            - y values for plotting
+            - x values used for fitting
+            - y values used for fitting
 
     Raises:
         ValueError: If input arrays have different lengths or contain invalid values.
@@ -61,7 +71,7 @@ def coats_redfern_method(
     alpha = np.clip(alpha, 0, 1)
 
     x = 1000 / temperature
-    y = _prepare_y_data(alpha, temperature, n)
+    y = _prepare_y_data(temperature, alpha, n)
 
     # Focus on the most linear part (typically 20% to 80% conversion)
     mask = (alpha >= 0.2) & (alpha <= 0.8)
@@ -79,9 +89,25 @@ def coats_redfern_method(
     # Calculate kinetic parameters
     r = 8.314  # Gas constant in J/(mol·K)
     e_a = -slope * r  # Activation energy in J/mol
-    a = np.exp(
-        intercept + np.log(heating_rate / e_a)
-    )  # Pre-exponential factor in min^-1
+
+    # Check if activation energy is physically plausible
+    if e_a <= 0:
+        logger.warning(
+            "Calculated activation energy is negative or zero. "
+            "This is physically implausible and indicates potential issues with the data or fitting."
+        )
+        # Use absolute value to proceed with calculation while avoiding math errors
+        e_a_for_calc = abs(e_a)
+    else:
+        e_a_for_calc = e_a
+
+    # Safely calculate pre-exponential factor
+    try:
+        ln_a = intercept + np.log(heating_rate / e_a_for_calc)
+        a = np.exp(ln_a)
+    except (ValueError, RuntimeWarning, FloatingPointError) as e:
+        logger.error(f"Error calculating pre-exponential factor: {str(e)}")
+        a = float("nan")
 
     return e_a, a, r_value**2, x, y, x_filtered, y_filtered
 
diff --git a/src/pkynetics/synthetic_data/basic_kinetic_data.py b/src/pkynetics/synthetic_data/basic_kinetic_data.py
index 2a0135a..8773f2c 100644
--- a/src/pkynetics/synthetic_data/basic_kinetic_data.py
+++ b/src/pkynetics/synthetic_data/basic_kinetic_data.py
@@ -44,7 +44,11 @@ def generate_basic_kinetic_data(
         time = (t - t[0]) / beta
         k = a * np.exp(-e_a / (R * t))
 
-        if reaction_model == "first_order":
+        # Special case: if n is exactly 1 and reaction_model is nth_order, use first_order formula
+        if reaction_model == "nth_order" and abs(n - 1.0) < 1e-10:
+            logger.info("Using first_order model when n=1 to avoid division by zero")
+            alpha = 1 - np.exp(-k * time)
+        elif reaction_model == "first_order":
             alpha = 1 - np.exp(-k * time)
         elif reaction_model == "nth_order":
             alpha = 1 - (1 + (n - 1) * k * time) ** (1 / (1 - n))
diff --git a/src/pkynetics/synthetic_data/model_specific_data.py b/src/pkynetics/synthetic_data/model_specific_data.py
index 6aa44a7..507a454 100644
--- a/src/pkynetics/synthetic_data/model_specific_data.py
+++ b/src/pkynetics/synthetic_data/model_specific_data.py
@@ -18,6 +18,7 @@ def generate_coats_redfern_data(
     t_range: Tuple[float, float],
     n: float = 1.5,
     noise_level: float = 0,
+    reaction_model: str = "nth_order",
 ) -> Tuple[NDArray[np.float64], NDArray[np.float64]]:
     """
     Generate data specific to Coats-Redfern analysis.
@@ -29,6 +30,7 @@ def generate_coats_redfern_data(
         t_range (Tuple[float, float]): Temperature range (start, end) in K
         n (float): Reaction order. Default is 1.5
         noise_level (float): Standard deviation of Gaussian noise to add
+        reaction_model (str): Reaction model to use ('first_order' or 'nth_order'). Default is 'nth_order'
 
     Returns:
         Tuple[np.ndarray, np.ndarray]: Temperature and conversion data
@@ -38,7 +40,7 @@ def generate_coats_redfern_data(
         a,
         np.array([heating_rate], dtype=np.float64),
         t_range,
-        reaction_model="nth_order",
+        reaction_model=reaction_model,
         noise_level=noise_level,
         n=n,
     )


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 3**

<details>
<summary>🔭 Outside diff range comments (1)</summary><blockquote>

<details>
<summary>docs/changelog.rst (1)</summary><blockquote>

`25-37`: _⚠️ Potential issue_

**Duplicate entries between v0.3.5 and v0.3.4**

There appears to be duplicate information between v0.3.5 and v0.3.4. The "Added" section for v0.3.4 lists the same two new functions that are also listed in v0.3.5:
- "New ``horowitz_metzger_plot`` function in model_fitting_methods module"
- "New ``plot_horowitz_metzger`` function in result_visualization module"

This could confuse users about which version these functions were actually added in.


Consider removing these duplicate entries from one of the versions or clarifying if there's a distinction between them.

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>src/pkynetics/synthetic_data/model_specific_data.py (1)</summary><blockquote>

`50-84`: **Consider adding reaction_model parameter to generate_freeman_carroll_data**

For consistency with the changes to `generate_coats_redfern_data`, consider adding the `reaction_model` parameter to `generate_freeman_carroll_data` as well. Currently, it hardcodes "nth_order" as the reaction model.


```diff
def generate_freeman_carroll_data(
    e_a: float,
    a: float,
    heating_rate: float,
    t_range: Tuple[float, float],
    n: float = 1.5,
    noise_level: float = 0,
+   reaction_model: str = "nth_order",
) -> Tuple[NDArray[np.float64], NDArray[np.float64], NDArray[np.float64]]:
    """
    Generate data specific to Freeman-Carroll analysis.

    Args:
        e_a (float): Activation energy in J/mol
        a (float): Pre-exponential factor in 1/s
        heating_rate (float): Heating rate in K/min
        t_range (Tuple[float, float]): Temperature range (start, end) in K
        n (float): Reaction order. Default is 1.5
        noise_level (float): Standard deviation of Gaussian noise to add
+       reaction_model (str): Reaction model to use ('first_order' or 'nth_order'). Default is 'nth_order'

    Returns:
        Tuple[NDArray[np.float64], NDArray[np.float64], NDArray[np.float64]]: Temperature, conversion, and time data
    """
    temp_data, conv_data = generate_basic_kinetic_data(
        e_a,
        a,
        np.array([heating_rate], dtype=np.float64),
        t_range,
-       reaction_model="nth_order",
+       reaction_model=reaction_model,
        noise_level=noise_level,
        n=n,
    )
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 62de3a16c49291ced34d83195bc104acc2c0f87e and cae9d4c29eddcccf3a4062ddfd94d6d080224555.

</details>

<details>
<summary>📒 Files selected for processing (6)</summary>

* `CHANGELOG.md` (1 hunks)
* `docs/changelog.rst` (1 hunks)
* `src/pkynetics/__about__.py` (1 hunks)
* `src/pkynetics/model_fitting_methods/coats_redfern.py` (3 hunks)
* `src/pkynetics/synthetic_data/basic_kinetic_data.py` (1 hunks)
* `src/pkynetics/synthetic_data/model_specific_data.py` (3 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 GitHub Check: codecov/patch</summary>

<details>
<summary>src/pkynetics/synthetic_data/basic_kinetic_data.py</summary>

[warning] 48-51: src/pkynetics/synthetic_data/basic_kinetic_data.py#L48-L51
Added lines #L48 - L51 were not covered by tests

</details>
<details>
<summary>src/pkynetics/model_fitting_methods/coats_redfern.py</summary>

[warning] 71-71: src/pkynetics/model_fitting_methods/coats_redfern.py#L71
Added line #L71 was not covered by tests

---

[warning] 91-92: src/pkynetics/model_fitting_methods/coats_redfern.py#L91-L92
Added lines #L91 - L92 were not covered by tests

---

[warning] 97-97: src/pkynetics/model_fitting_methods/coats_redfern.py#L97
Added line #L97 was not covered by tests

---

[warning] 99-99: src/pkynetics/model_fitting_methods/coats_redfern.py#L99
Added line #L99 was not covered by tests

---

[warning] 102-107: src/pkynetics/model_fitting_methods/coats_redfern.py#L102-L107
Added lines #L102 - L107 were not covered by tests

</details>

</details>
<details>
<summary>🪛 Ruff (0.8.2)</summary>

<details>
<summary>src/pkynetics/model_fitting_methods/coats_redfern.py</summary>

92-92: Undefined name `logger`

(F821)

---

106-106: Undefined name `logger`

(F821)

</details>

</details>
<details>
<summary>🪛 LanguageTool</summary>

<details>
<summary>CHANGELOG.md</summary>

[duplication] ~15-~15: Possible typo: you repeated a word.
Context: ...erate_coats_redfern_data` function  ### Fixed - Fixed missing imports in examples/horowitz_me...

(ENGLISH_WORD_REPEAT_RULE)

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (8)</summary><blockquote>

<details>
<summary>src/pkynetics/__about__.py (1)</summary>

`3-3`: **Version updated to 0.3.5**

The version update aligns with the changes documented in the changelog, including the addition of new functions and bug fixes.

</details>
<details>
<summary>src/pkynetics/synthetic_data/basic_kinetic_data.py (1)</summary>

`47-51`: <details>
<summary>❓ Verification inconclusive</summary>

**Good fix for division by zero case**

This change properly handles the special case when the reaction model is "nth_order" and n is very close to 1, which would otherwise cause a division by zero in line 54 where `1/(1-n)` appears in the exponent.


The static analysis indicates these new lines aren't covered by tests. Consider adding a test case for this specific scenario:

---

🏁 Script executed:

```shell
#!/bin/bash
# Check if there are tests for the special case n≈1 with nth_order reaction model

# Search for tests that might cover this special case
rg -A 5 -B 5 "nth_order.*[^a-zA-Z0-9]1\.0" --type py test/
rg -A 5 -B 5 "n\s*=\s*1" --type py test/

# Check if the special case is tested directly
rg -A 5 -B 5 "abs\(n\s*-\s*1" --type py test/
```

Length of output: 289

---



</details>

**Special Case Handling Approved – Please Add Tests**

The division-by-zero fix for when `reaction_model` is `"nth_order"` and `n` is very close to 1 is well implemented. However, static analysis indicates that this branch isn’t exercised by any tests (the search in the `test/` directory returned no results). To ensure future stability and prevent regressions (particularly at line 54 where `1/(1-n)` is used), please add a targeted test case simulating the scenario where *n* is approximately 1 for the `"nth_order"` model.

- **Location:** `src/pkynetics/synthetic_data/basic_kinetic_data.py`, lines 47–51  
- **Action:** Add a test that sets `n` to a value very close to `1.0` (within floating-point tolerance) while using the `"nth_order"` model and verify that the code correctly employs the first-order formula.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 GitHub Check: codecov/patch</summary>

[warning] 48-51: src/pkynetics/synthetic_data/basic_kinetic_data.py#L48-L51
Added lines #L48 - L51 were not covered by tests

</details>

</details>

</details>
<details>
<summary>src/pkynetics/synthetic_data/model_specific_data.py (1)</summary>

`21-21`: **Improved flexibility with reaction_model parameter**

Adding the `reaction_model` parameter to `generate_coats_redfern_data` enhances the function's flexibility and consistency with the underlying `generate_basic_kinetic_data` function. The docstring is properly updated, and the default value aligns with existing behavior.



Also applies to: 33-33, 43-44

</details>
<details>
<summary>docs/changelog.rst (1)</summary>

`9-24`: **Changelog entry for v0.3.5 looks good**

The changelog entry correctly documents all the changes in this release, including new functions and bug fixes.

</details>
<details>
<summary>CHANGELOG.md (3)</summary>

`8-8`: **Version bump looks good.**

No issues spotted with the new version entry `[v0.3.5]`.

---

`10-14`: **Additions look good.**

All newly listed functions and parameters match the pull request objectives.

---

`15-19`: **No action needed.**

Despite the static analysis hint about a repeated word, there's no apparent duplication issue. This appears to be a false positive.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 LanguageTool</summary>

[duplication] ~15-~15: Possible typo: you repeated a word.
Context: ...erate_coats_redfern_data` function  ### Fixed - Fixed missing imports in examples/horowitz_me...

(ENGLISH_WORD_REPEAT_RULE)

</details>

</details>

</details>
<details>
<summary>src/pkynetics/model_fitting_methods/coats_redfern.py (1)</summary>

`53-61`: **Docstring expansion approved.**

The updated return signature documentation is informative and accurate.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T00:11:11Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between cae9d4c29eddcccf3a4062ddfd94d6d080224555 and 0b8d896cfb0326d3ba719bb8f50635cca58136f7.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `src/pkynetics/model_fitting_methods/coats_redfern.py` (4 hunks)

</details>

<details>
<summary>🔇 Additional comments (5)</summary><blockquote>

<details>
<summary>src/pkynetics/model_fitting_methods/coats_redfern.py (5)</summary>

`3-3`: **Good implementation of logger setup**

The addition of the logging module import and proper logger setup addresses the issue raised in previous reviews. This will allow for proper error and warning messages throughout the code.



Also applies to: 10-11

---

`55-64`: **Well-documented return values**

The updated docstring clearly documents the expanded return values, making it much easier for users to understand what data they can expect from this function. The detailed description of each return value is especially helpful for visualization purposes.

---

`92-103`: **Good validation of physical plausibility**

Adding checks for physically implausible activation energy values (e_a <= 0) is an excellent improvement. The warning message and graceful handling using absolute value helps prevent mathematical errors while alerting users to potential data or fitting issues.

---

`112-112`: **Comprehensive return values for improved analysis**

The expanded return statement now provides all necessary data for both analysis and visualization, which is a significant improvement over the previous implementation.

---

`74-74`: <details>
<summary>❓ Verification inconclusive</summary>

**Function parameter order corrected**

The order of parameters to `_prepare_y_data` has been corrected, which matches the function's signature at line 115 (temperature, alpha, n).


---

🏁 Script executed:

```shell
#!/bin/bash
# Description: Search for tests that cover this function to ensure proper test coverage
fd "test_.*py" --type f --exec rg -A 3 "_prepare_y_data|coats_redfern_method" {}
```

Length of output: 84

---



</details>

**Parameter Order Correction Validated – Please Verify Test Coverage Manually**

The change in the parameter order to use `(temperature, alpha, n)` now correctly matches the function signature at line 115. However, our search for tests referencing `_prepare_y_data` or `coats_redfern_method` did not return any results. Please verify manually that there are appropriate tests covering these functions, or consider adding tests to ensure their proper operation.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T00:20:47Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (2)</summary><blockquote>

<details>
<summary>CHANGELOG.md (2)</summary><blockquote>

`10-12`: **Changelog "Added" Section Styling and Wording Feedback**

The header "### Added" and the bullet starting with "Added" are a bit redundant. For clarity and stylistic consistency, consider revising the bullet—e.g., change it to:

```diff
- Added `reaction_model` parameter to `generate_coats_redfern_data` function
+ `reaction_model` parameter added to the `generate_coats_redfern_data` function
```

Also, including the article “the” before the function name improves the readability.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 LanguageTool</summary>

[duplication] ~10-~10: Possible typo: you repeated a word.
Context: ...0.html).  ## [v0.3.5] - 2025-03-11  ### Added - Added `reaction_model` parameter to `generate...

(ENGLISH_WORD_REPEAT_RULE)

---

[uncategorized] ~11-~11: You might be missing the article “the” here.
Context: ...d - Added `reaction_model` parameter to `generate_coats_redfern_data` function  #...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

</details>

</details>

---

`13-16`: **Changelog "Fixed" Section Verification**

The fixes for the division by zero error in the nth_order reaction model and for the NaN values in the pre-exponential factor calculation are clearly documented. To improve clarity, consider refining the bullet points by removing the redundant use of "Fixed" in each line, as the header already conveys that these are fixes.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 LanguageTool</summary>

[duplication] ~13-~13: Possible typo: you repeated a word.
Context: ...erate_coats_redfern_data` function  ### Fixed - Fixed division by zero error in nth_order rea...

(ENGLISH_WORD_REPEAT_RULE)

</details>

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 0b8d896cfb0326d3ba719bb8f50635cca58136f7 and 4f64808085bc85641edaad50c8c81e496462b250.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `CHANGELOG.md` (1 hunks)
* `docs/changelog.rst` (1 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* docs/changelog.rst

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 LanguageTool</summary>

<details>
<summary>CHANGELOG.md</summary>

[duplication] ~10-~10: Possible typo: you repeated a word.
Context: ...0.html).  ## [v0.3.5] - 2025-03-11  ### Added - Added `reaction_model` parameter to `generate...

(ENGLISH_WORD_REPEAT_RULE)

---

[uncategorized] ~11-~11: You might be missing the article “the” here.
Context: ...d - Added `reaction_model` parameter to `generate_coats_redfern_data` function  #...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

---

[duplication] ~13-~13: Possible typo: you repeated a word.
Context: ...erate_coats_redfern_data` function  ### Fixed - Fixed division by zero error in nth_order rea...

(ENGLISH_WORD_REPEAT_RULE)

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (1)</summary><blockquote>

<details>
<summary>CHANGELOG.md (1)</summary>

`8-9`: **New Version Entry Added for v0.3.5**

This segment correctly introduces a new version entry with the date *2025-03-11*. The entry follows the Keep a Changelog format and is consistent with Semantic Versioning.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T00:25:00Z

Review comments:
diff_hunk: @@ -79,9 +86,25 @@
     # Calculate kinetic parameters
     r = 8.314  # Gas constant in J/(mol·K)
     e_a = -slope * r  # Activation energy in J/mol
-    a = np.exp(
-        intercept + np.log(heating_rate / e_a)
-    )  # Pre-exponential factor in min^-1
+
+    # Check if activation energy is physically plausible
+    if e_a <= 0:
+        logger.warning(
+            "Calculated activation energy is negative or zero. "
+            "This is physically implausible and indicates potential issues with the data or fitting."
+        )
+        # Use absolute value to proceed with calculation while avoiding math errors
+        e_a_for_calc = abs(e_a)
+    else:
+        e_a_for_calc = e_a
+
+    # Safely calculate pre-exponential factor
+    try:
+        ln_a = intercept + np.log(heating_rate / e_a_for_calc)
+        a = np.exp(ln_a)
+    except (ValueError, RuntimeWarning, FloatingPointError) as e:
+        logger.error(f"Error calculating pre-exponential factor: {str(e)}")
+        a = float("nan")
path: src/pkynetics/model_fitting_methods/coats_redfern.py
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Logger import missing (continued).**

This block also references `logger.error`. Ensure the logger definition is introduced before using it to prevent runtime errors. Additionally, consider adding a test scenario causing a `ValueError` or `FloatingPointError` to verify the error handling logic.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Ruff (0.8.2)</summary>

106-106: Undefined name `logger`

(F821)

</details>
<details>
<summary>🪛 GitHub Check: codecov/patch</summary>

[warning] 102-107: src/pkynetics/model_fitting_methods/coats_redfern.py#L102-L107
Added lines #L102 - L107 were not covered by tests

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-03-12T00:11:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -61,7 +68,7 @@
     alpha = np.clip(alpha, 0, 1)
 
     x = 1000 / temperature
-    y = _prepare_y_data(alpha, temperature, n)
+    y = _prepare_y_data(temperature, alpha, n)
path: src/pkynetics/model_fitting_methods/coats_redfern.py
user: login: coderabbitai[bot]
body: _💡 Verification agent_

<details>
<summary>❓ Verification inconclusive</summary>

**Consider adding test coverage.**

The line calculating `y = _prepare_y_data(...)` is currently uncovered by tests. Please add or extend tests to cover this logic to ensure it remains correct under various scenarios.

---

🏁 Script executed:

```shell
#!/bin/bash
# Description: Search for tests covering coats_redfern_method and `_prepare_y_data` usage in test files
fd test_ --extension py --exec rg -A 5 "coats_redfern_method|_prepare_y_data" 
```

Length of output: 79

---



</details>

**Action Required: Add Test Coverage for `_prepare_y_data`**

- **Location:** `src/pkynetics/model_fitting_methods/coats_redfern.py` (line 71)
- **Issue:** The call to `_prepare_y_data(temperature, alpha, n)` is currently not exercised by any tests.
- **Recommendation:** Please add or extend tests to cover this functionality. Ensuring that this logic is well-tested under a variety of input scenarios will help maintain its correctness over time.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 GitHub Check: codecov/patch</summary>

[warning] 71-71: src/pkynetics/model_fitting_methods/coats_redfern.py#L71
Added line #L71 was not covered by tests

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-03-12T00:11:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -79,9 +86,25 @@
     # Calculate kinetic parameters
     r = 8.314  # Gas constant in J/(mol·K)
     e_a = -slope * r  # Activation energy in J/mol
-    a = np.exp(
-        intercept + np.log(heating_rate / e_a)
-    )  # Pre-exponential factor in min^-1
+
+    # Check if activation energy is physically plausible
+    if e_a <= 0:
+        logger.warning(
+            "Calculated activation energy is negative or zero. "
+            "This is physically implausible and indicates potential issues with the data or fitting."
+        )
+        # Use absolute value to proceed with calculation while avoiding math errors
+        e_a_for_calc = abs(e_a)
+    else:
+        e_a_for_calc = e_a
path: src/pkynetics/model_fitting_methods/coats_redfern.py
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Logger import missing.**

Use of `logger.warning` and `logger.error` without an imported or defined `logger` name will raise a NameError at runtime.

Apply this diff to properly define a logger:

```diff
+import logging

 def coats_redfern_method(
     temperature: NDArray[np.float64],
     alpha: NDArray[np.float64],
     heating_rate: float,
     n: float = 1,
 ) -> Tuple[...]:
+    logger = logging.getLogger(__name__)
 
     if len(temperature) != len(alpha):
         raise ValueError("Temperature and alpha arrays must have the same length")

     ...
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
import logging

def coats_redfern_method(
    temperature: NDArray[np.float64],
    alpha: NDArray[np.float64],
    heating_rate: float,
    n: float = 1,
) -> Tuple[...]:
    logger = logging.getLogger(__name__)
    
    if len(temperature) != len(alpha):
        raise ValueError("Temperature and alpha arrays must have the same length")
    
    if e_a <= 0:
        logger.warning(
            "Calculated activation energy is negative or zero. "
            "This is physically implausible and indicates potential issues with the data or fitting."
        )
        # Use absolute value to proceed with calculation while avoiding math errors
        e_a_for_calc = abs(e_a)
    else:
        e_a_for_calc = e_a
    
    ...
`````

</details>

<!-- suggestion_end -->

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Ruff (0.8.2)</summary>

92-92: Undefined name `logger`

(F821)

</details>
<details>
<summary>🪛 GitHub Check: codecov/patch</summary>

[warning] 91-92: src/pkynetics/model_fitting_methods/coats_redfern.py#L91-L92
Added lines #L91 - L92 were not covered by tests

---

[warning] 97-97: src/pkynetics/model_fitting_methods/coats_redfern.py#L97
Added line #L97 was not covered by tests

---

[warning] 99-99: src/pkynetics/model_fitting_methods/coats_redfern.py#L99
Added line #L99 was not covered by tests

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-03-12T00:11:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -79,9 +89,25 @@
     # Calculate kinetic parameters
     r = 8.314  # Gas constant in J/(mol·K)
     e_a = -slope * r  # Activation energy in J/mol
-    a = np.exp(
-        intercept + np.log(heating_rate / e_a)
-    )  # Pre-exponential factor in min^-1
+
+    # Check if activation energy is physically plausible
+    if e_a <= 0:
+        logger.warning(
+            "Calculated activation energy is negative or zero. "
+            "This is physically implausible and indicates potential issues with the data or fitting."
+        )
+        # Use absolute value to proceed with calculation while avoiding math errors
+        e_a_for_calc = abs(e_a)
+    else:
+        e_a_for_calc = e_a
+
+    # Safely calculate pre-exponential factor
+    try:
+        ln_a = intercept + np.log(heating_rate / e_a_for_calc)
+        a = np.exp(ln_a)
+    except (ValueError, RuntimeWarning, FloatingPointError) as e:
+        logger.error(f"Error calculating pre-exponential factor: {str(e)}")
+        a = float("nan")
 
path: src/pkynetics/model_fitting_methods/coats_redfern.py
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Robust error handling for pre-exponential factor calculation**

The try-except block for calculating the pre-exponential factor addresses the NaN value issues mentioned in the PR objectives. By catching specific exceptions and providing a fallback value, the function becomes more robust.

However, I notice a potential issue with the error handling:

The exception handling includes `RuntimeWarning`, but this is not an exception type that can be caught with except. It should be handled using the `warnings` module or removed from the except clause:

```diff
-    except (ValueError, RuntimeWarning, FloatingPointError) as e:
+    except (ValueError, FloatingPointError) as e:
```

Alternatively, if you want to catch numpy warnings:

```diff
+import warnings
+with warnings.catch_warnings():
+    warnings.simplefilter("error")
     try:
         ln_a = intercept + np.log(heating_rate / e_a_for_calc)
         a = np.exp(ln_a)
-    except (ValueError, RuntimeWarning, FloatingPointError) as e:
+    except (ValueError, FloatingPointError, Warning) as e:
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
    # Safely calculate pre-exponential factor
    try:
        ln_a = intercept + np.log(heating_rate / e_a_for_calc)
        a = np.exp(ln_a)
    except (ValueError, FloatingPointError) as e:
        logger.error(f"Error calculating pre-exponential factor: {str(e)}")
        a = float("nan")
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-03-12T00:20:46Z
author_association: CONTRIBUTOR

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-03-12T00:07:58Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough
This pull request updates the project version to v0.3.5 and enhances functionality across several modules. A new version entry is added to both the markdown and reStructuredText changelogs. The `generate_coats_redfern_data` function now accepts a `reaction_model` parameter. The `coats_redfern_method` function is refactored to return additional plotting arrays and improved error handling. Special handling for nearly first-order "nth_order" kinetics is integrated. Minor fixes in documentation and import statements are also included.

## Changes

| Files                                                                                           | Change Summary                                                                                                                                                                                                                         |
|-------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `CHANGELOG.md`, `docs/changelog.rst`                                                            | Added new version entry [v0.3.5]; introduced `reaction_model` parameter to `generate_coats_redfern_data`; fixed division by zero error and NaN values in Coats-Redfern method; resolved documentation and import issues.               |
| `src/pkynetics/__about__.py`                                                                    | Updated version information from "0.3.4" to "0.3.5".                                                                                                                                                                                   |
| `src/pkynetics/model_fitting_methods/coats_redfern.py`                                          | Expanded `coats_redfern_method` return type to include plotting arrays; enhanced error handling and corrected parameter order when calling `_prepare_y_data`.                                                                        |
| `src/pkynetics/synthetic_data/basic_kinetic_data.py`                                          | Introduced special case handling for "nth_order" reactions when n is approximately 1, preventing a division by zero error.                                                                                                              |
| `src/pkynetics/synthetic_data/model_specific_data.py`                                         | Added a `reaction_model` parameter (default `"nth_order"`) to `generate_coats_redfern_data` with an updated docstring.                                                                                                                    |

## Sequence Diagram(s)
```mermaid
sequenceDiagram
    participant U as User
    participant G as Data Generator
    participant C as Kinetic Calculator
    participant P as Plot Functions

    U->>G: Call generate_coats_redfern_data(reaction_model)
    G->>C: Process kinetic data (apply reaction model)
    C->>C: Validate energy, compute arrays, handle errors
    C-->>G: Return extended data tuple
    U->>P: Call plot functions
    P-->>U: Display visualization
```

## Possibly related PRs
- **PPeitsch/pkynetics#28**: Involves modifications to `generate_coats_redfern_data`, particularly the addition of the `reaction_model` parameter.
- **PPeitsch/pkynetics#9**: Directly related to the modifications in the `generate_coats_redfern_data` function, which includes the same parameter addition.

## Poem
> I'm a rabbit dancing in code delight,  
> Hopping through changes, day and night.  
> Plots and data now sing in tune,  
> Bugs retreat like a shy monsoon.  
> With each new line, my joy takes flight!  
> 🐰✨

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=PPeitsch/pkynetics&utm_content=52):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR
user: login: codecov[bot]
created_at: 2025-03-12T00:09:00Z
body: ## [Codecov](https://app.codecov.io/gh/PPeitsch/pkynetics/pull/52?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PabloPeitsch) Report
Attention: Patch coverage is `16.66667%` with `15 lines` in your changes missing coverage. Please review.

:white_check_mark: All tests successful. No failed tests found.

| [Files with missing lines](https://app.codecov.io/gh/PPeitsch/pkynetics/pull/52?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PabloPeitsch) | Patch % | Lines |
|---|---|---|
| [...c/pkynetics/model\_fitting\_methods/coats\_redfern.py](https://app.codecov.io/gh/PPeitsch/pkynetics/pull/52?src=pr&el=tree&filepath=src%2Fpkynetics%2Fmodel_fitting_methods%2Fcoats_redfern.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PabloPeitsch#diff-c3JjL3BreW5ldGljcy9tb2RlbF9maXR0aW5nX21ldGhvZHMvY29hdHNfcmVkZmVybi5weQ==) | 15.38% | [11 Missing :warning: ](https://app.codecov.io/gh/PPeitsch/pkynetics/pull/52?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PabloPeitsch) |
| [src/pkynetics/synthetic\_data/basic\_kinetic\_data.py](https://app.codecov.io/gh/PPeitsch/pkynetics/pull/52?src=pr&el=tree&filepath=src%2Fpkynetics%2Fsynthetic_data%2Fbasic_kinetic_data.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PabloPeitsch#diff-c3JjL3BreW5ldGljcy9zeW50aGV0aWNfZGF0YS9iYXNpY19raW5ldGljX2RhdGEucHk=) | 0.00% | [4 Missing :warning: ](https://app.codecov.io/gh/PPeitsch/pkynetics/pull/52?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PabloPeitsch) |

| [Files with missing lines](https://app.codecov.io/gh/PPeitsch/pkynetics/pull/52?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PabloPeitsch) | Coverage Δ | |
|---|---|---|
| [src/pkynetics/\_\_about\_\_.py](https://app.codecov.io/gh/PPeitsch/pkynetics/pull/52?src=pr&el=tree&filepath=src%2Fpkynetics%2F__about__.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PabloPeitsch#diff-c3JjL3BreW5ldGljcy9fX2Fib3V0X18ucHk=) | `100.00% <100.00%> (ø)` | |
| [...rc/pkynetics/synthetic\_data/model\_specific\_data.py](https://app.codecov.io/gh/PPeitsch/pkynetics/pull/52?src=pr&el=tree&filepath=src%2Fpkynetics%2Fsynthetic_data%2Fmodel_specific_data.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PabloPeitsch#diff-c3JjL3BreW5ldGljcy9zeW50aGV0aWNfZGF0YS9tb2RlbF9zcGVjaWZpY19kYXRhLnB5) | `41.66% <ø> (ø)` | |
| [src/pkynetics/synthetic\_data/basic\_kinetic\_data.py](https://app.codecov.io/gh/PPeitsch/pkynetics/pull/52?src=pr&el=tree&filepath=src%2Fpkynetics%2Fsynthetic_data%2Fbasic_kinetic_data.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PabloPeitsch#diff-c3JjL3BreW5ldGljcy9zeW50aGV0aWNfZGF0YS9iYXNpY19raW5ldGljX2RhdGEucHk=) | `25.92% <0.00%> (-3.25%)` | :arrow_down: |
| [...c/pkynetics/model\_fitting\_methods/coats\_redfern.py](https://app.codecov.io/gh/PPeitsch/pkynetics/pull/52?src=pr&el=tree&filepath=src%2Fpkynetics%2Fmodel_fitting_methods%2Fcoats_redfern.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PabloPeitsch#diff-c3JjL3BreW5ldGljcy9tb2RlbF9maXR0aW5nX21ldGhvZHMvY29hdHNfcmVkZmVybi5weQ==) | `22.50% <15.38%> (-1.64%)` | :arrow_down: |

author_association: NONE