disdrodb 0.0.21__py3-none-any.whl → 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- disdrodb/__init__.py +132 -15
- disdrodb/_config.py +4 -2
- disdrodb/_version.py +9 -4
- disdrodb/api/checks.py +264 -237
- disdrodb/api/configs.py +4 -8
- disdrodb/api/create_directories.py +235 -290
- disdrodb/api/info.py +217 -26
- disdrodb/api/io.py +295 -269
- disdrodb/api/path.py +597 -173
- disdrodb/api/search.py +486 -0
- disdrodb/{metadata/scripts → cli}/disdrodb_check_metadata_archive.py +12 -7
- disdrodb/{utils/pandas.py → cli/disdrodb_data_archive_directory.py} +9 -18
- disdrodb/cli/disdrodb_download_archive.py +86 -0
- disdrodb/cli/disdrodb_download_metadata_archive.py +53 -0
- disdrodb/cli/disdrodb_download_station.py +84 -0
- disdrodb/{api/scripts → cli}/disdrodb_initialize_station.py +22 -10
- disdrodb/cli/disdrodb_metadata_archive_directory.py +32 -0
- disdrodb/{data_transfer/scripts/disdrodb_download_station.py → cli/disdrodb_open_data_archive.py} +22 -22
- disdrodb/cli/disdrodb_open_logs_directory.py +69 -0
- disdrodb/{data_transfer/scripts/disdrodb_upload_station.py → cli/disdrodb_open_metadata_archive.py} +22 -24
- disdrodb/cli/disdrodb_open_metadata_directory.py +71 -0
- disdrodb/cli/disdrodb_open_product_directory.py +74 -0
- disdrodb/cli/disdrodb_open_readers_directory.py +32 -0
- disdrodb/{l0/scripts → cli}/disdrodb_run_l0.py +38 -31
- disdrodb/{l0/scripts → cli}/disdrodb_run_l0_station.py +32 -30
- disdrodb/{l0/scripts → cli}/disdrodb_run_l0a.py +30 -21
- disdrodb/{l0/scripts → cli}/disdrodb_run_l0a_station.py +24 -33
- disdrodb/{l0/scripts → cli}/disdrodb_run_l0b.py +30 -21
- disdrodb/{l0/scripts → cli}/disdrodb_run_l0b_station.py +25 -34
- disdrodb/cli/disdrodb_run_l0c.py +130 -0
- disdrodb/cli/disdrodb_run_l0c_station.py +129 -0
- disdrodb/cli/disdrodb_run_l1.py +122 -0
- disdrodb/cli/disdrodb_run_l1_station.py +121 -0
- disdrodb/cli/disdrodb_run_l2e.py +122 -0
- disdrodb/cli/disdrodb_run_l2e_station.py +122 -0
- disdrodb/cli/disdrodb_run_l2m.py +122 -0
- disdrodb/cli/disdrodb_run_l2m_station.py +122 -0
- disdrodb/cli/disdrodb_upload_archive.py +105 -0
- disdrodb/cli/disdrodb_upload_station.py +98 -0
- disdrodb/configs.py +90 -25
- disdrodb/data_transfer/__init__.py +22 -0
- disdrodb/data_transfer/download_data.py +87 -90
- disdrodb/data_transfer/upload_data.py +64 -37
- disdrodb/data_transfer/zenodo.py +15 -18
- disdrodb/docs.py +1 -1
- disdrodb/issue/__init__.py +17 -4
- disdrodb/issue/checks.py +10 -23
- disdrodb/issue/reader.py +9 -12
- disdrodb/issue/writer.py +14 -17
- disdrodb/l0/__init__.py +17 -26
- disdrodb/l0/check_configs.py +35 -23
- disdrodb/l0/check_standards.py +32 -42
- disdrodb/l0/configs/{Thies_LPM → LPM}/bins_diameter.yml +44 -44
- disdrodb/l0/configs/{Thies_LPM → LPM}/bins_velocity.yml +40 -40
- disdrodb/l0/configs/LPM/l0a_encodings.yml +80 -0
- disdrodb/l0/configs/{Thies_LPM → LPM}/l0b_cf_attrs.yml +62 -59
- disdrodb/l0/configs/{Thies_LPM → LPM}/l0b_encodings.yml +9 -9
- disdrodb/l0/configs/{Thies_LPM → LPM}/raw_data_format.yml +245 -245
- disdrodb/l0/configs/{OTT_Parsivel → PARSIVEL}/bins_diameter.yml +66 -66
- disdrodb/l0/configs/{OTT_Parsivel → PARSIVEL}/bins_velocity.yml +64 -64
- disdrodb/l0/configs/PARSIVEL/l0a_encodings.yml +32 -0
- disdrodb/l0/configs/{OTT_Parsivel → PARSIVEL}/l0b_cf_attrs.yml +22 -20
- disdrodb/l0/configs/{OTT_Parsivel → PARSIVEL}/l0b_encodings.yml +17 -17
- disdrodb/l0/configs/{OTT_Parsivel → PARSIVEL}/raw_data_format.yml +77 -77
- disdrodb/l0/configs/{OTT_Parsivel2 → PARSIVEL2}/bins_diameter.yml +64 -64
- disdrodb/l0/configs/{OTT_Parsivel2 → PARSIVEL2}/bins_velocity.yml +64 -64
- disdrodb/l0/configs/PARSIVEL2/l0a_encodings.yml +39 -0
- disdrodb/l0/configs/{OTT_Parsivel2 → PARSIVEL2}/l0b_cf_attrs.yml +24 -22
- disdrodb/l0/configs/{OTT_Parsivel2 → PARSIVEL2}/l0b_encodings.yml +20 -20
- disdrodb/l0/configs/{OTT_Parsivel2 → PARSIVEL2}/raw_data_format.yml +98 -98
- disdrodb/l0/configs/{RD_80 → RD80}/bins_diameter.yml +40 -40
- disdrodb/l0/configs/RD80/l0a_encodings.yml +16 -0
- disdrodb/l0/configs/{RD_80 → RD80}/l0b_cf_attrs.yml +3 -3
- disdrodb/l0/configs/RD80/l0b_encodings.yml +135 -0
- disdrodb/l0/configs/{RD_80 → RD80}/raw_data_format.yml +48 -48
- disdrodb/l0/l0_reader.py +216 -340
- disdrodb/l0/l0a_processing.py +237 -208
- disdrodb/l0/l0b_nc_processing.py +227 -80
- disdrodb/l0/l0b_processing.py +93 -173
- disdrodb/l0/l0c_processing.py +627 -0
- disdrodb/l0/readers/{ARM → LPM/ARM}/ARM_LPM.py +36 -58
- disdrodb/l0/readers/LPM/AUSTRALIA/MELBOURNE_2007_LPM.py +226 -0
- disdrodb/l0/readers/LPM/BRAZIL/CHUVA_LPM.py +185 -0
- disdrodb/l0/readers/LPM/BRAZIL/GOAMAZON_LPM.py +183 -0
- disdrodb/l0/readers/LPM/ITALY/GID_LPM.py +179 -0
- disdrodb/l0/readers/{UK → LPM/UK}/DIVEN.py +14 -35
- disdrodb/l0/readers/PARSIVEL/AUSTRALIA/MELBOURNE_2007_PARSIVEL.py +157 -0
- disdrodb/l0/readers/PARSIVEL/CHINA/CHONGQING.py +113 -0
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/ARCTIC_2021.py +40 -57
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/COMMON_2011.py +37 -54
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/DAVOS_2009_2011.py +34 -51
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/EPFL_2009.py +34 -51
- disdrodb/l0/readers/{EPFL/PARADISO_2014.py → PARSIVEL/EPFL/EPFL_ROOF_2008.py} +38 -50
- disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_ROOF_2010.py +105 -0
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/EPFL_ROOF_2011.py +34 -51
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/EPFL_ROOF_2012.py +33 -51
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/GENEPI_2007.py +25 -44
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/GRAND_ST_BERNARD_2007.py +25 -44
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/GRAND_ST_BERNARD_2007_2.py +25 -44
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/HPICONET_2010.py +34 -51
- disdrodb/l0/readers/{EPFL/EPFL_ROOF_2010.py → PARSIVEL/EPFL/HYMEX_LTE_SOP2.py} +37 -50
- disdrodb/l0/readers/PARSIVEL/EPFL/HYMEX_LTE_SOP3.py +111 -0
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/HYMEX_LTE_SOP4.py +36 -54
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/LOCARNO_2018.py +34 -52
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/LOCARNO_2019.py +38 -56
- disdrodb/l0/readers/PARSIVEL/EPFL/PARADISO_2014.py +105 -0
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/PARSIVEL_2007.py +27 -45
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/PLATO_2019.py +24 -44
- disdrodb/l0/readers/PARSIVEL/EPFL/RACLETS_2019.py +140 -0
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/RACLETS_2019_WJF.py +41 -59
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/RIETHOLZBACH_2011.py +34 -51
- disdrodb/l0/readers/PARSIVEL/EPFL/SAMOYLOV_2017.py +117 -0
- disdrodb/l0/readers/PARSIVEL/EPFL/SAMOYLOV_2019.py +137 -0
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/UNIL_2022.py +42 -55
- disdrodb/l0/readers/PARSIVEL/GPM/IFLOODS.py +104 -0
- disdrodb/l0/readers/{GPM → PARSIVEL/GPM}/LPVEX.py +29 -48
- disdrodb/l0/readers/PARSIVEL/GPM/MC3E.py +184 -0
- disdrodb/l0/readers/PARSIVEL/NCAR/CCOPE_2015.py +113 -0
- disdrodb/l0/readers/{NCAR/VORTEX_SE_2016_P1.py → PARSIVEL/NCAR/OWLES_MIPS.py} +46 -72
- disdrodb/l0/readers/PARSIVEL/NCAR/PECAN_MOBILE.py +125 -0
- disdrodb/l0/readers/{NCAR/OWLES_MIPS.py → PARSIVEL/NCAR/PLOWS_MIPS.py} +45 -64
- disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2009.py +114 -0
- disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2010.py +176 -0
- disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2010_UF.py +183 -0
- disdrodb/l0/readers/{ARM/ARM_LD.py → PARSIVEL2/ARM/ARM_PARSIVEL2.py} +27 -50
- disdrodb/l0/readers/PARSIVEL2/BRAZIL/CHUVA_PARSIVEL2.py +163 -0
- disdrodb/l0/readers/PARSIVEL2/BRAZIL/GOAMAZON_PARSIVEL2.py +163 -0
- disdrodb/l0/readers/{DENMARK → PARSIVEL2/DENMARK}/EROSION_nc.py +14 -35
- disdrodb/l0/readers/PARSIVEL2/FRANCE/SIRTA_PARSIVEL2.py +119 -0
- disdrodb/l0/readers/PARSIVEL2/GPM/GCPEX.py +104 -0
- disdrodb/l0/readers/PARSIVEL2/GPM/NSSTC.py +176 -0
- disdrodb/l0/readers/PARSIVEL2/ITALY/GID_PARSIVEL2.py +32 -0
- disdrodb/l0/readers/PARSIVEL2/MEXICO/OH_IIUNAM_nc.py +56 -0
- disdrodb/l0/readers/PARSIVEL2/NCAR/PECAN_FP3.py +120 -0
- disdrodb/l0/readers/{NCAR → PARSIVEL2/NCAR}/PECAN_MIPS.py +45 -64
- disdrodb/l0/readers/PARSIVEL2/NCAR/RELAMPAGO_PARSIVEL2.py +181 -0
- disdrodb/l0/readers/PARSIVEL2/NCAR/SNOWIE_PJ.py +160 -0
- disdrodb/l0/readers/PARSIVEL2/NCAR/SNOWIE_SB.py +160 -0
- disdrodb/l0/readers/{NCAR/PLOWS_MIPS.py → PARSIVEL2/NCAR/VORTEX_SE_2016_P1.py} +49 -66
- disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_P2.py +118 -0
- disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_PIPS.py +152 -0
- disdrodb/l0/readers/PARSIVEL2/NETHERLANDS/DELFT.py +166 -0
- disdrodb/l0/readers/{NCAR/RELAMPAGO_RD80.py → RD80/BRAZIL/CHUVA_RD80.py} +36 -60
- disdrodb/l0/readers/{BRAZIL → RD80/BRAZIL}/GOAMAZON_RD80.py +36 -55
- disdrodb/l0/readers/{NCAR → RD80/NCAR}/CINDY_2011_RD80.py +35 -54
- disdrodb/l0/readers/{BRAZIL/CHUVA_RD80.py → RD80/NCAR/RELAMPAGO_RD80.py} +40 -54
- disdrodb/l0/readers/template_reader_raw_netcdf_data.py +62 -0
- disdrodb/l0/readers/{reader_template.py → template_reader_raw_text_data.py} +20 -44
- disdrodb/l0/routines.py +885 -581
- disdrodb/l0/standards.py +72 -236
- disdrodb/l0/template_tools.py +104 -109
- disdrodb/l1/__init__.py +17 -0
- disdrodb/l1/beard_model.py +716 -0
- disdrodb/l1/encoding_attrs.py +620 -0
- disdrodb/l1/fall_velocity.py +260 -0
- disdrodb/l1/filters.py +192 -0
- disdrodb/l1/processing.py +200 -0
- disdrodb/l1/resampling.py +236 -0
- disdrodb/l1/routines.py +357 -0
- disdrodb/l1_env/__init__.py +17 -0
- disdrodb/l1_env/routines.py +38 -0
- disdrodb/l2/__init__.py +17 -0
- disdrodb/l2/empirical_dsd.py +1735 -0
- disdrodb/l2/event.py +388 -0
- disdrodb/l2/processing.py +519 -0
- disdrodb/l2/processing_options.py +213 -0
- disdrodb/l2/routines.py +868 -0
- disdrodb/metadata/__init__.py +9 -2
- disdrodb/metadata/checks.py +165 -118
- disdrodb/metadata/download.py +81 -0
- disdrodb/metadata/geolocation.py +146 -0
- disdrodb/metadata/info.py +20 -13
- disdrodb/metadata/manipulation.py +1 -1
- disdrodb/metadata/reader.py +59 -8
- disdrodb/metadata/search.py +77 -144
- disdrodb/metadata/standards.py +7 -8
- disdrodb/metadata/writer.py +8 -14
- disdrodb/psd/__init__.py +38 -0
- disdrodb/psd/fitting.py +2146 -0
- disdrodb/psd/models.py +774 -0
- disdrodb/routines.py +1176 -0
- disdrodb/scattering/__init__.py +28 -0
- disdrodb/scattering/axis_ratio.py +344 -0
- disdrodb/scattering/routines.py +456 -0
- disdrodb/utils/__init__.py +17 -0
- disdrodb/utils/attrs.py +208 -0
- disdrodb/utils/cli.py +269 -0
- disdrodb/utils/compression.py +60 -42
- disdrodb/utils/dask.py +62 -0
- disdrodb/utils/decorators.py +110 -0
- disdrodb/utils/directories.py +107 -46
- disdrodb/utils/encoding.py +127 -0
- disdrodb/utils/list.py +29 -0
- disdrodb/utils/logger.py +168 -46
- disdrodb/utils/time.py +657 -0
- disdrodb/utils/warnings.py +30 -0
- disdrodb/utils/writer.py +57 -0
- disdrodb/utils/xarray.py +138 -47
- disdrodb/utils/yaml.py +0 -1
- disdrodb/viz/__init__.py +17 -0
- disdrodb/viz/plots.py +17 -0
- disdrodb-0.1.0.dist-info/METADATA +321 -0
- disdrodb-0.1.0.dist-info/RECORD +216 -0
- {disdrodb-0.0.21.dist-info → disdrodb-0.1.0.dist-info}/WHEEL +1 -1
- disdrodb-0.1.0.dist-info/entry_points.txt +30 -0
- disdrodb/data_transfer/scripts/disdrodb_download_archive.py +0 -53
- disdrodb/data_transfer/scripts/disdrodb_upload_archive.py +0 -57
- disdrodb/l0/configs/OTT_Parsivel/l0a_encodings.yml +0 -32
- disdrodb/l0/configs/OTT_Parsivel2/l0a_encodings.yml +0 -39
- disdrodb/l0/configs/RD_80/l0a_encodings.yml +0 -16
- disdrodb/l0/configs/RD_80/l0b_encodings.yml +0 -135
- disdrodb/l0/configs/Thies_LPM/l0a_encodings.yml +0 -80
- disdrodb/l0/io.py +0 -257
- disdrodb/l0/l0_processing.py +0 -1091
- disdrodb/l0/readers/AUSTRALIA/MELBOURNE_2007_OTT.py +0 -178
- disdrodb/l0/readers/AUSTRALIA/MELBOURNE_2007_THIES.py +0 -247
- disdrodb/l0/readers/BRAZIL/CHUVA_LPM.py +0 -204
- disdrodb/l0/readers/BRAZIL/CHUVA_OTT.py +0 -183
- disdrodb/l0/readers/BRAZIL/GOAMAZON_LPM.py +0 -204
- disdrodb/l0/readers/BRAZIL/GOAMAZON_OTT.py +0 -183
- disdrodb/l0/readers/CHINA/CHONGQING.py +0 -131
- disdrodb/l0/readers/EPFL/EPFL_ROOF_2008.py +0 -128
- disdrodb/l0/readers/EPFL/HYMEX_LTE_SOP2.py +0 -127
- disdrodb/l0/readers/EPFL/HYMEX_LTE_SOP3.py +0 -129
- disdrodb/l0/readers/EPFL/RACLETS_2019.py +0 -158
- disdrodb/l0/readers/EPFL/SAMOYLOV_2017.py +0 -136
- disdrodb/l0/readers/EPFL/SAMOYLOV_2019.py +0 -158
- disdrodb/l0/readers/FRANCE/SIRTA_OTT2.py +0 -138
- disdrodb/l0/readers/GPM/GCPEX.py +0 -123
- disdrodb/l0/readers/GPM/IFLOODS.py +0 -123
- disdrodb/l0/readers/GPM/MC3E.py +0 -123
- disdrodb/l0/readers/GPM/NSSTC.py +0 -164
- disdrodb/l0/readers/ITALY/GID.py +0 -199
- disdrodb/l0/readers/MEXICO/OH_IIUNAM_nc.py +0 -92
- disdrodb/l0/readers/NCAR/CCOPE_2015.py +0 -133
- disdrodb/l0/readers/NCAR/PECAN_FP3.py +0 -137
- disdrodb/l0/readers/NCAR/PECAN_MOBILE.py +0 -144
- disdrodb/l0/readers/NCAR/RELAMPAGO_OTT.py +0 -195
- disdrodb/l0/readers/NCAR/SNOWIE_PJ.py +0 -172
- disdrodb/l0/readers/NCAR/SNOWIE_SB.py +0 -179
- disdrodb/l0/readers/NCAR/VORTEX2_2009.py +0 -133
- disdrodb/l0/readers/NCAR/VORTEX2_2010.py +0 -188
- disdrodb/l0/readers/NCAR/VORTEX2_2010_UF.py +0 -191
- disdrodb/l0/readers/NCAR/VORTEX_SE_2016_P2.py +0 -135
- disdrodb/l0/readers/NCAR/VORTEX_SE_2016_PIPS.py +0 -170
- disdrodb/l0/readers/NETHERLANDS/DELFT.py +0 -187
- disdrodb/l0/readers/SPAIN/SBEGUERIA.py +0 -179
- disdrodb/l0/scripts/disdrodb_run_l0b_concat.py +0 -93
- disdrodb/l0/scripts/disdrodb_run_l0b_concat_station.py +0 -85
- disdrodb/utils/netcdf.py +0 -452
- disdrodb/utils/scripts.py +0 -102
- disdrodb-0.0.21.dist-info/AUTHORS.md +0 -18
- disdrodb-0.0.21.dist-info/METADATA +0 -186
- disdrodb-0.0.21.dist-info/RECORD +0 -168
- disdrodb-0.0.21.dist-info/entry_points.txt +0 -15
- /disdrodb/l0/configs/{RD_80 → RD80}/bins_velocity.yml +0 -0
- /disdrodb/l0/manuals/{Thies_LPM.pdf → LPM.pdf} +0 -0
- /disdrodb/l0/manuals/{ODM_470.pdf → ODM470.pdf} +0 -0
- /disdrodb/l0/manuals/{OTT_Parsivel.pdf → PARSIVEL.pdf} +0 -0
- /disdrodb/l0/manuals/{OTT_Parsivel2.pdf → PARSIVEL2.pdf} +0 -0
- /disdrodb/l0/manuals/{PWS_100.pdf → PWS100.pdf} +0 -0
- /disdrodb/l0/manuals/{RD_80.pdf → RD80.pdf} +0 -0
- {disdrodb-0.0.21.dist-info → disdrodb-0.1.0.dist-info/licenses}/LICENSE +0 -0
- {disdrodb-0.0.21.dist-info → disdrodb-0.1.0.dist-info}/top_level.txt +0 -0
disdrodb/l0/__init__.py
CHANGED
|
@@ -1,26 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"available_readers",
|
|
19
|
-
# Functions invoking the disdrodb_run_* scripts in the terminal
|
|
20
|
-
"run_disdrodb_l0a_station",
|
|
21
|
-
"run_disdrodb_l0b_station",
|
|
22
|
-
"run_disdrodb_l0_station",
|
|
23
|
-
"run_disdrodb_l0",
|
|
24
|
-
"run_disdrodb_l0a",
|
|
25
|
-
"run_disdrodb_l0b",
|
|
26
|
-
]
|
|
1
|
+
# -----------------------------------------------------------------------------.
|
|
2
|
+
# Copyright (c) 2021-2023 DISDRODB developers
|
|
3
|
+
#
|
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
|
+
# -----------------------------------------------------------------------------.
|
|
17
|
+
"""DISDRODB L0 software."""
|
disdrodb/l0/check_configs.py
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"""Check configuration files."""
|
|
20
20
|
|
|
21
21
|
import os
|
|
22
|
-
from typing import
|
|
22
|
+
from typing import Optional, Union
|
|
23
23
|
|
|
24
24
|
import numpy as np
|
|
25
25
|
from pydantic import BaseModel, ValidationError, field_validator, model_validator
|
|
@@ -105,7 +105,7 @@ def _check_variable_consistency(sensor_name: str) -> None:
|
|
|
105
105
|
|
|
106
106
|
|
|
107
107
|
class SchemaValidationException(Exception):
|
|
108
|
-
"""Exception raised when schema validation fails"""
|
|
108
|
+
"""Exception raised when schema validation fails."""
|
|
109
109
|
|
|
110
110
|
|
|
111
111
|
def _schema_error(object_to_validate: Union[str, list], schema: BaseModel, message) -> bool:
|
|
@@ -114,12 +114,11 @@ def _schema_error(object_to_validate: Union[str, list], schema: BaseModel, messa
|
|
|
114
114
|
Parameters
|
|
115
115
|
----------
|
|
116
116
|
object_to_validate : Union[str,list]
|
|
117
|
-
Object to validate
|
|
117
|
+
Object to validate.
|
|
118
118
|
schema : BaseModel
|
|
119
|
-
Base model
|
|
119
|
+
Base model.
|
|
120
120
|
|
|
121
121
|
"""
|
|
122
|
-
|
|
123
122
|
try:
|
|
124
123
|
schema(**object_to_validate)
|
|
125
124
|
except ValidationError as e:
|
|
@@ -127,6 +126,8 @@ def _schema_error(object_to_validate: Union[str, list], schema: BaseModel, messa
|
|
|
127
126
|
|
|
128
127
|
|
|
129
128
|
class L0BEncodingSchema(BaseModel):
|
|
129
|
+
"""Pydantic model for DISDRODB L0B encodings."""
|
|
130
|
+
|
|
130
131
|
contiguous: bool
|
|
131
132
|
dtype: str
|
|
132
133
|
zlib: bool
|
|
@@ -134,11 +135,12 @@ class L0BEncodingSchema(BaseModel):
|
|
|
134
135
|
shuffle: bool
|
|
135
136
|
fletcher32: bool
|
|
136
137
|
_FillValue: Optional[Union[int, float]]
|
|
137
|
-
chunksizes: Optional[Union[int,
|
|
138
|
+
chunksizes: Optional[Union[int, list[int]]]
|
|
138
139
|
|
|
139
140
|
# if contiguous=False, chunksizes specified, otherwise should be not !
|
|
140
141
|
@model_validator(mode="before")
|
|
141
142
|
def check_chunksizes_and_zlib(cls, values):
|
|
143
|
+
"""Check the chunksizes validity."""
|
|
142
144
|
contiguous = values.get("contiguous")
|
|
143
145
|
chunksizes = values.get("chunksizes")
|
|
144
146
|
if not contiguous and not chunksizes:
|
|
@@ -148,6 +150,7 @@ class L0BEncodingSchema(BaseModel):
|
|
|
148
150
|
# if contiguous = True, then zlib must be set to False
|
|
149
151
|
@model_validator(mode="before")
|
|
150
152
|
def check_contiguous_and_zlib(cls, values):
|
|
153
|
+
"""Check the the compression value validity."""
|
|
151
154
|
contiguous = values.get("contiguous")
|
|
152
155
|
zlib = values.get("zlib")
|
|
153
156
|
if contiguous and zlib:
|
|
@@ -157,6 +160,7 @@ class L0BEncodingSchema(BaseModel):
|
|
|
157
160
|
# if contiguous = True, then fletcher32 must be set to False
|
|
158
161
|
@model_validator(mode="before")
|
|
159
162
|
def check_contiguous_and_fletcher32(cls, values):
|
|
163
|
+
"""Check the fletcher value validity."""
|
|
160
164
|
contiguous = values.get("contiguous")
|
|
161
165
|
fletcher32 = values.get("fletcher32")
|
|
162
166
|
if contiguous and fletcher32:
|
|
@@ -165,14 +169,13 @@ class L0BEncodingSchema(BaseModel):
|
|
|
165
169
|
|
|
166
170
|
|
|
167
171
|
def check_l0b_encoding(sensor_name: str) -> None:
|
|
168
|
-
"""Check l0b_encodings.yml file based on the schema defined in the class L0BEncodingSchema
|
|
172
|
+
"""Check ``l0b_encodings.yml`` file based on the schema defined in the class ``L0BEncodingSchema``.
|
|
169
173
|
|
|
170
174
|
Parameters
|
|
171
175
|
----------
|
|
172
176
|
sensor_name : str
|
|
173
177
|
Name of the sensor.
|
|
174
178
|
"""
|
|
175
|
-
|
|
176
179
|
data = read_config_file(sensor_name, product="L0A", filename="l0b_encodings.yml")
|
|
177
180
|
|
|
178
181
|
# check that the second level of the dictionary match the schema
|
|
@@ -185,7 +188,7 @@ def check_l0b_encoding(sensor_name: str) -> None:
|
|
|
185
188
|
|
|
186
189
|
|
|
187
190
|
def check_l0a_encoding(sensor_name: str) -> None:
|
|
188
|
-
"""Check l0a_encodings.yml file.
|
|
191
|
+
"""Check ``l0a_encodings.yml`` file.
|
|
189
192
|
|
|
190
193
|
Parameters
|
|
191
194
|
----------
|
|
@@ -208,27 +211,31 @@ def check_l0a_encoding(sensor_name: str) -> None:
|
|
|
208
211
|
|
|
209
212
|
|
|
210
213
|
class RawDataFormatSchema(BaseModel):
|
|
214
|
+
"""Pydantic model for the DISDRODB RAW Data Format YAML files."""
|
|
215
|
+
|
|
211
216
|
n_digits: Optional[int]
|
|
212
217
|
n_characters: Optional[int]
|
|
213
218
|
n_decimals: Optional[int]
|
|
214
219
|
n_naturals: Optional[int]
|
|
215
|
-
data_range: Optional[
|
|
220
|
+
data_range: Optional[list[float]]
|
|
216
221
|
nan_flags: Optional[Union[int, str]] = None
|
|
217
|
-
valid_values: Optional[
|
|
218
|
-
dimension_order: Optional[
|
|
222
|
+
valid_values: Optional[list[float]] = None
|
|
223
|
+
dimension_order: Optional[list[str]] = None
|
|
219
224
|
n_values: Optional[int] = None
|
|
220
225
|
field_number: Optional[str] = None
|
|
221
226
|
|
|
222
227
|
@field_validator("data_range")
|
|
223
228
|
def check_list_length(cls, value):
|
|
229
|
+
"""Check the data_range validity."""
|
|
224
230
|
if value:
|
|
225
231
|
if len(value) != 2:
|
|
226
232
|
raise ValueError(f"data_range must have exactly 2 keys, {len(value)} element have been provided.")
|
|
227
233
|
return value
|
|
234
|
+
return None
|
|
228
235
|
|
|
229
236
|
|
|
230
237
|
def _check_raw_data_format(sensor_name: str) -> None:
|
|
231
|
-
"""
|
|
238
|
+
"""Check ``raw_data_format.yml`` file based on the schema defined in the class ``RawDataFormatSchema``.
|
|
232
239
|
|
|
233
240
|
Parameters
|
|
234
241
|
----------
|
|
@@ -247,7 +254,7 @@ def _check_raw_data_format(sensor_name: str) -> None:
|
|
|
247
254
|
|
|
248
255
|
|
|
249
256
|
def _check_cf_attributes(sensor_name: str) -> None:
|
|
250
|
-
"""Check that the l0b_cf_attrs.yml description, long_name and units values are strings.
|
|
257
|
+
"""Check that the ``l0b_cf_attrs.yml`` description, long_name and units values are strings.
|
|
251
258
|
|
|
252
259
|
Parameters
|
|
253
260
|
----------
|
|
@@ -271,7 +278,6 @@ def _check_bin_consistency(sensor_name: str) -> None:
|
|
|
271
278
|
sensor_name : str
|
|
272
279
|
Name of the sensor.
|
|
273
280
|
"""
|
|
274
|
-
|
|
275
281
|
diameter_bin_lower = np.array(get_diameter_bin_lower(sensor_name))
|
|
276
282
|
diameter_bin_upper = np.array(get_diameter_bin_upper(sensor_name))
|
|
277
283
|
diameter_bin_center = np.array(get_diameter_bin_center(sensor_name))
|
|
@@ -294,10 +300,16 @@ def _check_bin_consistency(sensor_name: str) -> None:
|
|
|
294
300
|
if all(arr.size > 1 for arr in [velocity_bin_center, velocity_bin_lower, velocity_bin_upper, velocity_bin_width]):
|
|
295
301
|
np.testing.assert_allclose(velocity_bin_upper - velocity_bin_lower, velocity_bin_width, atol=1e-3, rtol=1e-4)
|
|
296
302
|
np.testing.assert_allclose(
|
|
297
|
-
velocity_bin_lower + velocity_bin_width / 2,
|
|
303
|
+
velocity_bin_lower + velocity_bin_width / 2,
|
|
304
|
+
velocity_bin_center,
|
|
305
|
+
atol=1e-3,
|
|
306
|
+
rtol=1e-4,
|
|
298
307
|
)
|
|
299
308
|
np.testing.assert_allclose(
|
|
300
|
-
velocity_bin_upper - velocity_bin_width / 2,
|
|
309
|
+
velocity_bin_upper - velocity_bin_width / 2,
|
|
310
|
+
velocity_bin_center,
|
|
311
|
+
atol=1e-3,
|
|
312
|
+
rtol=1e-4,
|
|
301
313
|
)
|
|
302
314
|
|
|
303
315
|
|
|
@@ -318,7 +330,7 @@ def _check_raw_array(sensor_name: str) -> None:
|
|
|
318
330
|
|
|
319
331
|
# Get keys in raw_data_format where the value is "dimension_order"
|
|
320
332
|
dict_keys_with_dimension_order = {
|
|
321
|
-
key: value.get("dimension_order") for key, value in raw_data_format.items() if "dimension_order" in value
|
|
333
|
+
key: value.get("dimension_order") for key, value in raw_data_format.items() if "dimension_order" in value
|
|
322
334
|
}
|
|
323
335
|
|
|
324
336
|
l0b_encodings = read_config_file(sensor_name, product="L0A", filename="l0b_encodings.yml")
|
|
@@ -332,11 +344,11 @@ def _check_raw_array(sensor_name: str) -> None:
|
|
|
332
344
|
# Get chunksizes in l0b_encoding.yml and check that if len > 1, has dimension_order key in raw_data_format
|
|
333
345
|
list_attributes_l0b_encodings = [
|
|
334
346
|
i
|
|
335
|
-
for i in l0b_encodings
|
|
347
|
+
for i in l0b_encodings
|
|
336
348
|
if isinstance(l0b_encodings.get(i).get("chunksizes"), list) and len(l0b_encodings.get(i).get("chunksizes")) > 1
|
|
337
349
|
]
|
|
338
350
|
list_attributes_from_raw_data_format = [
|
|
339
|
-
i for i in raw_data_format
|
|
351
|
+
i for i in raw_data_format if raw_data_format.get(i).get("dimension_order") is not None
|
|
340
352
|
]
|
|
341
353
|
|
|
342
354
|
if not sorted(list_attributes_l0b_encodings) == sorted(list_attributes_from_raw_data_format):
|
|
@@ -344,7 +356,7 @@ def _check_raw_array(sensor_name: str) -> None:
|
|
|
344
356
|
|
|
345
357
|
|
|
346
358
|
def check_sensor_configs(sensor_name: str) -> None:
|
|
347
|
-
"""
|
|
359
|
+
"""Check validity of sensor configuration YAML files.
|
|
348
360
|
|
|
349
361
|
Parameters
|
|
350
362
|
----------
|
|
@@ -362,6 +374,6 @@ def check_sensor_configs(sensor_name: str) -> None:
|
|
|
362
374
|
|
|
363
375
|
|
|
364
376
|
def check_all_sensors_configs() -> None:
|
|
365
|
-
"""Check all sensors
|
|
366
|
-
for sensor_name in available_sensor_names(
|
|
377
|
+
"""Check all sensors configuration YAML files."""
|
|
378
|
+
for sensor_name in available_sensor_names():
|
|
367
379
|
check_sensor_configs(sensor_name=sensor_name)
|
disdrodb/l0/check_standards.py
CHANGED
|
@@ -25,24 +25,21 @@ import numpy as np
|
|
|
25
25
|
import pandas as pd
|
|
26
26
|
|
|
27
27
|
from disdrodb.l0.standards import (
|
|
28
|
+
allowed_l0_variables,
|
|
28
29
|
get_data_range_dict,
|
|
29
|
-
get_l0a_dtype,
|
|
30
30
|
get_valid_values_dict,
|
|
31
31
|
)
|
|
32
32
|
|
|
33
33
|
# Logger
|
|
34
|
-
from disdrodb.utils.logger import
|
|
35
|
-
log_error,
|
|
36
|
-
log_info,
|
|
37
|
-
)
|
|
34
|
+
from disdrodb.utils.logger import log_info
|
|
38
35
|
|
|
39
36
|
logger = logging.getLogger(__name__)
|
|
40
37
|
|
|
41
38
|
|
|
42
|
-
def _check_valid_range(df, dict_data_range
|
|
39
|
+
def _check_valid_range(df, dict_data_range):
|
|
43
40
|
"""Check valid value range of dataframe columns.
|
|
44
41
|
|
|
45
|
-
It assumes the dict_data_range values are list [min_val, max_val]
|
|
42
|
+
It assumes the ``dict_data_range`` values are list ``[min_val, max_val]``.
|
|
46
43
|
"""
|
|
47
44
|
list_wrong_columns = []
|
|
48
45
|
for column in df.columns:
|
|
@@ -56,14 +53,13 @@ def _check_valid_range(df, dict_data_range, verbose=False):
|
|
|
56
53
|
|
|
57
54
|
if len(list_wrong_columns) > 0:
|
|
58
55
|
msg = f"Columns {list_wrong_columns} has values outside the expected data range."
|
|
59
|
-
log_error(logger=logger, msg=msg, verbose=False)
|
|
60
56
|
raise ValueError(msg)
|
|
61
57
|
|
|
62
58
|
|
|
63
|
-
def _check_valid_values(df, dict_valid_values
|
|
59
|
+
def _check_valid_values(df, dict_valid_values):
|
|
64
60
|
"""Check valid values of dataframe columns.
|
|
65
61
|
|
|
66
|
-
It assumes the dict_valid_values values are
|
|
62
|
+
It assumes the ``dict_valid_values`` values are lists.
|
|
67
63
|
"""
|
|
68
64
|
list_msg = []
|
|
69
65
|
list_wrong_columns = []
|
|
@@ -81,16 +77,15 @@ def _check_valid_values(df, dict_valid_values, verbose=False):
|
|
|
81
77
|
|
|
82
78
|
if len(list_wrong_columns) > 0:
|
|
83
79
|
msg = "\n".join(list_msg)
|
|
84
|
-
log_error(logger=logger, msg=msg, verbose=False)
|
|
85
80
|
raise ValueError(f"Columns {list_wrong_columns} have invalid values.")
|
|
86
81
|
|
|
87
82
|
|
|
88
|
-
def _check_raw_fields_available(df: pd.DataFrame, sensor_name: str, verbose: bool = False) -> None:
|
|
83
|
+
def _check_raw_fields_available(df: pd.DataFrame, sensor_name: str, logger=None, verbose: bool = False) -> None:
|
|
89
84
|
"""Check the presence of the raw spectrum data according to the type of sensor.
|
|
90
85
|
|
|
91
86
|
Parameters
|
|
92
87
|
----------
|
|
93
|
-
df :
|
|
88
|
+
df : pandas.DataFrame
|
|
94
89
|
Dataframe
|
|
95
90
|
sensor_name : str
|
|
96
91
|
Name of the sensor.
|
|
@@ -98,7 +93,7 @@ def _check_raw_fields_available(df: pd.DataFrame, sensor_name: str, verbose: boo
|
|
|
98
93
|
Raises
|
|
99
94
|
------
|
|
100
95
|
ValueError
|
|
101
|
-
Error if the raw_drop_number field is missing.
|
|
96
|
+
Error if the ``raw_drop_number`` field is missing.
|
|
102
97
|
"""
|
|
103
98
|
from disdrodb.l0.standards import get_raw_array_nvalues
|
|
104
99
|
|
|
@@ -109,7 +104,6 @@ def _check_raw_fields_available(df: pd.DataFrame, sensor_name: str, verbose: boo
|
|
|
109
104
|
# Check that raw_drop_number is present
|
|
110
105
|
if "raw_drop_number" not in df.columns:
|
|
111
106
|
msg = "The 'raw_drop_number' column is not present in the dataframe."
|
|
112
|
-
log_error(logger=logger, msg=msg, verbose=False)
|
|
113
107
|
raise ValueError(msg)
|
|
114
108
|
|
|
115
109
|
# Report additional raw arrays that are missing
|
|
@@ -117,7 +111,6 @@ def _check_raw_fields_available(df: pd.DataFrame, sensor_name: str, verbose: boo
|
|
|
117
111
|
if len(missing_vars) > 0:
|
|
118
112
|
msg = f"The following raw array variable are missing: {missing_vars}"
|
|
119
113
|
log_info(logger=logger, msg=msg, verbose=verbose)
|
|
120
|
-
return None
|
|
121
114
|
|
|
122
115
|
|
|
123
116
|
def check_l0a_column_names(df: pd.DataFrame, sensor_name: str) -> None:
|
|
@@ -125,7 +118,7 @@ def check_l0a_column_names(df: pd.DataFrame, sensor_name: str) -> None:
|
|
|
125
118
|
|
|
126
119
|
Parameters
|
|
127
120
|
----------
|
|
128
|
-
df :
|
|
121
|
+
df : pandas.DataFrame
|
|
129
122
|
Input dataframe.
|
|
130
123
|
sensor_name : str
|
|
131
124
|
Name of the sensor.
|
|
@@ -133,47 +126,42 @@ def check_l0a_column_names(df: pd.DataFrame, sensor_name: str) -> None:
|
|
|
133
126
|
Raises
|
|
134
127
|
------
|
|
135
128
|
ValueError
|
|
136
|
-
Error if some columns do not meet the DISDRODB standards or if the 'time'
|
|
129
|
+
Error if some columns do not meet the DISDRODB standards or if the ``'time'``
|
|
130
|
+
column is missing in the dataframe.
|
|
137
131
|
|
|
138
132
|
"""
|
|
139
|
-
|
|
140
133
|
# Get valid columns
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
valid_columns = valid_columns + ["time", "latitude", "longitude"]
|
|
144
|
-
valid_columns = set(valid_columns)
|
|
134
|
+
valid_columns = set(allowed_l0_variables(sensor_name))
|
|
135
|
+
|
|
145
136
|
# Get dataframe column names
|
|
146
|
-
df_columns =
|
|
147
|
-
|
|
148
|
-
#
|
|
149
|
-
|
|
150
|
-
|
|
137
|
+
df_columns = set(df.columns)
|
|
138
|
+
|
|
139
|
+
# Find any columns in df that aren't in the valid list
|
|
140
|
+
invalid_columns = df_columns - valid_columns
|
|
141
|
+
|
|
142
|
+
# Raise error in case
|
|
151
143
|
if len(invalid_columns) > 0:
|
|
152
144
|
msg = f"The following columns do no met the DISDRODB standards: {invalid_columns}"
|
|
153
|
-
logger.error(msg)
|
|
154
145
|
raise ValueError(msg)
|
|
155
|
-
|
|
146
|
+
|
|
156
147
|
# Check time column is present
|
|
157
148
|
if "time" not in df_columns:
|
|
158
149
|
msg = "The 'time' column is missing in the dataframe."
|
|
159
|
-
log_error(logger=logger, msg=msg, verbose=False)
|
|
160
150
|
raise ValueError(msg)
|
|
161
|
-
# --------------------------------------------
|
|
162
|
-
return None
|
|
163
151
|
|
|
164
152
|
|
|
165
|
-
def check_l0a_standards(df: pd.DataFrame, sensor_name: str, verbose: bool = True) -> None:
|
|
153
|
+
def check_l0a_standards(df: pd.DataFrame, sensor_name: str, logger=None, verbose: bool = True) -> None:
|
|
166
154
|
"""Checks that a file respects the DISDRODB L0A standards.
|
|
167
155
|
|
|
168
156
|
Parameters
|
|
169
157
|
----------
|
|
170
|
-
df :
|
|
158
|
+
df : pandas.DataFrame
|
|
171
159
|
L0A dataframe.
|
|
172
160
|
sensor_name : str
|
|
173
161
|
Name of the sensor.
|
|
174
162
|
verbose : bool, optional
|
|
175
163
|
Whether to verbose the processing.
|
|
176
|
-
The default is True
|
|
164
|
+
The default value is ``True``.
|
|
177
165
|
|
|
178
166
|
Raises
|
|
179
167
|
------
|
|
@@ -184,23 +172,24 @@ def check_l0a_standards(df: pd.DataFrame, sensor_name: str, verbose: bool = True
|
|
|
184
172
|
# -------------------------------------
|
|
185
173
|
# Check data range
|
|
186
174
|
dict_data_range = get_data_range_dict(sensor_name)
|
|
187
|
-
_check_valid_range(df=df, dict_data_range=dict_data_range
|
|
175
|
+
_check_valid_range(df=df, dict_data_range=dict_data_range)
|
|
188
176
|
|
|
189
177
|
# -------------------------------------
|
|
190
178
|
# Check categorical data values
|
|
191
179
|
dict_valid_values = get_valid_values_dict(sensor_name)
|
|
192
|
-
_check_valid_values(df=df, dict_valid_values=dict_valid_values
|
|
180
|
+
_check_valid_values(df=df, dict_valid_values=dict_valid_values)
|
|
193
181
|
|
|
194
182
|
# -------------------------------------
|
|
195
183
|
# Check if raw spectrum and 1D derivate exists
|
|
196
|
-
_check_raw_fields_available(df=df, sensor_name=sensor_name, verbose=verbose)
|
|
184
|
+
_check_raw_fields_available(df=df, sensor_name=sensor_name, logger=logger, verbose=verbose)
|
|
197
185
|
|
|
198
186
|
# -------------------------------------
|
|
199
187
|
# Check if latitude and longitude are columns of the dataframe
|
|
200
188
|
# - They should be only provided if the instrument is moving !!!!
|
|
189
|
+
# - TODO: this should be removed and raise error if not platform_type: mobile
|
|
201
190
|
if "latitude" in df.columns:
|
|
202
191
|
msg = (
|
|
203
|
-
"
|
|
192
|
+
"The L0A dataframe has column 'latitude'. "
|
|
204
193
|
+ "This should be included only if the sensor is moving. "
|
|
205
194
|
+ "Otherwise, specify the 'latitude' in the metadata !"
|
|
206
195
|
)
|
|
@@ -208,7 +197,7 @@ def check_l0a_standards(df: pd.DataFrame, sensor_name: str, verbose: bool = True
|
|
|
208
197
|
|
|
209
198
|
if "longitude" in df.columns:
|
|
210
199
|
msg = (
|
|
211
|
-
"
|
|
200
|
+
"The L0A dataframe has column 'longitude'. "
|
|
212
201
|
+ "This should be included only if the sensor is moving. "
|
|
213
202
|
+ "Otherwise, specify the 'longitude' in the metadata !"
|
|
214
203
|
)
|
|
@@ -218,6 +207,7 @@ def check_l0a_standards(df: pd.DataFrame, sensor_name: str, verbose: bool = True
|
|
|
218
207
|
|
|
219
208
|
|
|
220
209
|
def check_l0b_standards(x: str) -> None:
|
|
221
|
-
|
|
210
|
+
"""Check L0B standards."""
|
|
222
211
|
# - Check for realistic values after having removed the flags !!!!
|
|
212
|
+
x = "noqa" # noqa: F841
|
|
223
213
|
pass
|
|
@@ -23,71 +23,71 @@ center:
|
|
|
23
23
|
21: 54
|
|
24
24
|
bounds:
|
|
25
25
|
0:
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
- 0.125
|
|
27
|
+
- 0.25
|
|
28
28
|
1:
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
- 0.25
|
|
30
|
+
- 0.375
|
|
31
31
|
2:
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
- 0.375
|
|
33
|
+
- 0.5
|
|
34
34
|
3:
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
- 0.5
|
|
36
|
+
- 0.75
|
|
37
37
|
4:
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
- 0.75
|
|
39
|
+
- 1.0
|
|
40
40
|
5:
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
- 1.0
|
|
42
|
+
- 1.25
|
|
43
43
|
6:
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
- 1.25
|
|
45
|
+
- 1.5
|
|
46
46
|
7:
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
- 1.5
|
|
48
|
+
- 1.75
|
|
49
49
|
8:
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
- 1.75
|
|
51
|
+
- 2.0
|
|
52
52
|
9:
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
- 2.0
|
|
54
|
+
- 2.5
|
|
55
55
|
10:
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
- 2.5
|
|
57
|
+
- 3.0
|
|
58
58
|
11:
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
- 3.0
|
|
60
|
+
- 3.5
|
|
61
61
|
12:
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
- 3.5
|
|
63
|
+
- 4.0
|
|
64
64
|
13:
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
- 4.0
|
|
66
|
+
- 4.5
|
|
67
67
|
14:
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
- 4.5
|
|
69
|
+
- 5.0
|
|
70
70
|
15:
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
- 5.0
|
|
72
|
+
- 5.5
|
|
73
73
|
16:
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
- 5.5
|
|
75
|
+
- 6.0
|
|
76
76
|
17:
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
- 6.0
|
|
78
|
+
- 6.5
|
|
79
79
|
18:
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
- 6.5
|
|
81
|
+
- 7.0
|
|
82
82
|
19:
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
- 7.0
|
|
84
|
+
- 7.5
|
|
85
85
|
20:
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
- 7.5
|
|
87
|
+
- 8.0
|
|
88
88
|
21:
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
- 8.0
|
|
90
|
+
- 100
|
|
91
91
|
width:
|
|
92
92
|
0: 0.125
|
|
93
93
|
1: 0.125
|
|
@@ -21,65 +21,65 @@ center:
|
|
|
21
21
|
19: 15.0
|
|
22
22
|
bounds:
|
|
23
23
|
0:
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
- 0.0
|
|
25
|
+
- 0.2
|
|
26
26
|
1:
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
- 0.2
|
|
28
|
+
- 0.4
|
|
29
29
|
2:
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
- 0.4
|
|
31
|
+
- 0.6
|
|
32
32
|
3:
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
- 0.6
|
|
34
|
+
- 0.8
|
|
35
35
|
4:
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
- 0.8
|
|
37
|
+
- 1.0
|
|
38
38
|
5:
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
- 1.0
|
|
40
|
+
- 1.4
|
|
41
41
|
6:
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
- 1.4
|
|
43
|
+
- 1.8
|
|
44
44
|
7:
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
- 1.8
|
|
46
|
+
- 2.2
|
|
47
47
|
8:
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
- 2.2
|
|
49
|
+
- 2.6
|
|
50
50
|
9:
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
- 2.6
|
|
52
|
+
- 3.0
|
|
53
53
|
10:
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
- 3.0
|
|
55
|
+
- 3.4
|
|
56
56
|
11:
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
- 3.4
|
|
58
|
+
- 4.2
|
|
59
59
|
12:
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
- 4.2
|
|
61
|
+
- 5.0
|
|
62
62
|
13:
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
- 5.0
|
|
64
|
+
- 5.8
|
|
65
65
|
14:
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
- 5.8
|
|
67
|
+
- 6.6
|
|
68
68
|
15:
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
- 6.6
|
|
70
|
+
- 7.4
|
|
71
71
|
16:
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
- 7.4
|
|
73
|
+
- 8.2
|
|
74
74
|
17:
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
- 8.2
|
|
76
|
+
- 9.0
|
|
77
77
|
18:
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
- 9.0
|
|
79
|
+
- 10.0
|
|
80
80
|
19:
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
- 10.0
|
|
82
|
+
- 20.0
|
|
83
83
|
width:
|
|
84
84
|
0: 0.2
|
|
85
85
|
1: 0.2
|