Skip to content

Conversation

@d-chambers
Copy link
Contributor

@d-chambers d-chambers commented Aug 27, 2025

Description

Adds a helper function for converting from radians to strain using Equation 3 of @lindsey2020broadband.

Checklist

I have (if applicable):

  • referenced the GitHub issue this PR closes.
  • documented the new feature with docstrings or appropriate doc page.
  • included a test. See testing guidelines.
  • your name has been added to the contributors page (docs/contributors.md).
  • added the "ready_for_review" tag once the PR is ready to be reviewed.

Summary by CodeRabbit

  • New Features
    • Added a radians→strain conversion to the public transform API and as an operation available on data patches, with optional gauge length, wavelength, stress constant, and refractive index parameters.
    • Conversion validates gauge length, warns and returns unchanged when input units aren’t radians, and errors on incompatible units.
  • Tests
    • New tests cover successful conversion, missing/invalid gauge length, non-radian inputs, and unit failures.
  • Documentation
    • Added a bibliography entry on broadband instrument response for fiber‑optic DAS.

@d-chambers d-chambers added the transform Related to transform operations label Aug 27, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 27, 2025

Walkthrough

Adds a new radians_to_strain transform with unit validation and conversion, re-exports it from dascore.transform, adds tests and a bibliography entry, and introduces a small local alias in Patch.channel_count. No existing public function signatures were removed.

Changes

Cohort / File(s) Summary
Transform: new conversion + export
dascore/transform/strain.py, dascore/transform/__init__.py
Implements radians_to_strain (unit checks, gauge_length handling, constant computation, data & attrs update) and re-exports it from dascore.transform.
Core: local alias
dascore/core/patch.py
Adds a local alias radians_to_strain = dascore.transform.radians_to_strain inside Patch.channel_count scope.
Tests: radians → strain
tests/test_transform/test_strain.py
Adds tests verifying conversion behavior, gauge_length validation, no-radians early-return (warning), and unit error cases.
Docs: bibliography
docs/references.bib
Adds BibTeX entry lindsey2020broadband.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant User
  participant Patch as Patch
  participant Transform as radians_to_strain
  participant Units as Unit Utils

  User->>Patch: call Patch.radians_to_strain(gauge_length?)
  Patch->>Transform: forward Patch and parameters
  Transform->>Patch: read data_units and attrs.gauge_length
  alt no "rad" in data_units
    Transform->>User: warn and return original Patch
  else
    Transform->>Transform: validate gauge_length (error if missing)
    Transform->>Units: get_factor_and_unit(patch.data_units)
    Units-->>Transform: factor, unit
    Transform->>Transform: compute const = wave_length / (4π * n * gauge * stress_const)
    Transform->>Patch: new_data = data * const * factor
    Transform->>Units: compute new_units (remove "rad" → strain)
    Transform->>User: return Patch with updated data and data_units
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

I nibble radians into threads of strain,
I check the gauge and hum the constant's name.
A bib for Lindsey tucked in my lair,
I hop through units with a careful hare.
🥕✨


📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between b105335 and 0783443.

📒 Files selected for processing (1)
  • dascore/transform/strain.py (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • dascore/transform/strain.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (16)
  • GitHub Check: test_code_min_deps (macos-latest, 3.12)
  • GitHub Check: test_code_min_deps (windows-latest, 3.12)
  • GitHub Check: test_code_min_deps (windows-latest, 3.13)
  • GitHub Check: test_code_min_deps (macos-latest, 3.13)
  • GitHub Check: test_code_min_deps (ubuntu-latest, 3.13)
  • GitHub Check: test_code_min_deps (ubuntu-latest, 3.12)
  • GitHub Check: test_code (windows-latest, 3.12)
  • GitHub Check: test_code (macos-latest, 3.10)
  • GitHub Check: test_code (ubuntu-latest, 3.11)
  • GitHub Check: test_code (ubuntu-latest, 3.12)
  • GitHub Check: test_code (macos-latest, 3.12)
  • GitHub Check: test_code (windows-latest, 3.11)
  • GitHub Check: test_code (macos-latest, 3.11)
  • GitHub Check: test_code (ubuntu-latest, 3.10)
  • GitHub Check: test_code (windows-latest, 3.10)
  • GitHub Check: test_build_docs
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch rad_2_strain

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbit in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbit 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:
    • @coderabbit gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbit read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbit help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbit ignore or @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbit summary or @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbit or @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 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

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@d-chambers d-chambers added the documentation Improvements or additions to documentation label Aug 27, 2025
@codecov
Copy link

codecov bot commented Aug 27, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.87%. Comparing base (d6e1c58) to head (0783443).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master     #521   +/-   ##
=======================================
  Coverage   99.87%   99.87%           
=======================================
  Files         121      121           
  Lines        9887     9912   +25     
=======================================
+ Hits         9875     9900   +25     
  Misses         12       12           
Flag Coverage Δ
unittests 99.87% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (6)
docs/references.bib (1)

50-59: Nice addition; consider adding DOI/URL metadata.

Adding a DOI (and optionally the URL) improves reproducibility and doc builds that auto-link citations.

dascore/core/patch.py (1)

256-256: Group transform aliases with the other transform methods.

For consistency/readability, place this alongside the other transform method mappings (lines 346+). Also prefer transform.radians_to_strain to match nearby aliases.

Apply this diff:

-    radians_to_strain = dascore.transform.radians_to_strain

Add near the other transform mappings:

@@
     tau_p = transform.tau_p
+    radians_to_strain = transform.radians_to_strain
tests/test_transform/test_strain.py (1)

195-197: Guard against divide-by-zero in ratio check.

Random data may contain zeros; mask to avoid spurious inf/NaN.

Apply this diff (in addition to the above):

-        const = out.data / rad_patch.data
-        assert np.allclose(const, expected_const)
+        mask = rad_patch.data != 0
+        const = out.data[mask] / rad_patch.data[mask]
+        assert np.allclose(const, expected_const)
dascore/transform/__init__.py (1)

13-16: Fix linter issues: wrap long import and declare re-exports.

Addresses E501 and F401 by line-wrapping and making the re-exports explicit.

Apply this diff:

-from .strain import velocity_to_strain_rate, velocity_to_strain_rate_edgeless, radians_to_strain
+from .strain import (
+    velocity_to_strain_rate,
+    velocity_to_strain_rate_edgeless,
+    radians_to_strain,
+)
+
+# Re-exported API
+__all__ = [
+    "differentiate",
+    "rfft",
+    "dft",
+    "idft",
+    "integrate",
+    "spectrogram",
+    "dispersion_phase_shift",
+    "tau_p",
+    "velocity_to_strain_rate",
+    "velocity_to_strain_rate_edgeless",
+    "radians_to_strain",
+]
dascore/transform/strain.py (2)

214-218: Docstring: clarify “strain (rate)” → “strain”.

Equation 3 converts phase (radians) to strain, not strain rate.

Apply this diff:

-    Convert data in radians to strain (rate).
+    Convert data in radians to strain.

260-263: Numerical constant matches Eq. 3; consider explicit typing for gauge_length.

Optional: annotate gauge_length: float | None for clarity.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between d6e1c58 and bba9fdc.

📒 Files selected for processing (5)
  • dascore/core/patch.py (1 hunks)
  • dascore/transform/__init__.py (1 hunks)
  • dascore/transform/strain.py (2 hunks)
  • docs/references.bib (1 hunks)
  • tests/test_transform/test_strain.py (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
dascore/transform/__init__.py (1)
dascore/transform/strain.py (1)
  • radians_to_strain (206-268)
dascore/core/patch.py (1)
dascore/transform/strain.py (1)
  • radians_to_strain (206-268)
tests/test_transform/test_strain.py (6)
tests/conftest.py (2)
  • random_patch (282-284)
  • patch (375-377)
dascore/core/patch.py (3)
  • data (213-215)
  • attrs (203-205)
  • Patch (27-380)
dascore/transform/strain.py (1)
  • radians_to_strain (206-268)
dascore/units.py (1)
  • get_unit (47-58)
dascore/proc/basic.py (1)
  • update_attrs (82-108)
dascore/exceptions.py (1)
  • ParameterError (26-27)
dascore/transform/strain.py (5)
dascore/exceptions.py (1)
  • ParameterError (26-27)
dascore/units.py (2)
  • get_factor_and_unit (97-106)
  • get_unit (47-58)
dascore/utils/patch.py (1)
  • patch_function (179-285)
dascore/core/attrs.py (2)
  • get (174-179)
  • update (234-248)
dascore/proc/basic.py (1)
  • update (152-192)
🪛 Ruff (0.12.2)
dascore/transform/__init__.py

13-13: .strain.velocity_to_strain_rate imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


13-13: .strain.velocity_to_strain_rate_edgeless imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


13-13: .strain.radians_to_strain imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


13-13: Line too long (96 > 88)

(E501)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (16)
  • GitHub Check: test_build_docs
  • GitHub Check: test_code (windows-latest, 3.12)
  • GitHub Check: test_code (macos-latest, 3.12)
  • GitHub Check: test_code (windows-latest, 3.10)
  • GitHub Check: test_code_min_deps (windows-latest, 3.12)
  • GitHub Check: test_code_min_deps (macos-latest, 3.13)
  • GitHub Check: test_code (macos-latest, 3.11)
  • GitHub Check: test_code (windows-latest, 3.11)
  • GitHub Check: test_code (ubuntu-latest, 3.10)
  • GitHub Check: test_code_min_deps (ubuntu-latest, 3.12)
  • GitHub Check: test_code (ubuntu-latest, 3.12)
  • GitHub Check: test_code (macos-latest, 3.10)
  • GitHub Check: test_code_min_deps (macos-latest, 3.12)
  • GitHub Check: test_code_min_deps (windows-latest, 3.13)
  • GitHub Check: test_code (ubuntu-latest, 3.11)
  • GitHub Check: test_code_min_deps (ubuntu-latest, 3.13)
🔇 Additional comments (1)
dascore/transform/strain.py (1)

7-8: Imports look correct.

NumPy and unit helpers are required by the new function.

Also applies to: 13-14

Comment on lines +188 to +197
def test_convert_data_units(self, rad_patch):
"""Ensure we can convert data units to strain."""
out = rad_patch.radians_to_strain()
# Strain should now be in the units.
assert str(dc.get_unit("strain")) in str(out.attrs.data_units)
# Ensure the constant published in @lindsey2020broadband eq 3 works
# because the test data also have 10m gauge length.
expected_const = 11.6e-9
const = out.data / rad_patch.data
assert np.allclose(const, expected_const)
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid magic number; compute expected constant from the formula.

Hard-coding 11.6e-9 is brittle and appears inconsistent with the defaults used in the implementation.

Apply this diff:

-        # Ensure the constant published in @lindsey2020broadband eq 3 works
-        # because the test data also have 10m gauge length.
-        expected_const = 11.6e-9
-        const = out.data / rad_patch.data
-        assert np.allclose(const, expected_const)
+        # Compute the expected constant from Eq. 3 using the defaults.
+        expected_const = (1550.0e-9) / (4 * np.pi * 1.445 * rad_patch.attrs.gauge_length * 0.79)
+        const = out.data / rad_patch.data
+        assert np.allclose(const, expected_const)
📝 Committable suggestion

‼️ 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.

Suggested change
def test_convert_data_units(self, rad_patch):
"""Ensure we can convert data units to strain."""
out = rad_patch.radians_to_strain()
# Strain should now be in the units.
assert str(dc.get_unit("strain")) in str(out.attrs.data_units)
# Ensure the constant published in @lindsey2020broadband eq 3 works
# because the test data also have 10m gauge length.
expected_const = 11.6e-9
const = out.data / rad_patch.data
assert np.allclose(const, expected_const)
def test_convert_data_units(self, rad_patch):
"""Ensure we can convert data units to strain."""
out = rad_patch.radians_to_strain()
# Strain should now be in the units.
assert str(dc.get_unit("strain")) in str(out.attrs.data_units)
# Compute the expected constant from Eq. 3 using the defaults.
expected_const = (1550.0e-9) / (4 * np.pi * 1.445 * rad_patch.attrs.gauge_length * 0.79)
const = out.data / rad_patch.data
assert np.allclose(const, expected_const)
🤖 Prompt for AI Agents
In tests/test_transform/test_strain.py around lines 188 to 197, the test uses a
magic number 11.6e-9 for expected_const; replace that hard-coded value by
computing expected_const from the same formula used by radians_to_strain
(Lindsey 2020 broadband eq. 3) using the patch's gauge length (rad_patch.attrs
or rad_patch.gauge_length, default 10 m) and proper unit conversions via dc
utilities so the test derives the expected constant dynamically and then asserts
np.allclose(const, expected_const).

@github-actions
Copy link

github-actions bot commented Aug 27, 2025

✅ Documentation built:
👉 Download
Note: You must be logged in to github and a DASDAE member to access the link.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (2)
tests/test_transform/test_strain.py (1)

188-197: Replace magic number with formula-derived constant (Eq. 3).

Hard-coding 11.6e-9 is brittle; compute from the same defaults the implementation uses.

-        # Ensure the constant published in @lindsey2020broadband eq 3 works
-        # because the test data also have 10m gauge length.
-        expected_const = 11.6e-9
-        const = out.data / rad_patch.data
-        assert np.allclose(const, expected_const)
+        # Compute the expected constant from Eq. 3 using defaults and GL=10 m.
+        wl = 1550.0e-9
+        n = 1.445
+        zeta = 0.79
+        Lg = rad_patch.attrs.gauge_length
+        expected_const = wl / (4 * np.pi * n * Lg * zeta)
+        const = out.data / rad_patch.data
+        assert np.allclose(const, expected_const)
dascore/transform/strain.py (1)

246-254: Radian presence check is brittle and may miss aliases; also fails on non-str inputs.

Prefer a lowercase substring check on the original units string; accept “rad”, “radian(s)”.

-    # If units doesn't contain radians just return so function is idempotent
-    quant = dc.get_quantity(patch.attrs.data_units)
-    if str(dc.get_unit("radians")) not in str(quant):
+    # If units don't contain any radian component, return idempotently.
+    units_str = str(patch.attrs.get("data_units", "")).lower()
+    if "rad" not in units_str:
         msg = (
             f"Patch {patch} has no radians in its data_units, "
             f"skipping strain conversion."
         )
         warnings.warn(msg)
         return patch
🧹 Nitpick comments (5)
tests/test_transform/test_strain.py (3)

175-187: Fixture is fine; consider modern RNG API.

Use numpy’s Generator for forward-compatibility and reproducibility.

-        rand = np.random.RandomState(42)
-        data = rand.random(random_patch.data.shape) - 0.5
+        rng = np.random.default_rng(42)
+        data = rng.random(random_patch.data.shape) - 0.5

199-208: Strengthen positive path check.

After the ParameterError case, also verify scaling is correct for an explicit gauge_length.

         out = patch.radians_to_strain(gauge_length=1)
         assert isinstance(out, dc.Patch)
+        wl, n, zeta = 1550.0e-9, 1.445, 0.79
+        expected = wl / (4 * np.pi * n * 1 * zeta)
+        assert np.allclose(out.data / rad_patch.data, expected)

209-217: Idempotence assertion is good; optionally also assert no history appended.

Ensures zero-op transform truly leaves Patch untouched.

         assert out is patch
+        assert list(getattr(out.attrs, "history", ())) == list(
+            getattr(patch.attrs, "history", ())
+        )
dascore/transform/strain.py (2)

214-215: Doc: this converts to strain, not strain-rate.

Fix the wording.

-    Convert data in radians to strain (rate).
+    Convert data in radians to strain.

266-268: Consider setting data_type="strain" on output.

Aligns attrs with the unit change.

-    new_attrs = patch.attrs.update(data_units=new_units)
+    new_attrs = patch.attrs.update(data_units=new_units, data_type="strain")
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 638f5ba and b105335.

📒 Files selected for processing (2)
  • dascore/transform/strain.py (2 hunks)
  • tests/test_transform/test_strain.py (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
dascore/transform/strain.py (3)
dascore/exceptions.py (1)
  • UnitError (106-107)
dascore/units.py (4)
  • convert_units (120-155)
  • get_factor_and_unit (97-106)
  • get_unit (47-58)
  • get_quantity (70-94)
dascore/utils/patch.py (1)
  • patch_function (179-285)
tests/test_transform/test_strain.py (4)
dascore/exceptions.py (2)
  • ParameterError (26-27)
  • UnitError (106-107)
dascore/core/patch.py (3)
  • data (213-215)
  • attrs (203-205)
  • Patch (27-380)
dascore/transform/strain.py (1)
  • radians_to_strain (206-268)
dascore/units.py (1)
  • get_unit (47-58)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (16)
  • GitHub Check: test_code_min_deps (windows-latest, 3.13)
  • GitHub Check: test_code_min_deps (windows-latest, 3.12)
  • GitHub Check: test_code_min_deps (macos-latest, 3.13)
  • GitHub Check: test_code_min_deps (ubuntu-latest, 3.12)
  • GitHub Check: test_code_min_deps (ubuntu-latest, 3.13)
  • GitHub Check: test_code_min_deps (macos-latest, 3.12)
  • GitHub Check: test_code (windows-latest, 3.11)
  • GitHub Check: test_code (windows-latest, 3.12)
  • GitHub Check: test_code (windows-latest, 3.10)
  • GitHub Check: test_code (macos-latest, 3.11)
  • GitHub Check: test_code (ubuntu-latest, 3.12)
  • GitHub Check: test_code (macos-latest, 3.12)
  • GitHub Check: test_code (macos-latest, 3.10)
  • GitHub Check: test_code (ubuntu-latest, 3.10)
  • GitHub Check: test_code (ubuntu-latest, 3.11)
  • GitHub Check: test_build_docs
🔇 Additional comments (1)
tests/test_transform/test_strain.py (1)

218-222: Good negative test for complex units.

Covers the “rad^2” path and expected UnitError.

Comment on lines 221 to 229
gauge_length ($L_g$)
The gauge length in meters.
wave_length ($\lambda$)
The laser wavelength in m.
stress_constant ($\zeta$)
The stress constant.
refractive_index ($\Delta \Phi$)
The refractive index of the cable.
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Doc: incorrect symbol/description for refractive index.

Use n for refractive index; ΔΦ is the phase change (the input), not n.

-    refractive_index ($\Delta \Phi$)
-        The refractive index of the cable.
+    refractive_index ($n$)
+        The refractive index of the fiber.
📝 Committable suggestion

‼️ 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.

Suggested change
gauge_length ($L_g$)
The gauge length in meters.
wave_length ($\lambda$)
The laser wavelength in m.
stress_constant ($\zeta$)
The stress constant.
refractive_index ($\Delta \Phi$)
The refractive index of the cable.
gauge_length ($L_g$)
The gauge length in meters.
wave_length ($\lambda$)
The laser wavelength in m.
stress_constant ($\zeta$)
The stress constant.
- refractive_index ($\Delta \Phi$)
refractive_index ($n$)
The refractive index of the fiber.
🤖 Prompt for AI Agents
In dascore/transform/strain.py around lines 221 to 229, the docstring
incorrectly labels the refractive index as "ΔΦ" and describes it as a phase
change; update the parameter name and description to use n for the refractive
index and clarify that ΔΦ is the phase change input (if present elsewhere), e.g.
change the parameter entry to "refractive_index (n) The refractive index of the
cable." and, if the phase change ΔΦ is documented here, add a separate entry
"phase_change (ΔΦ) The measured phase change." Ensure symbols and descriptions
match the function's inputs and any formulas in the docstring.

Comment on lines +258 to +266
data_units = patch.attrs.get("data_units", None)
d_factor, d_units = get_factor_and_unit(data_units, simplify=True)
new_units = get_unit(d_units) * get_unit("strain/radians")
# Radians wasn't eliminated from the output units. Something went wrong.
if str(dc.get_unit("radians")) in str(new_units):
msg = f"radians to strain failed to convert {data_units} to strain."
raise UnitError(msg)
# Build output patch
new_attrs = patch.attrs.update(data_units=new_units)
Copy link
Contributor

@coderabbitai coderabbitai bot Aug 29, 2025

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

new_units construction can raise on d_units=None and uses non-canonical “radians”.

Handle empty units safely and use singular “radian”; explicitly fail if rad remains.

-    data_units = patch.attrs.get("data_units", None)
-    d_factor, d_units = get_factor_and_unit(data_units, simplify=True)
-    new_units = get_unit(d_units) * get_unit("strain/radians")
-    # Radians wasn't eliminated from the output units. Something went wrong.
-    if str(dc.get_unit("radians")) in str(new_units):
-        msg = f"radians to strain failed to convert {data_units} to strain."
-        raise UnitError(msg)
-    # Build output patch
-    new_attrs = patch.attrs.update(data_units=new_units)
+    data_units = patch.attrs.get("data_units", None)
+    d_factor, d_units = get_factor_and_unit(data_units, simplify=True)
+    if d_units:
+        new_units = get_unit(d_units) * (get_unit("strain") / get_unit("radian"))
+    else:
+        new_units = get_unit("strain")
+    # If radians remain, units were too complex; bail out.
+    if "rad" in str(new_units).lower():
+        msg = f"radians to strain failed to convert {data_units} to strain."
+        raise UnitError(msg)
+    # Build output patch
+    new_attrs = patch.attrs.update(data_units=new_units)
📝 Committable suggestion

‼️ 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.

Suggested change
data_units = patch.attrs.get("data_units", None)
d_factor, d_units = get_factor_and_unit(data_units, simplify=True)
new_units = get_unit(d_units) * get_unit("strain/radians")
# Radians wasn't eliminated from the output units. Something went wrong.
if str(dc.get_unit("radians")) in str(new_units):
msg = f"radians to strain failed to convert {data_units} to strain."
raise UnitError(msg)
# Build output patch
new_attrs = patch.attrs.update(data_units=new_units)
data_units = patch.attrs.get("data_units", None)
d_factor, d_units = get_factor_and_unit(data_units, simplify=True)
if d_units:
new_units = get_unit(d_units) * (get_unit("strain") / get_unit("radian"))
else:
new_units = get_unit("strain")
# If radians remain, units were too complex; bail out.
if "rad" in str(new_units).lower():
msg = f"radians to strain failed to convert {data_units} to strain."
raise UnitError(msg)
# Build output patch
new_attrs = patch.attrs.update(data_units=new_units)
🤖 Prompt for AI Agents
In dascore/transform/strain.py around lines 258 to 266, new_units construction
can crash if d_units is None and the code checks/uses the non-canonical string
"radians"; also patch.attrs.update(...) returns None. Fix by first handling
d_units is None (treat as dimensionless) before calling
get_unit/get_factor_and_unit, use the singular "radian" when multiplying units,
then explicitly detect remaining "radian" in the resulting unit and raise
UnitError if present, and finally build new_attrs by copying patch.attrs (e.g.,
attrs_copy = patch.attrs.copy()) and then updating
attrs_copy['data_units']=new_units instead of assigning the return value of
update().

Copy link
Contributor Author

Choose a reason for hiding this comment

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

data units cant be `None because we check radians is in units in the line above.

Copy link
Contributor

Choose a reason for hiding this comment

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

@d-chambers You're absolutely right! Looking at the control flow, the function already checks for radians in patch.attrs.data_units and returns early if none are found, so by the time we reach the unit conversion logic, data_units will indeed contain radians and won't be None. My suggestion to handle the None case was unnecessary given this guard. Thank you for the clarification!

@d-chambers d-chambers merged commit 5edff1a into master Aug 29, 2025
20 checks passed
@d-chambers d-chambers deleted the rad_2_strain branch August 29, 2025 16:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation transform Related to transform operations

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants