From a67c42150d6898f79450a92c478d0584c853bda8 Mon Sep 17 00:00:00 2001 From: Jeff Klenzing Date: Thu, 14 Sep 2023 17:41:28 -0400 Subject: [PATCH 1/9] ENH: add reach dosimeter --- pysatNASA/instruments/__init__.py | 4 +- pysatNASA/instruments/methods/__init__.py | 1 + pysatNASA/instruments/methods/reach.py | 7 ++ pysatNASA/instruments/reach_dosimeter.py | 142 ++++++++++++++++++++++ 4 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 pysatNASA/instruments/methods/reach.py create mode 100644 pysatNASA/instruments/reach_dosimeter.py diff --git a/pysatNASA/instruments/__init__.py b/pysatNASA/instruments/__init__.py index 5407b031..e914912a 100644 --- a/pysatNASA/instruments/__init__.py +++ b/pysatNASA/instruments/__init__.py @@ -11,8 +11,8 @@ 'de2_lang', 'de2_nacs', 'de2_rpa', 'de2_vefi', 'de2_wats', 'dmsp_ssusi', 'formosat1_ivm', 'icon_euv', 'icon_fuv', 'icon_ivm', 'icon_mighti', - 'igs_gps', 'iss_fpmu', 'jpl_gps', 'omni_hro', 'ses14_gold', - 'timed_guvi', 'timed_saber', 'timed_see'] + 'igs_gps', 'iss_fpmu', 'jpl_gps', 'omni_hro', 'reach_dosimeter', + 'ses14_gold', 'timed_guvi', 'timed_saber', 'timed_see'] for inst in __all__: exec("from pysatNASA.instruments import {x}".format(x=inst)) diff --git a/pysatNASA/instruments/methods/__init__.py b/pysatNASA/instruments/methods/__init__.py index 4459d353..a1910352 100644 --- a/pysatNASA/instruments/methods/__init__.py +++ b/pysatNASA/instruments/methods/__init__.py @@ -12,5 +12,6 @@ from pysatNASA.instruments.methods import iss # noqa F401 from pysatNASA.instruments.methods import jhuapl # noqa F401 from pysatNASA.instruments.methods import omni # noqa F401 +from pysatNASA.instruments.methods import reach # noqa F401 from pysatNASA.instruments.methods import ses14 # noqa F401 from pysatNASA.instruments.methods import timed # noqa F401 diff --git a/pysatNASA/instruments/methods/reach.py b/pysatNASA/instruments/methods/reach.py new file mode 100644 index 00000000..caadb7f6 --- /dev/null +++ b/pysatNASA/instruments/methods/reach.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +"""Provides non-instrument specific routines for REACH data.""" + +ackn_str = ' '.join(("Insert ackn")) + +refs = {'dosimeter': ' '.join(('Insert ref')) + } diff --git a/pysatNASA/instruments/reach_dosimeter.py b/pysatNASA/instruments/reach_dosimeter.py new file mode 100644 index 00000000..de74ece0 --- /dev/null +++ b/pysatNASA/instruments/reach_dosimeter.py @@ -0,0 +1,142 @@ +# -*- coding: utf-8 -*- +"""The REACH dosimeter instrument. + +Supports the dosimeter instrument on the Responsive Environmental Assessment +Commercially Hosted (REACH) mission. + +The Responsive Environmental Assessment Commercially Hosted (REACH) +constellation is collection of 32 small sensors hosted on six orbital planes of +the Iridium-Next space vehicles in low earth orbit. Each sensor contains two +micro-dosimeters sensitive to the passage of charged particles from the Earth's +radiation belts. There are six distinct dosimeter types spread among the 64 +individual sensors, which are unique in shielding and electronic threshold. +When taken together, this effectively enables a high time-cadence measurement +of protons and electrons in six integral energy channels over the entire globe. + +Properties +---------- +platform + 'reach' +name + 'dosimeter' +tag + None Supported +inst_id + '101', '102', '105', '108', '113', '114', '115', '116', '133', '134', '135', + '136', '137', '138', '139', '140', '148', '149', '162', '163', '164', '165', + '166', '169', '170', '171', '172', '173', '175', '176', '180', '181' + + +""" + +import datetime as dt +import functools + +from pysat.instruments.methods import general as mm_gen +from pysat.utils.io import load_netcdf + +from pysatNASA.instruments.methods import cdaweb as cdw +from pysatNASA.instruments.methods import reach as mm_reach +from pysatNASA.instruments.methods import general as mm_nasa + +# ---------------------------------------------------------------------------- +# Instrument attributes + +platform = 'reach' +name = 'dosimeter' +tags = {'': 'Dosimeter data from the REACH mission'} +iids = ['101', '102', '105', '108', '113', '114', '115', '116', '133', '134', + '135', '136', '137', '138', '139', '140', '148', '149', '162', '163', + '164', '165', '166', '169', '170', '171', '172', '173', '175', '176', + '180', '181'] +inst_ids = {iid: [tag for tag in tags.keys()] for iid in iids} + +# ---------------------------------------------------------------------------- +# Instrument test attributes + +_test_dates = {iid: {tag: dt.datetime(2019, 12, 1) for tag in tags.keys()} + for iid in inst_ids.keys()} + +# ---------------------------------------------------------------------------- +# Instrument methods + + +# Use standard init routine +init = functools.partial(mm_nasa.init, module=mm_reach, name=name) + +# Use default clean +clean = mm_nasa.clean + +# ---------------------------------------------------------------------------- +# Instrument functions +# +# Use the default CDAWeb and pysat methods + +# Set the list_files routine +datestr = '{year:4d}{month:02d}{day:02d}' +fname = 'reach-vid-{inst_id}_dosimeter-l1c_{datestr}_v{{version:01d}}.nc' +supported_tags = {iid: {'': fname.format(inst_id=iid, datestr=datestr)} + for iid in inst_ids.keys()} +list_files = functools.partial(mm_gen.list_files, + supported_tags=supported_tags) + + +def load(fnames, tag=None, inst_id=None): + """Load REACH data into `pandas.DataFrame` and `pysat.Meta` objects. + + This routine is called as needed by pysat. It is not intended + for direct user interaction. + + Parameters + ---------- + fnames : array-like + iterable of filename strings, full path, to data files to be loaded. + This input is nominally provided by pysat itself. + tag : string + tag name used to identify particular data set to be loaded. + This input is nominally provided by pysat itself. + inst_id : string + Satellite ID used to identify particular data set to be loaded. + This input is nominally provided by pysat itself. + + Returns + ------- + data : pds.DataFrame + A pandas DataFrame with data prepared for the pysat.Instrument + meta : pysat.Meta + Metadata formatted for a pysat.Instrument object. + + Note + ---- + Any additional keyword arguments passed to pysat.Instrument + upon instantiation are passed along to this routine. + + Examples + -------- + :: + + inst = pysat.Instrument('icon', 'ivm', inst_id='a', tag='') + inst.load(2020, 1) + + """ + + # Use standard netcdf interface + labels = {'units': ('UNITS', str), 'name': ('LONG_NAME', str), + 'notes': ('VAR_NOTES', str), 'desc': ('CATDESC', str), + 'min_val': ('VALIDMIN', (int, float)), + 'max_val': ('VALIDMAX', (int, float)), + 'fill_val': ('_FillValue', (int, float))} + data, meta = load_netcdf(fnames, epoch_name='Epoch', + meta_kwargs={'labels': labels}) + + return data, meta + + +# Support download routine +download_tags = {iid: {'': 'REACH-VID-{iid}_DOSIMETER-L1C'.format(iid=iid)} + for iid in inst_ids.keys()} +download = functools.partial(cdw.cdas_download, supported_tags=download_tags) + +# Support listing files currently on CDAWeb +list_remote_files = functools.partial(cdw.cdas_list_remote_files, + supported_tags=download_tags) From 5fd49151e2e65dded617c8e846fd7c5baebbdbec Mon Sep 17 00:00:00 2001 From: Jeff Klenzing Date: Thu, 14 Sep 2023 17:41:42 -0400 Subject: [PATCH 2/9] BUG: fix docstrings --- pysatNASA/instruments/methods/formosat.py | 2 +- pysatNASA/instruments/methods/igs.py | 2 +- pysatNASA/instruments/methods/iss.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pysatNASA/instruments/methods/formosat.py b/pysatNASA/instruments/methods/formosat.py index 41ee0f22..840acd12 100644 --- a/pysatNASA/instruments/methods/formosat.py +++ b/pysatNASA/instruments/methods/formosat.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -"""Provides non-instrument specific routines for C/NOFS data.""" +"""Provides non-instrument specific routines for FORMOSAT data.""" ackn_str = ' '.join(('Data provided through NASA CDAWeb Key Parameters -', 'Shin-Yi Su (Institute of Space Science, National Central', diff --git a/pysatNASA/instruments/methods/igs.py b/pysatNASA/instruments/methods/igs.py index 63ad4a5d..c050e447 100644 --- a/pysatNASA/instruments/methods/igs.py +++ b/pysatNASA/instruments/methods/igs.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -"""Provides non-instrument specific routines for JPL ROTI data.""" +"""Provides non-instrument specific routines for IGS GPS data.""" ackn_str = ' '.join(("The GPS Total Electron Content (TEC) data", "produced by the International Global Navigation", diff --git a/pysatNASA/instruments/methods/iss.py b/pysatNASA/instruments/methods/iss.py index 24ed41ce..dd7553e4 100644 --- a/pysatNASA/instruments/methods/iss.py +++ b/pysatNASA/instruments/methods/iss.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -"""Provides non-instrument specific routines for C/NOFS data.""" +"""Provides non-instrument specific routines for ISS data.""" ackn_str = ' '.join(("R.M. Suggs, S.L. Koontz, NASA Johnson Space Center", "Contact Rob Suggs for support and use.", From 3e4ee5e25a7e130cd98bf7eb35f1cb9d31a9b6c3 Mon Sep 17 00:00:00 2001 From: Jeff Klenzing Date: Thu, 14 Sep 2023 17:42:15 -0400 Subject: [PATCH 3/9] DOC: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5776df1..ad7e0fdd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/). ## [0.X.X] - 2023-XX-XX +* New Instruments + * REACH Dosimeter * Bug Fix * New window needs to be integer for calculate_imf_steadiness * Documentation From 69750090da49aa5c0ec624c4df55762cd47f002a Mon Sep 17 00:00:00 2001 From: Jeff Klenzing <19592220+jklenzing@users.noreply.github.com> Date: Fri, 15 Sep 2023 09:37:48 -0400 Subject: [PATCH 4/9] Update reach_dosimeter.py --- pysatNASA/instruments/reach_dosimeter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pysatNASA/instruments/reach_dosimeter.py b/pysatNASA/instruments/reach_dosimeter.py index de74ece0..6dc6a33c 100644 --- a/pysatNASA/instruments/reach_dosimeter.py +++ b/pysatNASA/instruments/reach_dosimeter.py @@ -36,8 +36,8 @@ from pysat.utils.io import load_netcdf from pysatNASA.instruments.methods import cdaweb as cdw -from pysatNASA.instruments.methods import reach as mm_reach from pysatNASA.instruments.methods import general as mm_nasa +from pysatNASA.instruments.methods import reach as mm_reach # ---------------------------------------------------------------------------- # Instrument attributes From d3f6a351e49631377682a8516fe2bbf576cfe300 Mon Sep 17 00:00:00 2001 From: Jeff Klenzing Date: Mon, 18 Sep 2023 13:15:35 -0400 Subject: [PATCH 5/9] DOC: update supported instruments --- docs/supported_instruments.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/supported_instruments.rst b/docs/supported_instruments.rst index 0980414e..deee1932 100644 --- a/docs/supported_instruments.rst +++ b/docs/supported_instruments.rst @@ -186,6 +186,14 @@ OMNI HRO .. automodule:: pysatNASA.instruments.omni_hro :members: calculate_clock_angle, calculate_imf_steadiness, time_shift_to_magnetic_poles +.. _reach_dosimeter: + +REACH DOSIMETER +---------- + +.. automodule:: pysatNASA.instruments.reach_dosimeter + :members: + .. _ses14_gold: SES14 GOLD From 19bc1329f9610ab10ed8143284aba9a9e8ef50f1 Mon Sep 17 00:00:00 2001 From: Jeff Klenzing Date: Mon, 2 Oct 2023 13:31:12 -0400 Subject: [PATCH 6/9] DOC: add refs and acknowledgements --- pysatNASA/instruments/methods/reach.py | 18 +++++++++++++++--- pysatNASA/instruments/reach_dosimeter.py | 11 ++++++++++- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/pysatNASA/instruments/methods/reach.py b/pysatNASA/instruments/methods/reach.py index caadb7f6..17329378 100644 --- a/pysatNASA/instruments/methods/reach.py +++ b/pysatNASA/instruments/methods/reach.py @@ -1,7 +1,19 @@ # -*- coding: utf-8 -*- """Provides non-instrument specific routines for REACH data.""" -ackn_str = ' '.join(("Insert ackn")) +ackn_str = "Please load a file for full acknowledgments." -refs = {'dosimeter': ' '.join(('Insert ref')) - } +refs = {'dosimeter': + '\n'.join((' '.join(("Guild, T., O'Brien, T.P., Boyd,", + "A.J., Mazur, J.E., Halford, A.J., (2019)", + "Intra-calibration of REACH Dosimeters,", + "AEROSPACE REPORT NO. TOR-2019-02361")), + ' '.join(("Halford, A.J., Guild, T., O'Brien, T.P., Boyd,", + "A.J., Mazur, J.E. (2019)", + "REACH Maps and Indices for UDL: Version 1,", + "AEROSPACE REPORT NO. TOR-2019-02650")), + ' '.join(("Guild, T., O'Brien, T.P., Boyd, A.J., Mazur,", + "J.E. (2021)", + "REACH Maps and Indices for UDL: Version 1", + "AEROSPACE REPORT NO. TOR-2021-01076")) + ))} diff --git a/pysatNASA/instruments/reach_dosimeter.py b/pysatNASA/instruments/reach_dosimeter.py index 6dc6a33c..64e83943 100644 --- a/pysatNASA/instruments/reach_dosimeter.py +++ b/pysatNASA/instruments/reach_dosimeter.py @@ -67,13 +67,22 @@ # Use default clean clean = mm_nasa.clean + +def preprocess(self): + """Update acknowledgement with info from file.""" + + self.acknowledgements = self.meta.header.Acknowledgement + + return + + # ---------------------------------------------------------------------------- # Instrument functions # # Use the default CDAWeb and pysat methods # Set the list_files routine -datestr = '{year:4d}{month:02d}{day:02d}' +datestr = '{year:04d}{month:02d}{day:02d}' fname = 'reach-vid-{inst_id}_dosimeter-l1c_{datestr}_v{{version:01d}}.nc' supported_tags = {iid: {'': fname.format(inst_id=iid, datestr=datestr)} for iid in inst_ids.keys()} From 27ebf392be4b63425d5ef9194bbad5e33b976f42 Mon Sep 17 00:00:00 2001 From: Jeff Klenzing <19592220+jklenzing@users.noreply.github.com> Date: Mon, 2 Oct 2023 15:02:02 -0400 Subject: [PATCH 7/9] Apply suggestions from code review Co-authored-by: Angeline Burrell --- pysatNASA/instruments/methods/reach.py | 3 +-- pysatNASA/instruments/reach_dosimeter.py | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/pysatNASA/instruments/methods/reach.py b/pysatNASA/instruments/methods/reach.py index 17329378..cc9b11e1 100644 --- a/pysatNASA/instruments/methods/reach.py +++ b/pysatNASA/instruments/methods/reach.py @@ -15,5 +15,4 @@ ' '.join(("Guild, T., O'Brien, T.P., Boyd, A.J., Mazur,", "J.E. (2021)", "REACH Maps and Indices for UDL: Version 1", - "AEROSPACE REPORT NO. TOR-2021-01076")) - ))} + "AEROSPACE REPORT NO. TOR-2021-01076"))))} diff --git a/pysatNASA/instruments/reach_dosimeter.py b/pysatNASA/instruments/reach_dosimeter.py index 64e83943..8400a755 100644 --- a/pysatNASA/instruments/reach_dosimeter.py +++ b/pysatNASA/instruments/reach_dosimeter.py @@ -101,10 +101,10 @@ def load(fnames, tag=None, inst_id=None): fnames : array-like iterable of filename strings, full path, to data files to be loaded. This input is nominally provided by pysat itself. - tag : string + tag : str tag name used to identify particular data set to be loaded. This input is nominally provided by pysat itself. - inst_id : string + inst_id : str Satellite ID used to identify particular data set to be loaded. This input is nominally provided by pysat itself. @@ -124,7 +124,7 @@ def load(fnames, tag=None, inst_id=None): -------- :: - inst = pysat.Instrument('icon', 'ivm', inst_id='a', tag='') + inst = pysat.Instrument('reach', 'dosimeter', inst_id='101', tag='') inst.load(2020, 1) """ From 7e213e8310bd0b4dbf27775f930a5f022d347661 Mon Sep 17 00:00:00 2001 From: Jeff Klenzing Date: Wed, 4 Oct 2023 14:07:53 -0400 Subject: [PATCH 8/9] ENH: update meta header values --- pysatNASA/instruments/reach_dosimeter.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pysatNASA/instruments/reach_dosimeter.py b/pysatNASA/instruments/reach_dosimeter.py index 8400a755..3ff9debe 100644 --- a/pysatNASA/instruments/reach_dosimeter.py +++ b/pysatNASA/instruments/reach_dosimeter.py @@ -32,6 +32,7 @@ import datetime as dt import functools +from pysat._meta import MetaHeader from pysat.instruments.methods import general as mm_gen from pysat.utils.io import load_netcdf @@ -138,6 +139,17 @@ def load(fnames, tag=None, inst_id=None): data, meta = load_netcdf(fnames, epoch_name='Epoch', meta_kwargs={'labels': labels}) + # Update header variables + header = meta.header.to_dict() + new_header = {} + for key in header.keys(): + new_key = key.replace('-', '_to_') + new_header[new_key] = header[key] + if np.isnan(new_header['Notes']): + new_header['Notes'] = '' + + meta.header = MetaHeader(new_header) + return data, meta From 1819e04d69d29b4939ad0ae817501da7e371d405 Mon Sep 17 00:00:00 2001 From: Jeff Klenzing <19592220+jklenzing@users.noreply.github.com> Date: Wed, 4 Oct 2023 15:56:02 -0400 Subject: [PATCH 9/9] Update pysatNASA/instruments/reach_dosimeter.py --- pysatNASA/instruments/reach_dosimeter.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pysatNASA/instruments/reach_dosimeter.py b/pysatNASA/instruments/reach_dosimeter.py index 3ff9debe..c7cebdcb 100644 --- a/pysatNASA/instruments/reach_dosimeter.py +++ b/pysatNASA/instruments/reach_dosimeter.py @@ -31,6 +31,7 @@ import datetime as dt import functools +import numpy as np from pysat._meta import MetaHeader from pysat.instruments.methods import general as mm_gen