88
99from imap_processing .cdf .imap_cdf_manager import ImapCdfAttributes
1010from imap_processing .glows .l0 .decom_glows import decom_packets
11- from imap_processing .glows .l0 .glows_l0_data import DirectEventL0
11+ from imap_processing .glows .l0 .glows_l0_data import DirectEventL0 , HistogramL0
1212from imap_processing .glows .l1a .glows_l1a_data import DirectEventL1A , HistogramL1A
13- from imap_processing .spice .time import TTJ2000_EPOCH , met_to_ttj2000ns
13+ from imap_processing .glows .l1b .glows_l1b_data import HistogramL1B
14+ from imap_processing .spice .time import (
15+ met_to_datetime64 ,
16+ met_to_ttj2000ns ,
17+ )
1418
1519
1620def create_glows_attr_obj (data_version : str ) -> ImapCdfAttributes :
@@ -66,13 +70,19 @@ def glows_l1a(packet_filepath: Path, data_version: str) -> list[xr.Dataset]:
6670 # Create dictionaries to group data by day
6771 de_by_day = process_de_l0 (de_l0 )
6872 hists_by_day = defaultdict (list )
73+ # Assume the observational day starts with the first packet, then find any new
74+ # observation days.
75+ # TODO: replace determine_observational_day with spin table API
76+ obs_days = [hist_l0 [0 ].SEC ]
77+ obs_days += determine_observational_day (hist_l0 )
6978
70- # TODO: Make this its own function?
7179 for hist in hist_l0 :
7280 hist_l1a = HistogramL1A (hist )
73- # Split by IMAP start time
74- # TODO: Should this be MET?
75- hist_day = (TTJ2000_EPOCH + met_to_ttj2000ns (hist .SEC )).astype ("datetime64[D]" )
81+ # Determine the day the histogram belongs to. This finds the observation
82+ # day in obs_day that is nearest the histogram timestamp without going over.
83+ hist_day = next (
84+ (day for day in reversed (obs_days ) if day <= hist .SEC ), obs_days [- 1 ]
85+ )
7686 hists_by_day [hist_day ].append (hist_l1a )
7787
7888 # Generate CDF files for each day
@@ -88,6 +98,36 @@ def glows_l1a(packet_filepath: Path, data_version: str) -> list[xr.Dataset]:
8898 return output_datasets
8999
90100
101+ def determine_observational_day (hist_l0 : list [HistogramL0 ]) -> list :
102+ """
103+ Find the timestamps for each observational day.
104+
105+ This function temporarily uses the is_night flag to determine the start of a new
106+ observational day, but should eventually use the spin table APIs.
107+
108+ Parameters
109+ ----------
110+ hist_l0 : list[HistogramL0]
111+ List of HistogramL0 objects.
112+
113+ Returns
114+ -------
115+ list
116+ List of start times for each observational day.
117+ """
118+ prev_is_night = - 1
119+ obs_day_change = []
120+ for hist in hist_l0 :
121+ flags = HistogramL1B .deserialize_flags (hist .FLAGS )
122+ is_night : int = int (flags [6 ])
123+ if prev_is_night and not is_night :
124+ obs_day_change .append (hist .SEC )
125+
126+ prev_is_night = is_night
127+
128+ return obs_day_change
129+
130+
91131def process_de_l0 (
92132 de_l0 : list [DirectEventL0 ],
93133) -> dict [np .datetime64 , list [DirectEventL1A ]]:
@@ -111,7 +151,7 @@ def process_de_l0(
111151 de_by_day = dict ()
112152
113153 for de in de_l0 :
114- de_day = (TTJ2000_EPOCH + met_to_ttj2000ns (de .MET )).astype ("datetime64[D]" )
154+ de_day = (met_to_datetime64 (de .MET )).astype ("datetime64[D]" )
115155 if de_day not in de_by_day :
116156 de_by_day [de_day ] = [DirectEventL1A (de )]
117157 # Putting not first data int o last direct event list.
@@ -315,7 +355,7 @@ def generate_histogram_dataset(
315355 Dataset containing the GLOWS L1A histogram CDF output.
316356 """
317357 # Store timestamps for each HistogramL1A object.
318- time_data = np .zeros (len (hist_l1a_list ), dtype = "datetime64[ns] " )
358+ time_data = np .zeros (len (hist_l1a_list ), dtype = "int64 " )
319359 # TODO Add daily average of histogram counts
320360 # TODO compute average temperature etc
321361 # Data in lists, for each of the 25 time varying datapoints in HistogramL1A
0 commit comments