wxdata 2.0.3__tar.gz → 2.0.4__tar.gz

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.
Files changed (94) hide show
  1. {wxdata-2.0.3/src/wxdata.egg-info → wxdata-2.0.4}/PKG-INFO +1 -1
  2. {wxdata-2.0.3 → wxdata-2.0.4}/pyproject.toml +1 -1
  3. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/soundings/wyoming_soundings.py +166 -80
  4. {wxdata-2.0.3 → wxdata-2.0.4/src/wxdata.egg-info}/PKG-INFO +1 -1
  5. {wxdata-2.0.3 → wxdata-2.0.4}/LICENSE +0 -0
  6. {wxdata-2.0.3 → wxdata-2.0.4}/README.md +0 -0
  7. {wxdata-2.0.3 → wxdata-2.0.4}/setup.cfg +0 -0
  8. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/__init__.py +0 -0
  9. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/aigefs/__init__.py +0 -0
  10. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/aigefs/aigefs.py +0 -0
  11. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/aigefs/paths.py +0 -0
  12. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/aigefs/url_scanners.py +0 -0
  13. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/aigfs/__init__.py +0 -0
  14. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/aigfs/aigfs.py +0 -0
  15. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/aigfs/paths.py +0 -0
  16. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/aigfs/url_scanners.py +0 -0
  17. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/calc/__init__.py +0 -0
  18. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/calc/derived_fields.py +0 -0
  19. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/calc/kinematics.py +0 -0
  20. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/calc/thermodynamics.py +0 -0
  21. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/calc/unit_conversion.py +0 -0
  22. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/cfs/__init__.py +0 -0
  23. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/cfs/cfs.py +0 -0
  24. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/cfs/file_scanner.py +0 -0
  25. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/cfs/url_scanners.py +0 -0
  26. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/client/__init__.py +0 -0
  27. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/client/byte_range.py +0 -0
  28. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/client/client.py +0 -0
  29. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/client/level_coords.py +0 -0
  30. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/ecmwf/__init__.py +0 -0
  31. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/ecmwf/ecmwf.py +0 -0
  32. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/ecmwf/file_funcs.py +0 -0
  33. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/ecmwf/keys.py +0 -0
  34. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/ecmwf/parsers.py +0 -0
  35. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/ecmwf/paths.py +0 -0
  36. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/ecmwf/url_scanners.py +0 -0
  37. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/fems/__init__.py +0 -0
  38. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/fems/meta_data.py +0 -0
  39. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/fems/observations.py +0 -0
  40. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/gefs/__init__.py +0 -0
  41. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/gefs/exception_messages.py +0 -0
  42. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/gefs/file_funcs.py +0 -0
  43. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/gefs/gefs.py +0 -0
  44. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/gefs/paths.py +0 -0
  45. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/gefs/url_scanners.py +0 -0
  46. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/gfs/__init__.py +0 -0
  47. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/gfs/exception_messages.py +0 -0
  48. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/gfs/gfs.py +0 -0
  49. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/gfs/paths.py +0 -0
  50. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/gfs/url_scanners.py +0 -0
  51. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/hgefs/__init__.py +0 -0
  52. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/hgefs/hgefs.py +0 -0
  53. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/hgefs/paths.py +0 -0
  54. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/hgefs/url_scanner.py +0 -0
  55. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/metars/__init__.py +0 -0
  56. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/metars/_clean_data.py +0 -0
  57. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/metars/metar_obs.py +0 -0
  58. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/noaa/__init__.py +0 -0
  59. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/noaa/nws.py +0 -0
  60. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/post_processors/__init__.py +0 -0
  61. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/post_processors/aigefs_post_processing.py +0 -0
  62. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/post_processors/aigfs_post_processing.py +0 -0
  63. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/post_processors/cfs_post_processing.py +0 -0
  64. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/post_processors/ecmwf_post_processing.py +0 -0
  65. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/post_processors/gefs_post_processing.py +0 -0
  66. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/post_processors/gfs_post_processing.py +0 -0
  67. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/post_processors/hgefs_post_processing.py +0 -0
  68. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/post_processors/rtma_post_processing.py +0 -0
  69. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/radar/__init__.py +0 -0
  70. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/radar/nexrad2.py +0 -0
  71. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/radar/url_scanner.py +0 -0
  72. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/rtma/__init__.py +0 -0
  73. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/rtma/file_funcs.py +0 -0
  74. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/rtma/file_scanner.py +0 -0
  75. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/rtma/keys.py +0 -0
  76. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/rtma/rtma.py +0 -0
  77. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/rtma/url_scanners.py +0 -0
  78. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/soundings/__init__.py +0 -0
  79. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/soundings/_exceptions.py +0 -0
  80. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/utils/__init__.py +0 -0
  81. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/utils/coords.py +0 -0
  82. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/utils/exceptions.py +0 -0
  83. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/utils/file_funcs.py +0 -0
  84. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/utils/file_scanner.py +0 -0
  85. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/utils/nomads_gribfilter.py +0 -0
  86. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/utils/progress_bar.py +0 -0
  87. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/utils/recycle_bin.py +0 -0
  88. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/utils/scripts.py +0 -0
  89. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/utils/tools.py +0 -0
  90. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata/utils/xmacis2_cleanup.py +0 -0
  91. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata.egg-info/SOURCES.txt +0 -0
  92. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata.egg-info/dependency_links.txt +0 -0
  93. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata.egg-info/requires.txt +0 -0
  94. {wxdata-2.0.3 → wxdata-2.0.4}/src/wxdata.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wxdata
3
- Version: 2.0.3
3
+ Version: 2.0.4
4
4
  Summary: A Python package of end-to-end weather data clients & raw data clients with VPN/PROXY support, data processors that decode variable keys from GRIB format into a plain-language format & various tools for assisting Python automated workflows, querying meteorological datasets and filling gaps in meteorological data.
5
5
  Author: Eric J. Drewitz
6
6
  Project-URL: Documentation, https://github.com/edrewitz/wxdata/blob/main/Documentation/Landing%20Page.md
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "wxdata"
3
- version = "2.0.3"
3
+ version = "2.0.4"
4
4
  description = "A Python package of end-to-end weather data clients & raw data clients with VPN/PROXY support, data processors that decode variable keys from GRIB format into a plain-language format & various tools for assisting Python automated workflows, querying meteorological datasets and filling gaps in meteorological data."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -14,7 +14,6 @@ import metpy.calc as _mpcalc
14
14
  import sys as _sys
15
15
  import wxdata.soundings._exceptions as _exceptions
16
16
 
17
- from wxdata.calc.thermodynamics import relative_humidity as _relative_humidity
18
17
  from wxdata.calc.kinematics import get_u_and_v as _get_u_and_v
19
18
  from metpy.units import units as _units
20
19
  from bs4 import BeautifulSoup as _BeautifulSoup
@@ -44,6 +43,129 @@ except Exception as e:
44
43
  now = _datetime.utcnow()
45
44
 
46
45
 
46
+ def _parse_sounding_text(data, usecols, names, widths=None):
47
+ """
48
+ Parse the fixed-width Wyoming sounding text response while preserving the first
49
+ pressure level row. The text includes header lines that should not be treated as
50
+ data rows.
51
+
52
+ Required Arguments:
53
+
54
+ 1) data (Bytes) - The sounding data in bytes format.
55
+
56
+ 2) usecols (Integer List) - The list of columns to be used.
57
+
58
+ 3) names (String List) - Column names.
59
+
60
+ Optional Arguments:
61
+
62
+ 1) widths - Width of columns.
63
+
64
+ Returns
65
+ -------
66
+
67
+ A Pandas.DataFrame of the sounding data.
68
+ """
69
+ if widths is None:
70
+ widths = [7] * 8
71
+
72
+ if hasattr(data, "readlines"):
73
+ lines = data.readlines()
74
+ else:
75
+ lines = data.splitlines()
76
+
77
+ cleaned_lines = [line.rstrip("\n") for line in lines]
78
+ start_idx = None
79
+
80
+ for idx, line in enumerate(cleaned_lines):
81
+ stripped = line.strip()
82
+ if not stripped:
83
+ continue
84
+
85
+ parts = stripped.split()
86
+ if not parts:
87
+ continue
88
+
89
+ first_token = parts[0]
90
+ if first_token.replace(".", "", 1).replace("-", "", 1).replace("+", "", 1).isdigit():
91
+ start_idx = idx
92
+ break
93
+
94
+ if start_idx is None:
95
+ raise ValueError("No sounding data rows found")
96
+
97
+ return _pd.read_fwf(
98
+ _StringIO("\n".join(cleaned_lines[start_idx:])),
99
+ widths=widths,
100
+ usecols=usecols,
101
+ names=names,
102
+ )
103
+
104
+
105
+ def _url_scanner(date,
106
+ station_number,
107
+ proxies):
108
+
109
+ """
110
+ Scans URLs for a 200 response.
111
+
112
+ Required Arguments:
113
+
114
+ 1) date (datetime) - The date and time of the observation.
115
+
116
+ 2) station_number (Integer) - The number corresponding to the site.
117
+
118
+ 3) proxies (String) - Default = None. If the user is requesting the data on a machine using a proxy server,
119
+ the user must set proxy='proxy_url'. The default setting assumes the user is not using a proxy server conenction.
120
+
121
+ proxies=None ---> proxies={
122
+ 'http':'http://your-proxy-address:port',
123
+ 'https':'http://your-proxy-address:port'
124
+ }
125
+
126
+ Optional Arguments: None
127
+
128
+ Returns
129
+ -------
130
+
131
+ The URL for data access.
132
+
133
+ """
134
+
135
+ bufr = f"https://weather.uwyo.edu/wsgi/sounding?datetime={date.strftime('%Y-%m-%d')}%20{date.hour}:00:00&id={station_number}&src=BUFR&type=TEXT:LIST"
136
+ fm35 = f"https://weather.uwyo.edu/wsgi/sounding?datetime={date.strftime('%Y-%m-%d')}%20{date.hour}:00:00&id={station_number}&src=FM35&type=TEXT:LIST"
137
+ fm37 = f"https://weather.uwyo.edu/wsgi/sounding?datetime={date.strftime('%Y-%m-%d')}%20{date.hour}:00:00&id={station_number}&src=FM37&type=TEXT:LIST"
138
+
139
+ if proxies == None:
140
+ bufr_response = _requests.get(bufr)
141
+ fm35_response = _requests.get(fm35)
142
+ fm37_response = _requests.get(fm37)
143
+
144
+ else:
145
+ bufr_response = _requests.get(bufr,
146
+ proxies=proxies)
147
+ fm35_response = _requests.get(fm35,
148
+ proxies=proxies)
149
+ fm37_response = _requests.get(fm37,
150
+ proxies=proxies)
151
+
152
+ urls = []
153
+ urls.append(bufr)
154
+ urls.append(fm35)
155
+ urls.append(fm37)
156
+
157
+ responses = []
158
+ responses.append(bufr_response)
159
+ responses.append(fm35_response)
160
+ responses.append(fm37_response)
161
+
162
+ for r, url in zip(responses, urls):
163
+ if r.status_code == 200:
164
+ url = url
165
+ break
166
+
167
+ return url
168
+
47
169
  def _station_ids(station_id):
48
170
 
49
171
  """
@@ -408,7 +530,7 @@ def get_observed_sounding_data(station_id,
408
530
  if current == True:
409
531
  date = now
410
532
  if date.hour <= 12:
411
- hour = 00
533
+ hour = 0
412
534
  else:
413
535
  hour = 12
414
536
 
@@ -427,15 +549,9 @@ def get_observed_sounding_data(station_id,
427
549
  except Exception as e:
428
550
  _exceptions.date_format_exception(date)
429
551
 
430
-
431
- if hour == 0:
432
- url = (f"http://weather.uwyo.edu/cgi-bin/sounding?region=naconf&TYPE=TEXT%3ALIST"
433
- f"&YEAR={date.strftime('%Y')}&MONTH={date.strftime('%m')}&FROM={date.strftime('%d')}0{hour}&TO={date.strftime('%d')}0{hour}"
434
- f"&STNM={station_number}")
435
- else:
436
- url = (f"http://weather.uwyo.edu/cgi-bin/sounding?region=naconf&TYPE=TEXT%3ALIST"
437
- f"&YEAR={date.strftime('%Y')}&MONTH={date.strftime('%m')}&FROM={date.strftime('%d')}{hour}&TO={date.strftime('%d')}{hour}"
438
- f"&STNM={station_number}")
552
+ url = _url_scanner(date,
553
+ station_number,
554
+ proxies)
439
555
 
440
556
  max_retries = 5
441
557
  retry = 0
@@ -469,14 +585,9 @@ def get_observed_sounding_data(station_id,
469
585
  date = date - _timedelta(hours=12)
470
586
  hour = date.hour
471
587
 
472
- if hour == 0:
473
- url = (f"http://weather.uwyo.edu/cgi-bin/sounding?region=naconf&TYPE=TEXT%3ALIST"
474
- f"&YEAR={date.strftime('%Y')}&MONTH={date.strftime('%m')}&FROM={date.strftime('%d')}0{hour}&TO={date.strftime('%d')}0{hour}"
475
- f"&STNM={station_number}")
476
- else:
477
- url = (f"http://weather.uwyo.edu/cgi-bin/sounding?region=naconf&TYPE=TEXT%3ALIST"
478
- f"&YEAR={date.strftime('%Y')}&MONTH={date.strftime('%m')}&FROM={date.strftime('%d')}{hour}&TO={date.strftime('%d')}{hour}"
479
- f"&STNM={station_number}")
588
+ url = _url_scanner(date,
589
+ station_number,
590
+ proxies)
480
591
 
481
592
  max_retries = 5
482
593
  retry = 0
@@ -513,13 +624,17 @@ def get_observed_sounding_data(station_id,
513
624
  col_names = ['PRES', 'HGHT', 'TEMP', 'DWPT', 'RELH', 'MIXR', 'DRCT', 'SKNT', 'THTA', 'THTE', 'THTV']
514
625
 
515
626
  try:
516
- df = _pd.read_fwf(data, widths=[7] * 8, skiprows=5,
517
- usecols=[0, 1, 2, 3, 6, 7], names=col_names)
627
+ df = _parse_sounding_text(
628
+ data,
629
+ usecols=[0, 1, 2, 3, 4, 5, 6, 7],
630
+ names=col_names,
631
+ widths=[7] * 8,
632
+ )
518
633
  except Exception as e:
519
634
  _exceptions.station_id_exception(station_id)
520
635
 
521
636
  df['U-WIND'], df['V-WIND'] = _get_u_and_v(df['SKNT'], df['DRCT'])
522
- df['RH'] = _relative_humidity(df['TEMP'], df['DWPT'])
637
+ df = df.rename(columns={'RELH': 'RH'})
523
638
  pressure = df['PRES'].values * _units('hPa')
524
639
  temperature = df['TEMP'].values * _units('degC')
525
640
  dewpoint = df['DWPT'].values * _units('degC')
@@ -538,7 +653,7 @@ def get_observed_sounding_data(station_id,
538
653
  if current == True:
539
654
  date = now
540
655
  if date.hour <= 12:
541
- hour = 00
656
+ hour = 0
542
657
  else:
543
658
  hour = 12
544
659
 
@@ -559,24 +674,14 @@ def get_observed_sounding_data(station_id,
559
674
 
560
675
  date_24 = date - _timedelta(hours=24)
561
676
 
562
- if hour == 0:
563
- url = (f"http://weather.uwyo.edu/cgi-bin/sounding?region=naconf&TYPE=TEXT%3ALIST"
564
- f"&YEAR={date.strftime('%Y')}&MONTH={date.strftime('%m')}&FROM={date.strftime('%d')}0{hour}&TO={date.strftime('%d')}0{hour}"
565
- f"&STNM={station_number}")
566
-
567
- url_24 = (f"http://weather.uwyo.edu/cgi-bin/sounding?region=naconf&TYPE=TEXT%3ALIST"
568
- f"&YEAR={date.strftime('%Y')}&MONTH={date_24.strftime('%m')}&FROM={date_24.strftime('%d')}0{hour}&TO={date_24.strftime('%d')}0{hour}"
569
- f"&STNM={station_number}")
570
-
571
- else:
572
- url = (f"http://weather.uwyo.edu/cgi-bin/sounding?region=naconf&TYPE=TEXT%3ALIST"
573
- f"&YEAR={date.strftime('%Y')}&MONTH={date.strftime('%m')}&FROM={date.strftime('%d')}{hour}&TO={date.strftime('%d')}{hour}"
574
- f"&STNM={station_number}")
575
-
576
- url_24 = (f"http://weather.uwyo.edu/cgi-bin/sounding?region=naconf&TYPE=TEXT%3ALIST"
577
- f"&YEAR={date_24.strftime('%Y')}&MONTH={date_24.strftime('%m')}&FROM={date_24.strftime('%d')}{hour}&TO={date_24.strftime('%d')}{hour}"
578
- f"&STNM={station_number}")
677
+ url = _url_scanner(date,
678
+ station_number,
679
+ proxies)
579
680
 
681
+ url_24 = _url_scanner(date_24,
682
+ station_number,
683
+ proxies)
684
+
580
685
  max_retries = 5
581
686
  retry = 0
582
687
  if proxies == None:
@@ -621,23 +726,13 @@ def get_observed_sounding_data(station_id,
621
726
  date_24 = date - _timedelta(hours=24)
622
727
  hour = date.hour
623
728
 
624
- if hour == 0:
625
- url = (f"http://weather.uwyo.edu/cgi-bin/sounding?region=naconf&TYPE=TEXT%3ALIST"
626
- f"&YEAR={date.strftime('%Y')}&MONTH={date.strftime('%m')}&FROM={date.strftime('%d')}0{hour}&TO={date.strftime('%d')}0{hour}"
627
- f"&STNM={station_number}")
628
-
629
- url_24 = (f"http://weather.uwyo.edu/cgi-bin/sounding?region=naconf&TYPE=TEXT%3ALIST"
630
- f"&YEAR={date.strftime('%Y')}&MONTH={date_24.strftime('%m')}&FROM={date_24.strftime('%d')}0{hour}&TO={date_24.strftime('%d')}0{hour}"
631
- f"&STNM={station_number}")
632
-
633
- else:
634
- url = (f"http://weather.uwyo.edu/cgi-bin/sounding?region=naconf&TYPE=TEXT%3ALIST"
635
- f"&YEAR={date.strftime('%Y')}&MONTH={date.strftime('%m')}&FROM={date.strftime('%d')}{hour}&TO={date.strftime('%d')}{hour}"
636
- f"&STNM={station_number}")
637
-
638
- url_24 = (f"http://weather.uwyo.edu/cgi-bin/sounding?region=naconf&TYPE=TEXT%3ALIST"
639
- f"&YEAR={date_24.strftime('%Y')}&MONTH={date_24.strftime('%m')}&FROM={date_24.strftime('%d')}{hour}&TO={date_24.strftime('%d')}{hour}"
640
- f"&STNM={station_number}")
729
+ url = _url_scanner(date,
730
+ station_number,
731
+ proxies)
732
+
733
+ url_24 = _url_scanner(date_24,
734
+ station_number,
735
+ proxies)
641
736
 
642
737
  max_retries = 5
643
738
  retry = 0
@@ -684,13 +779,17 @@ def get_observed_sounding_data(station_id,
684
779
  col_names = ['PRES', 'HGHT', 'TEMP', 'DWPT', 'RELH', 'MIXR', 'DRCT', 'SKNT', 'THTA', 'THTE', 'THTV']
685
780
 
686
781
  try:
687
- df = _pd.read_fwf(data, widths=[7] * 8, skiprows=5,
688
- usecols=[0, 1, 2, 3, 6, 7], names=col_names)
782
+ df = _parse_sounding_text(
783
+ data,
784
+ usecols=[0, 1, 2, 3, 4, 5, 6, 7],
785
+ names=col_names,
786
+ widths=[7] * 8,
787
+ )
689
788
  except Exception as e:
690
789
  _exceptions.station_id_exception(station_id)
691
790
 
692
791
  df['U-WIND'], df['V-WIND'] = _get_u_and_v(df['SKNT'], df['DRCT'])
693
- df['RH'] = _relative_humidity(df['TEMP'], df['DWPT'])
792
+ df = df.rename(columns={'RELH': 'RH'})
694
793
  pressure = df['PRES'].values * _units('hPa')
695
794
  temperature = df['TEMP'].values * _units('degC')
696
795
  dewpoint = df['DWPT'].values * _units('degC')
@@ -701,13 +800,17 @@ def get_observed_sounding_data(station_id,
701
800
  df['WET-BULB'] = _mpcalc.wet_bulb_temperature(pressure, temperature, dewpoint)
702
801
 
703
802
  try:
704
- df_24 = _pd.read_fwf(data_24, widths=[7] * 8, skiprows=5,
705
- usecols=[0, 1, 2, 3, 6, 7], names=col_names)
803
+ df_24 = _parse_sounding_text(
804
+ data_24,
805
+ usecols=[0, 1, 2, 3, 4, 5, 6, 7],
806
+ names=col_names,
807
+ widths=[7] * 8,
808
+ )
706
809
  except Exception as e:
707
810
  _exceptions.station_id_exception(station_id)
708
811
 
709
812
  df_24['U-WIND'], df_24['V-WIND'] = _get_u_and_v(df_24['SKNT'], df_24['DRCT'])
710
- df_24['RH'] = _relative_humidity(df_24['TEMP'], df_24['DWPT'])
813
+ df_24 = df_24.rename(columns={'RELH': 'RH'})
711
814
  pressure_24 = df_24['PRES'].values * _units('hPa')
712
815
  temperature_24 = df_24['TEMP'].values * _units('degC')
713
816
  dewpoint_24 = df_24['DWPT'].values * _units('degC')
@@ -724,20 +827,3 @@ def get_observed_sounding_data(station_id,
724
827
  df_24.dropna(axis=0, inplace=True)
725
828
 
726
829
  return df, df_24, date, date_24
727
-
728
-
729
-
730
-
731
-
732
-
733
-
734
-
735
-
736
-
737
-
738
-
739
-
740
-
741
-
742
-
743
-
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wxdata
3
- Version: 2.0.3
3
+ Version: 2.0.4
4
4
  Summary: A Python package of end-to-end weather data clients & raw data clients with VPN/PROXY support, data processors that decode variable keys from GRIB format into a plain-language format & various tools for assisting Python automated workflows, querying meteorological datasets and filling gaps in meteorological data.
5
5
  Author: Eric J. Drewitz
6
6
  Project-URL: Documentation, https://github.com/edrewitz/wxdata/blob/main/Documentation/Landing%20Page.md
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes