Skip to content

API reference

earthcarekit.calval

Functions for EarthCARE calibration and validation.

Notes

This module depends on other internal modules:


compare_bsc_ext_lr_depol

compare_bsc_ext_lr_depol(
    input_ec: str | Dataset,
    input_ground: str | Dataset | None = None,
    time_var_ground: str = "time",
    height_var_ground: str = "height",
    bsc_var_ground: str | tuple[str, str] | list[str | tuple[str, str]] = [],
    ext_var_ground: str | tuple[str, str] | list[str | tuple[str, str]] = [],
    lr_var_ground: str | tuple[str, str] | list[str | tuple[str, str]] = [],
    depol_var_ground: str | tuple[str, str] | list[str | tuple[str, str]] = [],
    input_ec2: str | Dataset | None = None,
    input_ec3: str | Dataset | None = None,
    input_ec4: str | Dataset | None = None,
    input_ground2: str | Dataset | None = None,
    input_ground3: str | Dataset | None = None,
    input_ground4: str | Dataset | None = None,
    time_var_ground2: str | None = None,
    height_var_ground2: str | None = None,
    time_var_ground3: str | None = None,
    height_var_ground3: str | None = None,
    time_var_ground4: str | None = None,
    height_var_ground4: str | None = None,
    bsc_var_ground2: str | tuple[str, str] | list[str | tuple[str, str]] | None = None,
    ext_var_ground2: str | tuple[str, str] | list[str | tuple[str, str]] | None = None,
    lr_var_ground2: str | tuple[str, str] | list[str | tuple[str, str]] | None = None,
    depol_var_ground2: str | tuple[str, str] | list[str | tuple[str, str]] | None = None,
    bsc_var_ground3: str | tuple[str, str] | list[str | tuple[str, str]] | None = None,
    ext_var_ground3: str | tuple[str, str] | list[str | tuple[str, str]] | None = None,
    lr_var_ground3: str | tuple[str, str] | list[str | tuple[str, str]] | None = None,
    depol_var_ground3: str | tuple[str, str] | list[str | tuple[str, str]] | None = None,
    bsc_var_ground4: str | tuple[str, str] | list[str | tuple[str, str]] | None = None,
    ext_var_ground4: str | tuple[str, str] | list[str | tuple[str, str]] | None = None,
    lr_var_ground4: str | tuple[str, str] | list[str | tuple[str, str]] | None = None,
    depol_var_ground4: str | tuple[str, str] | list[str | tuple[str, str]] | None = None,
    site: SiteLike | None = None,
    radius_km: float = 100.0,
    resolution: str = "_low_resolution",
    resolution2: str | None = None,
    resolution3: str | None = None,
    resolution4: str | None = None,
    height_range: tuple[float, float] | None = (0, 30000.0),
    selection_height_range: tuple[float, float] | None = None,
    selection_height_range_bsc: tuple[float, float] | None = None,
    selection_height_range_ext: tuple[float, float] | None = None,
    selection_height_range_lr: tuple[float, float] | None = None,
    selection_height_range_depol: tuple[float, float] | None = None,
    value_range_bsc: ValueRangeLike | None = (0, 8e-06),
    value_range_ext: ValueRangeLike | None = (0, 0.0003),
    value_range_lr: ValueRangeLike | None = (0, 100),
    value_range_depol: ValueRangeLike | None = (0, 0.6),
    colors_ec: list[str] = ["ec:red", "ec:orange", "ec:yellow", "ec:purple"],
    colors_ground: list[str] = [
        "ec:blue",
        "ec:darkblue",
        "ec:lightgreen",
        "ec:darkgreen",
        "ec:purple",
    ],
    linewidth_ec: list[float | int] | float | int = 1.5,
    linewidth_ground: list[float | int] | float | int = 1.5,
    linestyle_ec: list[str] | str = "solid",
    linestyle_ground: list[str] | str = "solid",
    label_ec: list[str | None] = [],
    label_ground: list[str | None] = [],
    alpha: float = 1.0,
    show_steps: bool = DEFAULT_PROFILE_SHOW_STEPS,
    show_error_ec: bool = False,
    show_quality_status: bool = False,
    show_rebinned: bool = False,
    quality_status_width_scale: float = 1.0,
    quality_status_var: str = "quality_status",
    quality_status_value_range: tuple[float | None, float | None] | None = None,
    to_mega: bool = False,
    single_figsize: tuple[float | int, float | int] = (5 * CM_AS_INCH, 12 * CM_AS_INCH),
    label_bsc: str = "Bsc. coeff.",
    label_ext: str = "Ext. coeff.",
    label_lr: str = "Lidar ratio",
    label_depol: str = "Depol. ratio",
    units_bsc: str = "m$^{-1}$ sr$^{-1}$",
    units_ext: str = "m$^{-1}$",
    units_lr: str = "sr",
    units_depol: str = "",
    verbose: bool = True,
) -> _CompareBscExtLRDepolResults

Compares Lidar profiles from up to 3 EarthCARE source dataset an one ground-based dataset by creating plots and statistics dataframe.

Parameters:

Name Type Description Default
input_ec str | Dataset

A opened EarthCARE or file path.

required
input_ground str | Dataset

A opened ground-based NetCDF dataset or file path (e.g., PollyNET data).

None
time_var_ground str

The name of the time variable in the ground-based dataset (e.g., for single profile PollyNET data use "start_time"). Defaults to "height".

'time'
height_var_ground str

The name of the height variable in the ground-based dataset. Defaults to "height".

'height'
bsc_var_ground str | tuple | list[str | tuple]

Backscatter variable name in the ground-based dataset. Multiple variables can be provided as list. Variable errors can be provided as tuples (e.g., [("bsc", "bsc_err"), ("bsc2", "bsc2_err"), ...]). Defaults to empty list.

[]
ext_var_ground str | tuple | list[str | tuple]

Extinction variable name in the ground-based dataset. Multiple variables can be provided as list. Variable errors can be provided as tuples (e.g., [("ext", "ext_err"), ("ext2", "ext2_err"), ...]). Defaults to empty list.

[]
lr_var_ground str | tuple | list[str | tuple]

Lidar ratio variable name in the ground-based dataset. Multiple variables can be provided as list. Variable errors can be provided as tuples (e.g., [("lr", "lr_err"), ("lr2", "lr2_err"), ...]). Defaults to empty list.

[]
depol_var_ground str | tuple | list[str | tuple]

Depol. ratio variable name in the ground-based dataset. Multiple variables can be provided as list. Variable errors can be provided as tuples (e.g., [("depol", "depol_err"), ("depol2", "depol2_err"), ...]). Defaults to empty list.

[]
input_ec2 str | Dataset

An optional seconds EarthCARE dataset to compare. Defaults to None.

None
input_ec3 str | Dataset

An optional third EarthCARE dataset to compare. Defaults to None.

None
site SiteLike | None

Ground site or location of the ground-based data as a Site object or by name string (e.g., "mindelo"). Defaults to None.

None
radius_km float

Radius around the ground site. Defaults to 100.0.

100.0
resolution str

Sets the used resolution of the EarthCARE data if applicable (e.g., for A-EBD). Defaults to "_low_resolution".

'_low_resolution'
height_range tuple[float, float] | None

Height range in meters to restrict the data for plotting. Defaults to (0, 30e3).

(0, 30000.0)
selection_height_range tuple[float, float] | None

Height range in meters to select data for statistsics. Defaults to None.

None
selection_height_range_bsc tuple[float, float] | None

Height range in meters to select bsc. data for statistsics. Defaults to None (i.e., selection_height_range).

None
selection_height_range_ext tuple[float, float] | None

Height range in meters to select ext. data for statistsics. Defaults to None (i.e., selection_height_range).

None
selection_height_range_lr tuple[float, float] | None

Height range in meters to select LR data for statistsics. Defaults to None (i.e., selection_height_range).

None
selection_height_range_depol tuple[float, float] | None

Height range in meters to select depol. data for statistsics. Defaults to None (i.e., selection_height_range).

None
value_range_bsc ValueRangeLike | None

Tuple setting minimum and maximum value on x-axis. Defaults to (0, 8e-6).

(0, 8e-06)
value_range_ext ValueRangeLike | None

Tuple setting minimum and maximum value on x-axis. Defaults to (0, 3e-4).

(0, 0.0003)
value_range_lr ValueRangeLike | None

Tuple setting minimum and maximum value on x-axis. Defaults to (0, 100).

(0, 100)
value_range_depol ValueRangeLike | None

Tuple setting minimum and maximum value on x-axis. Defaults to (0, 0.6).

(0, 0.6)
colors_ec list[str]

List of colors for the EarthCARE profiles.

['ec:red', 'ec:orange', 'ec:yellow', 'ec:purple']
colors_ground list[str]

List of colors for the ground-based profiles.

['ec:blue', 'ec:darkblue', 'ec:lightgreen', 'ec:darkgreen', 'ec:purple']
linewidth_ec Number | list[Number]

Value or list of line width for the EarthCARE profiles. Defaults to 1.5.

1.5
linewidth_ground Number | list[Number]

Value or list of line width for the ground-based profiles. Defaults to 1.5.

1.5
linestyle_ec Number | list[Number]

Value or list of line style for the EarthCARE profiles. Defaults to "solid".

'solid'
linestyle_ground Number | list[Number]

Value or list of line style for the ground-based profiles. Defaults to "solid".

'solid'
label_ec list[str]

List of legend labels for the EarthCARE profiles.

[]
label_ground list[str]

List of legend labels for the ground-based profiles.

[]
alpha float

Transparency value for the profile lines (value between 0 and 1). Defaults to 1.0.

1.0
show_steps bool

If True, profiles will be plotted as step functions instead of bin centers.

DEFAULT_PROFILE_SHOW_STEPS
show_error_ec bool

If True, plot error ribbons for EarthCARE profiles.

False
show_rebinned bool

If True, ground-based profiles will be plotted rebinnned to the first EarthCARE profile. Defaults to False.

False
to_mega bool

If Ture, converts bsc. and ext. data results (i.e., plot and statistics) to [Mm-1 sr-1] and [Mm-1]. Defaults to False.

False
single_figsize tuple[float, float]

2-element tuple setting width and height of the subfigures (i.e., for each profile plot).

(5 * CM_AS_INCH, 12 * CM_AS_INCH)
label_bsc str

Label displayed on the backscatter sub-figure. Defaults to "Bsc. coeff.".

'Bsc. coeff.'
label_ext str

Label displayed on the extinction sub-figure. Defaults to "Ext. coeff.".

'Ext. coeff.'
label_lr str

Label displayed on the lidar ratio sub-figure. Defaults to "Lidar ratio".

'Lidar ratio'
label_depol str

Label displayed on the depol sub-figure. Defaults to "Depol. ratio".

'Depol. ratio'
units_bsc str

Units displayed on the backscatter sub-figure. Defaults to "m$^{-1}$ sr$^{-1}$".

'm$^{-1}$ sr$^{-1}$'
units_ext str

Units displayed on the extinction sub-figure. Defaults to "m$^{-1}$".

'm$^{-1}$'
units_lr str

Units displayed on the lidar ratio sub-figure. Defaults to "sr".

'sr'
units_depol str

Units displayed on the depol sub-figure. Defaults to "".

''
verbose bool

Whether logs about processing steps appear in the console. Defaults to True.

True

Returns:

Name Type Description
results _CompareBscExtLRDepolResults

An object containing the plot and statistical results. - results.fig: The matplotlib figure - results.fig_bsc: Backscatter subfigure as ProfileFigure - results.fig_ext: Extinction subfigure as ProfileFigure - results.fig_lr: Lidar ratio subfigure as ProfileFigure - results.fig_depol: Depol. ratio subfigure as ProfileFigure - results.stats: Statistical results as a pandas.DataFrame

Source code in earthcarekit/calval/_compare_bsc_ext_lr_depol.py
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
def compare_bsc_ext_lr_depol(
    input_ec: str | xr.Dataset,
    input_ground: str | xr.Dataset | None = None,
    time_var_ground: str = "time",
    height_var_ground: str = "height",
    bsc_var_ground: str | tuple[str, str] | list[str | tuple[str, str]] = [],
    ext_var_ground: str | tuple[str, str] | list[str | tuple[str, str]] = [],
    lr_var_ground: str | tuple[str, str] | list[str | tuple[str, str]] = [],
    depol_var_ground: str | tuple[str, str] | list[str | tuple[str, str]] = [],
    input_ec2: str | xr.Dataset | None = None,
    input_ec3: str | xr.Dataset | None = None,
    input_ec4: str | xr.Dataset | None = None,
    input_ground2: str | xr.Dataset | None = None,
    input_ground3: str | xr.Dataset | None = None,
    input_ground4: str | xr.Dataset | None = None,
    time_var_ground2: str | None = None,
    height_var_ground2: str | None = None,
    time_var_ground3: str | None = None,
    height_var_ground3: str | None = None,
    time_var_ground4: str | None = None,
    height_var_ground4: str | None = None,
    bsc_var_ground2: str | tuple[str, str] | list[str | tuple[str, str]] | None = None,
    ext_var_ground2: str | tuple[str, str] | list[str | tuple[str, str]] | None = None,
    lr_var_ground2: str | tuple[str, str] | list[str | tuple[str, str]] | None = None,
    depol_var_ground2: (str | tuple[str, str] | list[str | tuple[str, str]] | None) = None,
    bsc_var_ground3: str | tuple[str, str] | list[str | tuple[str, str]] | None = None,
    ext_var_ground3: str | tuple[str, str] | list[str | tuple[str, str]] | None = None,
    lr_var_ground3: str | tuple[str, str] | list[str | tuple[str, str]] | None = None,
    depol_var_ground3: (str | tuple[str, str] | list[str | tuple[str, str]] | None) = None,
    bsc_var_ground4: str | tuple[str, str] | list[str | tuple[str, str]] | None = None,
    ext_var_ground4: str | tuple[str, str] | list[str | tuple[str, str]] | None = None,
    lr_var_ground4: str | tuple[str, str] | list[str | tuple[str, str]] | None = None,
    depol_var_ground4: (str | tuple[str, str] | list[str | tuple[str, str]] | None) = None,
    site: SiteLike | None = None,
    radius_km: float = 100.0,
    resolution: str = "_low_resolution",
    resolution2: str | None = None,
    resolution3: str | None = None,
    resolution4: str | None = None,
    height_range: tuple[float, float] | None = (0, 30e3),
    selection_height_range: tuple[float, float] | None = None,
    selection_height_range_bsc: tuple[float, float] | None = None,
    selection_height_range_ext: tuple[float, float] | None = None,
    selection_height_range_lr: tuple[float, float] | None = None,
    selection_height_range_depol: tuple[float, float] | None = None,
    value_range_bsc: ValueRangeLike | None = (0, 8e-6),
    value_range_ext: ValueRangeLike | None = (0, 3e-4),
    value_range_lr: ValueRangeLike | None = (0, 100),
    value_range_depol: ValueRangeLike | None = (0, 0.6),
    colors_ec: list[str] = [
        "ec:red",
        "ec:orange",
        "ec:yellow",
        "ec:purple",
    ],
    colors_ground: list[str] = [
        "ec:blue",
        "ec:darkblue",
        "ec:lightgreen",
        "ec:darkgreen",
        "ec:purple",
    ],
    linewidth_ec: list[float | int] | float | int = 1.5,
    linewidth_ground: list[float | int] | float | int = 1.5,
    linestyle_ec: list[str] | str = "solid",
    linestyle_ground: list[str] | str = "solid",
    label_ec: list[str | None] = [],
    label_ground: list[str | None] = [],
    alpha: float = 1.0,
    show_steps: bool = DEFAULT_PROFILE_SHOW_STEPS,
    show_error_ec: bool = False,
    show_quality_status: bool = False,
    show_rebinned: bool = False,
    quality_status_width_scale: float = 1.0,
    quality_status_var: str = "quality_status",
    quality_status_value_range: tuple[float | None, float | None] | None = None,
    to_mega: bool = False,
    single_figsize: tuple[float | int, float | int] = (5 * CM_AS_INCH, 12 * CM_AS_INCH),
    label_bsc: str = "Bsc. coeff.",
    label_ext: str = "Ext. coeff.",
    label_lr: str = "Lidar ratio",
    label_depol: str = "Depol. ratio",
    units_bsc: str = "m$^{-1}$ sr$^{-1}$",
    units_ext: str = "m$^{-1}$",
    units_lr: str = "sr",
    units_depol: str = "",
    verbose: bool = True,
) -> _CompareBscExtLRDepolResults:
    """Compares Lidar profiles from up to 3 EarthCARE source dataset an one ground-based dataset by creating plots and statistics dataframe.

    Args:
        input_ec (str | xr.Dataset): A opened EarthCARE or file path.
        input_ground (str | xr.Dataset, optional): A opened ground-based NetCDF dataset or file path (e.g., PollyNET data).
        time_var_ground (str, optional): The name of the time variable in the ground-based dataset (e.g., for single profile PollyNET data use `"start_time"`). Defaults to `"height"`.
        height_var_ground (str, optional): The name of the height variable in the ground-based dataset. Defaults to `"height"`.
        bsc_var_ground (str | tuple | list[str | tuple], optional): Backscatter variable name in the ground-based dataset.
            Multiple variables can be provided as list. Variable errors can be provided as tuples (e.g., `[("bsc", "bsc_err"), ("bsc2", "bsc2_err"), ...]`). Defaults to empty list.
        ext_var_ground (str | tuple | list[str | tuple], optional): Extinction variable name in the ground-based dataset.
            Multiple variables can be provided as list. Variable errors can be provided as tuples (e.g., `[("ext", "ext_err"), ("ext2", "ext2_err"), ...]`). Defaults to empty list.
        lr_var_ground (str | tuple | list[str | tuple], optional): Lidar ratio variable name in the ground-based dataset.
            Multiple variables can be provided as list. Variable errors can be provided as tuples (e.g., `[("lr", "lr_err"), ("lr2", "lr2_err"), ...]`). Defaults to empty list.
        depol_var_ground (str | tuple | list[str | tuple], optional): Depol. ratio variable name in the ground-based dataset.
            Multiple variables can be provided as list. Variable errors can be provided as tuples (e.g., `[("depol", "depol_err"), ("depol2", "depol2_err"), ...]`). Defaults to empty list.
        input_ec2 (str | xr.Dataset, optional): An optional seconds EarthCARE dataset to compare. Defaults to None.
        input_ec3 (str | xr.Dataset, optional): An optional third EarthCARE dataset to compare. Defaults to None.
        site (SiteLike | None, optional): Ground site or location of the ground-based data as a `Site` object or by name string (e.g., `"mindelo"`). Defaults to None.
        radius_km (float, optional): Radius around the ground site. Defaults to 100.0.
        resolution (str, optional): Sets the used resolution of the EarthCARE data if applicable (e.g., for A-EBD). Defaults to "_low_resolution".
        height_range (tuple[float, float] | None, optional): Height range in meters to restrict the data for plotting. Defaults to (0, 30e3).
        selection_height_range (tuple[float, float] | None, optional): Height range in meters to select data for statistsics. Defaults to None.
        selection_height_range_bsc (tuple[float, float] | None, optional): Height range in meters to select bsc. data for statistsics. Defaults to None (i.e., `selection_height_range`).
        selection_height_range_ext (tuple[float, float] | None, optional): Height range in meters to select ext. data for statistsics. Defaults to None (i.e., `selection_height_range`).
        selection_height_range_lr (tuple[float, float] | None, optional): Height range in meters to select LR data for statistsics. Defaults to None (i.e., `selection_height_range`).
        selection_height_range_depol (tuple[float, float] | None, optional): Height range in meters to select depol. data for statistsics. Defaults to None (i.e., `selection_height_range`).
        value_range_bsc (ValueRangeLike | None, optional): Tuple setting minimum and maximum value on x-axis. Defaults to (0, 8e-6).
        value_range_ext (ValueRangeLike | None, optional): Tuple setting minimum and maximum value on x-axis. Defaults to (0, 3e-4).
        value_range_lr (ValueRangeLike | None, optional): Tuple setting minimum and maximum value on x-axis. Defaults to (0, 100).
        value_range_depol (ValueRangeLike | None, optional): Tuple setting minimum and maximum value on x-axis. Defaults to (0, 0.6).
        colors_ec (list[str], optional): List of colors for the EarthCARE profiles.
        colors_ground (list[str], optional): List of colors for the ground-based profiles.
        linewidth_ec (Number | list[Number], optional): Value or list of line width for the EarthCARE profiles. Defaults to 1.5.
        linewidth_ground (Number | list[Number], optional): Value or list of line width for the ground-based profiles. Defaults to 1.5.
        linestyle_ec (Number | list[Number], optional): Value or list of line style for the EarthCARE profiles. Defaults to "solid".
        linestyle_ground (Number | list[Number], optional): Value or list of line style for the ground-based profiles. Defaults to "solid".
        label_ec (list[str], optional): List of legend labels for the EarthCARE profiles.
        label_ground (list[str], optional): List of legend labels for the ground-based profiles.
        alpha (float, optional): Transparency value for the profile lines (value between 0 and 1). Defaults to 1.0.
        show_steps (bool, optional): If True, profiles will be plotted as step functions instead of bin centers.
        show_error_ec (bool, optional): If True, plot error ribbons for EarthCARE profiles.
        show_rebinned (bool, optional): If True, ground-based profiles will be plotted rebinnned to the first EarthCARE profile. Defaults to False.
        to_mega (bool, optional): If Ture, converts bsc. and ext. data results (i.e., plot and statistics) to [Mm-1 sr-1] and [Mm-1]. Defaults to False.
        single_figsize (tuple[float, float], optional): 2-element tuple setting width and height of the subfigures (i.e., for each profile plot).
        label_bsc (str, optional): Label displayed on the backscatter sub-figure. Defaults to "Bsc. coeff.".
        label_ext (str, optional): Label displayed on the extinction sub-figure. Defaults to "Ext. coeff.".
        label_lr (str, optional): Label displayed on the lidar ratio sub-figure. Defaults to "Lidar ratio".
        label_depol (str, optional): Label displayed on the depol sub-figure. Defaults to "Depol. ratio".
        units_bsc (str, optional): Units displayed on the backscatter sub-figure. Defaults to "m$^{-1}$ sr$^{-1}$".
        units_ext (str, optional): Units displayed on the extinction sub-figure. Defaults to "m$^{-1}$".
        units_lr (str, optional): Units displayed on the lidar ratio sub-figure. Defaults to "sr".
        units_depol (str, optional): Units displayed on the depol sub-figure. Defaults to "".
        verbose (bool, optional): Whether logs about processing steps appear in the console. Defaults to True.

    Returns:
        results (_CompareBscExtLRDepolResults): An object containing the plot and statistical results.
            - `results.fig`: The `matplotlib` figure
            - `results.fig_bsc`: Backscatter subfigure as `ProfileFigure`
            - `results.fig_ext`: Extinction subfigure as `ProfileFigure`
            - `results.fig_lr`: Lidar ratio subfigure as `ProfileFigure`
            - `results.fig_depol`: Depol. ratio subfigure as `ProfileFigure`
            - `results.stats`: Statistical results as a `pandas.DataFrame`
    """
    _logger = logging.getLogger()
    ctx = nullcontext() if verbose else silence_logger(_logger)
    with ctx:
        _vars_main: list[str | tuple[str, str]] = _get_ec_vars(
            input_ec,
            resolution,
            show_error=show_error_ec,
        )
        _closest: bool = _get_ec_is_closest(input_ec)

        label = [
            label_bsc,
            label_ext,
            label_lr,
            label_depol,
        ]

        units = [
            units_bsc,
            units_ext,
            units_lr,
            units_depol,
        ]

        if not isinstance(resolution2, str):
            resolution2 = resolution
        if not isinstance(resolution3, str):
            resolution3 = resolution
        if not isinstance(resolution4, str):
            resolution4 = resolution

        if not isinstance(time_var_ground2, str):
            time_var_ground2 = time_var_ground
        if not isinstance(time_var_ground3, str):
            time_var_ground3 = time_var_ground
        if not isinstance(time_var_ground4, str):
            time_var_ground4 = time_var_ground

        if not isinstance(height_var_ground2, str):
            height_var_ground2 = height_var_ground
        if not isinstance(height_var_ground3, str):
            height_var_ground3 = height_var_ground
        if not isinstance(height_var_ground4, str):
            height_var_ground4 = height_var_ground

        if bsc_var_ground2 is None:
            bsc_var_ground2 = bsc_var_ground
        if bsc_var_ground3 is None:
            bsc_var_ground3 = bsc_var_ground
        if bsc_var_ground4 is None:
            bsc_var_ground4 = bsc_var_ground

        if ext_var_ground2 is None:
            ext_var_ground2 = ext_var_ground
        if ext_var_ground3 is None:
            ext_var_ground3 = ext_var_ground
        if ext_var_ground4 is None:
            ext_var_ground4 = ext_var_ground

        if lr_var_ground2 is None:
            lr_var_ground2 = lr_var_ground
        if lr_var_ground3 is None:
            lr_var_ground3 = lr_var_ground
        if lr_var_ground4 is None:
            lr_var_ground4 = lr_var_ground

        if depol_var_ground2 is None:
            depol_var_ground2 = depol_var_ground
        if depol_var_ground3 is None:
            depol_var_ground3 = depol_var_ground
        if depol_var_ground4 is None:
            depol_var_ground4 = depol_var_ground

        _vars_main2: list[str | tuple[str, str]] | None = None
        _closest2: bool | None = None
        if input_ec2 is not None:
            _vars_main2 = _get_ec_vars(
                input_ec2,
                resolution2,
                show_error=show_error_ec,
            )
            _closest2 = _get_ec_is_closest(input_ec2)

        _vars_main3: list[str | tuple[str, str]] | None = None
        _closest3: bool | None = None
        if input_ec3 is not None:
            _vars_main3 = _get_ec_vars(
                input_ec3,
                resolution3,
                show_error=show_error_ec,
            )
            _closest3 = _get_ec_is_closest(input_ec3)

        _vars_main4: list[str | tuple[str, str]] | None = None
        _closest4: bool | None = None
        if input_ec4 is not None:
            _vars_main4 = _get_ec_vars(
                input_ec4,
                resolution4,
                show_error=show_error_ec,
            )
            _closest4 = _get_ec_is_closest(input_ec4)

        with (
            read_product(input_ec) as ds_ec,
            nullcontext(None if input_ec2 is None else read_product(input_ec2)) as ds_ec2,
            nullcontext(None if input_ec3 is None else read_product(input_ec3)) as ds_ec3,
            nullcontext(None if input_ec4 is None else read_product(input_ec4)) as ds_ec4,
            nullcontext(None if input_ground is None else read_any(input_ground)) as ds_target,
            nullcontext(None if input_ground2 is None else read_any(input_ground2)) as ds_target2,
            nullcontext(None if input_ground3 is None else read_any(input_ground3)) as ds_target3,
            nullcontext(None if input_ground4 is None else read_any(input_ground4)) as ds_target4,
        ):
            ncols: int = 4
            width_scale: float | list[float] = 1.0
            if show_quality_status:
                ncols = 5
                width_scale = [1.0, 1.0, 1.0, 1.0, quality_status_width_scale]
            _output = create_column_figure_layout(
                ncols=ncols,
                single_figsize=single_figsize,
                margin=0.6,
                width_scale=width_scale,
            )
            fig = _output.fig
            axs = _output.axs

            vars_target: list[str | tuple[str, str] | list[str | tuple[str, str]]] = [
                bsc_var_ground,
                ext_var_ground,
                lr_var_ground,
                depol_var_ground,
            ]

            vars_target2: list[str | tuple[str, str] | list[str | tuple[str, str]]] = [
                bsc_var_ground2,
                ext_var_ground2,
                lr_var_ground2,
                depol_var_ground2,
            ]

            vars_target3: list[str | tuple[str, str] | list[str | tuple[str, str]]] = [
                bsc_var_ground3,
                ext_var_ground3,
                lr_var_ground3,
                depol_var_ground3,
            ]

            vars_target4: list[str | tuple[str, str] | list[str | tuple[str, str]]] = [
                bsc_var_ground4,
                ext_var_ground4,
                lr_var_ground4,
                depol_var_ground4,
            ]

            value_range: list = [
                value_range_bsc,
                value_range_ext,
                value_range_lr,
                value_range_depol,
            ]

            if selection_height_range_bsc is None:
                selection_height_range_bsc = selection_height_range
            if selection_height_range_ext is None:
                selection_height_range_ext = selection_height_range
            if selection_height_range_lr is None:
                selection_height_range_lr = selection_height_range
            if selection_height_range_depol is None:
                selection_height_range_depol = selection_height_range

            _selection_height_range = [
                selection_height_range_bsc,
                selection_height_range_ext,
                selection_height_range_lr,
                selection_height_range_depol,
            ]

            pfs: list[ProfileFigure] = []
            dfs: list[pd.DataFrame] = []
            for i in range(len(_vars_main)):
                _flip_height_axis: bool = False
                _show_height_ticks: bool = True
                _show_height_label: bool = False

                if i == 0:
                    _show_height_label = True
                    _show_height_ticks = True
                _pf, _df = compare_ec_profiles_with_target(
                    ds_ec=ds_ec,
                    ds_ec2=ds_ec2,
                    ds_ec3=ds_ec3,
                    ds_ec4=ds_ec4,
                    ds_target=ds_target,
                    ds_target2=ds_target2,
                    ds_target3=ds_target3,
                    ds_target4=ds_target4,
                    var_ec=_vars_main[i],
                    var_ec2=None if _vars_main2 is None else _vars_main2[i],
                    var_ec3=None if _vars_main3 is None else _vars_main3[i],
                    var_ec4=None if _vars_main4 is None else _vars_main4[i],
                    var_target=vars_target[i],
                    var_target2=vars_target2[i],
                    var_target3=vars_target3[i],
                    var_target4=vars_target4[i],
                    selection_height_range=_selection_height_range[i],
                    height_range=height_range,
                    site=site,
                    radius_km=radius_km,
                    closest=_closest,
                    closest2=False if _closest2 is None else _closest2,
                    closest3=False if _closest3 is None else _closest3,
                    closest4=False if _closest4 is None else _closest4,
                    time_var_target=time_var_ground,
                    height_var_target=height_var_ground,
                    time_var_target2=time_var_ground2,
                    height_var_target2=height_var_ground2,
                    time_var_target3=time_var_ground3,
                    height_var_target3=height_var_ground3,
                    time_var_target4=time_var_ground4,
                    height_var_target4=height_var_ground4,
                    ax=axs[i],
                    label=label[i],
                    units=units[i],
                    value_range=value_range[i],
                    flip_height_axis=_flip_height_axis,
                    show_height_ticks=_show_height_ticks,
                    show_height_label=_show_height_label,
                    colors_ec=colors_ec,
                    colors_ground=colors_ground,
                    linewidth_ec=linewidth_ec,
                    linewidth_ground=linewidth_ground,
                    linestyle_ec=linestyle_ec,
                    linestyle_ground=linestyle_ground,
                    label_ec=label_ec,
                    label_ground=label_ground,
                    alpha=alpha,
                    show_steps=show_steps,
                    show_rebinned=show_rebinned,
                    to_mega=False if i > 1 else to_mega,
                    single_figsize=single_figsize,
                )
                pfs.append(_pf)
                dfs.append(_df)
            df = pd.concat(dfs, ignore_index=True)

            # Optional: plot quality status
            if show_quality_status:
                _dss: list = []
                _var: str = quality_status_var
                _ps_qs: list[Profile] = []
                for _ds in [ds_ec, ds_ec2, ds_ec3, ds_ec4]:
                    if (
                        isinstance(_ds, xr.Dataset)
                        and not any([_ds.equals(x) for x in _dss])
                        and _var in _ds
                    ):
                        p_qs = _extract_earthcare_profile(
                            ds=_ds,
                            var=_var,
                            site=site,
                            radius_km=radius_km,
                            closest=True,
                        )
                        p_qs.platform = (
                            "EC"
                            if p_qs.platform is None
                            else (
                                p_qs.platform.replace("res.", "")
                                .replace("low", "")
                                .replace("medium", "")
                                .replace("high", "")
                                .strip()
                            )
                        )
                        _ps_qs.append(p_qs)
                        _dss.append(_ds)
                vrange = quality_status_value_range
                if vrange is None and _var == "quality_status":
                    vrange = (-0.2, 4.2)
                _plot_profiles(
                    _ps_qs,
                    ax=axs[-1],
                    selection_height_range=selection_height_range,
                    height_range=height_range,
                    value_range=vrange,
                    flip_height_axis=False,
                    show_height_ticks=True,
                    show_height_label=False,
                    colors_ec=colors_ec,
                    linewidth_ec=linewidth_ec,
                    linestyle_ec=linestyle_ec,
                    label_ec=label_ec,
                    alpha=alpha,
                    show_steps=show_steps,
                    figsize=single_figsize,
                )

    return _CompareBscExtLRDepolResults(
        fig=fig,
        fig_bsc=pfs[0],
        fig_ext=pfs[1],
        fig_lr=pfs[2],
        fig_depol=pfs[3],
        stats=df,
    )

perform_anom_depol_statistics

perform_anom_depol_statistics(
    ds_anom: Dataset,
    selection_height_range: DistanceRangeLike,
    is_rayleigh_corrected: bool = False,
    rayleigh_correction_factor: float = 0.004,
    **kwargs
) -> _ANOMDepolCalculationResults

Calculate depolarization statistics and uncertainties within a height range.

This function adds the depol. ratio (DPOL) calculated from co- (CPOL) and cross-polarized (XPOL) attenuated backscatter to the dataset (ATL_NOM_1B) and computes related statistics. Mean values and standard deviations are calculated for CPOL, XPOL, and DPOL within the selected height range. Variability is separated into vertical and temporal components. Errors of DPOL are derived using error propagation for the XPOL/CPOL ratio.

Parameters:

Name Type Description Default
ds_anom Dataset

ATL_NOM_1B dataset with cross- and co-polar signals.

required
selection_height_range DistanceRangeLike

Height range for statistics.

required
is_rayleight_corrected bool

If True, the mean cross-polar profile is corrected by substracting the mean rayleigh profile scaled by a correction factor. Defaults to False.

required
rayleigh_correction_factor float

The scaling factor used when is_rayleight_corrected is True. Defaults to 0.004.

0.004

Returns:

Name Type Description
_ANOMDepolCalculationResults _ANOMDepolCalculationResults

Results container with

  • Mean and standard deviation of depolarization ratio.
  • Mean, vertical, temporal, and combined spreads for co- and cross-polar signals.
  • Propagated uncertainty of δ (total, vertical, temporal).
  • Input dataset with depolarization ratio added.
Example
import earthcarekit as eck

ft = "ANOM"
oaf = "01508B"
site = "dushanbe"
radius_km = 100
sel_hrange = (1e3, 4e3)

# # Optionally, download required data
# eck.ecdownload(file_type=ft, orbit_and_frame=oaf)

df = eck.search_product(file_type=ft, orbit_and_frame=oaf)
fp = df.filepath[-1]

with eck.read_any(fp) as ds:
    ds = eck.filter_radius(ds, radius_km=radius_km, site=site)
    results = eck.perform_anom_depol_statistics(ds, sel_hrange)
    results.print()  # prints statistics

    # # Optionally, save statistics as CSV file
    # results.stats.to_csv("./stats.csv")

    # # Optionally, save profile figure as PNG file
    # fig = results.plot(height_range=(0, 10e3))
    # eck.save_plot(fig, filepath="./depol_profile.png")
Source code in earthcarekit/calval/_perform_anom_depol_statistics.py
def perform_anom_depol_statistics(
    ds_anom: xr.Dataset,
    selection_height_range: DistanceRangeLike,
    is_rayleigh_corrected: bool = False,
    rayleigh_correction_factor: float = 0.004,
    **kwargs,
) -> _ANOMDepolCalculationResults:
    """
    Calculate depolarization statistics and uncertainties within a height range.

    This function adds the depol. ratio (`DPOL`) calculated from co- (`CPOL`) and cross-polarized (`XPOL`)
    attenuated backscatter to the dataset (ATL_NOM_1B) and computes related statistics.
    Mean values and standard deviations are calculated for `CPOL`, `XPOL`, and `DPOL` within the selected
    height range. Variability is separated into vertical and temporal components. Errors of `DPOL` are derived
    using error propagation for the `XPOL`/`CPOL` ratio.

    Args:
        ds_anom (xr.Dataset): ATL_NOM_1B dataset with cross- and co-polar signals.
        selection_height_range (DistanceRangeLike): Height range for statistics.
        is_rayleight_corrected (bool): If True, the mean cross-polar profile is corrected by substracting the
            mean rayleigh profile scaled by a correction factor. Defaults to False.
        rayleigh_correction_factor (float): The scaling factor used when `is_rayleight_corrected` is True.
            Defaults to 0.004.

    Returns:
        _ANOMDepolCalculationResults: Results container with

            - Mean and standard deviation of depolarization ratio.
            - Mean, vertical, temporal, and combined spreads for co- and cross-polar signals.
            - Propagated uncertainty of δ (total, vertical, temporal).
            - Input dataset with depolarization ratio added.

    Example:
        ```python
        import earthcarekit as eck

        ft = "ANOM"
        oaf = "01508B"
        site = "dushanbe"
        radius_km = 100
        sel_hrange = (1e3, 4e3)

        # # Optionally, download required data
        # eck.ecdownload(file_type=ft, orbit_and_frame=oaf)

        df = eck.search_product(file_type=ft, orbit_and_frame=oaf)
        fp = df.filepath[-1]

        with eck.read_any(fp) as ds:
            ds = eck.filter_radius(ds, radius_km=radius_km, site=site)
            results = eck.perform_anom_depol_statistics(ds, sel_hrange)
            results.print()  # prints statistics

            # # Optionally, save statistics as CSV file
            # results.stats.to_csv("./stats.csv")

            # # Optionally, save profile figure as PNG file
            # fig = results.plot(height_range=(0, 10e3))
            # eck.save_plot(fig, filepath="./depol_profile.png")
        ```
    """

    selection_height_range = validate_numeric_range(selection_height_range)

    ds_anom = add_depol_ratio(ds_anom, **kwargs)

    cpol_p: Profile = Profile.from_dataset(ds_anom, var="cpol_cleaned_for_ratio_calculation")
    xpol_p: Profile = Profile.from_dataset(ds_anom, var="xpol_cleaned_for_ratio_calculation")
    ray_p: Profile = Profile.from_dataset(ds_anom, var="ray_cleaned_for_ratio_calculation")
    cpol_mean_p: Profile = cpol_p.mean()
    xpol_mean_p: Profile = xpol_p.mean()
    ray_mean_p: Profile = ray_p.mean()

    if is_rayleigh_corrected:
        xpol_mean_p = xpol_mean_p - (ray_mean_p * rayleigh_correction_factor)

    dpol_mean_p: Profile = xpol_mean_p / cpol_mean_p
    cpol_std_p: Profile = cpol_p.std()
    xpol_std_p: Profile = xpol_p.std()

    cpol_stats = cpol_p.stats(selection_height_range)
    if is_rayleigh_corrected:
        xpol_p_corr = xpol_p - (ray_p * rayleigh_correction_factor)
        xpol_stats = xpol_p_corr.stats(selection_height_range)
    else:
        xpol_stats = xpol_p.stats(selection_height_range)
    dpol_stats = dpol_mean_p.stats(selection_height_range)

    dpol_mean: float = dpol_stats.mean
    dpol_std: float = dpol_stats.std
    cpol_mean: float = cpol_stats.mean
    xpol_mean: float = xpol_stats.mean
    cpol_std_t: float = cpol_std_p.stats(selection_height_range).std
    xpol_std_t: float = xpol_std_p.stats(selection_height_range).std
    cpol_std_z: float = cpol_stats.std
    xpol_std_z: float = xpol_stats.std
    cpol_std: float = cpol_std_t + cpol_std_z
    xpol_std: float = xpol_std_t + xpol_std_z

    def calc_error(xsd, csd):
        return np.sqrt((xsd / cpol_mean) ** 2 + (((xpol_mean / (cpol_mean**2)) * csd) ** 2))

    error = calc_error(xpol_std, cpol_std)
    error_z = calc_error(xpol_std_z, cpol_std_z)
    error_t = calc_error(xpol_std_t, cpol_std_t)

    return _ANOMDepolCalculationResults(
        ds=ds_anom.copy(),
        selection_height_range=selection_height_range,
        dpol_mean=dpol_mean,
        dpol_std=dpol_std,
        cpol_mean=cpol_mean,
        cpol_std_t=cpol_std_t,
        cpol_std_z=cpol_std_z,
        cpol_std=cpol_std,
        xpol_mean=xpol_mean,
        xpol_std_t=xpol_std_t,
        xpol_std_z=xpol_std_z,
        xpol_std=xpol_std,
        error=error,
        error_t=error_t,
        error_z=error_z,
    )