Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Development #21

Merged
merged 6 commits into from
Jun 19, 2024
Merged

Development #21

merged 6 commits into from
Jun 19, 2024

Conversation

leaver2000
Copy link
Owner

@leaver2000 leaver2000 commented Jun 19, 2024

Summary by Sourcery

This pull request introduces several new features for atmospheric calculations, including functions for parcel mixing ratio, most unstable parcel identification, mixed layer calculations, and CAPE/CIN computations. It also includes significant enhancements to existing functions, adding support for conditional calculations and improving broadcasting and masking capabilities. Comprehensive tests and documentation updates are provided to ensure robustness and clarity.

  • New Features:
    • Introduced parcel_mixing_ratio function to calculate the mixing ratio of a parcel based on pressure, temperature, and dewpoint.
    • Added most_unstable_parcel function to identify the most unstable parcel in a given atmospheric profile.
    • Implemented mixed_layer function to calculate the mixed layer temperature and dewpoint.
    • Added most_unstable_cape_cin function to compute CAPE and CIN for the most unstable parcel.
  • Enhancements:
    • Refactored downdraft_cape, ccl, el, and lfc functions to include optional where parameter for conditional calculations.
    • Improved broadcast_and_nanmask function to handle broadcasting and masking of input arrays more efficiently.
    • Enhanced parcel_profile_with_lcl to include broadcasting and masking capabilities.
    • Updated moist_lapse function to support where parameter for conditional calculations.
    • Refactored pressure_vector class to include methods for checking and masking pressure levels.
  • Documentation:
    • Updated docstrings for equivalent_potential_temperature and other functions to include detailed parameter descriptions and examples.
  • Tests:
    • Added new tests for parcel_mixing_ratio, most_unstable_parcel, mixed_layer, and most_unstable_cape_cin functions.
    • Enhanced existing tests to cover new broadcasting and masking functionalities.
    • Included regression tests to ensure compatibility with previous versions.

@leaver2000 leaver2000 merged commit 15c1203 into master Jun 19, 2024
Copy link

sourcery-ai bot commented Jun 19, 2024

Reviewer's Guide by Sourcery

This pull request introduces significant refactoring and new features to the nzthermo library. Key changes include the addition of the pressure_vector class, new functions for calculating mixed layer and most unstable parcel properties, and updates to existing functions to support broadcasting and additional parameters. The tests have been updated to cover these new scenarios and ensure compatibility with the refactored code.

File-Level Changes

Files Changes
src/nzthermo/core.py
src/nzthermo/_core.pyx
src/nzthermo/utils.py
src/nzthermo/_ufunc.pyx
src/lib/libthermo.cpp
src/nzthermo/functional.py
Refactored core functions to use new pressure_vector class and updated logic for LCL, EL, LFC, and CAPE/CIN calculations.
tests/core_test.py
tests/functional_test.py
Added new tests for mixed_layer, most_unstable_parcel, and most_unstable_cape_cin functions. Updated existing tests to include broadcasting scenarios.
src/nzthermo/_ufunc.pyi
src/nzthermo/_C.pxd
src/include/libthermo.hpp
Updated type definitions and function signatures to support new pressure_vector class and additional parameters.

Tips
  • Trigger a new Sourcery review by commenting @sourcery-ai review on the pull request.
  • You can change your review settings at any time by accessing your dashboard:
    • Enable or disable the Sourcery-generated pull request summary or reviewer's guide;
    • Change the review language;
  • You can always contact us if you have any questions or feedback.

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey @leaver2000 - I've reviewed your changes and they look great!

Here's what I looked at during the review
  • 🟡 General issues: 6 issues found
  • 🟢 Security: all looks good
  • 🟡 Testing: 3 issues found
  • 🟢 Complexity: all looks good
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment to tell me if it was helpful.

src/nzthermo/core.py Show resolved Hide resolved
Comment on lines +117 to +118
# pressure = pressure.where(pressure >= p_top[:, newaxis], NaN)
pressure = pressure.where(pressure.is_below(p_top[:, newaxis], close=True), NaN)
Copy link

Choose a reason for hiding this comment

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

nitpick: Commented-out code

Consider removing the commented-out line if it is no longer needed. Keeping commented-out code can lead to confusion and clutter.

temperature,
"increasing",
log_x=True,
).where_above(LCL)

is_lcl = (no_lfc := LFC.is_nan().all(axis=1, keepdims=True)) & greater_or_close(
no_lfc = LFC.is_nan().all(Axis.Z, out=np.empty((N, 1), dtype=np.bool_), keepdims=True)
Copy link

Choose a reason for hiding this comment

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

suggestion (performance): Potential performance issue with np.empty

Using np.empty without initializing values can lead to unpredictable behavior if the array is used before being fully populated. Consider using np.zeros or np.full for safer initialization.

Suggested change
no_lfc = LFC.is_nan().all(Axis.Z, out=np.empty((N, 1), dtype=np.bool_), keepdims=True)
no_lfc = LFC.is_nan().all(Axis.Z, out=np.zeros((N, 1), dtype=np.bool_), keepdims=True)

np.ndarray pressure,
np.ndarray temperature,
np.ndarray dewpoint,
def broadcast_and_nanmask(
Copy link

Choose a reason for hiding this comment

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

suggestion: Function documentation improvement

The docstring for the 'broadcast_and_nanmask' function is detailed but could benefit from a clearer explanation of the 'where' parameter and its expected behavior.

Suggested change
def broadcast_and_nanmask(
def broadcast_and_nanmask(
np.ndarray pressure,
np.ndarray temperature,
np.ndarray dewpoint,
where=None
):

pressure = pressure.reshape(1, -1)
mode = BROADCAST
else:
mode = MATRIX

if where is not None:
Copy link

Choose a reason for hiding this comment

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

issue: Unsupported 'where' argument

The 'where' argument is not supported in the 'moist_lapse' function. Consider either implementing support for it or removing the parameter to avoid confusion.


elif pint is not None:

def magnitude(x, unit):
if isinstance(x, pint.Quantity):
return x.to(unit).magnitude
x = x.to(unit).magnitude
Copy link

Choose a reason for hiding this comment

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

issue: Inconsistent return type

The 'magnitude' function should consistently return a numpy array. Ensure that the return type is always np.asarray(x) to avoid potential type issues.

@@ -301,8 +312,17 @@ def test_moist_lapse(dtype):
# ............................................................................................... #
# nzthermo._core.parcel_profile
# ............................................................................................... #
@pytest.mark.broadcasting
Copy link

Choose a reason for hiding this comment

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

suggestion (testing): Add edge case for empty input arrays

Consider adding a test case to handle empty input arrays for the test_parcel_profile_broadcasting function. This will ensure that the function can gracefully handle scenarios where no data is provided.

Suggested change
@pytest.mark.broadcasting
@pytest.mark.broadcasting
@pytest.mark.parametrize("input_data", [[], np.array([])])
def test_parcel_profile_broadcasting(input_data) -> None:

)


@pytest.mark.regression
Copy link

Choose a reason for hiding this comment

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

suggestion (testing): Add edge case for extreme values

Consider adding a test case to handle extreme values (e.g., very high or very low temperatures and pressures) for the test_parcel_profile_metpy_regression function. This will ensure that the function can handle a wide range of input values.

Suggested change
@pytest.mark.regression
@pytest.mark.regression
@pytest.mark.parametrize("depth, temperature, pressure", [
(30000.0, 273.15, 1013.25), # Normal conditions
(30000.0, 373.15, 500.0), # High temperature, low pressure
(30000.0, 173.15, 2000.0), # Low temperature, high pressure
])

@@ -1055,6 +1089,15 @@
# ............................................................................................... #
# nzthermo.core.lfc
# ............................................................................................... #
@pytest.mark.broadcasting
@pytest.mark.lfc
Copy link

Choose a reason for hiding this comment

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

suggestion (testing): Add edge case for empty input arrays

Consider adding a test case to handle empty input arrays for the test_lfc_broadcasting function. This will ensure that the function can gracefully handle scenarios where no data is provided.

Suggested change
@pytest.mark.lfc
@pytest.mark.lfc
def test_lfc_broadcasting_empty_input() -> None:
empty_array = np.array([])
assert_array_equal(lfc(empty_array), empty_array)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant