pvlib 0.12.1a1__py3-none-any.whl → 0.13.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.
pvlib/iotools/psm4.py CHANGED
@@ -11,6 +11,7 @@ from urllib.parse import urljoin
11
11
  import requests
12
12
  import pandas as pd
13
13
  from json import JSONDecodeError
14
+ from pvlib import tools
14
15
 
15
16
  NSRDB_API_BASE = "https://developer.nrel.gov/api/nsrdb/v2/solar/"
16
17
  PSM4_AGG_ENDPOINT = "nsrdb-GOES-aggregated-v4-0-0-download.csv"
@@ -71,7 +72,7 @@ REQUEST_VARIABLE_MAP = {
71
72
 
72
73
 
73
74
  def get_nsrdb_psm4_aggregated(latitude, longitude, api_key, email,
74
- year='2023', time_step=60,
75
+ year, time_step=60,
75
76
  parameters=PARAMETERS, leap_day=True,
76
77
  full_name=PVLIB_PYTHON,
77
78
  affiliation=PVLIB_PYTHON,
@@ -82,7 +83,7 @@ def get_nsrdb_psm4_aggregated(latitude, longitude, api_key, email,
82
83
  Aggregated v4 API.
83
84
 
84
85
  The NSRDB is described in [1]_ and the PSM4 NSRDB GOES Aggregated v4 API is
85
- described in [2]_,.
86
+ described in [2]_.
86
87
 
87
88
  Parameters
88
89
  ----------
@@ -95,7 +96,7 @@ def get_nsrdb_psm4_aggregated(latitude, longitude, api_key, email,
95
96
  email : str
96
97
  NREL API uses this to automatically communicate messages back
97
98
  to the user only if necessary
98
- year : str, default '2023'
99
+ year : int or str
99
100
  PSM4 API parameter specifing year (e.g. ``2023``) to download. The
100
101
  allowed values update periodically, so consult the NSRDB reference
101
102
  below for the current set of options. Called ``names`` in NSRDB API.
@@ -132,7 +133,7 @@ def get_nsrdb_psm4_aggregated(latitude, longitude, api_key, email,
132
133
  timeseries data from NREL PSM4
133
134
  metadata : dict
134
135
  metadata from NREL PSM4 about the record, see
135
- :func:`pvlib.iotools.parse_nsrdb_psm4` for fields
136
+ :func:`pvlib.iotools.read_nsrdb_psm4` for fields
136
137
 
137
138
  Raises
138
139
  ------
@@ -151,19 +152,15 @@ def get_nsrdb_psm4_aggregated(latitude, longitude, api_key, email,
151
152
  result in rejected requests.
152
153
 
153
154
  .. warning:: PSM4 is limited to data found in the NSRDB, please consult
154
- the references below for locations with available data. Additionally,
155
- querying data with < 30-minute resolution uses a different API endpoint
156
- with fewer available fields (see [4]_).
155
+ the references below for locations with available data.
157
156
 
158
157
  See Also
159
158
  --------
160
159
  pvlib.iotools.get_nsrdb_psm4_tmy, pvlib.iotools.get_nsrdb_psm4_conus,
161
- pvlib.iotools.get_nsrdb_psm4_full_disc, pvlib.iotools.read_nsrdb_psm4,
162
- pvlib.iotools.parse_nsrdb_psm4
160
+ pvlib.iotools.get_nsrdb_psm4_full_disc, pvlib.iotools.read_nsrdb_psm4
163
161
 
164
162
  References
165
163
  ----------
166
-
167
164
  .. [1] `NREL National Solar Radiation Database (NSRDB)
168
165
  <https://nsrdb.nrel.gov/>`_
169
166
  .. [2] `NSRDB GOES Aggregated V4.0.0
@@ -176,9 +173,6 @@ def get_nsrdb_psm4_aggregated(latitude, longitude, api_key, email,
176
173
  latitude = ('%8.4f' % latitude).strip()
177
174
  # TODO: make format_WKT(object_type, *args) in tools.py
178
175
 
179
- # convert to string to accomodate integer years being passed in
180
- year = str(year)
181
-
182
176
  # convert pvlib names in parameters to PSM4 convention
183
177
  parameters = [REQUEST_VARIABLE_MAP.get(a, a) for a in parameters]
184
178
 
@@ -213,7 +207,7 @@ def get_nsrdb_psm4_aggregated(latitude, longitude, api_key, email,
213
207
  # the CSV is in the response content as a UTF-8 bytestring
214
208
  # to use pandas we need to create a file buffer from the response
215
209
  fbuf = io.StringIO(response.content.decode('utf-8'))
216
- return parse_nsrdb_psm4(fbuf, map_variables)
210
+ return read_nsrdb_psm4(fbuf, map_variables)
217
211
 
218
212
 
219
213
  def get_nsrdb_psm4_tmy(latitude, longitude, api_key, email, year='tmy',
@@ -225,7 +219,7 @@ def get_nsrdb_psm4_tmy(latitude, longitude, api_key, email, year='tmy',
225
219
  TMY v4 API.
226
220
 
227
221
  The NSRDB is described in [1]_ and the PSM4 NSRDB GOES TMY v4 API is
228
- described in [2]_,.
222
+ described in [2]_.
229
223
 
230
224
  Parameters
231
225
  ----------
@@ -276,7 +270,7 @@ def get_nsrdb_psm4_tmy(latitude, longitude, api_key, email, year='tmy',
276
270
  timeseries data from NREL PSM4
277
271
  metadata : dict
278
272
  metadata from NREL PSM4 about the record, see
279
- :func:`pvlib.iotools.parse_nsrdb_psm4` for fields
273
+ :func:`pvlib.iotools.read_nsrdb_psm4` for fields
280
274
 
281
275
  Raises
282
276
  ------
@@ -295,19 +289,16 @@ def get_nsrdb_psm4_tmy(latitude, longitude, api_key, email, year='tmy',
295
289
  result in rejected requests.
296
290
 
297
291
  .. warning:: PSM4 is limited to data found in the NSRDB, please consult
298
- the references below for locations with available data. Additionally,
299
- querying data with < 30-minute resolution uses a different API endpoint
300
- with fewer available fields (see [4]_).
292
+ the references below for locations with available data.
301
293
 
302
294
  See Also
303
295
  --------
304
296
  pvlib.iotools.get_nsrdb_psm4_aggregated,
305
297
  pvlib.iotools.get_nsrdb_psm4_conus, pvlib.iotools.get_nsrdb_psm4_full_disc,
306
- pvlib.iotools.read_nsrdb_psm4,pvlib.iotools.parse_nsrdb_psm4
298
+ pvlib.iotools.read_nsrdb_psm4
307
299
 
308
300
  References
309
301
  ----------
310
-
311
302
  .. [1] `NREL National Solar Radiation Database (NSRDB)
312
303
  <https://nsrdb.nrel.gov/>`_
313
304
  .. [2] `NSRDB GOES Tmy V4.0.0
@@ -320,9 +311,6 @@ def get_nsrdb_psm4_tmy(latitude, longitude, api_key, email, year='tmy',
320
311
  latitude = ('%8.4f' % latitude).strip()
321
312
  # TODO: make format_WKT(object_type, *args) in tools.py
322
313
 
323
- # convert to string to accomodate integer years being passed in
324
- year = str(year)
325
-
326
314
  # convert pvlib names in parameters to PSM4 convention
327
315
  parameters = [REQUEST_VARIABLE_MAP.get(a, a) for a in parameters]
328
316
 
@@ -357,10 +345,10 @@ def get_nsrdb_psm4_tmy(latitude, longitude, api_key, email, year='tmy',
357
345
  # the CSV is in the response content as a UTF-8 bytestring
358
346
  # to use pandas we need to create a file buffer from the response
359
347
  fbuf = io.StringIO(response.content.decode('utf-8'))
360
- return parse_nsrdb_psm4(fbuf, map_variables)
348
+ return read_nsrdb_psm4(fbuf, map_variables)
361
349
 
362
350
 
363
- def get_nsrdb_psm4_conus(latitude, longitude, api_key, email, year='2023',
351
+ def get_nsrdb_psm4_conus(latitude, longitude, api_key, email, year,
364
352
  time_step=60, parameters=PARAMETERS, leap_day=True,
365
353
  full_name=PVLIB_PYTHON, affiliation=PVLIB_PYTHON,
366
354
  utc=False, map_variables=True, url=None, timeout=30):
@@ -369,7 +357,7 @@ def get_nsrdb_psm4_conus(latitude, longitude, api_key, email, year='2023',
369
357
  v4 API.
370
358
 
371
359
  The NSRDB is described in [1]_ and the PSM4 NSRDB GOES CONUS v4 API is
372
- described in [2]_,.
360
+ described in [2]_.
373
361
 
374
362
  Parameters
375
363
  ----------
@@ -382,7 +370,7 @@ def get_nsrdb_psm4_conus(latitude, longitude, api_key, email, year='2023',
382
370
  email : str
383
371
  NREL API uses this to automatically communicate messages back
384
372
  to the user only if necessary
385
- year : str, default '2023'
373
+ year : int or str
386
374
  PSM4 API parameter specifing year (e.g. ``2023``) to download. The
387
375
  allowed values update periodically, so consult the NSRDB reference
388
376
  below for the current set of options. Called ``names`` in NSRDB API.
@@ -418,7 +406,7 @@ def get_nsrdb_psm4_conus(latitude, longitude, api_key, email, year='2023',
418
406
  timeseries data from NREL PSM4
419
407
  metadata : dict
420
408
  metadata from NREL PSM4 about the record, see
421
- :func:`pvlib.iotools.parse_nsrdb_psm4` for fields
409
+ :func:`pvlib.iotools.read_nsrdb_psm4` for fields
422
410
 
423
411
  Raises
424
412
  ------
@@ -437,19 +425,16 @@ def get_nsrdb_psm4_conus(latitude, longitude, api_key, email, year='2023',
437
425
  result in rejected requests.
438
426
 
439
427
  .. warning:: PSM4 is limited to data found in the NSRDB, please consult
440
- the references below for locations with available data. Additionally,
441
- querying data with < 30-minute resolution uses a different API endpoint
442
- with fewer available fields (see [4]_).
428
+ the references below for locations with available data.
443
429
 
444
430
  See Also
445
431
  --------
446
432
  pvlib.iotools.get_nsrdb_psm4_aggregated,
447
433
  pvlib.iotools.get_nsrdb_psm4_tmy, pvlib.iotools.get_nsrdb_psm4_full_disc,
448
- pvlib.iotools.read_nsrdb_psm4, pvlib.iotools.parse_nsrdb_psm4
434
+ pvlib.iotools.read_nsrdb_psm4
449
435
 
450
436
  References
451
437
  ----------
452
-
453
438
  .. [1] `NREL National Solar Radiation Database (NSRDB)
454
439
  <https://nsrdb.nrel.gov/>`_
455
440
  .. [2] `NSRDB GOES Conus V4.0.0
@@ -462,9 +447,6 @@ def get_nsrdb_psm4_conus(latitude, longitude, api_key, email, year='2023',
462
447
  latitude = ('%8.4f' % latitude).strip()
463
448
  # TODO: make format_WKT(object_type, *args) in tools.py
464
449
 
465
- # convert to string to accomodate integer years being passed in
466
- year = str(year)
467
-
468
450
  # convert pvlib names in parameters to PSM4 convention
469
451
  parameters = [REQUEST_VARIABLE_MAP.get(a, a) for a in parameters]
470
452
 
@@ -499,11 +481,11 @@ def get_nsrdb_psm4_conus(latitude, longitude, api_key, email, year='2023',
499
481
  # the CSV is in the response content as a UTF-8 bytestring
500
482
  # to use pandas we need to create a file buffer from the response
501
483
  fbuf = io.StringIO(response.content.decode('utf-8'))
502
- return parse_nsrdb_psm4(fbuf, map_variables)
484
+ return read_nsrdb_psm4(fbuf, map_variables)
503
485
 
504
486
 
505
487
  def get_nsrdb_psm4_full_disc(latitude, longitude, api_key, email,
506
- year='2023', time_step=60,
488
+ year, time_step=60,
507
489
  parameters=PARAMETERS, leap_day=True,
508
490
  full_name=PVLIB_PYTHON,
509
491
  affiliation=PVLIB_PYTHON, utc=False,
@@ -513,7 +495,7 @@ def get_nsrdb_psm4_full_disc(latitude, longitude, api_key, email,
513
495
  Disc v4 API.
514
496
 
515
497
  The NSRDB is described in [1]_ and the PSM4 NSRDB GOES Full Disc v4 API is
516
- described in [2]_,.
498
+ described in [2]_.
517
499
 
518
500
  Parameters
519
501
  ----------
@@ -526,7 +508,7 @@ def get_nsrdb_psm4_full_disc(latitude, longitude, api_key, email,
526
508
  email : str
527
509
  NREL API uses this to automatically communicate messages back
528
510
  to the user only if necessary
529
- year : str, default '2023'
511
+ year : int or str
530
512
  PSM4 API parameter specifing year (e.g. ``2023``) to download. The
531
513
  allowed values update periodically, so consult the NSRDB reference
532
514
  below for the current set of options. Called ``names`` in NSRDB API.
@@ -563,7 +545,7 @@ def get_nsrdb_psm4_full_disc(latitude, longitude, api_key, email,
563
545
  timeseries data from NREL PSM4
564
546
  metadata : dict
565
547
  metadata from NREL PSM4 about the record, see
566
- :func:`pvlib.iotools.parse_nsrdb_psm4` for fields
548
+ :func:`pvlib.iotools.read_nsrdb_psm4` for fields
567
549
 
568
550
  Raises
569
551
  ------
@@ -582,19 +564,16 @@ def get_nsrdb_psm4_full_disc(latitude, longitude, api_key, email,
582
564
  result in rejected requests.
583
565
 
584
566
  .. warning:: PSM4 is limited to data found in the NSRDB, please consult
585
- the references below for locations with available data. Additionally,
586
- querying data with < 30-minute resolution uses a different API endpoint
587
- with fewer available fields (see [4]_).
567
+ the references below for locations with available data.
588
568
 
589
569
  See Also
590
570
  --------
591
571
  pvlib.iotools.get_nsrdb_psm4_aggregated,
592
572
  pvlib.iotools.get_nsrdb_psm4_tmy, pvlib.iotools.get_nsrdb_psm4_conus,
593
- pvlib.iotools.read_nsrdb_psm4, pvlib.iotools.parse_nsrdb_psm4
573
+ pvlib.iotools.read_nsrdb_psm4
594
574
 
595
575
  References
596
576
  ----------
597
-
598
577
  .. [1] `NREL National Solar Radiation Database (NSRDB)
599
578
  <https://nsrdb.nrel.gov/>`_
600
579
  .. [2] `NSRDB GOES Full Disc V4.0.0
@@ -607,9 +586,6 @@ def get_nsrdb_psm4_full_disc(latitude, longitude, api_key, email,
607
586
  latitude = ('%8.4f' % latitude).strip()
608
587
  # TODO: make format_WKT(object_type, *args) in tools.py
609
588
 
610
- # convert to string to accomodate integer years being passed in
611
- year = str(year)
612
-
613
589
  # convert pvlib names in parameters to PSM4 convention
614
590
  parameters = [REQUEST_VARIABLE_MAP.get(a, a) for a in parameters]
615
591
 
@@ -644,19 +620,19 @@ def get_nsrdb_psm4_full_disc(latitude, longitude, api_key, email,
644
620
  # the CSV is in the response content as a UTF-8 bytestring
645
621
  # to use pandas we need to create a file buffer from the response
646
622
  fbuf = io.StringIO(response.content.decode('utf-8'))
647
- return parse_nsrdb_psm4(fbuf, map_variables)
623
+ return read_nsrdb_psm4(fbuf, map_variables)
648
624
 
649
625
 
650
- def parse_nsrdb_psm4(fbuf, map_variables=True):
626
+ def read_nsrdb_psm4(filename, map_variables=True):
651
627
  """
652
- Parse an NSRDB PSM4 weather file (formatted as SAM CSV).
628
+ Read an NSRDB PSM4 weather file (formatted as SAM CSV).
653
629
 
654
630
  The NSRDB is described in [1]_ and the SAM CSV format is described in [2]_.
655
631
 
656
632
  Parameters
657
633
  ----------
658
- fbuf: file-like object
659
- File-like object containing data to read.
634
+ filename: str, path-like, or buffer
635
+ Filename or in-memory buffer of a file containing data to read.
660
636
  map_variables: bool, default True
661
637
  When true, renames columns of the Dataframe to pvlib variable names
662
638
  where applicable. See variable :const:`VARIABLE_MAP`.
@@ -726,12 +702,19 @@ def parse_nsrdb_psm4(fbuf, map_variables=True):
726
702
  Examples
727
703
  --------
728
704
  >>> # Read a local PSM4 file:
705
+ >>> df, metadata = iotools.read_nsrdb_psm4("data.csv") # doctest: +SKIP
706
+
707
+ >>> # Read a file object or an in-memory buffer:
729
708
  >>> with open(filename, 'r') as f: # doctest: +SKIP
730
- ... df, metadata = iotools.parse_nsrdb_psm4(f) # doctest: +SKIP
709
+ ... df, metadata = iotools.read_nsrdb_psm4(f) # doctest: +SKIP
731
710
 
732
711
  See Also
733
712
  --------
734
- pvlib.iotools.read_nsrdb_psm4, pvlib.iotools.get_psm4
713
+ pvlib.iotools.get_nsrdb_psm4_aggregated
714
+ pvlib.iotools.get_nsrdb_psm4_tmy
715
+ pvlib.iotools.get_nsrdb_psm4_conus
716
+ pvlib.iotools.get_nsrdb_psm4_full_disc
717
+ pvlib.iotools.read_psm3
735
718
 
736
719
  References
737
720
  ----------
@@ -740,11 +723,26 @@ def parse_nsrdb_psm4(fbuf, map_variables=True):
740
723
  .. [2] `Standard Time Series Data File Format
741
724
  <https://web.archive.org/web/20170207203107/https://sam.nrel.gov/sites/default/files/content/documents/pdf/wfcsv.pdf>`_
742
725
  """
743
- # The first 2 lines of the response are headers with metadata
744
- metadata_fields = fbuf.readline().split(',')
745
- metadata_fields[-1] = metadata_fields[-1].strip() # strip trailing newline
746
- metadata_values = fbuf.readline().split(',')
747
- metadata_values[-1] = metadata_values[-1].strip() # strip trailing newline
726
+ with tools._file_context_manager(filename) as fbuf:
727
+ # The first 2 lines of the response are headers with metadata
728
+ metadata_fields = fbuf.readline().split(',')
729
+ metadata_values = fbuf.readline().split(',')
730
+ # get the column names so we can set the dtypes
731
+ columns = fbuf.readline().split(',')
732
+ columns[-1] = columns[-1].strip() # strip trailing newline
733
+ # Since the header has so many columns, excel saves blank cols in the
734
+ # data below the header lines.
735
+ columns = [col for col in columns if col != '']
736
+ dtypes = dict.fromkeys(columns, float)
737
+ dtypes.update({'Year': int, 'Month': int, 'Day': int, 'Hour': int,
738
+ 'Minute': int, 'Cloud Type': int, 'Fill Flag': int})
739
+
740
+ data = pd.read_csv(
741
+ fbuf, header=None, names=columns, usecols=columns, dtype=dtypes,
742
+ delimiter=',', lineterminator='\n') # skip carriage returns \r
743
+
744
+ metadata_fields[-1] = metadata_fields[-1].strip() # trailing newline
745
+ metadata_values[-1] = metadata_values[-1].strip() # trailing newline
748
746
  metadata = dict(zip(metadata_fields, metadata_values))
749
747
  # the response is all strings, so set some metadata types to numbers
750
748
  metadata['Local Time Zone'] = int(metadata['Local Time Zone'])
@@ -752,22 +750,9 @@ def parse_nsrdb_psm4(fbuf, map_variables=True):
752
750
  metadata['Latitude'] = float(metadata['Latitude'])
753
751
  metadata['Longitude'] = float(metadata['Longitude'])
754
752
  metadata['Elevation'] = int(metadata['Elevation'])
755
- # get the column names so we can set the dtypes
756
- columns = fbuf.readline().split(',')
757
- columns[-1] = columns[-1].strip() # strip trailing newline
758
- # Since the header has so many columns, excel saves blank cols in the
759
- # data below the header lines.
760
- columns = [col for col in columns if col != '']
761
- dtypes = dict.fromkeys(columns, float) # all floats except datevec
762
- dtypes.update(Year=int, Month=int, Day=int, Hour=int, Minute=int)
763
- dtypes['Cloud Type'] = int
764
- dtypes['Fill Flag'] = int
765
- data = pd.read_csv(
766
- fbuf, header=None, names=columns, usecols=columns, dtype=dtypes,
767
- delimiter=',', lineterminator='\n') # skip carriage returns \r
753
+
768
754
  # the response 1st 5 columns are a date vector, convert to datetime
769
- dtidx = pd.to_datetime(
770
- data[['Year', 'Month', 'Day', 'Hour', 'Minute']])
755
+ dtidx = pd.to_datetime(data[['Year', 'Month', 'Day', 'Hour', 'Minute']])
771
756
  # in USA all timezones are integers
772
757
  tz = 'Etc/GMT%+d' % -metadata['Time Zone']
773
758
  data.index = pd.DatetimeIndex(dtidx).tz_localize(tz)
@@ -779,41 +764,3 @@ def parse_nsrdb_psm4(fbuf, map_variables=True):
779
764
  metadata['altitude'] = metadata.pop('Elevation')
780
765
 
781
766
  return data, metadata
782
-
783
-
784
- def read_nsrdb_psm4(filename, map_variables=True):
785
- """
786
- Read an NSRDB PSM4 weather file (formatted as SAM CSV).
787
-
788
- The NSRDB is described in [1]_ and the SAM CSV format is described in [2]_.
789
-
790
- Parameters
791
- ----------
792
- filename: str or path-like
793
- Filename of a file containing data to read.
794
- map_variables: bool, default True
795
- When true, renames columns of the Dataframe to pvlib variable names
796
- where applicable. See variable :const:`VARIABLE_MAP`.
797
-
798
- Returns
799
- -------
800
- data : pandas.DataFrame
801
- timeseries data from NREL PSM4
802
- metadata : dict
803
- metadata from NREL PSM4 about the record, see
804
- :func:`pvlib.iotools.parse_nsrdb_psm4` for fields
805
-
806
- See Also
807
- --------
808
- pvlib.iotools.parse_nsrdb_psm4, pvlib.iotools.get_psm4
809
-
810
- References
811
- ----------
812
- .. [1] `NREL National Solar Radiation Database (NSRDB)
813
- <https://nsrdb.nrel.gov/>`_
814
- .. [2] `Standard Time Series Data File Format
815
- <https://web.archive.org/web/20170207203107/https://sam.nrel.gov/sites/default/files/content/documents/pdf/wfcsv.pdf>`_
816
- """
817
- with open(str(filename), 'r') as fbuf:
818
- content = parse_nsrdb_psm4(fbuf, map_variables)
819
- return content