diff --git a/install/database/2026_09_10_solohi_source.sql b/install/database/2026_09_10_solohi_source.sql new file mode 100644 index 00000000..e3b33990 --- /dev/null +++ b/install/database/2026_09_10_solohi_source.sql @@ -0,0 +1,25 @@ +INSERT INTO datasources ( + id, + name, + description, + units, + layeringOrder, + enabled, + sourceIdGroup, + displayOrder +) +VALUES + (503, 'SoloHI', 'Solar Orbiter Heliospheric Imager', NULL, 1, 0, '', 0); + +INSERT INTO datasource_property ( + sourceId, + label, + name, + fitsName, + description, + uiOrder +) +VALUES + (503, 'Observatory', 'SOLO', 'Solar_Orbiter', 'Solar Orbiter', 1), + (503, 'Instrument', 'SoloHI', 'SoloHI', 'SoloHI', 2), + (503, 'Measurement', 'Difference Mosaic', 'Difference Mosaic', 'Difference Mosaic', 3); diff --git a/install/helioviewer/db.py b/install/helioviewer/db.py index cebb7a5c..31c83e68 100644 --- a/install/helioviewer/db.py +++ b/install/helioviewer/db.py @@ -365,6 +365,7 @@ def create_datasource_table(cursor): (134, 'PUNCH', 'PUNCH WFI+NFI PAM Mosaic', NULL, 1, 0, '', 0, 0, 0, 0), (132, 'GOES', 'CCOR-1', NULL, 1, 0, '', 0, 0, 0, 0), (133, 'SWFO-L1', 'CCOR-2', NULL, 1, 0, '', 0, 0, 0, 0), +(503, 'SoloHI', 'Solar Orbiter Heliospheric Imager', NULL, 1, 0, '', 0, 0, 0, 0), (601, 'SPICE 77.04', 'Solar Orbiter SPICE 77.04', 'NM', 1, 0, '', 0, 0, 0, 0), (602, 'SPICE 103.19', 'Solar Orbiter SPICE 103.19', 'NM', 1, 0, '', 0, 0, 0, 0), (603, 'SPICE 70.38', 'Solar Orbiter SPICE 70.38', 'NM', 1, 0, '', 0, 0, 0, 0), @@ -942,6 +943,9 @@ def create_datasource_property_table(cursor): (133, 'Instrument', 'CCOR-2', 'CCOR2', 'CCOR-2',2), (133, 'Detector', 'CCOR-2', '1', 'CCOR-2',2), (133, 'Measurement', 'white-light', 'white-light', 'White Light',3), +(503, 'Observatory', 'SOLO', 'Solar_Orbiter', 'Solar Orbiter', 1), +(503, 'Instrument', 'SoloHI', 'SoloHI', 'SoloHI', 2), +(503, 'Measurement', 'Difference Mosaic', 'Difference Mosaic', 'Difference Mosaic', 3), (601, 'Observatory', 'SOLO', 'Solar_Orbiter', 'Solar Orbiter', 1), (601, 'Instrument', 'SPICE', 'SPICE', 'SPICE', 2), (601, 'Measurement', 'intensity', 'intensity', 'intensity', 3), diff --git a/install/helioviewer/hvpull/net/daemon.py b/install/helioviewer/hvpull/net/daemon.py index e1ed453d..a7571b3e 100644 --- a/install/helioviewer/hvpull/net/daemon.py +++ b/install/helioviewer/hvpull/net/daemon.py @@ -876,6 +876,7 @@ def get_servers(cls): "kcor": "KCORDataServer", "hv_kcor": "HVKCORDataServer", "solar_orbiter": "SolarOrbiterDataServer", + "solohi": "SoloHIDataServer", "spice": "SpiceDataServer", "suvi": "SUVIDataServer", "iris": "IRISDataServer", diff --git a/install/helioviewer/hvpull/servers/__init__.py b/install/helioviewer/hvpull/servers/__init__.py index 8a099e2a..56bd4e7f 100644 --- a/install/helioviewer/hvpull/servers/__init__.py +++ b/install/helioviewer/hvpull/servers/__init__.py @@ -52,9 +52,8 @@ def get_starttime(self): """Default start time to use when retrieving data""" return datetime.datetime.utcnow() - datetime.timedelta(hours=6) - def get_dates(self, starttime, endtime): + def get_dates(self, starttime, endtime, fmt = "%Y/%m/%d"): """Get a complete list of dates between the start and the end time""" - fmt = "%Y/%m/%d" dates = [starttime.strftime(fmt)] date = starttime.date() diff --git a/install/helioviewer/hvpull/servers/solohi.py b/install/helioviewer/hvpull/servers/solohi.py new file mode 100644 index 00000000..d5601336 --- /dev/null +++ b/install/helioviewer/hvpull/servers/solohi.py @@ -0,0 +1,23 @@ +import os +import datetime +from helioviewer.hvpull.servers import DataServer + +class SoloHIDataServer(DataServer): + def __init__(self): + """Defines the root directory of where the data is kept at LMSAL.""" + DataServer.__init__(self, "https://solohi.nrl.navy.mil/so_data/MOS_jp2/", "SoloHI") + + def compute_directories(self, start_date, end_date): + """Computes a list of remote directories expected to contain files""" + dirs = [] + + for date in self.get_dates(start_date, end_date, "%Y%m%d"): + dirs.append(os.path.join(self.uri, date)) + + return dirs + + def get_datetime_from_file(self, filename): + url_filename = os.path.basename(filename) + url_datetime = url_filename[-23:-8] + return datetime.datetime.strptime(url_datetime, '%Y%m%d_%H%M%S') + diff --git a/install/helioviewer/jp2parser.py b/install/helioviewer/jp2parser.py index 40700915..91a88666 100644 --- a/install/helioviewer/jp2parser.py +++ b/install/helioviewer/jp2parser.py @@ -99,6 +99,9 @@ def getData(self): # For PUNCH, the different types (e.g. CAM, PAM) are only in the file name, # not anywhere inside the metadata. image['detector'] = self._get_punch_file_type(self._filepath) + elif image['instrument'] == 'SoloHI': + imageData.nickname = 'HI Difference Mosaic' + image['detector'] = "SoloHI" # In sunpy V3, the nickname changed to include the filter. # Having the space in it breaks how helioviewer loads images due to # the space in the file name. To prevent this problem we're selecting @@ -129,6 +132,8 @@ def getData(self): elif image['instrument'] == "SPICE": image['measurement'] = 'intensity' image['line'] = self._get_spice_line(imageData) + elif image['instrument'] == 'SoloHI': + image['measurement'] = 'Difference Mosaic' else: image['measurement'] = measurement image['date'] = self._get_date(imageData) diff --git a/management/data/get_jp2_info.py b/management/data/get_jp2_info.py index 29579c79..21b744b4 100644 --- a/management/data/get_jp2_info.py +++ b/management/data/get_jp2_info.py @@ -57,11 +57,11 @@ def get_config(filepath): default_userconfig = os.path.join(basedir, 'settings/settings.cfg') if filepath is not None and os.path.isfile(filepath): - config.readfp(open(filepath)) + config.read_file(open(filepath)) elif os.path.isfile(default_userconfig): - config.readfp(open(default_userconfig)) + config.read_file(open(default_userconfig)) else: - config.readfp(open(os.path.join(basedir, 'settings/settings.example.cfg'))) + config.read_file(open(os.path.join(basedir, 'settings/settings.example.cfg'))) return config @@ -72,12 +72,12 @@ def get_db_with_config(cfg): dbuser = conf.get('database', 'dbuser') dbpass = conf.get('database', 'dbpass') db, cursor = get_db_cursor(dbhost, dbname, dbuser, dbpass) - return cursor + return db, cursor def main(): args = parse_args() print(args) - cursor = get_db_with_config(args.config) + db, cursor = get_db_with_config(args.config) extract_datasource_name(args.jp2_file, cursor)