Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uszu gets unreliable #993

Open
CaeruleusAqua opened this issue Jan 11, 2025 · 4 comments
Open

Uszu gets unreliable #993

CaeruleusAqua opened this issue Jan 11, 2025 · 4 comments

Comments

@CaeruleusAqua
Copy link
Contributor

CaeruleusAqua commented Jan 11, 2025

Hi folks,

I have noticed several times that uszu unfortunately often works unreliably. sometimes it just seems to miss things.
What is worse, however, is that there are some scripts that control the brightness depending on the position of the sun and uszu only makes nonsense.

I then tried to debug this and noticed that a Python thread was running amok.
Permanently 100% CPU.

I have now been able to narrow down the problem to the ephem library. The problem is that the calculation of the position of the sun and the moon converges badly under some constellations (_find_rise_or_set). Unfortunately, this also explains why uszu sometimes runs completely without problems. I have installed a counter as a test, and the function currently does not converge even over 100 million iterations, and blocks the complete uszu .

There are also some issue entries in ephem

brandon-rhodes/pyephem#266
brandon-rhodes/pyephem#232

Unfortunately, nothing has happened for years

@CaeruleusAqua
Copy link
Contributor Author

I have limited the number of iterations to 1000 as a test and everything seems to be working again. However, I have no idea how much this affects the calculation of the time points.

@bmxp
Copy link
Member

bmxp commented Jan 12, 2025

I thought that Skyfield could be a nice replacement for pyephem. But when I examined this some years ago it just was not ready and it needed external files to be downloaded from internet source so I decided to wait.
Maybe you want to try to exchange pyephem for another solution?

In the meantime: Would you mind share your changes? We could implement a fix at best

@onkelandy
Copy link
Member

Gow did you linit iterations? Would a parameter for the plugin be a solution?

@CaeruleusAqua
Copy link
Contributor Author

I have changed code directly in ephem, if then we would have to fork ephem, maybe we also get a pull request with a new parameter for the function through...

But I think the best thing would be to replace the lib...

ephem/init.py

    def _find_rise_or_set(self, body, start, use_center, direction, do_rising, max_iterations = 1000):
        if isinstance(body, EarthSatellite):
            raise TypeError(
                'the rising and settings methods do not'
                ' support earth satellites because of their speed;'
                ' please use the higher-resolution next_pass() method'
                )

        original_pressure = self.pressure
        original_date = self.date
        try:
            self.pressure = 0.0  # otherwise geometry doesn't work
            if start is not None:
                self.date = start
            prev_ha = None
            iterations = 0
            while True:
                iterations+=1
                if isnan(self.date):
                    raise ValueError('cannot find a next rising or setting'
                                     ' if the date is NaN')
                body.compute(self)
                horizon = self.horizon
                if not use_center:
                    horizon -= body.radius
                if original_pressure:
                    horizon = unrefract(original_pressure, self.temp, horizon)
                abs_target_ha = self._target_hour_angle(body, horizon)
                if do_rising:
                    target_ha = - abs_target_ha  # rises in east (az 0-180)
                else:
                    target_ha = abs_target_ha    # sets in west (az 180-360)
                ha = body.ha
                difference = target_ha - ha
                if prev_ha is None:
                    difference %= tau  # force angle to be positive
                    if direction < 0:
                        difference -= tau
                    bump = difference / tau
                    if abs(bump) < default_newton_precision:
                        # Already at target event: move forward to next one.
                        bump += direction
                else:
                    difference = _plusminus_pi(difference)
                    bump = difference / tau
                if abs(bump) < default_newton_precision:
                    break
                if iterations > max_iterations:
                    break;
                self.date += bump
                prev_ha = ha

            if abs_target_ha == _slightly_more_than_pi:
                raise AlwaysUpError('%r is above the horizon at %s'
                                    % (body.name, self.date))

            if abs_target_ha == _slightly_less_than_zero:
                raise NeverUpError('%r is below the horizon at %s'
                                   % (body.name, self.date))

            return self.date
        finally:
            if self.pressure != original_pressure:
                self.pressure = original_pressure
                body.compute(self)
            self.date = original_date

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants