Skip to content

BUG - possible bug in MAG time conversion #2464

@subagonsouth

Description

@subagonsouth

Description of the issue

While poking around in IALiRT/MAG processing code due to spin-phase offset that Laura identified, I found the following:
In the mag_l1a_data.py TimeTuple class, the conversion from integer coarse and fine clock ticks to floating point seconds is:

MAX_FINE_TIME = np.iinfo(np.uint16).max  # This is equal to 65535
float(self.coarse_time + self.fine_time / MAX_FINE_TIME)

This seems like it might have a tiny error in the conversion. If the fine clock tick register counts up to 65535 and then rolls over to 0 and increments the coarse clock counter, then each fine tick is actually 1/65536 of a second. As implemented, the fine clock counter would count up to 65534 before resetting to zero.

I suggest going through the __add__(), to_seconds(), and to_j2000ns() methods and fixing this issue.

An additional (very tiny) error is introduced in the conversion to j2000ns. The met_to_j2000ns() function is written to take floating point met time and correctly convert that to j2000ns. The issue with the current implementation is that it assumes that the fine clock ticks exactly once every 1/65536th of a second. In actuality, the s/c clocks drift. The sclk kernel accounts for this drift. I submit that the correct conversion is:

j2000ns = np.int64(met_to_ttj2000ns(self.to_seconds()))

Steps to reproduce the issue

No response

Expected behavior (What should happen)

No response

Actual behavior (What does happen)

No response

Code Snippet:

Additional notes, affected areas, and suggested fixes

    def __add__(self, seconds: float) -> TimeTuple:
        """
        Add a number of seconds to the time tuple.

        Parameters
        ----------
        seconds : float
            Number of seconds to add.

        Returns
        -------
        time : TimeTuple
            New time tuple with the current time tuple + seconds.
        """
        # Add whole seconds to coarse time
        coarse = self.coarse_time + floor(seconds)
        # fine time is 1/65535th of a second
        # ===> fine time is 1/65536th of a second
        fine = self.fine_time + round((seconds % 1) * (MAX_FINE_TIME + 1))

        # If fine is larger than the max, move the excess into coarse time.
        if fine > MAX_FINE_TIME:
            coarse = coarse + floor(fine / (MAX_FINE_TIME + 1))
            fine = fine % (MAX_FINE_TIME + 1)

        return TimeTuple(coarse, fine)
    def to_seconds(self) -> float:
        """
        Convert time tuple into seconds (float).

        Returns
        -------
        seconds : float
            Time in seconds.
        """
        return float(self.coarse_time + self.fine_time / (MAX_FINE_TIME + 1))
    def to_j2000ns(self) -> np.int64:
        """
        Convert time tuple into J2000ns.

        Returns
        -------
        j2000ns : numpy.int64
            Time in nanoseconds since J2000 epoch.
        """
        return np.int64(met_to_ttj2000ns(self.to_seconds()))

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

Projects

Status

No status

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions