Skip to content

Commit 3886715

Browse files
authored
Merge pull request #310 from sageyu123/master
Major Update: Integrate WSClean into EOVSA Synoptic Imaging Pipeline and fix an issue with ephemeris retrieval in task_ptclean6.py
2 parents 1e92904 + 237a0a0 commit 3886715

21 files changed

Lines changed: 3771 additions & 460 deletions

suncasa/dspec/dspec.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1315,7 +1315,7 @@ def format_coord(x, y):
13151315
elif pol == 'IV':
13161316
spec_plt_1 = I_plot
13171317
spec_plt_2 = V_plot
1318-
cmap2 = 'gray'
1318+
cmap2 = 'RdBu_r'
13191319
if (vmax2 is None) and (vmin2 is None):
13201320
vmax2 = np.nanmax(np.abs(spec_plt_2))
13211321
vmin2 = -vmax2
@@ -1328,7 +1328,7 @@ def format_coord(x, y):
13281328
# this is for Stokes I + polarization degree
13291329
spec_plt_1 = I_plot
13301330
spec_plt_2 = V_plot / I_plot
1331-
cmap2 = 'gray'
1331+
cmap2 = 'RdBu_r'
13321332
if (vmax2 is None) and (vmin2 is None):
13331333
vmax2 = 1.
13341334
vmin2 = -1.

suncasa/eovsa/eovsa_diskmodel.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,11 +1102,24 @@ def pipeline_run(vis, outputvis='', workdir=None, slfcaltbdir=None, imgoutdir=No
11021102
return None
11031103

11041104
# Copy original ms to local directory
1105-
if os.path.exists(os.path.basename(vis)):
1106-
shutil.rmtree(os.path.basename(vis))
1107-
print('Copy {} to working directory {}/'.format(vis, os.getcwd()))
1108-
shutil.copytree(vis, os.path.basename(vis))
1109-
vis = os.path.basename(vis)
1105+
if vis.lower().endswith('.ms'):
1106+
if os.path.exists(os.path.basename(vis)):
1107+
shutil.rmtree(os.path.basename(vis))
1108+
print('Copy {} to working directory {}/'.format(vis, os.getcwd()))
1109+
shutil.copytree(vis, os.path.basename(vis))
1110+
vis = os.path.basename(vis)
1111+
elif vis.lower().endswith('.tar.gz'):
1112+
if os.path.exists(os.path.basename(vis)):
1113+
shutil.rmtree(os.path.basename(vis))
1114+
if os.path.exists(os.path.basename(vis.rstrip('.tar.gz'))):
1115+
shutil.rmtree(os.path.basename(vis.rstrip('.tar.gz')))
1116+
print(f'Extracting {vis} to working directory {os.getcwd()}/')
1117+
os.system(f'tar -xzf {vis} -C {os.getcwd()}')
1118+
vis = os.path.basename(vis.rstrip('.tar.gz'))
1119+
else:
1120+
print('Input vis file must be either a .ms or .tar.gz file.')
1121+
return None
1122+
11101123
# Generate calibrated visibility by self calibrating on the solar disk
11111124
##ms_slfcaled, diskxmlfile = disk_slfcal(vis, slfcaltbdir=slfcaltbdir)
11121125
flagmanager(vis, mode='save', versionname='pipeline_init')

suncasa/eovsa/eovsa_fitsutils.py

Lines changed: 75 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -94,138 +94,90 @@ def rewriteImageFits(datestr, verbose=False, writejp2=False, overwritejp2=False,
9494
ndfits.write_j2000_image(fj2name, data[::-1, :], hdu.header)
9595
return
9696

97+
def main(dateobj=None, ndays=1, overwritejp2=False, overwritefits=False):
98+
"""
99+
Main pipeline for creating compressed FITS and JP2 files of EOVSA daily full-disk images.
100+
101+
:param dateobj: The starting datetime for processing. If None, defaults to two days before now.
102+
:type dateobj: datetime, optional
103+
:param ndays: Number of days to process (spanning from dateobj - ndays + 1 to dateobj), defaults to 1.
104+
:type ndays: int, optional
105+
:param overwritejp2: If True, overwrite existing EOVSA JP2 files, defaults to False.
106+
:type overwritejp2: bool, optional
107+
:param overwritefits: If True, overwrite existing EOVSA FITS files, defaults to False.
108+
:type overwritefits: bool, optional
109+
:raises Exception: If an error occurs during processing.
110+
:return: None
111+
:rtype: None
112+
"""
113+
from datetime import timedelta
114+
import numpy as np
115+
from astropy.time import Time
97116

98-
def main(year=None, month=None, day=None, ndays=1, overwritejp2=False, overwritefits=False):
99-
# tst = datetime.strptime("2017-04-01", "%Y-%m-%d")
100-
# ted = datetime.strptime("2019-12-31", "%Y-%m-%d")
101-
if year:
102-
ted = datetime(year, month, day)
103-
else:
117+
# Use dateobj if provided; otherwise, default to two days before now.
118+
if dateobj is None:
104119
ted = datetime.now() - timedelta(days=2)
120+
else:
121+
ted = dateobj
122+
123+
# Compute the start date (tst) for processing based on ndays.
105124
tst = Time(np.fix(Time(ted).mjd) - ndays + 1, format='mjd').datetime
106-
print("Running pipeline_fitsutils for date from {} to {}".format(tst.strftime("%Y-%m-%d"),
107-
ted.strftime("%Y-%m-%d")))
125+
print("Running pipeline_fitsutils for date from {} to {}.".format(
126+
tst.strftime("%Y-%m-%d"), ted.strftime("%Y-%m-%d")))
108127
dateobs = tst
109128
while dateobs <= ted:
110129
datestr = dateobs.strftime("%Y-%m-%d")
111-
rewriteImageFits(datestr, verbose=True, writejp2=True, overwritejp2=overwritejp2, overwritefits=overwritefits)
130+
rewriteImageFits(datestr, verbose=True, writejp2=True,
131+
overwritejp2=overwritejp2, overwritefits=overwritefits)
112132
dateobs = dateobs + timedelta(days=1)
113133

114134

115135
if __name__ == '__main__':
116-
'''
117-
Name:
118-
eovsa_fitsutils --- pipeline for created the compressed fits and jp2 files of EOVSA daily full-disk images.
119-
120-
Synopsis:
121-
eovsa_fitsutils.py [options]... [DATE_IN_YY_MM_DD]
122-
123-
Description:
124-
Plot EOVSA daily full-disk images at multi frequencies of the date specified
125-
by DATE_IN_YY_MM_DD (or from ndays before the DATE_IN_YY_MM_DD if option --ndays/-n is provided).
126-
If DATE_IN_YY_MM_DD is omitted, it will be set to 2 days before now by default.
127-
The are no mandatory arguments in this command.
128-
129-
-c, --clearcache
130-
Remove temporary files
131-
132-
-n, --ndays
133-
Processing the date spanning from DATE_IN_YY_MM_DD-ndays to DATE_IN_YY_MM_DD. Default is 30
134-
135-
-o, --overwritejp2
136-
If True, overwrite eovsa jp2 files.
137-
Syntax: True, False, T, F, 1, 0
138-
139-
-O, --overwritefits
140-
If True, overwrite eovsa fits files.
141-
Syntax: True, False, T, F, 1, 0
142-
143-
144-
Example:
145-
eovsa_fitsutils.py -c True -n 2 -o True -O True 2020 06 10
146-
'''
147-
import sys
148-
import numpy as np
149-
import getopt
136+
import argparse
150137
from datetime import datetime, timedelta
138+
from astropy.time import Time
139+
140+
parser = argparse.ArgumentParser(
141+
description='Pipeline for creating compressed FITS and JP2 files of EOVSA daily full-disk images.'
142+
)
143+
# Default date is set to two days before the current date at 20:00 UT (YYYY-MM-DDT20:00).
144+
default_date = (datetime.now() - timedelta(days=2)).strftime('%Y-%m-%dT20:00')
145+
parser.add_argument(
146+
'--date', type=str, default=default_date,
147+
help='Date to process in YYYY-MM-DDT20:00 format, defaults to 20:00 UT two days before the current date.'
148+
)
149+
parser.add_argument(
150+
'--ndays', type=int, default=1,
151+
help='Process data spanning from DATE minus ndays to DATE (default: 1 day).'
152+
)
153+
parser.add_argument(
154+
'--overwritejp2', action='store_true',
155+
help='Overwrite existing EOVSA JP2 files.'
156+
)
157+
parser.add_argument(
158+
'--overwritefits', action='store_true',
159+
help='Overwrite existing EOVSA FITS files.'
160+
)
161+
# Optional positional date arguments: year month day (overrides --date if provided)
162+
parser.add_argument(
163+
'date_args', type=int, nargs='*',
164+
help='Optional date arguments: year month day. If provided, overrides --date.'
165+
)
166+
167+
args = parser.parse_args()
168+
169+
# Determine the processing date.
170+
if len(args.date_args) == 3:
171+
year, month, day = args.date_args
172+
dateobj = datetime(year, month, day, 20) # Use 20:00 UT for the specified date.
173+
else:
174+
dateobj = Time(args.date).datetime
151175

152-
# import subprocess
153-
# shell = subprocess.check_output('echo $0', shell=True).decode().replace('\n', '').split('/')[-1]
154-
# print("shell " + shell + " is using")
155-
156-
print(sys.argv)
157-
year = None
158-
month = None
159-
day = None
160-
ndays = 1
161-
clearcache = True
162-
opts = []
163-
overwritejp2 = False
164-
overwritefits = False
165-
try:
166-
argv = sys.argv[1:]
167-
opts, args = getopt.getopt(argv, "c:n:o:O:", ['clearcache=', 'ndays=', 'overwritejp2=', 'overwritefits='])
168-
print(opts, args)
169-
for opt, arg in opts:
170-
if opt in ['-c', '--clearcache']:
171-
if arg in ['True', 'T', '1']:
172-
clearcache = True
173-
elif arg in ['False', 'F', '0']:
174-
clearcache = False
175-
else:
176-
clearcache = np.bool_(arg)
177-
elif opt in ('-n', '--ndays'):
178-
ndays = int(arg)
179-
elif opt in ('-o', '--overwritejp2'):
180-
if arg in ['True', 'T', '1']:
181-
overwritejp2 = True
182-
elif arg in ['False', 'F', '0']:
183-
overwritejp2 = False
184-
else:
185-
overwritejp2 = np.bool_(arg)
186-
elif opt in ('-O', '--overwritefits'):
187-
if arg in ['True', 'T', '1']:
188-
overwritefits = True
189-
elif arg in ['False', 'F', '0']:
190-
overwritefits = False
191-
else:
192-
overwritefits = np.bool_(arg)
193-
nargs = len(args)
194-
if nargs == 3:
195-
year = int(args[0])
196-
month = int(args[1])
197-
day = int(args[2])
198-
else:
199-
year = None
200-
month = None
201-
day = None
202-
except getopt.GetoptError as err:
203-
print(err)
204-
print('Error interpreting command line argument')
205-
year = None
206-
month = None
207-
day = None
208-
ndays = 1
209-
clearcache = True
210-
opts = []
211-
overwritejp2 = False
212-
overwritefits = False
213-
214-
# ##debug
215-
# year = 2023
216-
# month = 1
217-
# day = 5
218-
# ndays = 1
219-
# clearcache = False
220-
# overwritejp2 = True
221-
# overwritefits = True
222-
223-
print("Running eovsa_fitsutils for date {}-{}-{}.".format(year, month, day))
224-
kargs = {'ndays': ndays,
225-
'clearcache': clearcache,
226-
'overwritejp2': overwritejp2,
227-
'overwritefits': overwritefits}
228-
for k, v in kargs.items():
229-
print(k, v)
230-
231-
main(year, month, day, ndays, overwritejp2=overwritejp2, overwritefits=overwritefits)
176+
print(f"Running eovsa_fitsutils for date {dateobj.strftime('%Y-%m-%d')}.")
177+
print("Arguments:")
178+
print(f" ndays: {args.ndays}")
179+
print(f" overwritejp2: {args.overwritejp2}")
180+
print(f" overwritefits: {args.overwritefits}")
181+
182+
# Call the main function with the parsed datetime object.
183+
main(dateobj, args.ndays, overwritejp2=args.overwritejp2, overwritefits=args.overwritefits)

suncasa/eovsa/eovsa_flare_pipeline.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,55 @@ def get_user_confirmation(prompt):
6868
print("Invalid input. Please enter 'y' or 'n'.")
6969

7070
class FlareSelfCalib():
71+
"""
72+
FlareSelfCalib provides a pipeline for self-calibration and imaging of EOVSA solar flare data.
73+
74+
This class handles the detection of flare times and locations, self-calibration of visibility data,
75+
and final imaging steps for flare events, as well as renaming and moving the output files to designated
76+
web directories.
77+
78+
:param vis: Full path for the input visibility data or a pre-processed flare-calibrated dataset, defaults to None
79+
:type vis: str or object, optional
80+
:param workpath: Working directory path for pipeline outputs, defaults to './'
81+
:type workpath: str, optional
82+
:param logfile: Path to the logfile. If not provided, a default log file is generated based on the current time, defaults to None
83+
:type logfile: str, optional
84+
85+
:raises ValueError: If the input visibility (when provided as a string) does not exist.
86+
87+
Example:
88+
from suncasa.eovsa import eovsa_flare_pipeline
89+
from eovsapy.util import Time
90+
91+
trange_str = ['2023-12-14T16:54:00', '2023-12-14T17:10:00']
92+
flare_id = '20231214170000'
93+
94+
# Initialize the pipeline with a given time range
95+
trange = Time(trange_str)
96+
fp = eovsa_flare_pipeline.FlareSelfCalib(vis=trange)
97+
98+
# Run the self-calibration and imaging pipeline
99+
fp.slfcal_pipeline(doselfcal=True, doimaging=True)
100+
101+
# Rename and move the output files to the designated web directories
102+
fp.rename_move_files(
103+
flare_id=flare_id,
104+
fitsdir_web_tp='/data1/eovsa/fits/flares/',
105+
movdir_web_tp='/common/webplots/SynopticImg/eovsamedia/eovsa-browser/',
106+
msdir_web_tp='/data1/eovsa/fits/flares/',
107+
dorename_fits=True,
108+
domove_fits=True,
109+
dorename_mov=True,
110+
domove_mov=True,
111+
domove_ms=True,
112+
dormworkdir=True,
113+
docopy=True
114+
)
115+
116+
:return: None
117+
:rtype: None
118+
"""
119+
71120
def __init__(self, vis=None, workpath='./', logfile=None):
72121
##========================= initial setups =================================
73122
self.workpath = workpath

0 commit comments

Comments
 (0)