`create_meta_pixels` should check the time bins edges (rather than just center) to return time mask
Closed this issue · 3 comments
Currently, in create_meta_pixels
to find the data that is contained within the times and energies, only the center of the time bins are checked.
For example here:
https://github.com/TCDSolar/stixpy/blob/main/stixpy/calibration/visibility.py#L119
the time-range passed is only checked against the center time of the data bins. However, if the bins are large (e.g. 20s or something), then the time-range passed could be within the bin, however it isn't satisfied by the center value.
For example:
In this extreme example, this data only have one time bin, which is quite large (890s). Following the logic from L119 from the visibility.py, this isn't satisfied
>>> time_range = ["2023-04-01T07:32:17.850", "2023-04-01T07:35:37.850"]
>>> pixel_data = Product("https://pub099.cs.technik.fhnw.ch/data/fits/L1/2023/04/01/SCI/solo_L1_stix-sci-xray-cpd_20230401T073020-20230401T074511_V02_2304011277-50312.fits")
>>> t_mask = (pixel_data.times >= Time(time_range[0])) & (pixel_data.times <= Time(time_range[1]))
>>> t_mask
array([False])
however, its just because the center of the time bin is:
>>> pixel_data.times
<Time object: scale='utc' format='isot' value=['2023-04-01T07:37:45.999']>
however the passed time_range is within the bin of the data (here as its only one time point):
>>> pixel_data.time_range
<sunpy.time.timerange.TimeRange object at 0x1180da180>
Start: 2023-04-01 07:30:20
End: 2023-04-01 07:45:11
Center:2023-04-01 07:37:45
Duration:0.010309027777777757 days or
0.24741666666666617 hours or
14.84499999999997 minutes or
890.6999999999982 seconds
so it really should be checking that the passed time range is withing the edge of the bins, something like pixel.start_times and pixel.end_times? This could be inferred from the duration.
For context, this is what the IDL software does as far as I know.
like a simple solution would be something like:
pixel_starts = pixel_data.times - pixel_data.durtaion/2
pixel_ends = pixel_data.times + pixel_data.durtaion/2
t_mask = (pixel_starts >= Time(time_range[0])) & (pixel_ends <= Time(time_range[1]))
what do you think @samaloney ?
We also need to consider bins where the time range is inside the bin edges so I think the following three cases should work
t_mask_1 = (pixel_starts >= Time(time_range[0])) & (pixel_ends <= Time(time_range[1]))
t_mask_2 = (Time(time_range[0]) - pixel_starts < pixel_data.durtaion) & (Time(time_range[0]) - pixel_starts > 0 * u.s)
t_mask_3 = (pixel_ends - Time(time_range[1]) < pixel_data.durtaion) & (pixel_ends - Time(time_range[0]) > 0 * u.s)
t_mask = np.logical_or(t_mask_1, t_mask_2, t_mask_3)