| Conditions | 21 |
| Total Lines | 133 |
| Lines | 32 |
| Ratio | 24.06 % |
| Changes | 3 | ||
| Bugs | 0 | Features | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like get_layer() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | # Copyright (c) 2008-2017 MetPy Developers. |
||
| 337 | @exporter.export |
||
| 338 | @check_units('[pressure]') |
||
| 339 | def get_layer(p, *args, heights=None, bottom=None, depth=100 * units.hPa, interpolate=True): |
||
| 340 | r"""Return an atmospheric layer from upper air data with the requested bottom and depth. |
||
| 341 | |||
| 342 | This function will subset an upper air dataset to contain only the specified layer. The |
||
| 343 | bottom of the layer can be specified with a pressure or height above the surface |
||
| 344 | pressure. The bottom defaults to the surface pressure. The depth of the layer can be |
||
| 345 | specified in terms of pressure or height above the bottom of the layer. If the top and |
||
| 346 | bottom of the layer are not in the data, they are interpolated by default. |
||
| 347 | |||
| 348 | Parameters |
||
| 349 | ---------- |
||
| 350 | p : array-like |
||
| 351 | Atmospheric pressure profile |
||
| 352 | *args : array-like |
||
| 353 | Atmospheric variable(s) measured at the given pressures |
||
| 354 | bottom : `pint.Quantity` |
||
| 355 | The bottom of the layer as a pressure or height above the surface pressure |
||
| 356 | depth : `pint.Quantity` |
||
| 357 | The thickness of the layer as a pressure or height above the bottom of the layer |
||
| 358 | interpolate : bool |
||
| 359 | Interpolate the top and bottom points if they are not in the given data |
||
| 360 | |||
| 361 | Returns |
||
| 362 | ------- |
||
| 363 | `pint.Quantity, pint.Quantity` |
||
| 364 | The pressure and data variables of the layer |
||
| 365 | |||
| 366 | """ |
||
| 367 | # Make sure pressure and datavar are the same length |
||
| 368 | for datavar in args: |
||
| 369 | if len(p) != len(datavar): |
||
| 370 | raise ValueError('Pressure and data variable must have the same length.') |
||
| 371 | |||
| 372 | # |
||
| 373 | # Bottom of layer calculations |
||
| 374 | # |
||
| 375 | |||
| 376 | # If no bottom is specified, use the first pressure value |
||
| 377 | if bottom is None: |
||
| 378 | bottom_pressure = p[0] |
||
| 379 | if heights is not None: |
||
| 380 | bottom_height = heights[0] |
||
| 381 | else: |
||
| 382 | bottom_height = pressure_to_height_std(bottom_pressure) |
||
| 383 | |||
| 384 | # If the bottom pressure is specified |
||
| 385 | else: |
||
| 386 | # in pressure units, assign it |
||
| 387 | View Code Duplication | if bottom.dimensionality == {'[length]': -1.0, '[mass]': 1.0, '[time]': -2.0}: |
|
|
|
|||
| 388 | bottom_pressure = bottom |
||
| 389 | if heights is not None: |
||
| 390 | bottom_height = log_interp(bottom_pressure, p, heights) |
||
| 391 | else: |
||
| 392 | bottom_height = pressure_to_height_std(bottom_pressure) |
||
| 393 | # in height units |
||
| 394 | elif bottom.dimensionality == {'[length]': 1.0}: |
||
| 395 | bottom_height = bottom |
||
| 396 | if heights is not None: |
||
| 397 | bottom_pressure = np.interp(np.array([bottom_height.m]), heights, |
||
| 398 | p)[0] * p.units |
||
| 399 | else: |
||
| 400 | bottom_pressure = height_to_pressure_std(bottom_height) |
||
| 401 | |||
| 402 | # |
||
| 403 | # Top of layer calculations |
||
| 404 | # |
||
| 405 | |||
| 406 | # Depth is in pressure |
||
| 407 | View Code Duplication | if depth.dimensionality == {'[length]': -1.0, '[mass]': 1.0, '[time]': -2.0}: |
|
| 408 | top_pressure = bottom_pressure - depth |
||
| 409 | if heights is not None: |
||
| 410 | top_height = log_interp(top_pressure, p, heights) |
||
| 411 | else: |
||
| 412 | top_height = pressure_to_height_std(top_pressure) |
||
| 413 | |||
| 414 | # Depth is in height |
||
| 415 | elif depth.dimensionality == {'[length]': 1.0}: |
||
| 416 | top_height = bottom_height + depth |
||
| 417 | if heights is not None: |
||
| 418 | top_pressure = np.interp(np.array([top_height.m]), heights, p)[0] * p.units |
||
| 419 | else: |
||
| 420 | top_pressure = height_to_pressure_std(top_height) |
||
| 421 | |||
| 422 | # Depth is in invalid units |
||
| 423 | else: |
||
| 424 | raise ValueError('Depth must be in units of length or pressure.') |
||
| 425 | |||
| 426 | # Handle top or bottom values that are invalid |
||
| 427 | if bottom_pressure > p[0]: |
||
| 428 | raise ValueError( |
||
| 429 | 'Bottom of layer pressure is greater than the largest pressure in data.') |
||
| 430 | if top_pressure < p[-1]: |
||
| 431 | raise ValueError('Top of layer pressure is less than the lowest pressure in data.') |
||
| 432 | if bottom_pressure < top_pressure: |
||
| 433 | raise ValueError( |
||
| 434 | 'Pressure at the top of the layer is greater than that at the bottom.') |
||
| 435 | |||
| 436 | ret = [] # returned data variables in layer |
||
| 437 | |||
| 438 | # Ensure pressures are sorted in ascending order |
||
| 439 | sort_inds = np.argsort(p) |
||
| 440 | p = p[sort_inds] |
||
| 441 | |||
| 442 | # Mask based on top and bottom pressure |
||
| 443 | inds = (p <= bottom_pressure) & (p >= top_pressure) |
||
| 444 | p_interp = p[inds] |
||
| 445 | |||
| 446 | # Interpolate pressures at bounds if necessary and sort |
||
| 447 | if interpolate: |
||
| 448 | # If we don't have the bottom or top requested, append them |
||
| 449 | if top_pressure not in p_interp: |
||
| 450 | p_interp = np.sort(np.append(p_interp, top_pressure)) * p.units |
||
| 451 | if bottom_pressure not in p_interp: |
||
| 452 | p_interp = np.sort(np.append(p_interp, bottom_pressure)) * p.units |
||
| 453 | |||
| 454 | ret.append(p_interp[::-1]) |
||
| 455 | |||
| 456 | for datavar in args: |
||
| 457 | # Ensure that things are sorted in ascending order |
||
| 458 | datavar = datavar[sort_inds] |
||
| 459 | |||
| 460 | if interpolate: |
||
| 461 | # Interpolate for the possibly missing bottom/top values |
||
| 462 | datavar_interp = log_interp(p_interp, p, datavar) |
||
| 463 | datavar = datavar_interp |
||
| 464 | else: |
||
| 465 | datavar = datavar[inds] |
||
| 466 | |||
| 467 | ret.append(datavar[::-1]) |
||
| 468 | |||
| 469 | return ret |
||
| 470 |